From c615b9355a934a87a4b701583218e8448b5ff57c Mon Sep 17 00:00:00 2001 From: Ivan 'provod' Avdeev Date: Fri, 3 Feb 2023 11:00:34 -0800 Subject: [PATCH] rt: only do alpha test shadows after opaque geometry this honestly barely helps ;_; --- ref_vk/shaders/light_common.glsl | 52 ++++++++++++++++++-------------- ref_vk/shaders/ray_interop.h | 5 +-- ref_vk/shaders/ray_primary.comp | 2 +- ref_vk/vk_ray_accel.c | 2 +- 4 files changed, 35 insertions(+), 26 deletions(-) diff --git a/ref_vk/shaders/light_common.glsl b/ref_vk/shaders/light_common.glsl index 0a7b2054..5c3c2190 100644 --- a/ref_vk/shaders/light_common.glsl +++ b/ref_vk/shaders/light_common.glsl @@ -24,20 +24,22 @@ uint traceShadowRay(vec3 pos, vec3 dir, float dist, uint flags) { #endif #if defined(RAY_QUERY) -void shadowRayQuery(rayQueryEXT rq, vec3 pos, vec3 dir, float dist, uint flags) { - rayQueryInitializeEXT(rq, tlas, flags, GEOMETRY_BIT_OPAQUE, pos, 0., dir, dist - shadow_offset_fudge); +bool shadowTestAlphaMask(vec3 pos, vec3 dir, float dist) { + rayQueryEXT rq; + const uint flags = 0 + | gl_RayFlagsCullFrontFacingTrianglesEXT + //| gl_RayFlagsNoOpaqueEXT + | gl_RayFlagsTerminateOnFirstHitEXT + ; + rayQueryInitializeEXT(rq, tlas, flags, GEOMETRY_BIT_ALPHA_TEST, pos, 0., dir, dist); while (rayQueryProceedEXT(rq)) { - if (0 != (rayQueryGetRayFlagsEXT(rq) & gl_RayFlagsOpaqueEXT)) - continue; - // Alpha test, takes 10ms // TODO check other possible ways of doing alpha test. They might be more efficient: // 1. Do a separate ray query for alpha masked geometry. Reason: here we might accidentally do the expensive // texture sampling for geometry that's ultimately invisible (i.e. behind walls). Also, shader threads congruence. // Separate pass could be more efficient as it'd be doing the same thing for every invocation. // 2. Same as the above, but also with a completely independent TLAS. Why: no need to mask-check geometry for opaque-vs-alpha -#if 1 const uint instance_kusochki_offset = rayQueryGetIntersectionInstanceCustomIndexEXT(rq, false); const uint geometry_index = rayQueryGetIntersectionGeometryIndexEXT(rq, false); const uint kusok_index = instance_kusochki_offset + geometry_index; @@ -61,8 +63,9 @@ void shadowRayQuery(rayQueryEXT rq, vec3 pos, vec3 dir, float dist, uint flags) if (texture_color.a >= alpha_mask_threshold) { rayQueryConfirmIntersectionEXT(rq); } -#endif } + + return rayQueryGetIntersectionTypeEXT(rq, true) == gl_RayQueryCommittedIntersectionTriangleEXT; } #endif @@ -77,25 +80,30 @@ bool shadowed(vec3 pos, vec3 dir, float dist, bool check_sky) { const uint hit_type = traceShadowRay(pos, dir, dist, flags); return check_sky ? payload_shadow.hit_type != SHADOW_SKY : payload_shadow.hit_type == SHADOW_HIT; #elif defined(RAY_QUERY) - const uint flags = 0 - //| gl_RayFlagsCullFrontFacingTrianglesEXT - //| gl_RayFlagsOpaqueEXT - | gl_RayFlagsTerminateOnFirstHitEXT - ; - rayQueryEXT rq; - shadowRayQuery(rq, pos, dir, dist, flags); + { + const uint flags = 0 + | gl_RayFlagsCullFrontFacingTrianglesEXT + | gl_RayFlagsOpaqueEXT + | gl_RayFlagsTerminateOnFirstHitEXT + ; + rayQueryEXT rq; + rayQueryInitializeEXT(rq, tlas, flags, GEOMETRY_BIT_OPAQUE, pos, 0., dir, dist - shadow_offset_fudge); + while (rayQueryProceedEXT(rq)) {} - if (!check_sky) { - return rayQueryGetIntersectionTypeEXT(rq, true) == gl_RayQueryCommittedIntersectionTriangleEXT; + if (rayQueryGetIntersectionTypeEXT(rq, true) == gl_RayQueryCommittedIntersectionTriangleEXT) { + if (!check_sky) + return true; + + const int instance_kusochki_offset = rayQueryGetIntersectionInstanceCustomIndexEXT(rq, true); + const int kusok_index = instance_kusochki_offset + rayQueryGetIntersectionGeometryIndexEXT(rq, true); + const uint tex_base_color = getKusok(kusok_index).tex_base_color; + if ((tex_base_color & KUSOK_MATERIAL_FLAG_SKYBOX) == 0) + return true; + } } - if (rayQueryGetIntersectionTypeEXT(rq, true) != gl_RayQueryCommittedIntersectionTriangleEXT) - return true; + return shadowTestAlphaMask(pos, dir, dist); - const int instance_kusochki_offset = rayQueryGetIntersectionInstanceCustomIndexEXT(rq, true); - const int kusok_index = instance_kusochki_offset + rayQueryGetIntersectionGeometryIndexEXT(rq, true); - const uint tex_base_color = getKusok(kusok_index).tex_base_color; - return (tex_base_color & KUSOK_MATERIAL_FLAG_SKYBOX) == 0; #else #error RAY_TRACE or RAY_QUERY #endif diff --git a/ref_vk/shaders/ray_interop.h b/ref_vk/shaders/ray_interop.h index f4307ad7..88ad0a4c 100644 --- a/ref_vk/shaders/ray_interop.h +++ b/ref_vk/shaders/ray_interop.h @@ -47,8 +47,9 @@ LIST_SPECIALIZATION_CONSTANTS(DECLARE_SPECIALIZATION_CONSTANT) #endif // not GLSL #define GEOMETRY_BIT_OPAQUE 0x01 -#define GEOMETRY_BIT_ADDITIVE 0x02 -#define GEOMETRY_BIT_REFRACTIVE 0x04 +#define GEOMETRY_BIT_ALPHA_TEST 0x02 +#define GEOMETRY_BIT_ADDITIVE 0x04 +#define GEOMETRY_BIT_REFRACTIVE 0x08 #define SHADER_OFFSET_MISS_REGULAR 0 #define SHADER_OFFSET_MISS_SHADOW 1 diff --git a/ref_vk/shaders/ray_primary.comp b/ref_vk/shaders/ray_primary.comp index 96eb77ac..6c9fc3e9 100644 --- a/ref_vk/shaders/ray_primary.comp +++ b/ref_vk/shaders/ray_primary.comp @@ -51,7 +51,7 @@ void main() { //| gl_RayFlagsSkipClosestHitShaderEXT ; const float L = 10000.; // TODO Why 10k? - rayQueryInitializeEXT(rq, tlas, flags, GEOMETRY_BIT_OPAQUE, origin, 0., direction, L); + rayQueryInitializeEXT(rq, tlas, flags, GEOMETRY_BIT_OPAQUE | GEOMETRY_BIT_ALPHA_TEST, origin, 0., direction, L); while (rayQueryProceedEXT(rq)) { if (0 != (rayQueryGetRayFlagsEXT(rq) & gl_RayFlagsOpaqueEXT)) continue; diff --git a/ref_vk/vk_ray_accel.c b/ref_vk/vk_ray_accel.c index da6638a9..efa00818 100644 --- a/ref_vk/vk_ray_accel.c +++ b/ref_vk/vk_ray_accel.c @@ -179,7 +179,7 @@ void RT_VkAccelPrepareTlas(VkCommandBuffer cmdbuf) { inst[i].flags = VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_KHR; break; case MaterialMode_Opaque_AlphaTest: - inst[i].mask = GEOMETRY_BIT_OPAQUE; + inst[i].mask = GEOMETRY_BIT_ALPHA_TEST; inst[i].instanceShaderBindingTableRecordOffset = SHADER_OFFSET_HIT_ALPHA_TEST, inst[i].flags = VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_KHR; break;