OverviewFilesCommitsIssuesDocsReleasesPeers

nvidia-rtx-godot commits / 792cefb

Keep CUSTOM0-3 out of the shared hit-shader structs
Carrying vec4 custom[4] in VertexAttributes and HitData put 64 bytes of live state into structs the DEFAULT hit group also uses, so every hit shader in the scene -- including the ones that never touch CUSTOM -- paid the register pressure, and register pressure costs occupancy in RT shaders. Fetch the customs at the two custom-hit-group include sites instead. The default path is back to exactly its previous shape, and fetch_custom still early-outs on surfaces without the array, so this is cheap where unused. The cost is recomputing the triangle indices for custom hit groups, which is three buffer reads against four texture fetches. Also drops TYPED_TABLE_CAPACITY from 256 to 32. Bounded bindings are written in full on every rebuild of the shared bindless set, so 4x256 meant padding out 1024 descriptors each time; 32 is comfortably above what any material here uses (dc_terrain has the most, at four array atlases). Investigating a 60->20fps regression; this removes two costs I introduced rather than being a confirmed fix for it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
792cefb98bd0178a7328f4881661415e383a4517
by plankatron <fleeky@gmail.com> · 2026-07-29T15:46:12.000Z

Changed files (4) +27 -35

servers/rendering/renderer_rd/bindless_block.h +1 -1
……@@ -62,7 +62,7 @@ public:
6262 // Fixed capacity of the typed (bounded) tables. Bounded bindings do not get
6363 // PARTIALLY_BOUND, so these are always written in full, padded with the
6464 // kind's default texture.
65 constexpr static uint32_t TYPED_TABLE_CAPACITY = 256;
65 constexpr static uint32_t TYPED_TABLE_CAPACITY = 32;
6666
6767 static bool is_unbounded(TextureKind p_kind) { return p_kind == TEXTURE_2D; }
6868 static uint32_t get_binding(TextureKind p_kind) { return (uint32_t)p_kind; }
servers/rendering/renderer_rd/shaders/raytracing/raytracing_closest_hit_common_inc.glsl +0 -2
……@@ -20,7 +20,6 @@ struct HitData {
2020 vec3 bitangent; // World space.
2121 vec2 uv; // Raw UV (no material scale/offset applied).
2222 vec4 color; // Vertex color (white if not present).
23 vec4 custom[4]; // CUSTOM0-3 (zero if not present); only filled for custom HGs.
2423 bool is_front_face;
2524 uint geometry_idx;
2625};
……@@ -41,7 +40,6 @@ HitData compute_hit_data() {
4140#endif
4241 h.uv = attrs.uv;
4342 h.color = attrs.color;
44 h.custom = attrs.custom;
4543
4644 mat3 model_rotation = mat3(gl_ObjectToWorldEXT);
4745 mat3 normal_matrix = mat3(
servers/rendering/renderer_rd/shaders/raytracing/raytracing_hit_inc.glsl +1 -16
……@@ -12,7 +12,6 @@ struct VertexAttributes {
1212 vec3 tangent;
1313 float bitangent_sign;
1414 vec4 color;
15 vec4 custom[4]; // CUSTOM0-3; vec4(0) when the surface has no such array.
1615 bool has_uv;
1716 bool has_normal;
1817 bool has_tangent;
……@@ -285,8 +284,7 @@ TBNResult fetch_tbn(in GeometryData geom, uint i0, uint i1, uint i2, vec3 bary)
285284#define FETCH_UV (1u << 0)
286285#define FETCH_TBN (1u << 1)
287286#define FETCH_COLOR (1u << 2)
288#define FETCH_CUSTOM (1u << 3)
289#define FETCH_ALL (FETCH_UV | FETCH_TBN | FETCH_COLOR | FETCH_CUSTOM)
287#define FETCH_ALL (FETCH_UV | FETCH_TBN | FETCH_COLOR)
290288
291289#ifdef RT_HIT_ATTRIBS_DECLARED
292290VertexAttributes fetch_vertex_attributes(in GeometryData geom, vec2 hit_attribs, uint fetch_flags) {
……@@ -296,10 +294,6 @@ VertexAttributes fetch_vertex_attributes(in GeometryData geom, vec2 hit_attribs,
296294 attrs.tangent = vec3(1.0, 0.0, 0.0);
297295 attrs.bitangent_sign = 1.0;
298296 attrs.color = vec4(1.0);
299 attrs.custom[0] = vec4(0.0);
300 attrs.custom[1] = vec4(0.0);
301 attrs.custom[2] = vec4(0.0);
302 attrs.custom[3] = vec4(0.0);
303297 attrs.has_uv = false;
304298 attrs.has_normal = false;
305299 attrs.has_tangent = false;
……@@ -320,15 +314,6 @@ VertexAttributes fetch_vertex_attributes(in GeometryData geom, vec2 hit_attribs,
320314 attrs.has_color = true;
321315 }
322316
323 // fetch_custom early-outs per index, so a surface with no custom arrays pays
324 // four compares rather than four buffer reads.
325 if ((fetch_flags & FETCH_CUSTOM) != 0u) {
326 attrs.custom[0] = fetch_custom(geom, 0u, i0, i1, i2, bary);
327 attrs.custom[1] = fetch_custom(geom, 1u, i0, i1, i2, bary);
328 attrs.custom[2] = fetch_custom(geom, 2u, i0, i1, i2, bary);
329 attrs.custom[3] = fetch_custom(geom, 3u, i0, i1, i2, bary);
330 }
331
332317 if ((fetch_flags & FETCH_TBN) != 0u && geom.normal_byte_offset != OFFSET_NONE) {
333318 TBNResult tbn = fetch_tbn(geom, i0, i1, i2, bary);
334319 attrs.normal = tbn.normal;
servers/rendering/renderer_rd/shaders/raytracing/scene_raytracing_raygen.glsl +25 -16
……@@ -269,10 +269,10 @@ layout(location = 0) rayPayloadInEXT PathPayload payload;
269269// the 2D table -- the only one that needs to scale -- stays unbounded and last.
270270// Keep these sizes in sync with BindlessBlock::TYPED_TABLE_CAPACITY, and the
271271// binding numbers with BindlessBlock::TextureKind.
272layout(set = 1, binding = 0) uniform texture2DArray bindless_textures_2d_array[256];
273layout(set = 1, binding = 1) uniform texture3D bindless_textures_3d[256];
274layout(set = 1, binding = 2) uniform textureCube bindless_textures_cube[256];
275layout(set = 1, binding = 3) uniform textureCubeArray bindless_textures_cube_array[256];
272layout(set = 1, binding = 0) uniform texture2DArray bindless_textures_2d_array[32];
273layout(set = 1, binding = 1) uniform texture3D bindless_textures_3d[32];
274layout(set = 1, binding = 2) uniform textureCube bindless_textures_cube[32];
275layout(set = 1, binding = 3) uniform textureCubeArray bindless_textures_cube_array[32];
276276layout(set = 1, binding = 4) uniform texture2D bindless_textures[];
277277
278278#include "raytracing_samplers_inc.glsl"
……@@ -327,10 +327,19 @@ void main() {
327327 vec3 rt_hit_pos = h.hit_pos;
328328 vec2 rt_uv = h.uv;
329329 vec4 rt_color = h.color;
330 vec4 rt_custom0 = h.custom[0];
331 vec4 rt_custom1 = h.custom[1];
332 vec4 rt_custom2 = h.custom[2];
333 vec4 rt_custom3 = h.custom[3];
330 // Fetched here rather than carried through HitData/VertexAttributes: those
331 // structs are shared with the DEFAULT hit group, and four extra vec4s of
332 // live state cost register pressure (and so occupancy) on every hit shader,
333 // including the ones that never touch CUSTOM. fetch_custom early-outs on
334 // surfaces without the array, so this is cheap when unused.
335 GeometryData rt_cgeom = geometries[h.geometry_idx];
336 uint rt_ci0, rt_ci1, rt_ci2;
337 get_triangle_indices(rt_cgeom, rt_ci0, rt_ci1, rt_ci2);
338 vec3 rt_cbary = vec3(1.0 - attribs.x - attribs.y, attribs.x, attribs.y);
339 vec4 rt_custom0 = fetch_custom(rt_cgeom, 0u, rt_ci0, rt_ci1, rt_ci2, rt_cbary);
340 vec4 rt_custom1 = fetch_custom(rt_cgeom, 1u, rt_ci0, rt_ci1, rt_ci2, rt_cbary);
341 vec4 rt_custom2 = fetch_custom(rt_cgeom, 2u, rt_ci0, rt_ci1, rt_ci2, rt_cbary);
342 vec4 rt_custom3 = fetch_custom(rt_cgeom, 3u, rt_ci0, rt_ci1, rt_ci2, rt_cbary);
334343 vec3 rt_normal = h.geometry_normal;
335344 vec3 rt_tangent = h.tangent;
336345 vec3 rt_bitangent = h.bitangent;
……@@ -477,10 +486,10 @@ layout(set = 0, binding = 5, std430) readonly buffer MaterialBuffer {
477486// the 2D table -- the only one that needs to scale -- stays unbounded and last.
478487// Keep these sizes in sync with BindlessBlock::TYPED_TABLE_CAPACITY, and the
479488// binding numbers with BindlessBlock::TextureKind.
480layout(set = 1, binding = 0) uniform texture2DArray bindless_textures_2d_array[256];
481layout(set = 1, binding = 1) uniform texture3D bindless_textures_3d[256];
482layout(set = 1, binding = 2) uniform textureCube bindless_textures_cube[256];
483layout(set = 1, binding = 3) uniform textureCubeArray bindless_textures_cube_array[256];
489layout(set = 1, binding = 0) uniform texture2DArray bindless_textures_2d_array[32];
490layout(set = 1, binding = 1) uniform texture3D bindless_textures_3d[32];
491layout(set = 1, binding = 2) uniform textureCube bindless_textures_cube[32];
492layout(set = 1, binding = 3) uniform textureCubeArray bindless_textures_cube_array[32];
484493layout(set = 1, binding = 4) uniform texture2D bindless_textures[];
485494
486495#include "raytracing_samplers_inc.glsl"
……@@ -614,10 +623,10 @@ layout(set = 0, binding = 5, std430) readonly buffer MaterialBuffer {
614623// the 2D table -- the only one that needs to scale -- stays unbounded and last.
615624// Keep these sizes in sync with BindlessBlock::TYPED_TABLE_CAPACITY, and the
616625// binding numbers with BindlessBlock::TextureKind.
617layout(set = 1, binding = 0) uniform texture2DArray bindless_textures_2d_array[256];
618layout(set = 1, binding = 1) uniform texture3D bindless_textures_3d[256];
619layout(set = 1, binding = 2) uniform textureCube bindless_textures_cube[256];
620layout(set = 1, binding = 3) uniform textureCubeArray bindless_textures_cube_array[256];
626layout(set = 1, binding = 0) uniform texture2DArray bindless_textures_2d_array[32];
627layout(set = 1, binding = 1) uniform texture3D bindless_textures_3d[32];
628layout(set = 1, binding = 2) uniform textureCube bindless_textures_cube[32];
629layout(set = 1, binding = 3) uniform textureCubeArray bindless_textures_cube_array[32];
621630layout(set = 1, binding = 4) uniform texture2D bindless_textures[];
622631
623632#include "raytracing_samplers_inc.glsl"