计算着色器中的sampler2D,编译错误

问题描述 投票:0回答:1

我正在尝试将 Windows 程序移植到 GNU/Linux,但计算着色器无法编译。

我对 GLSL 有一些了解。所以我想知道是否有解决方法可以让着色器正常工作。

我编写了一个显示编译错误的最小示例。

这是计算着色器:

#version 430 core
#extension GL_ARB_gpu_shader_int64 : enable
//#extension GL_ARB_bindless_texture : enable

layout(binding = 1) uniform TextureHandles {
    uvec2 texture_handles[512];
};

vec3 SampleTexture(uint texture_index, vec2 uv) {
    uv.y = 1.f - uv.y;
    sampler2D tex_sampler = sampler2D(texture_handles[texture_index]);
    return textureLod(tex_sampler, uv, 0.0f).xyz;
}

void main() {
}

以下是编译错误:

0:11(2): error: image/sampler variables may only be declared as function parameters or uniform-qualified global variables
0:11(2): error: opaque variables must be declared uniform
0:11(26): error: cannot initialize tex_sampler variable opaque
0:11(26): error: cannot construct opaque type `sampler2D'
0:12(20): warning: `tex_sampler' used uninitialized

关于不透明类型sampler2D的构造,我在网上看到需要启用GL_ARB_bindless_texture扩展,但是当我启用它时,出现错误,说它在计算着色器中不受支持。

这是使用 GLEW 和 GLFW 的最小程序,显示错误:

#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>

#define GLEW_STATIC
#include <GL/glew.h>

#include <stdlib.h>
#include <stdio.h>

/////////////////////////////////////////////////////////
//
// Shader programs for core profile:
//
const char * csprog_core =
"#version 430 core\n\
#extension GL_ARB_gpu_shader_int64 : enable\n\
//#extension GL_ARB_bindless_texture : enable\n\
\n\
layout(binding = 1) uniform TextureHandles {\n\
    uvec2 texture_handles[512];\n\
};\n\
\n\
vec3 SampleTexture(uint texture_index, vec2 uv) {\n\
    uv.y = 1.f - uv.y;\n\
    sampler2D tex_sampler = sampler2D(texture_handles[texture_index]);\n\
    return textureLod(tex_sampler, uv, 0.0f).xyz;\n\
}\n\
\n\
void main() {\n\
}\n\
\n";


int width, height;

void error_callback(int error, const char* description) {
  fprintf(stderr, "Error: %s\n", description);
}

int main( int argc, char *argv[ ], char *envp[ ] ) { 
  if(!glfwInit()) {
    exit(EXIT_FAILURE);
  }
  glfwSetErrorCallback(error_callback);
  
  glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
  glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
  GLFWwindow* window = glfwCreateWindow(640, 480, "Program", NULL, NULL);
  if(!window) {
    exit(EXIT_FAILURE);
  }
  glfwMakeContextCurrent(window);
  glfwSwapInterval(1);
  
  glfwGetFramebufferSize(window, &width, &height);

  // get version info
  const GLubyte* renderer;
  const GLubyte* version;

  ///////////////////////////////////////////////////////////////////////
  //
  // start GLEW extension handler
  //
  glewExperimental = GL_TRUE;
  GLenum err = glewInit();
  if(GLEW_OK != err) {
    fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
    return(-1);
  }
  fprintf(stdout, "Status: Using GLEW %s\n", glewGetString(GLEW_VERSION));
  
  // get version info
  renderer = glGetString(GL_RENDERER); // get renderer string
  version = glGetString(GL_VERSION); // version as a string
  printf("\nRenderer: %s", renderer);
  printf("\nOpenGL version supported %s\n", version);
  fflush(stdout);
  
  // tell GL to only draw onto a pixel if the shape is closer to the viewer
  glEnable(GL_DEPTH_TEST); // enable depth-testing
  glDepthFunc(GL_LESS); // depth-testing interprets a smaller value as "closer"

  //////////////////////////////////////////////////////////
  //
  // Shaders:
  //
  GLint params;
  GLint len;

  GLuint cscore = glCreateShader(GL_COMPUTE_SHADER);
  glShaderSource(cscore, 1, &csprog_core, NULL);
  glCompileShader(cscore);
  glGetShaderiv(cscore,GL_COMPILE_STATUS,&params);
  if(params == GL_FALSE) {
    GLchar log[100000];
    glGetShaderInfoLog(cscore,100000,&len,log);
    printf("\n\n%s\n\n",log);
    exit(EXIT_FAILURE);
  }
  //
  //////////////////////////////////////////////////////////
  
  glfwDestroyWindow(window);
  glfwTerminate();
  
  exit(EXIT_SUCCESS);
}
c++ opengl glsl compute-shader opengl-4
1个回答
0
投票

根据 Erdal Küçük 评论,我实现了纹理数组。将其宽度和高度设置为最大纹理的值。

我必须设置一些制服,以便在着色器中计算每个纹理的宽度和高度函数的 u 和 v 值。但 u 和 v 值的比例因子可以在 CPU 上预先计算。

计算着色器如下所示:

#version 430 core
#extension GL_ARB_gpu_shader_int64 : enable

uniform sampler2DArray Textures;
uniform uint maxwidth;
uniform uint maxheight;
uniform uint texwidths[MAX_TEXTURES];
uniform uint texheights[MAX_TEXTURES];

vec3 SampleTexture(uint texture_index, vec2 uv) {
    uv.y = 1.f - uv.y;
    uv.x = uv.x * float(texwidths[texture_index]) / maxwidth;
    uv.y = uv.y * float(texheights[texture_index]) / maxheight;
    return textureLod(Textures, vec3(uv, texture_index), 0.0f).xyz;
}

void main() {
}

硬件支持的数组的最大层数可以通过以下调用得知:

glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &value);

为了将纹理上传到 GPU,我使用此代码,设置纹理中最大宽度和高度值的纹理数组:

GLuint texture_array = 0;
glGenTextures(1,&texture_array);
glBindTexture(GL_TEXTURE_2D_ARRAY,texture_array);
int maxwidth = 0;
int maxheight = 0;
for(auto i = 0; i < textures.size(); ++i) {
  if(maxwidth < textures[i].width) maxwidth = textures[i].width;
  if(maxheight < textures[i].height) maxheight = textures[i].height;
}
glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, maxwidth, maxheight, textures.size());
    
std::vector<u_int32_t> clear_data(maxwidth * maxheight, 0);

for (auto i = 0; i < textures.size(); ++i) {
  auto & tex = textures[i];
      
  // Set to zero the texture at layer i:
  glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, i, maxwidth, maxheight, 1, GL_RGBA, GL_UNSIGNED_BYTE, &clear_data[0]);
      
  // copy the texture to GPU at layer i:
  glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, i, tex.width, tex.height, 1, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[textures[i].data_start]);
  
  texwidths_[i] = tex.width;
  texheights_[i] = tex.height;
}
glTexParameteri(GL_TEXTURE_2D_ARRAY,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D_ARRAY,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

glBindTexture(GL_TEXTURE_2D_ARRAY, NULL);

在启动着色器计算之前,我只需绑定纹理数组,并设置每个纹理的宽度和高度的统一值。

© www.soinside.com 2019 - 2024. All rights reserved.