17
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-10-17 05:09:20 +02:00

Cull instances by compact records and draw them from a shader storage buffer

This commit is contained in:
2026-10-16 00:37:54 +02:00
parent fd98d4eea5
commit 9277c28805
13 changed files with 269 additions and 228 deletions

View File

@@ -14,7 +14,7 @@ void gl::glsl_common_setup()
"#define MAX_LIGHTS " + std::to_string(MAX_LIGHTS) + "U\n" +
"#define MAX_CASCADES " + std::to_string(MAX_CASCADES) + "U\n" +
"#define MAX_PARAMS " + std::to_string(MAX_PARAMS) + "U\n" +
"#define MAX_INSTANCES_PER_BATCH " + std::to_string(MAX_INSTANCES_PER_BATCH) + "U\n" +
"#define INSTANCE_SSBO_BINDING " + std::to_string(INSTANCE_SSBO_BINDING) + "\n" +
"#define LIGHT_SSBO_BINDING " + std::to_string(LIGHT_SSBO_BINDING) + "\n" +
"#define CLUSTER_GRID_X " + std::to_string(CLUSTER_GRID_X) + "\n" +
"#define CLUSTER_GRID_Y " + std::to_string(CLUSTER_GRID_Y) + "\n" +
@@ -184,24 +184,21 @@ void gl::glsl_common_setup()
vec4 wiper_timer_return;
};
// Per-instance modelview matrices for GPU-instanced draws.
// The UBO itself is declared in every stage so the binding stays valid,
// but the helper functions reference gl_InstanceID which is vertex-only,
// so they are guarded behind STAGE_VERTEX.
layout (std140) uniform instance_ubo
#ifdef STAGE_VERTEX
// Per-instance modelview matrices for GPU-instanced draws, element 0 is identity.
// Draws which aren't instanced have gl_BaseInstance == 0 and gl_InstanceID == 0,
// so effective_modelview() reduces to model_ubo.modelview. For instanced draws
// the C++ side uploads camera-space root transforms of the instances and draws
// them from base instance onwards, with model_ubo.modelview set to the submodel-local
// chain (computed from identity, NOT from the camera/instance), so the product
// gives the correct final transform per instance per submodel.
layout(std430, binding = INSTANCE_SSBO_BINDING) readonly buffer instance_ssbo
{
mat4 instance_modelview[MAX_INSTANCES_PER_BATCH];
mat4 instance_modelview[];
};
#ifdef STAGE_VERTEX
// For non-instanced draws gl_InstanceID == 0 and slot 0 is permanently set
// to identity, so effective_modelview() reduces to model_ubo.modelview.
// For instanced draws the C++ side uploads camera-space root transforms for
// instances 0..N-1 and sets model_ubo.modelview to the submodel-local chain
// (computed from identity, NOT from the camera/instance), so the product
// gives the correct final transform per instance per submodel.
mat4 effective_modelview() {
return instance_modelview[gl_InstanceID] * modelview;
return instance_modelview[gl_BaseInstance + gl_InstanceID] * modelview;
}
mat3 effective_modelviewnormal() {
// instance_modelview can include per-instance scale (uniform or per-axis),
@@ -209,7 +206,7 @@ void gl::glsl_common_setup()
// case. Compute the correct normal matrix via transpose(inverse(...)).
// For pure rotation+translation this still produces the rotation matrix
// (one extra mat3 inverse per vertex — modern GPUs handle it cheaply).
mat3 instance_mv3 = mat3(instance_modelview[gl_InstanceID]);
mat3 instance_mv3 = mat3(instance_modelview[gl_BaseInstance + gl_InstanceID]);
mat3 instance_normal = transpose(inverse(instance_mv3));
return instance_normal * modelviewnormal;
}

View File

@@ -281,9 +281,6 @@ void gl::program::init()
if ((index = glGetUniformBlockIndex(*this, "model_ubo")) != GL_INVALID_INDEX)
glUniformBlockBinding(*this, index, 1);
if ((index = glGetUniformBlockIndex(*this, "instance_ubo")) != GL_INVALID_INDEX)
glUniformBlockBinding(*this, index, 3);
}
gl::program::program()

View File

@@ -104,17 +104,6 @@ namespace gl
static_assert(sizeof(model_ubs) == 208 + 16 * MAX_PARAMS, "bad size of ubs");
// maximum number of instances per single GPU-instanced draw call.
// 256 mat4 = 16 KiB, the guaranteed minimum UBO size. Bigger batches must split.
const size_t MAX_INSTANCES_PER_BATCH = 256;
struct instance_ubs
{
glm::mat4 instance_modelview[MAX_INSTANCES_PER_BATCH];
};
static_assert(sizeof(instance_ubs) == 64 * MAX_INSTANCES_PER_BATCH, "bad size of instance_ubs");
// layout std430 (shader storage buffers)
// structs must match with GLSL, offsets checked below
@@ -295,6 +284,10 @@ namespace gl
const GLuint ATMOSPHERE_RESULT_SSBO_BINDING = 7;
const GLuint ATMOSPHERE_UBO_BINDING = 4;
// binding point of the per-instance modelview matrices of instanced draws (glsl: instance_ssbo, mat4 per instance).
// element 0 is identity, the matrix of every draw which isn't instanced
const GLuint INSTANCE_SSBO_BINDING = 8;
// number of coefficients of the spherical harmonics of order 2 (bands 0..2)
const size_t SKY_SH_COEFFICIENTS = 9;