代码之家  ›  专栏  ›  技术社区  ›  Rafael Sabino

为什么OpenCL着色器在写入OpenGL纹理时会忽略绿色、蓝色和Alpha通道?

  •  4
  • Rafael Sabino  · 技术社区  · 7 年前

    我有一个opencl着色器,它试图将颜色写入纹理,但由于某些原因,只有红色通道应用于纹理,其余部分被忽略。不仅如此,这个红色通道值被复制到所有其他通道,给我一些透明的白色。有人知道为什么会这样吗?在Mac上使用Xcode进行Am编程(OpenCL 1.2)。纹理首先使用OpenGL创建,并与OpenCL共享。

    void TextureManager::createTexture3D(TextureManager::TexturesInfo 
    *texturesInfo, GLuint textureName)
    {
        glError();
        glBindTexture(GL_TEXTURE_3D, texturesInfo->tex[textureName]);
        glError();
        glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        glError();
        GLint level = 0, border = 0;
    
        GLint rgbType = GL_RGBA32F;
        GLint format = GL_RGBA;
        glTexImage3D(GL_TEXTURE_3D, level, rgbType, LPV::LPV_WIDTH, LPV::LPV_HEIGHT, LPV::LPV_DEPTH, border, format, GL_FLOAT, NULL);
        glError();
    }
    

    这是与OpenCL创建共享资源的代码:

    GLint error;
    accume_buffer = clCreateFromGLTexture(context,CL_MEM_READ_ONLY, GL_TEXTURE_3D, 0, _lpvTextures.accumeBuffer, &error);
    assert(error == CL_SUCCESS);
    accume_buffer2 = clCreateFromGLTexture(context,CL_MEM_WRITE_ONLY, GL_TEXTURE_3D, 0, _lpvTextures.accumeBuffer2, &error);
    assert(error == CL_SUCCESS);
    

    这是运行opencl着色器的代码:

    void LPV::runComputeShader(){
    
    glFlush();
    glFinish();
    GLint error = 0;
    cl_event opengl_get_completion;
    error =clEnqueueAcquireGLObjects(command_queue, 1, &accume_buffer, 0,0,&opengl_get_completion);
    clWaitForEvents(1, &opengl_get_completion);
    clReleaseEvent(opengl_get_completion);
    assert(error == CL_SUCCESS);
    error =clEnqueueAcquireGLObjects(command_queue, 1, &accume_buffer2, 0,0,0);
    assert(error == CL_SUCCESS);
    
    error |= clSetKernelArg(computeKernel, 0, sizeof(cl_image), &accume_buffer);
    assert( error == CL_SUCCESS);
    error |= clSetKernelArg(computeKernel, 1, sizeof(cl_image), (void*)&accume_buffer2);
    assert( error == CL_SUCCESS);
    
    
    GLuint dimensions = 3;
    size_t globalWorkSize[] = {LPV::LPV_WIDTH, LPV_HEIGHT, LPV_DEPTH };
    size_t localWorkSize[] = { 1, 1, 1};
    
    cl_event kernel_completion;
    error = clEnqueueNDRangeKernel(command_queue, computeKernel, dimensions, NULL, globalWorkSize, nullptr, 0, NULL, &kernel_completion);
    assert(error == CL_SUCCESS);
    error = clWaitForEvents(1, &kernel_completion);
    error |= clReleaseEvent(kernel_completion);
    assert(error == CL_SUCCESS);
    
    
    error = clEnqueueReleaseGLObjects(command_queue, 1, &accume_buffer, 0, 0, 0);
    assert(error == CL_SUCCESS);
    error = clEnqueueReleaseGLObjects(command_queue, 1, &accume_buffer2, 0, 0, 0);
    assert(error == CL_SUCCESS);
    
    clFlush(command_queue);
    clFinish(command_queue);
    
    
    }
    

    #pragma OPENCL EXTENSION cl_khr_3d_image_writes : enable
    
    const sampler_t lpvSampler = CLK_NORMALIZED_COORDS_FALSE | 
    CLK_ADDRESS_CLAMP_TO_EDGE | CLK_FILTER_NEAREST;
    
    
    kernel void propagate_lpv
                        (
                          read_only image3d_t src_buffer,
                          write_only image3d_t dest_buffer
                        )
    {
        int4 coord;
        coord.x = (int)get_global_id(0);
        coord.y = (int)get_global_id(1);
        coord.z = (int)get_global_id(2);
        coord.w = 1;
    
    float4 color = float4(1.0f, 0.0f, 0.0f, 1.0f);
    write_imagef(dest_buffer, coord, color);
    
    
    }
    

    有人知道为什么会这样吗?谢谢

    1 回复  |  直到 7 年前
        1
  •  2
  •   Rafael Sabino    7 年前

    问题是我使用了错误的语法。遗憾的是,OpenCL和GLSL似乎没有遵循我假设的相同语法。根据OpenCL编程指南,正确的语法如下:

    (float4)( float, float, float, float )
    (float4)( float2, float, float )
    (float4)( float, float2, float )
    (float4)( float, float, float2 )
    (float4)( float2, float2 )
    (float4)( float3, float )
    (float4)( float, float3 )
    (float4)( float )
    

    float4 color = float4(1.0f, 0.0f, 0.0f, 1.0f);
    

    收件人:

    float4 color = (float4)(1.0f, 0.0f, 0.0f, 1.0f);
    

    给我一个红色的纹理,这是我所期望的。