diff --git a/WickedEngine/shaders/globals.hlsli b/WickedEngine/shaders/globals.hlsli index b125b9828..8d8205766 100644 --- a/WickedEngine/shaders/globals.hlsli +++ b/WickedEngine/shaders/globals.hlsli @@ -333,7 +333,7 @@ SamplerComparisonState sampler_cmp_depth : register(s109); // Direct heap indexing compatibility functions for HLSL6.6+: // Note: on PS5 this feature is implemented in the preincluded HLSL_to_PSSL.h file -#if defined(__hlsl_dx_compiler) && !defined(__spirv__) && __SHADER_TARGET_MAJOR >= 6 && __SHADER_TARGET_MINOR >= 6 +#if defined(__hlsl_dx_compiler) && __SHADER_TARGET_MAJOR >= 6 && __SHADER_TARGET_MINOR >= 6 template struct BindlessResource { @@ -344,9 +344,9 @@ struct BindlessResource { SamplerState operator[](uint index) { return SamplerState(SamplerDescriptorHeap[index]); } }; -#endif // defined(__hlsl_dx_compiler) && !defined(__spirv__) && __SHADER_TARGET_MAJOR >= 6 && __SHADER_TARGET_MINOR >= 6 +#endif // defined(__hlsl_dx_compiler) && __SHADER_TARGET_MAJOR >= 6 && __SHADER_TARGET_MINOR >= 6 -#if defined(__PSSL__) || (defined(__hlsl_dx_compiler) && !defined(__spirv__) && __SHADER_TARGET_MAJOR >= 6 && __SHADER_TARGET_MINOR >= 6) +#if defined(__PSSL__) || (defined(__hlsl_dx_compiler) && __SHADER_TARGET_MAJOR >= 6 && __SHADER_TARGET_MINOR >= 6) static const BindlessResource bindless_samplers; static const BindlessResource bindless_textures; static const BindlessResource bindless_buffers; @@ -394,67 +394,12 @@ static const BindlessResource > bindless_rwtextures_uint2; static const BindlessResource > bindless_rwtextures_uint3; static const BindlessResource > bindless_rwtextures_uint4; -#ifdef __hlsl_dx_compiler +#ifdef RTAPI +#ifdef __spirv__ +[[vk::binding(0, 1)]] RaytracingAccelerationStructure bindless_accelerationstructures[]; +#elif defined(__hlsl_dx_compiler) static const BindlessResource bindless_accelerationstructures; #endif // __hlsl_dx_compiler - -#elif defined(__spirv__) -// In Vulkan, we can manually overlap descriptor sets to reduce bindings: -// Note that HLSL register space declaration was not working correctly with overlapped spaces, -// But vk::binding works correctly in this case. -// HLSL register space declaration is working well with Vulkan when spaces are not overlapping. -// This layout with two descriptor sets can be implemented onn Vulkan side with mutable descriptors. -static const uint DESCRIPTOR_SET_BINDLESS_SAMPLER = 1; -static const uint DESCRIPTOR_SET_BINDLESS_RESOURCE = 2; - -[[vk::binding(0, DESCRIPTOR_SET_BINDLESS_SAMPLER)]] SamplerState bindless_samplers[]; -[[vk::binding(0, DESCRIPTOR_SET_BINDLESS_RESOURCE)]] ByteAddressBuffer bindless_buffers[]; -[[vk::binding(0, DESCRIPTOR_SET_BINDLESS_RESOURCE)]] Buffer bindless_buffers_uint[]; -[[vk::binding(0, DESCRIPTOR_SET_BINDLESS_RESOURCE)]] Buffer bindless_buffers_uint2[]; -[[vk::binding(0, DESCRIPTOR_SET_BINDLESS_RESOURCE)]] Buffer bindless_buffers_uint3[]; -[[vk::binding(0, DESCRIPTOR_SET_BINDLESS_RESOURCE)]] Buffer bindless_buffers_uint4[]; -[[vk::binding(0, DESCRIPTOR_SET_BINDLESS_RESOURCE)]] Buffer bindless_buffers_float[]; -[[vk::binding(0, DESCRIPTOR_SET_BINDLESS_RESOURCE)]] Buffer bindless_buffers_float2[]; -[[vk::binding(0, DESCRIPTOR_SET_BINDLESS_RESOURCE)]] Buffer bindless_buffers_float3[]; -[[vk::binding(0, DESCRIPTOR_SET_BINDLESS_RESOURCE)]] Buffer bindless_buffers_float4[]; -[[vk::binding(0, DESCRIPTOR_SET_BINDLESS_RESOURCE)]] Buffer bindless_buffers_half[]; -[[vk::binding(0, DESCRIPTOR_SET_BINDLESS_RESOURCE)]] Buffer bindless_buffers_half2[]; -[[vk::binding(0, DESCRIPTOR_SET_BINDLESS_RESOURCE)]] Buffer bindless_buffers_half3[]; -[[vk::binding(0, DESCRIPTOR_SET_BINDLESS_RESOURCE)]] Buffer bindless_buffers_half4[]; -[[vk::binding(0, DESCRIPTOR_SET_BINDLESS_RESOURCE)]] Texture2D bindless_textures[]; -[[vk::binding(0, DESCRIPTOR_SET_BINDLESS_RESOURCE)]] Texture2DArray bindless_textures2DArray[]; -[[vk::binding(0, DESCRIPTOR_SET_BINDLESS_RESOURCE)]] Texture2DArray bindless_textures2DArray_half4[]; -[[vk::binding(0, DESCRIPTOR_SET_BINDLESS_RESOURCE)]] TextureCube bindless_cubemaps[]; -[[vk::binding(0, DESCRIPTOR_SET_BINDLESS_RESOURCE)]] TextureCube bindless_cubemaps_half4[]; -[[vk::binding(0, DESCRIPTOR_SET_BINDLESS_RESOURCE)]] TextureCubeArray bindless_cubearrays[]; -[[vk::binding(0, DESCRIPTOR_SET_BINDLESS_RESOURCE)]] Texture3D bindless_textures3D[]; -[[vk::binding(0, DESCRIPTOR_SET_BINDLESS_RESOURCE)]] Texture3D bindless_textures3D_half4[]; -[[vk::binding(0, DESCRIPTOR_SET_BINDLESS_RESOURCE)]] Texture2D bindless_textures_float[]; -[[vk::binding(0, DESCRIPTOR_SET_BINDLESS_RESOURCE)]] Texture2D bindless_textures_float2[]; -[[vk::binding(0, DESCRIPTOR_SET_BINDLESS_RESOURCE)]] Texture2D bindless_textures_uint[]; -[[vk::binding(0, DESCRIPTOR_SET_BINDLESS_RESOURCE)]] Texture2D bindless_textures_uint4[]; -[[vk::binding(0, DESCRIPTOR_SET_BINDLESS_RESOURCE)]] Texture2D bindless_textures_half4[]; -[[vk::binding(0, DESCRIPTOR_SET_BINDLESS_RESOURCE)]] Texture1D bindless_textures1D[]; -[[vk::binding(0, DESCRIPTOR_SET_BINDLESS_RESOURCE)]] Texture1D bindless_textures1D_half4[]; - -[[vk::binding(0, DESCRIPTOR_SET_BINDLESS_RESOURCE)]] RWByteAddressBuffer bindless_rwbuffers[]; -[[vk::binding(0, DESCRIPTOR_SET_BINDLESS_RESOURCE)]] RWBuffer bindless_rwbuffers_uint[]; -[[vk::binding(0, DESCRIPTOR_SET_BINDLESS_RESOURCE)]] RWBuffer bindless_rwbuffers_uint2[]; -[[vk::binding(0, DESCRIPTOR_SET_BINDLESS_RESOURCE)]] RWBuffer bindless_rwbuffers_uint3[]; -[[vk::binding(0, DESCRIPTOR_SET_BINDLESS_RESOURCE)]] RWBuffer bindless_rwbuffers_uint4[]; -[[vk::binding(0, DESCRIPTOR_SET_BINDLESS_RESOURCE)]] RWBuffer bindless_rwbuffers_float[]; -[[vk::binding(0, DESCRIPTOR_SET_BINDLESS_RESOURCE)]] RWBuffer bindless_rwbuffers_float2[]; -[[vk::binding(0, DESCRIPTOR_SET_BINDLESS_RESOURCE)]] RWBuffer bindless_rwbuffers_float3[]; -[[vk::binding(0, DESCRIPTOR_SET_BINDLESS_RESOURCE)]] RWBuffer bindless_rwbuffers_float4[]; -[[vk::binding(0, DESCRIPTOR_SET_BINDLESS_RESOURCE)]] RWTexture2D bindless_rwtextures[]; -[[vk::binding(0, DESCRIPTOR_SET_BINDLESS_RESOURCE)]] RWTexture2DArray bindless_rwtextures2DArray[]; -[[vk::binding(0, DESCRIPTOR_SET_BINDLESS_RESOURCE)]] RWTexture3D bindless_rwtextures3D[]; -[[vk::binding(0, DESCRIPTOR_SET_BINDLESS_RESOURCE)]] RWTexture2D bindless_rwtextures_uint[]; -[[vk::binding(0, DESCRIPTOR_SET_BINDLESS_RESOURCE)]] RWTexture2D bindless_rwtextures_uint2[]; -[[vk::binding(0, DESCRIPTOR_SET_BINDLESS_RESOURCE)]] RWTexture2D bindless_rwtextures_uint3[]; -[[vk::binding(0, DESCRIPTOR_SET_BINDLESS_RESOURCE)]] RWTexture2D bindless_rwtextures_uint4[]; -#ifdef RTAPI -[[vk::binding(0, DESCRIPTOR_SET_BINDLESS_RESOURCE)]] RaytracingAccelerationStructure bindless_accelerationstructures[]; #endif // RTAPI #else @@ -508,11 +453,11 @@ RWTexture2D bindless_rwtextures_uint2[] : register(space113); RWTexture2D bindless_rwtextures_uint3[] : register(space114); RWTexture2D bindless_rwtextures_uint4[] : register(space115); -#endif // __spirv__ +#endif // defined(__PSSL__) || (defined(__hlsl_dx_compiler) && __SHADER_TARGET_MAJOR >= 6 && __SHADER_TARGET_MINOR >= 6) #include "ShaderInterop_Renderer.h" -#if defined(__PSSL__) || (defined(__hlsl_dx_compiler) && !defined(__spirv__) && __SHADER_TARGET_MAJOR >= 6 && __SHADER_TARGET_MINOR >= 6) +#if defined(__PSSL__) || (defined(__hlsl_dx_compiler) && __SHADER_TARGET_MAJOR >= 6 && __SHADER_TARGET_MINOR >= 6) static const BindlessResource > bindless_structured_meshinstance; static const BindlessResource > bindless_structured_geometry; static const BindlessResource > bindless_structured_meshlet; @@ -522,16 +467,6 @@ static const BindlessResource > bindless_struct static const BindlessResource > bindless_structured_uint; static const BindlessResource > bindless_structured_terrain_chunks; static const BindlessResource > bindless_structured_ddi_probes; -#elif defined(__spirv__) -[[vk::binding(0, DESCRIPTOR_SET_BINDLESS_RESOURCE)]] StructuredBuffer bindless_structured_meshinstance[]; -[[vk::binding(0, DESCRIPTOR_SET_BINDLESS_RESOURCE)]] StructuredBuffer bindless_structured_geometry[]; -[[vk::binding(0, DESCRIPTOR_SET_BINDLESS_RESOURCE)]] StructuredBuffer bindless_structured_meshlet[]; -[[vk::binding(0, DESCRIPTOR_SET_BINDLESS_RESOURCE)]] StructuredBuffer bindless_structured_cluster[]; -[[vk::binding(0, DESCRIPTOR_SET_BINDLESS_RESOURCE)]] StructuredBuffer bindless_structured_cluster_bounds[]; -[[vk::binding(0, DESCRIPTOR_SET_BINDLESS_RESOURCE)]] StructuredBuffer bindless_structured_material[]; -[[vk::binding(0, DESCRIPTOR_SET_BINDLESS_RESOURCE)]] StructuredBuffer bindless_structured_uint[]; -[[vk::binding(0, DESCRIPTOR_SET_BINDLESS_RESOURCE)]] StructuredBuffer bindless_structured_terrain_chunks[]; -[[vk::binding(0, DESCRIPTOR_SET_BINDLESS_RESOURCE)]] StructuredBuffer bindless_structured_ddi_probes[]; #else StructuredBuffer bindless_structured_meshinstance[] : register(space200); StructuredBuffer bindless_structured_geometry[] : register(space201); @@ -542,7 +477,7 @@ StructuredBuffer bindless_structured_material[] : register(space StructuredBuffer bindless_structured_uint[] : register(space206); StructuredBuffer bindless_structured_terrain_chunks[] : register(space207); StructuredBuffer bindless_structured_ddi_probes[] : register(space208); -#endif // defined(__PSSL__) || (defined(__hlsl_dx_compiler) && !defined(__spirv__) && __SHADER_TARGET_MAJOR >= 6 && __SHADER_TARGET_MINOR >= 6) +#endif // defined(__PSSL__) || (defined(__hlsl_dx_compiler) && __SHADER_TARGET_MAJOR >= 6 && __SHADER_TARGET_MINOR >= 6) // Note: these are macros, the SPIRV compilation is a LOT slower and uses a LOT more memory when functions return large structs, issue: https://github.com/microsoft/DirectXShaderCompiler/issues/7493 #define GetFrame() (g_xFrame) diff --git a/WickedEngine/wiGraphicsDevice_Vulkan.cpp b/WickedEngine/wiGraphicsDevice_Vulkan.cpp index 049798136..52f9c51d7 100644 --- a/WickedEngine/wiGraphicsDevice_Vulkan.cpp +++ b/WickedEngine/wiGraphicsDevice_Vulkan.cpp @@ -37,17 +37,6 @@ namespace vulkan_internal static constexpr uint64_t timeout_value = 3'000'000'000ull; // 3 seconds static constexpr uint64_t dynamic_cbv_maxsize = 64 * 1024; - // These shifts are made so that Vulkan resource bindings slots don't interfere with each other across shader stages: - // These are also defined in wi::shadercompiler.cpp as hard coded compiler arguments for SPIRV, so they need to be the same - enum - { - VULKAN_BINDING_SHIFT_B = 0, - VULKAN_BINDING_SHIFT_T = 1000, - VULKAN_BINDING_SHIFT_U = 2000, - VULKAN_BINDING_SHIFT_S = 3000, - }; - - // Converters: constexpr VkFormat _ConvertFormat(Format value) { @@ -3222,15 +3211,17 @@ using namespace vulkan_internal; assert(features_1_2.descriptorBindingStorageTexelBufferUpdateAfterBind == VK_TRUE); // Note: bindless uniform buffer is not used, don't need to check it - allocationhandler->bindless_samplers.init(this, VK_DESCRIPTOR_TYPE_SAMPLER, std::min(BINDLESS_SAMPLER_CAPACITY, properties_1_2.maxDescriptorSetUpdateAfterBindSampledImages)); - descriptor_set_layouts[DESCRIPTOR_SET_BINDLESS_SAMPLER] = allocationhandler->bindless_samplers.descriptorSetLayout; - uint32_t bindless_resource_capacity_real = BINDLESS_RESOURCE_CAPACITY; bindless_resource_capacity_real = std::min(bindless_resource_capacity_real, properties_1_2.maxDescriptorSetUpdateAfterBindSampledImages); bindless_resource_capacity_real = std::min(bindless_resource_capacity_real, properties_1_2.maxDescriptorSetUpdateAfterBindStorageImages); bindless_resource_capacity_real = std::min(bindless_resource_capacity_real, properties_1_2.maxDescriptorSetUpdateAfterBindStorageBuffers); allocationhandler->bindless_resources.init(this, VK_DESCRIPTOR_TYPE_MUTABLE_EXT, bindless_resource_capacity_real); descriptor_set_layouts[DESCRIPTOR_SET_BINDLESS_RESOURCE] = allocationhandler->bindless_resources.descriptorSetLayout; + descriptor_heaps[DESCRIPTOR_HEAP_RESOURCE] = allocationhandler->bindless_resources.descriptorSet; + + allocationhandler->bindless_samplers.init(this, VK_DESCRIPTOR_TYPE_SAMPLER, std::min(BINDLESS_SAMPLER_CAPACITY, properties_1_2.maxDescriptorSetUpdateAfterBindSampledImages)); + descriptor_set_layouts[DESCRIPTOR_SET_BINDLESS_SAMPLER] = allocationhandler->bindless_samplers.descriptorSetLayout; + descriptor_heaps[DESCRIPTOR_HEAP_SAMPLER] = allocationhandler->bindless_samplers.descriptorSet; } // Pipeline layouts: @@ -6391,11 +6382,6 @@ using namespace vulkan_internal; vulkan_check(vkBeginCommandBuffer(commandlist.GetCommandBuffer(), &beginInfo)); - const VkDescriptorSet descriptor_sets[] = { - allocationhandler->bindless_samplers.descriptorSet, - allocationhandler->bindless_resources.descriptorSet, - }; - if (queue == QUEUE_GRAPHICS) { vkCmdSetRasterizerDiscardEnable(commandlist.GetCommandBuffer(), VK_FALSE); @@ -6449,8 +6435,8 @@ using namespace vulkan_internal; VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout, 1, - arraysize(descriptor_sets), - descriptor_sets, + arraysize(descriptor_heaps), + descriptor_heaps, 0, nullptr ); @@ -6460,8 +6446,8 @@ using namespace vulkan_internal; VK_PIPELINE_BIND_POINT_COMPUTE, pipeline_layout, 1, - arraysize(descriptor_sets), - descriptor_sets, + arraysize(descriptor_heaps), + descriptor_heaps, 0, nullptr ); @@ -6473,8 +6459,8 @@ using namespace vulkan_internal; VK_PIPELINE_BIND_POINT_COMPUTE, pipeline_layout, 1, - arraysize(descriptor_sets), - descriptor_sets, + arraysize(descriptor_heaps), + descriptor_heaps, 0, nullptr ); @@ -8482,17 +8468,13 @@ using namespace vulkan_internal; vkCmdBindPipeline(commandlist.GetCommandBuffer(), VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, to_internal(rtpso)->pipeline); // Note: bind descriptor set for RT here instead of BeginCommandList to not set it needlessly - const VkDescriptorSet descriptor_sets[] = { - allocationhandler->bindless_samplers.descriptorSet, - allocationhandler->bindless_resources.descriptorSet, - }; vkCmdBindDescriptorSets( commandlist.GetCommandBuffer(), VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline_layout, 1, - arraysize(descriptor_sets), - descriptor_sets, + arraysize(descriptor_heaps), + descriptor_heaps, 0, nullptr ); diff --git a/WickedEngine/wiGraphicsDevice_Vulkan.h b/WickedEngine/wiGraphicsDevice_Vulkan.h index 2b5b70165..7c729c7fe 100644 --- a/WickedEngine/wiGraphicsDevice_Vulkan.h +++ b/WickedEngine/wiGraphicsDevice_Vulkan.h @@ -37,6 +37,21 @@ namespace wi::graphics class GraphicsDevice_Vulkan final : public GraphicsDevice { friend struct CommandQueue; + public: + enum VULKAN_BINDING_SHIFT + { + VULKAN_BINDING_SHIFT_B = 0, + VULKAN_BINDING_SHIFT_T = 1000, + VULKAN_BINDING_SHIFT_U = 2000, + VULKAN_BINDING_SHIFT_S = 3000, + }; + enum DESCRIPTOR_SET + { + DESCRIPTOR_SET_BINDINGS, + DESCRIPTOR_SET_BINDLESS_RESOURCE, + DESCRIPTOR_SET_BINDLESS_SAMPLER, + DESCRIPTOR_SET_COUNT, + }; protected: VkInstance instance = VK_NULL_HANDLE; VkDebugUtilsMessengerEXT debugUtilsMessenger = VK_NULL_HANDLE; @@ -111,15 +126,16 @@ namespace wi::graphics VkPipelineLayout pipeline_layout = VK_NULL_HANDLE; - enum DESCRIPTOR_SET - { - DESCRIPTOR_SET_BINDINGS, - DESCRIPTOR_SET_BINDLESS_SAMPLER, - DESCRIPTOR_SET_BINDLESS_RESOURCE, - DESCRIPTOR_SET_COUNT, - }; VkDescriptorSetLayout descriptor_set_layouts[DESCRIPTOR_SET_COUNT] = {}; + enum DESCRIPTOR_HEAP + { + DESCRIPTOR_HEAP_RESOURCE, + DESCRIPTOR_HEAP_SAMPLER, + DESCRIPTOR_HEAP_COUNT, + }; + VkDescriptorSet descriptor_heaps[DESCRIPTOR_HEAP_COUNT] = {}; + uint32_t dynamic_cbv_count = ROOT_CBV_COUNT; wi::vector binding_layout_allocations; diff --git a/WickedEngine/wiShaderCompiler.cpp b/WickedEngine/wiShaderCompiler.cpp index af0b49276..eff46633f 100644 --- a/WickedEngine/wiShaderCompiler.cpp +++ b/WickedEngine/wiShaderCompiler.cpp @@ -25,6 +25,7 @@ using namespace Microsoft::WRL; #ifdef SHADERCOMPILER_ENABLED_DXCOMPILER #include "Utility/dxc/dxcapi.h" +#include "wiGraphicsDevice_Vulkan.h" #endif // SHADERCOMPILER_ENABLED_DXCOMPILER #ifdef SHADERCOMPILER_ENABLED_D3DCOMPILER @@ -180,10 +181,12 @@ namespace wi::shadercompiler args.push_back(L"-fspv-target-env=vulkan1.3"); args.push_back(L"-fvk-use-dx-layout"); args.push_back(L"-fvk-use-dx-position-w"); - //args.push_back(L"-fvk-b-shift"); args.push_back(L"0"); args.push_back(L"0"); - args.push_back(L"-fvk-t-shift"); args.push_back(L"1000"); args.push_back(L"0"); - args.push_back(L"-fvk-u-shift"); args.push_back(L"2000"); args.push_back(L"0"); - args.push_back(L"-fvk-s-shift"); args.push_back(L"3000"); args.push_back(L"0"); + args.push_back(L"-fvk-b-shift"); args.push_back(std::to_wstring((int)wi::graphics::GraphicsDevice_Vulkan::VULKAN_BINDING_SHIFT_B)); args.push_back(L"0"); + args.push_back(L"-fvk-t-shift"); args.push_back(std::to_wstring((int)wi::graphics::GraphicsDevice_Vulkan::VULKAN_BINDING_SHIFT_T)); args.push_back(L"0"); + args.push_back(L"-fvk-u-shift"); args.push_back(std::to_wstring((int)wi::graphics::GraphicsDevice_Vulkan::VULKAN_BINDING_SHIFT_U)); args.push_back(L"0"); + args.push_back(L"-fvk-s-shift"); args.push_back(std::to_wstring((int)wi::graphics::GraphicsDevice_Vulkan::VULKAN_BINDING_SHIFT_S)); args.push_back(L"0"); + args.push_back(L"-fvk-bind-resource-heap"); args.push_back(L"0"); args.push_back(std::to_wstring((int)wi::graphics::GraphicsDevice_Vulkan::DESCRIPTOR_SET_BINDLESS_RESOURCE)); + args.push_back(L"-fvk-bind-sampler-heap"); args.push_back(L"0"); args.push_back(std::to_wstring((int)wi::graphics::GraphicsDevice_Vulkan::DESCRIPTOR_SET_BINDLESS_SAMPLER)); break; case ShaderFormat::METAL: args.push_back(L"-D"); args.push_back(L"__metal__"); @@ -204,10 +207,9 @@ namespace wi::shadercompiler args.push_back(L"-enable-16bit-types"); } - if (input.format == ShaderFormat::METAL) + if (input.format == ShaderFormat::SPIRV || input.format == ShaderFormat::METAL) { - // handling SM6.6 style bindless in Metal API is simpler than unbounded descriptor tables: - minshadermodel = ShaderModel::SM_6_6; + minshadermodel = std::max(minshadermodel, ShaderModel::SM_6_6); } args.push_back(L"-T");