# o GLSL.std.450main  rend3-pbr/shaders/src/cull.comp rend3-pbr/shaders/src/structures.glslƒ¸// OpModuleProcessed entry-point main // OpModuleProcessed client vulkan100 // OpModuleProcessed target-env vulkan1.0 // OpModuleProcessed entry-point main #line 1 #version 440 #include "structures.glsl" layout(local_size_x = 256) in; struct CullingUniforms { mat4 view; mat4 view_proj; Frustum frustum; uint object_count; }; #ifdef ATOMIC_CULL #define OBJECT_OUTPUT_DATA_BUFFER_BINDING 2 #define INDIRECT_BUFFER_BINDING 3 #else // ATOMIC_CULL #define OBJECT_OUTPUT_DATA_BUFFER_BINDING 4 #define INDIRECT_BUFFER_BINDING 5 #endif // ATOMIC_CULL layout(set = 0, binding = 0, std430) restrict readonly buffer ObjectInputDataBuffer { ObjectInputData object_input[]; }; layout(set = 0, binding = 1) uniform ObjectInputUniforms { CullingUniforms uniforms; }; #ifndef ATOMIC_CULL layout(set = 0, binding = 2, std430) restrict buffer IntermediateBufferA { uint result_index_a[]; }; layout(set = 0, binding = 3, std430) restrict buffer IntermediateBufferB { uint result_index_b[]; }; #endif layout(set = 0, binding = OBJECT_OUTPUT_DATA_BUFFER_BINDING, std430) restrict buffer ObjectOutputDataBuffer { ObjectOutputData object_output[]; }; layout(set = 0, binding = INDIRECT_BUFFER_BINDING, std430) restrict buffer IndirectBuffer { uint draw_call_count; uint _2; uint _3; uint _4; IndirectCall indirect_call[]; }; float plane_distance(Plane plane, vec3 location) { return dot(plane.inner.xyz, location) + plane.inner.w; } bool frustum_contains_sphere(Frustum frustum, vec4 sphere) { vec3 location = sphere.xyz; float neg_radius = -sphere.w; if (!(plane_distance(frustum.left, location) >= neg_radius)) { return false; } if (!(plane_distance(frustum.right, location) >= neg_radius)) { return false; } if (!(plane_distance(frustum.top, location) >= neg_radius)) { return false; } if (!(plane_distance(frustum.bottom, location) >= neg_radius)) { return false; } if (!(plane_distance(frustum.near, location) >= neg_radius)) { return false; } return true; } vec4 transform_sphere(vec4 sphere, mat4 transform) { float max_scale = max(max(length(transform[0].xyz), length(transform[1].xyz)), length(transform[2].xyz)); vec4 center = transform * vec4(sphere.xyz, 1.0); return vec4(center.xyz, sphere.w * max_scale); } void write_output(ObjectInputData in_data, uint index) { ObjectOutputData out_data; out_data.model_view = uniforms.view * in_data.transform; out_data.model_view_proj = uniforms.view_proj * in_data.transform; out_data.inv_trans_model_view = inverse(transpose(mat3(uniforms.view * in_data.transform))); out_data.material_idx = in_data.material_idx; object_output[index] = out_data; IndirectCall call; call.vertex_count = in_data.count; call.instance_count = 1; call.base_index = in_data.start_idx; call.vertex_offset = in_data.vertex_offset; call.base_instance = index; indirect_call[index] = call; } #ifdef ATOMIC_CULL void main() { uint input_idx = gl_GlobalInvocationID.x; if (input_idx >= uniforms.object_count) { return; } ObjectInputData in_data = object_input[input_idx]; mat4 model_view = uniforms.view * in_data.transform; vec4 mesh_sphere = transform_sphere(in_data.bounding_sphere, model_view); bool visible = frustum_contains_sphere(uniforms.frustum, mesh_sphere); if (!visible) { return; } uint output_idx = atomicAdd(draw_call_count, 1); write_output(in_data, output_idx); } #endif // ATOMIC_CULL #ifdef PREFIX_CULL void main() { uint input_idx = gl_GlobalInvocationID.x; if (input_idx >= uniforms.object_count) { return; } ObjectInputData in_data = object_input[input_idx]; mat4 model_view = uniforms.view * in_data.transform; vec4 mesh_sphere = transform_sphere(in_data.bounding_sphere, model_view); bool visible = frustum_contains_sphere(uniforms.frustum, mesh_sphere); uint result_index_1 = bitfieldInsert(0, uint(visible), 31, 1); uint result_index_2 = bitfieldInsert(result_index_1, uint(visible), 0, 31); result_index_a[input_idx] = result_index_2; } #endif // PREFIX_CULL #ifdef PREFIX_SUM layout(push_constant) uniform PushConstants { uint stride; }; void main() { uint my_idx = gl_GlobalInvocationID.x; if (my_idx >= uniforms.object_count) { return; } if (my_idx < stride) { result_index_b[my_idx] = result_index_a[my_idx]; return; } uint other_idx = my_idx - stride; uint me = result_index_a[my_idx]; uint other = result_index_a[other_idx]; uint result = me; result = bitfieldInsert(result, bitfieldExtract(me, 0, 31) + bitfieldExtract(other, 0, 31), 0, 31); result_index_b[my_idx] = result; } #endif // PREFIX_SUM #ifdef PREFIX_OUTPUT void main() { uint input_idx = gl_GlobalInvocationID.x; if (input_idx >= uniforms.object_count) { return; } uint result = result_index_a[input_idx]; uint objects_before = bitfieldExtract(result, 0, 31); uint output_idx = objects_before - 1; bool enabled = bool(bitfieldExtract(result, 31, 1)); if (input_idx == uniforms.object_count - 1) { draw_call_count = objects_before; } if (!enabled) { return; } write_output(object_input[input_idx], output_idx); } #endif ¸#ifndef SHADER_STRUCTURES_GLSL #define SHADER_STRUCTURES_GLSL struct Plane { vec4 inner; }; struct Frustum { Plane left; Plane right; Plane top; Plane bottom; // No far plane Plane near; }; struct ObjectInputData { uint start_idx; uint count; int vertex_offset; uint material_idx; mat4 transform; // xyz position; w radius vec4 bounding_sphere; }; /// If you change this struct, change the object output size in culling.rs struct ObjectOutputData { mat4 model_view; mat4 model_view_proj; mat3 inv_trans_model_view; uint material_idx; }; struct IndirectCall { uint vertex_count; uint instance_count; uint base_index; int vertex_offset; uint base_instance; }; #define FLAGS_ALBEDO_ACTIVE 0x0001 #define FLAGS_ALBEDO_BLEND 0x0002 #define FLAGS_ALBEDO_VERTEX_SRGB 0x0004 #define FLAGS_BICOMPONENT_NORMAL 0x0008 #define FLAGS_SWIZZLED_NORMAL 0x0010 #define FLAGS_AOMR_COMBINED 0x0020 #define FLAGS_AOMR_SWIZZLED_SPLIT 0x0040 #define FLAGS_AOMR_SPLIT 0x0080 #define FLAGS_AOMR_BW_SPLIT 0x0100 #define FLAGS_CC_GLTF_COMBINED 0x0200 #define FLAGS_CC_GLTF_SPLIT 0x0400 #define FLAGS_CC_BW_SPLIT 0x0800 #define FLAGS_UNLIT 0x1000 #define FLAGS_NEAREST 0x2000 #define MATERIAL_FLAG(name) bool(material.material_flags & name) struct GPUMaterialData { uint albedo_tex; uint normal_tex; uint roughness_tex; uint metallic_tex; // -- 16 -- uint reflectance_tex; uint clear_coat_tex; uint clear_coat_roughness_tex; uint emissive_tex; // -- 16 -- uint anisotropy_tex; uint ambient_occlusion_tex; uint _padding0; uint _padding1; // -- 16 -- mat3 uv_transform0; // -- 16 -- mat3 uv_transform1; // -- 16 -- vec4 albedo; // -- 16 -- vec3 emissive; float roughness; // -- 16 -- float metallic; float reflectance; float clear_coat; float clear_coat_roughness; // -- 16 -- float anisotropy; float ambient_occlusion; float alpha_cutout; uint material_flags; }; struct CPUMaterialData { mat3 uv_transform0; // -- 16 -- mat3 uv_transform1; // -- 16 -- vec4 albedo; // -- 16 -- vec3 emissive; float roughness; // -- 16 -- float metallic; float reflectance; float clear_coat; float clear_coat_roughness; // -- 16 -- float anisotropy; float ambient_occlusion; float alpha_cutout; uint material_flags; // -- 16 -- uint texture_enable; }; struct UniformData { mat4 view; mat4 view_proj; mat4 inv_view; mat4 inv_origin_view_proj; Frustum frustum; vec4 ambient; }; struct DirectionalLightBufferHeader { uint total_lights; }; struct DirectionalLight { mat4 view_proj; vec3 color; vec3 direction; }; #endif  GL_GOOGLE_cpp_style_line_directiveGL_GOOGLE_include_directivemain gl_GlobalInvocationIDPlaneinnerFrustumleftrighttopbottomnearCullingUniformsviewview_projfrustumobject_countObjectInputUniformsuniforms(PushConstants(stride*2IntermediateBufferB2result_index_b47IntermediateBufferA7result_index_a9G H#H#H#H# H#0H#@HH#HHH#@HH#€H#ÐH#GG"G!H(#G(G1H2H2#G2G4"G4!G6H7H7#G7G9"G9!G[ !     ; +   ; ++ "( ) (;)* + 121 32;34676 87;89+P+Y+Z, [YZZ6ø÷mûnøn™A =›A =! ®"#!÷%ú#$%ø$œùmø%ŸA+,*=-,°".-÷0ú./0ø/ A;9=<;A=4>=<¡ùmø0¤‚C-¦AF9=GF§AJ9C=KJ©ËQGPËSKP€TQSÉUGTPªAX4>XUùmømý8