【问题标题】:max uniform buffer size最大统一缓冲区大小
【发布时间】:2022-11-20 18:53:42
【问题描述】:

考虑以下 glsl 代码:

layout (std140) uniform ubo_lights {
    mat4 a;
    mat4 b;
    mat4 c; // <-- results in error. removing or sticking to vec4 is ok
};

我得到的错误是:

GL_INVALID_OPERATION:使用太小的统一缓冲区是未定义的行为。

在我当前的机器上,WebGl Report 显示:

Uniform Buffers
Max Uniform Buffer Bindings:    72
Max Uniform Block Size: 65536
Uniform Buffer Offset Alignment:    256
Max Combined Uniform Blocks:    32
Max Combined Vertex Uniform Components: 266240
Max Combined Fragment Uniform Components: 266240

为什么我会达到这个限制?我认为应该有比 3 个矩阵更多的回旋余地!

对于它的价值,我真的想做的是这样的,例如存储 8 种不同的灯:

#define MAX_LIGHTS 8

struct UboLight
{
    vec4 direction;
    vec4 color;
    vec4 position;
    vec4 extra;
};

layout (std140) uniform ubo_lights {
    UboLight lights[MAX_LIGHTS];
};

因此,非常感谢针对该目标的任何提示

【问题讨论】:

  • 听起来像是您正在使用的任何平台上的任何浏览器的实现中的错误。

标签: webgl webgl2


【解决方案1】:

这最终是一个没有向 ubo 上传足够大的缓冲区的错误。

所以,在上面的例子中,结构本身有 16 个元素,我们有 8 个实例,所以需要的数据量是 128 个值。

上传太小的缓冲区会导致此处出现错误。

上传时未绑定到正确的 UBO 也会发生这种情况(因为预期的 UBO 将没有提供足够的数据)

这是一个显示问题的codepen。例如注释掉第 60 行(提供少于所需数据)以查看错误:

https://codepen.io/dakom/pen/wvXPqrE?editors=1010

<canvas id="canvas"></canvas>
// not really drawing anything visible
const ubo = `
layout(std140) uniform foo_t {
    vec4 screen_and_position;
    vec4 color;
} foo;
`;

const vertexShaderSource = `#version 300 es
precision mediump float;

${ubo}

void main() {
    vec2 screen = foo.screen_and_position.xy;
    vec2 pos = foo.screen_and_position.zw;
    float aspect = screen.y / screen.x;
    vec2 scale = vec2(aspect, 1);
    gl_Position = vec4(pos * scale, 0, 1);
    gl_PointSize = 10.0;
}
`;

const fragmentShaderSource = `#version 300 es

precision mediump float;

layout(location = 0) out vec4 color;

${ubo}

void main() {
    color = foo.color;
}

`;

const canvas = document.getElementById("canvas");
const gl = canvas.getContext("webgl2");
gl.viewport(0,0,canvas.width,canvas.height);
const program = compileProgram();

draw();

function draw() {
  gl.useProgram(program);
  gl.clearColor(0.5, 0.5, 0.5, 0.9);
  gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
  
  uploadBufferData();  
  gl.drawArrays(gl.POINTS, 0, 1);
}

function uploadBufferData() {
  const buffer = gl.createBuffer();
  // make sure to supply all the data!
  const data = Float32Array.from([
    canvas.width, canvas.height, 0, 0,
    // e.g. commenting out this line will fail
    1.0, 0.0, 0.0, 1.0
  ]);
  gl.bindBuffer(gl.UNIFORM_BUFFER, buffer);
  gl.bufferData(gl.UNIFORM_BUFFER, data, gl.DYNAMIC_DRAW);
  gl.bindBufferBase(gl.UNIFORM_BUFFER, 0, buffer);
}
function compileProgram() {
  const program = gl.createProgram();
  
  const vShader = compileShader(program, gl.VERTEX_SHADER, vertexShaderSource);
  const fShader = compileShader(program, gl.FRAGMENT_SHADER, fragmentShaderSource);
                   
  console.log("linking...");
  
  gl.linkProgram(program);
  
  if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
    console.error("error linking shader");
    console.error(gl.getProgramInfoLog(program));
  } else {
    console.log("linked shader :)");
  }
    
  return program;
}
function compileShader(program, shaderType, shaderSource) {
  const shaderName = shaderType === gl.VERTEX_SHADER ? "vertex" : "fragment";
  const shader = gl.createShader(shaderType);
  
  console.log(`compiling ${shaderName}...`);
  
  gl.shaderSource(shader, shaderSource);
  gl.compileShader(shader);
  
  if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
    console.error(`Got compile error for ${shaderName}`);
    console.error(gl.getShaderInfoLog(shader));
  } else {
    console.log(`compiled ${shaderName} :)`);
  }
    
  gl.attachShader(program,shader); 
  return shader;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-23
    • 2016-02-20
    相关资源
    最近更新 更多