From 447723b88bd826a715fa9bb489dc71a50485f440 Mon Sep 17 00:00:00 2001 From: Hans-Kristian Arntzen Date: Mon, 11 Oct 2021 12:38:08 +0200 Subject: [PATCH] Enable PrimitiveCulling capability if enabled. For DXR 1.1, this capability must be enabled in case the shader uses ray flags 0x100 or 0x200. --- dxil_converter.cpp | 8 ++ dxil_converter.hpp | 13 +- dxil_spirv.cpp | 7 + dxil_spirv_c.cpp | 9 ++ dxil_spirv_c.h | 9 +- opcodes/converter_impl.hpp | 2 + opcodes/opcodes_dxil_builtins.cpp | 15 ++ .../dxil-builtin/trace-ray-flags-2.rgen | 128 ++++++++++++++++++ .../shaders/dxil-builtin/trace-ray-flags.rgen | 107 +++++++++++++++ shaders/dxil-builtin/trace-ray-flags-2.rgen | 27 ++++ shaders/dxil-builtin/trace-ray-flags.rgen | 22 +++ 11 files changed, 345 insertions(+), 2 deletions(-) create mode 100644 reference/shaders/dxil-builtin/trace-ray-flags-2.rgen create mode 100644 reference/shaders/dxil-builtin/trace-ray-flags.rgen create mode 100644 shaders/dxil-builtin/trace-ray-flags-2.rgen create mode 100644 shaders/dxil-builtin/trace-ray-flags.rgen diff --git a/dxil_converter.cpp b/dxil_converter.cpp index 95387ba6..a127b13e 100644 --- a/dxil_converter.cpp +++ b/dxil_converter.cpp @@ -4286,6 +4286,8 @@ bool Converter::Impl::emit_execution_modes_ray_tracing(spv::ExecutionModel model { auto &builder = spirv_module.get_builder(); builder.addCapability(spv::CapabilityRayTracingKHR); + if (options.ray_tracing_primitive_culling_enabled && shader_analysis.can_require_primitive_culling) + builder.addCapability(spv::CapabilityRayTraversalPrimitiveCullingKHR); builder.addExtension("SPV_KHR_ray_tracing"); builder.addExtension("SPV_EXT_descriptor_indexing"); @@ -4982,6 +4984,11 @@ void Converter::Impl::set_option(const OptionBase &cap) options.shader_i8_dot_enabled = static_cast(cap).supported; break; + case Option::ShaderRayTracingPrimitiveCulling: + options.ray_tracing_primitive_culling_enabled = + static_cast(cap).supported; + break; + default: break; } @@ -5029,6 +5036,7 @@ bool Converter::recognizes_option(Option cap) case Option::DescriptorQA: case Option::MinPrecisionNative16Bit: case Option::ShaderI8Dot: + case Option::ShaderRayTracingPrimitiveCulling: return true; default: diff --git a/dxil_converter.hpp b/dxil_converter.hpp index f8bae589..8308ab28 100644 --- a/dxil_converter.hpp +++ b/dxil_converter.hpp @@ -207,7 +207,8 @@ enum class Option : uint32_t StorageInputOutput16 = 14, DescriptorQA = 15, MinPrecisionNative16Bit = 16, - ShaderI8Dot = 17 + ShaderI8Dot = 17, + ShaderRayTracingPrimitiveCulling = 18 }; enum class ResourceClass : uint32_t @@ -402,6 +403,16 @@ struct OptionShaderI8Dot : OptionBase bool supported = false; }; +struct OptionShaderRayTracingPrimitiveCulling : OptionBase +{ + OptionShaderRayTracingPrimitiveCulling() + : OptionBase(Option::ShaderRayTracingPrimitiveCulling) + { + } + + bool supported = false; +}; + struct DescriptorTableEntry { ResourceClass type; diff --git a/dxil_spirv.cpp b/dxil_spirv.cpp index e1a25d66..ee52bc4e 100644 --- a/dxil_spirv.cpp +++ b/dxil_spirv.cpp @@ -744,6 +744,13 @@ int main(int argc, char **argv) dxil_spv_converter_add_option(converter, &helper.base); } + { + const dxil_spv_option_shader_ray_tracing_primitive_culling helper = + { { DXIL_SPV_OPTION_SHADER_RAY_TRACING_PRIMITIVE_CULLING }, + DXIL_SPV_TRUE }; + dxil_spv_converter_add_option(converter, &helper.base); + } + if (args.dual_source_blending) { const dxil_spv_option_dual_source_blending helper = { { DXIL_SPV_OPTION_DUAL_SOURCE_BLENDING }, DXIL_SPV_TRUE }; diff --git a/dxil_spirv_c.cpp b/dxil_spirv_c.cpp index c2936708..2b762cf0 100644 --- a/dxil_spirv_c.cpp +++ b/dxil_spirv_c.cpp @@ -803,6 +803,15 @@ dxil_spv_result dxil_spv_converter_add_option(dxil_spv_converter converter, cons break; } + case DXIL_SPV_OPTION_SHADER_RAY_TRACING_PRIMITIVE_CULLING: + { + OptionShaderRayTracingPrimitiveCulling helper; + helper.supported = bool(reinterpret_cast(option)->supported); + + converter->options.emplace_back(duplicate(helper)); + break; + } + default: return DXIL_SPV_ERROR_UNSUPPORTED_FEATURE; } diff --git a/dxil_spirv_c.h b/dxil_spirv_c.h index 5ca3e2a9..42388090 100644 --- a/dxil_spirv_c.h +++ b/dxil_spirv_c.h @@ -28,7 +28,7 @@ extern "C" { #endif #define DXIL_SPV_API_VERSION_MAJOR 2 -#define DXIL_SPV_API_VERSION_MINOR 11 +#define DXIL_SPV_API_VERSION_MINOR 12 #define DXIL_SPV_API_VERSION_PATCH 0 #define DXIL_SPV_DESCRIPTOR_QA_INTERFACE_VERSION 1 @@ -278,6 +278,7 @@ typedef enum dxil_spv_option DXIL_SPV_OPTION_DESCRIPTOR_QA = 15, DXIL_SPV_OPTION_MIN_PRECISION_NATIVE_16BIT = 16, DXIL_SPV_OPTION_SHADER_I8_DOT = 17, + DXIL_SPV_OPTION_SHADER_RAY_TRACING_PRIMITIVE_CULLING = 18, DXIL_SPV_OPTION_INT_MAX = 0x7fffffff } dxil_spv_option; @@ -415,6 +416,12 @@ typedef struct dxil_spv_option_shader_i8_dot dxil_spv_bool supported; } dxil_spv_option_shader_i8_dot; +typedef struct dxil_spv_option_shader_ray_tracing_primitive_culling +{ + dxil_spv_option_base base; + dxil_spv_bool supported; +} dxil_spv_option_shader_ray_tracing_primitive_culling; + /* Gets the ABI version used to build this library. Used to detect API/ABI mismatches. */ DXIL_SPV_PUBLIC_API void dxil_spv_get_version(unsigned *major, unsigned *minor, unsigned *patch); diff --git a/opcodes/converter_impl.hpp b/opcodes/converter_impl.hpp index 619a0a4a..d1540857 100644 --- a/opcodes/converter_impl.hpp +++ b/opcodes/converter_impl.hpp @@ -406,6 +406,7 @@ struct Converter::Impl bool descriptor_qa_sink_handles = true; bool min_precision_prefer_native_16bit = false; bool shader_i8_dot_enabled = false; + bool ray_tracing_primitive_culling_enabled = false; } options; struct BindlessInfo @@ -462,6 +463,7 @@ struct Converter::Impl // Only relevant for fragment shaders. bool has_side_effects = false; bool discards = false; + bool can_require_primitive_culling = false; } shader_analysis; // For descriptor QA, we need to rewrite how resource handles are emitted. diff --git a/opcodes/opcodes_dxil_builtins.cpp b/opcodes/opcodes_dxil_builtins.cpp index 154ae707..2e0e035e 100644 --- a/opcodes/opcodes_dxil_builtins.cpp +++ b/opcodes/opcodes_dxil_builtins.cpp @@ -526,6 +526,21 @@ bool analyze_dxil_instruction(Converter::Impl &impl, const llvm::CallInst *instr impl.handle_to_storage_class[alloca_inst] = spv::StorageClassRayPayloadKHR; } } + + if (const auto *flags_inst = llvm::dyn_cast(instruction->getOperand(2))) + { + if ((flags_inst->getUniqueInteger().getZExtValue() & (spv::RayFlagsSkipTrianglesKHRMask | + spv::RayFlagsSkipAABBsKHRMask)) != 0) + { + impl.shader_analysis.can_require_primitive_culling = true; + } + } + else + { + // Non constant flags, so we must be conservative. + impl.shader_analysis.can_require_primitive_culling = true; + } + break; } diff --git a/reference/shaders/dxil-builtin/trace-ray-flags-2.rgen b/reference/shaders/dxil-builtin/trace-ray-flags-2.rgen new file mode 100644 index 00000000..42061e77 --- /dev/null +++ b/reference/shaders/dxil-builtin/trace-ray-flags-2.rgen @@ -0,0 +1,128 @@ +#version 460 +#extension GL_EXT_ray_tracing : require +#extension GL_EXT_ray_flags_primitive_culling : require +#extension GL_EXT_nonuniform_qualifier : require +layout(primitive_culling); + +struct _20 +{ + vec4 _m0; +}; + +layout(set = 0, binding = 0, std140) uniform Flags +{ + vec4 _m0[1]; +} Flags_1; + +layout(set = 0, binding = 0) uniform accelerationStructureEXT AS; +layout(set = 0, binding = 0) uniform writeonly image2D IMG; +layout(location = 0) rayPayloadEXT _20 _22; + +void main() +{ + traceRayEXT(AS, floatBitsToUint(Flags_1._m0[0u]).x, 0u, 1u, 2u, 3u, vec3(1.0, 2.0, 3.0), 7.0, vec3(4.0, 5.0, 6.0), 8.0, 0); + imageStore(IMG, ivec2(uvec2(0u)), vec4(_22._m0)); +} + + +#if 0 +// SPIR-V disassembly +; SPIR-V +; Version: 1.4 +; Generator: Unknown(30017); 21022 +; Bound: 57 +; Schema: 0 +OpCapability Shader +OpCapability UniformBufferArrayDynamicIndexing +OpCapability SampledImageArrayDynamicIndexing +OpCapability StorageBufferArrayDynamicIndexing +OpCapability StorageImageArrayDynamicIndexing +OpCapability StorageImageWriteWithoutFormat +OpCapability RayTraversalPrimitiveCullingKHR +OpCapability RayTracingKHR +OpCapability RuntimeDescriptorArray +OpCapability UniformBufferArrayNonUniformIndexing +OpCapability SampledImageArrayNonUniformIndexing +OpCapability StorageBufferArrayNonUniformIndexing +OpCapability StorageImageArrayNonUniformIndexing +OpExtension "SPV_EXT_descriptor_indexing" +OpExtension "SPV_KHR_ray_tracing" +OpMemoryModel Logical GLSL450 +OpEntryPoint RayGenerationNV %3 "main" %8 %12 %19 %22 +OpName %3 "main" +OpName %8 "AS" +OpName %12 "IMG" +OpName %17 "Flags" +OpName %19 "Flags" +OpName %20 "" +OpDecorate %8 DescriptorSet 0 +OpDecorate %8 Binding 0 +OpDecorate %12 DescriptorSet 0 +OpDecorate %12 Binding 0 +OpDecorate %12 NonReadable +OpDecorate %16 ArrayStride 16 +OpMemberDecorate %17 0 Offset 0 +OpDecorate %17 Block +OpDecorate %19 DescriptorSet 0 +OpDecorate %19 Binding 0 +%1 = OpTypeVoid +%2 = OpTypeFunction %1 +%5 = OpTypeInt 32 1 +%6 = OpTypeAccelerationStructureKHR +%7 = OpTypePointer UniformConstant %6 +%8 = OpVariable %7 UniformConstant +%9 = OpTypeFloat 32 +%10 = OpTypeImage %9 2D 0 0 0 2 Unknown +%11 = OpTypePointer UniformConstant %10 +%12 = OpVariable %11 UniformConstant +%13 = OpTypeInt 32 0 +%14 = OpConstant %13 1 +%15 = OpTypeVector %9 4 +%16 = OpTypeArray %15 %14 +%17 = OpTypeStruct %16 +%18 = OpTypePointer Uniform %17 +%19 = OpVariable %18 Uniform +%20 = OpTypeStruct %15 +%21 = OpTypePointer RayPayloadNV %20 +%22 = OpVariable %21 RayPayloadNV +%23 = OpConstant %13 0 +%24 = OpTypePointer Uniform %15 +%27 = OpTypeVector %13 4 +%31 = OpConstant %13 2 +%32 = OpConstant %13 3 +%33 = OpConstant %9 1 +%34 = OpConstant %9 4 +%35 = OpConstant %9 2 +%36 = OpConstant %9 5 +%37 = OpConstant %9 3 +%38 = OpConstant %9 6 +%39 = OpConstant %9 7 +%40 = OpConstant %9 8 +%41 = OpTypeVector %9 3 +%44 = OpTypePointer RayPayloadNV %15 +%52 = OpTypeVector %13 2 +%3 = OpFunction %1 None %2 +%4 = OpLabel +OpBranch %55 +%55 = OpLabel +%25 = OpAccessChain %24 %19 %23 %23 +%26 = OpLoad %15 %25 +%28 = OpBitcast %27 %26 +%29 = OpCompositeExtract %13 %28 0 +%30 = OpLoad %6 %8 +%42 = OpCompositeConstruct %41 %33 %35 %37 +%43 = OpCompositeConstruct %41 %34 %36 %38 +OpTraceRayKHR %30 %29 %23 %14 %31 %32 %42 %39 %43 %40 %22 +%45 = OpInBoundsAccessChain %44 %22 %23 +%46 = OpLoad %15 %45 +%47 = OpLoad %10 %12 +%48 = OpCompositeExtract %9 %46 0 +%49 = OpCompositeExtract %9 %46 1 +%50 = OpCompositeExtract %9 %46 2 +%51 = OpCompositeExtract %9 %46 3 +%53 = OpCompositeConstruct %52 %23 %23 +%54 = OpCompositeConstruct %15 %48 %49 %50 %51 +OpImageWrite %47 %53 %54 +OpReturn +OpFunctionEnd +#endif diff --git a/reference/shaders/dxil-builtin/trace-ray-flags.rgen b/reference/shaders/dxil-builtin/trace-ray-flags.rgen new file mode 100644 index 00000000..e355e0ef --- /dev/null +++ b/reference/shaders/dxil-builtin/trace-ray-flags.rgen @@ -0,0 +1,107 @@ +#version 460 +#extension GL_EXT_ray_tracing : require +#extension GL_EXT_ray_flags_primitive_culling : require +#extension GL_EXT_nonuniform_qualifier : require +layout(primitive_culling); + +struct _14 +{ + vec4 _m0; +}; + +layout(set = 0, binding = 0) uniform accelerationStructureEXT AS; +layout(set = 0, binding = 0) uniform writeonly image2D IMG; +layout(location = 0) rayPayloadEXT _14 _16; + +void main() +{ + traceRayEXT(AS, 273u, 0u, 1u, 2u, 3u, vec3(1.0, 2.0, 3.0), 7.0, vec3(4.0, 5.0, 6.0), 8.0, 0); + imageStore(IMG, ivec2(uvec2(0u)), vec4(_16._m0)); +} + + +#if 0 +// SPIR-V disassembly +; SPIR-V +; Version: 1.4 +; Generator: Unknown(30017); 21022 +; Bound: 48 +; Schema: 0 +OpCapability Shader +OpCapability UniformBufferArrayDynamicIndexing +OpCapability SampledImageArrayDynamicIndexing +OpCapability StorageBufferArrayDynamicIndexing +OpCapability StorageImageArrayDynamicIndexing +OpCapability StorageImageWriteWithoutFormat +OpCapability RayTraversalPrimitiveCullingKHR +OpCapability RayTracingKHR +OpCapability RuntimeDescriptorArray +OpCapability UniformBufferArrayNonUniformIndexing +OpCapability SampledImageArrayNonUniformIndexing +OpCapability StorageBufferArrayNonUniformIndexing +OpCapability StorageImageArrayNonUniformIndexing +OpExtension "SPV_EXT_descriptor_indexing" +OpExtension "SPV_KHR_ray_tracing" +OpMemoryModel Logical GLSL450 +OpEntryPoint RayGenerationNV %3 "main" %8 %12 %16 +OpName %3 "main" +OpName %8 "AS" +OpName %12 "IMG" +OpName %14 "" +OpDecorate %8 DescriptorSet 0 +OpDecorate %8 Binding 0 +OpDecorate %12 DescriptorSet 0 +OpDecorate %12 Binding 0 +OpDecorate %12 NonReadable +%1 = OpTypeVoid +%2 = OpTypeFunction %1 +%5 = OpTypeInt 32 1 +%6 = OpTypeAccelerationStructureKHR +%7 = OpTypePointer UniformConstant %6 +%8 = OpVariable %7 UniformConstant +%9 = OpTypeFloat 32 +%10 = OpTypeImage %9 2D 0 0 0 2 Unknown +%11 = OpTypePointer UniformConstant %10 +%12 = OpVariable %11 UniformConstant +%13 = OpTypeVector %9 4 +%14 = OpTypeStruct %13 +%15 = OpTypePointer RayPayloadNV %14 +%16 = OpVariable %15 RayPayloadNV +%18 = OpTypeInt 32 0 +%19 = OpConstant %18 273 +%20 = OpConstant %18 0 +%21 = OpConstant %18 1 +%22 = OpConstant %18 2 +%23 = OpConstant %18 3 +%24 = OpConstant %9 1 +%25 = OpConstant %9 4 +%26 = OpConstant %9 2 +%27 = OpConstant %9 5 +%28 = OpConstant %9 3 +%29 = OpConstant %9 6 +%30 = OpConstant %9 7 +%31 = OpConstant %9 8 +%32 = OpTypeVector %9 3 +%35 = OpTypePointer RayPayloadNV %13 +%43 = OpTypeVector %18 2 +%3 = OpFunction %1 None %2 +%4 = OpLabel +OpBranch %46 +%46 = OpLabel +%17 = OpLoad %6 %8 +%33 = OpCompositeConstruct %32 %24 %26 %28 +%34 = OpCompositeConstruct %32 %25 %27 %29 +OpTraceRayKHR %17 %19 %20 %21 %22 %23 %33 %30 %34 %31 %16 +%36 = OpInBoundsAccessChain %35 %16 %20 +%37 = OpLoad %13 %36 +%38 = OpLoad %10 %12 +%39 = OpCompositeExtract %9 %37 0 +%40 = OpCompositeExtract %9 %37 1 +%41 = OpCompositeExtract %9 %37 2 +%42 = OpCompositeExtract %9 %37 3 +%44 = OpCompositeConstruct %43 %20 %20 +%45 = OpCompositeConstruct %13 %39 %40 %41 %42 +OpImageWrite %38 %44 %45 +OpReturn +OpFunctionEnd +#endif diff --git a/shaders/dxil-builtin/trace-ray-flags-2.rgen b/shaders/dxil-builtin/trace-ray-flags-2.rgen new file mode 100644 index 00000000..5832fbd7 --- /dev/null +++ b/shaders/dxil-builtin/trace-ray-flags-2.rgen @@ -0,0 +1,27 @@ +struct Payload +{ + float4 color; +}; + +RaytracingAccelerationStructure AS : register(t0); +RWTexture2D IMG : register(u0); + +cbuffer Flags : register(b0) +{ + uint flags; +}; + +[shader("raygeneration")] +void RayGen() +{ + RayDesc ray; + ray.Origin = float3(1, 2, 3); + ray.Direction = float3(4, 5, 6); + ray.TMin = 7.0; + ray.TMax = 8.0; + + Payload payload0; + TraceRay(AS, flags, 0, 1, 2, 3, ray, payload0); + + IMG[int2(0, 0)] = payload0.color; +} diff --git a/shaders/dxil-builtin/trace-ray-flags.rgen b/shaders/dxil-builtin/trace-ray-flags.rgen new file mode 100644 index 00000000..4366861e --- /dev/null +++ b/shaders/dxil-builtin/trace-ray-flags.rgen @@ -0,0 +1,22 @@ +struct Payload +{ + float4 color; +}; + +RaytracingAccelerationStructure AS : register(t0); +RWTexture2D IMG : register(u0); + +[shader("raygeneration")] +void RayGen() +{ + RayDesc ray; + ray.Origin = float3(1, 2, 3); + ray.Direction = float3(4, 5, 6); + ray.TMin = 7.0; + ray.TMax = 8.0; + + Payload payload0; + TraceRay(AS, 17 | 0x100, 0, 1, 2, 3, ray, payload0); + + IMG[int2(0, 0)] = payload0.color; +}