bindless imageLoad 및 imageStore를 사용하는 프래그먼트 셰이더를 통해 3D 1 구성 요소 플로트 텍스처로 렌더링하는 코드를 너무 길게 썼습니다.nVidia OpenGL에서 glGetTexImage 및 imageStore를 혼합 할 때의 문제
코드가 제대로 작동하고 있습니다.
그런 다음 일부 GLSL 컴파일러 버그를 해결해야하므로 위의 3D 텍스처를 glGetTexImage를 통해 호스트로 다시 읽고 싶었습니다. 예, 저는 glMemoryBarrierEXT (GL_ALL_BARRIER_BITS)를했습니다. glGetTexLevelparameteriv() 및 일치하는 모든 것을 통해 텍스처 정보를 확인했습니다. OpenGL 오류가 있는지 확인한 적이 없었습니다.
슬프게도 glGetTexImage는 프래그먼트 셰이더에 의해 작성된 내용을 읽지 않습니다. 대신 glTexImage3D()를 호출하여 텍스처를 생성 할 때 가짜 값을 반환합니다.
예상되는 동작입니까? 설명서에 별도로 나와 있습니다.
실제로 glGetTexImage가 작동하는 경우, 3D 텍스처 (장치에 상주합니까?)에있는 데이터를 어떻게 다시 읽을 수 있습니까? 텍스처에 비거주 자료가있을 때와 마찬가지로 드라이버가이를 수행 할 수 있습니다. 확실히 glGetTexImage가 그렇게 작동 여부를했는데 만약 내가 요구 한
...이 간단한 일을 할 수있는 간단한 방법이있다. 여기
void Bindless3DArray::dump_array(Array3D<float> &out)
{
bool was_mapped = m_image_mapped;
if (was_mapped)
unmap_array(); // unmap array so it's accessible to opengl
out.resize(m_depth, m_height, m_width);
glBindTexture(GL_TEXTURE_3D, m_textureid); // from glGenTextures()
#if 0
int w,h,d;
glGetTexLevelParameteriv(GL_TEXTURE_3D, 0, GL_TEXTURE_WIDTH, &w);
glGetTexLevelParameteriv(GL_TEXTURE_3D, 0, GL_TEXTURE_HEIGHT, &h);
glGetTexLevelParameteriv(GL_TEXTURE_3D, 0, GL_TEXTURE_DEPTH, &d);
int internal_format;
glGetTexLevelParameteriv(GL_TEXTURE_3D, 0, GL_TEXTURE_INTERNAL_FORMAT, &internal_format);
int data_type_r, data_type_g;
glGetTexLevelParameteriv(GL_TEXTURE_3D, 0, GL_TEXTURE_RED_TYPE, &data_type_r);
glGetTexLevelParameteriv(GL_TEXTURE_3D, 0, GL_TEXTURE_GREEN_TYPE, &data_type_g);
int size_r, size_g;
glGetTexLevelParameteriv(GL_TEXTURE_3D, 0, GL_TEXTURE_RED_SIZE, &size_r);
glGetTexLevelParameteriv(GL_TEXTURE_3D, 0, GL_TEXTURE_GREEN_SIZE, &size_g);
#endif
glGetTexImage(GL_TEXTURE_3D, 0, GL_RED, GL_FLOAT, &out(0,0,0));
glBindTexture(GL_TEXTURE_3D, 0);
CHECK_GLERROR();
if (was_mapped)
map_array_to_cuda(); // restore state
}
bindless 배열 생성 코드 것 : 여기에 코드입니다
void Bindless3DArray::allocate(int w, int h, int d, ElementType t)
{
if (!m_textureid)
glGenTextures(1, &m_textureid);
m_type = t;
m_width = w;
m_height = h;
m_depth = d;
glBindTexture(GL_TEXTURE_3D, m_textureid);
CHECK_GLERROR();
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, 0); // ensure only 1 miplevel is allocated
CHECK_GLERROR();
Array3D<float> foo(d, h, w);
// DEBUG -- glGetTexImage returns THIS data, not what's on device
for (int z=0; z<m_depth; ++z)
for (int y=0; y<m_height; ++y)
for (int x=0; x<m_width; ++x)
foo(z,y,x) = 3.14159;
//-- Texture creation
if (t == ElementInteger)
glTexImage3D(GL_TEXTURE_3D, 0, GL_R32UI, w, h, d, 0, GL_RED_INTEGER, GL_INT, 0);
else if (t == ElementFloat)
glTexImage3D(GL_TEXTURE_3D, 0, GL_R32F, w, h, d, 0, GL_RED, GL_FLOAT, &foo(0,0,0));
else
throw "Invalid type for Bindless3DArray";
CHECK_GLERROR();
m_handle = glGetImageHandleNV(m_textureid, 0, true, 0, (t == ElementInteger) ? GL_R32UI : GL_R32F);
glMakeImageHandleResidentNV(m_handle, GL_READ_WRITE);
CHECK_GLERROR();
#ifdef USE_CUDA
checkCuda(cudaGraphicsGLRegisterImage(&m_image_resource, m_textureid, GL_TEXTURE_3D, cudaGraphicsRegisterFlagsSurfaceLoadStore));
#endif
}
내가 OpenGL을 조각 프로그램을 통해 그것을 렌더링, 배열을 할당 한 다음 내가 dump_array 전화는() 읽기 다시 데이터. 슬프게도, 나는 allocate 호출에서로드 한 것을 얻는다.
void App::clear_deepz()
{
deepz_clear_program.bind();
deepz_clear_program.setUniformValue("sentinel", SENTINEL);
deepz_clear_program.setUniformValue("deepz", deepz_array.handle());
deepz_clear_program.setUniformValue("sem", semaphore_array.handle());
run_program();
glMemoryBarrierEXT(GL_ALL_BARRIER_BITS);
// glMemoryBarrierEXT(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
// glMemoryBarrierEXT(GL_SHADER_GLOBAL_ACCESS_BARRIER_BIT_NV);
deepz_clear_program.release();
}
과 조각 프로그램처럼
렌더 프로그램은 같습니다 무엇 discard
수단이 아니다
#version 420\n
in vec4 gl_FragCoord;
uniform float sentinel;
coherent uniform layout(size1x32) image3D deepz;
coherent uniform layout(size1x32) uimage3D sem;
void main(void)
{
ivec3 coords = ivec3(gl_FragCoord.x, gl_FragCoord.y, 0);
imageStore(deepz, coords, vec4(sentinel));
imageStore(sem, coords, ivec4(0));
discard; // don't write to FBO at all
}
실제 코드를 표시하지 않을 때 문제가 무엇인지 말하기는 어렵습니다. –
요청에 따라 코드를 추가했습니다. –
'glMemoryBarrierEXT (GL_ALL_BARRIER_BITS);'이것은 EXT_shader_image_load_store에서 온 것입니다. 그러나 다른 모든 것들은 핵심 OpenGL 4.2/ARB_shader_image_load_store 기능을 사용하고 있습니다. EXT가 없어야합니다. –