#  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_directivemainPlaneinnerFrustumleftrighttopbottomnearCullingUniformsviewview_projfrustumobject_countObjectInputUniformsuniformsObjectOutputDatamodel_viewmodel_view_proj inv_trans_model_viewmaterial_idxObjectOutputDataBufferobject_outputIndirectCallvertex_countinstance_countbase_indexvertex_offsetbase_instanceIndirectBufferdraw_call_count_2_3_4indirect_callgl_GlobalInvocationIDObjectInputDatastart_idxcountvertex_offsetmaterial_idxtransformbounding_sphereObjectInputDataBufferobject_input H#H#H#H# H#0H#@HH#HHH#@HH#H#H#GG"G!HH#HHH#@HHH#HH#GHH#GG"G!H#H#H#H# H#GHH#HH#HH#HH# HH#GG"G!G H#H#H#H# HH#HH#PG`HHH#GG "G !Gj !    # $ +$-*L+$N+$[+$h+$u)+?  # ; # ;  #+####$##### ; $ #  ;+# ###$#  ;  " B+#i, ji6kllfA=#hA-h=#iklA"# -=$#Q#%$Q#'$Q$)$Q#+$Q-$Q /$nA3--=4374-KQ x7O yxx zByQ |7O }|| ~B} (z~Q 7O  B (LQ/Q/Q/P  7NQ/QQQP qABC-[=DCQEDQ GEQIDQ KIQMDQ OMQQDQ SQQUDQ WU=4O 50O GGQG780O KKQK:;0O OOQO=>0O SSQS@A0O WW Q W   C DGLLLLLs]_]^_^tk_wAb-#cbUA-N=-VP(y}T)( *")YA3-c->37A5-cN>5A7-c[>7*A9-ch>9+aAJuc->J'ALucN>LANuc[>N%APuch>P)ARucu>Rcykk8