| … | … | @@ -200,6 +200,13 @@ layout(set = 0, binding = 13, std430) readonly buffer CustomDataBuf { |
| 200 | 200 | // indices. The generator emits HBLK_ATLAS_W beside the block constants. |
| 201 | 201 | layout(set = 0, binding = 14, r32f) uniform readonly image2D custom_data_tex; |
| 202 | 202 | |
| 203 | // GENERATOR_SAMPLER_BINDINGS |
| 204 | // Bindings 15..22 (eight noise volumes) are injected HERE, and only when the |
| 205 | // generator body samples them -- see _build_custom_shader. NOTE the numbers |
| 206 | // differ from edge_intersect.glsl (14..21): binding 14 is already custom_data_tex |
| 207 | // on this side. The body refers to the volumes BY NAME, so the two shaders need |
| 208 | // not agree on numbering, only on the names. |
| 209 | |
| 203 | 210 | // --- Mesh SDF helper functions --- |
| 204 | 211 | |
| 205 | 212 | float aabb_point_dist_sq(vec3 p, vec3 bmin, vec3 bmax) { |
| … | … | @@ -741,8 +748,35 @@ static std::string _build_default_shader() { |
| 741 | 748 | } |
| 742 | 749 | |
| 743 | 750 | // Wrap custom evaluate_density() function body in compute shader template |
| 751 | // True when a generator body samples the noise volumes, i.e. when the density |
| 752 | // shader must declare bindings 15..22 and DCCompute must supply descriptors for |
| 753 | // them. Declaring bindings the body never reads risks them being optimised out |
| 754 | // of the SPIR-V, after which uniform_set_create is handed descriptors the shader |
| 755 | // does not reflect and fails -- so absence has to agree too, not just presence. |
| 756 | static bool _body_uses_noise_volumes(const char* custom_body) { |
| 757 | return custom_body != nullptr |
| 758 | && std::string(custom_body).find("noiseVol") != std::string::npos; |
| 759 | } |
| 760 | |
| 744 | 761 | static std::string _build_custom_shader(const char* custom_body) { |
| 745 | | return std::string(DENSITY_GLSL_HEADER) + "\n" + custom_body + "\n" + DENSITY_GLSL_MAIN; |
| 762 | std::string header(DENSITY_GLSL_HEADER); |
| 763 | const std::string marker = "// GENERATOR_SAMPLER_BINDINGS"; |
| 764 | size_t pos = header.find(marker); |
| 765 | if (pos != std::string::npos) { |
| 766 | std::string decls; |
| 767 | if (_body_uses_noise_volumes(custom_body)) { |
| 768 | for (int i = 0; i < 4; i++) { |
| 769 | decls += "layout(set = 0, binding = " + std::to_string(15 + i) |
| 770 | + ") uniform sampler3D noiseVol" + std::to_string(i) + ";\n"; |
| 771 | } |
| 772 | for (int i = 0; i < 4; i++) { |
| 773 | decls += "layout(set = 0, binding = " + std::to_string(19 + i) |
| 774 | + ") uniform sampler3D packedNoiseVol" + std::to_string(i) + ";\n"; |
| 775 | } |
| 776 | } |
| 777 | header.replace(pos, marker.length(), decls); |
| 778 | } |
| 779 | return header + "\n" + custom_body + "\n" + DENSITY_GLSL_MAIN; |
| 746 | 780 | } |
| 747 | 781 | |
| 748 | 782 | #endif // DC_SHADER_SOURCE_H |