From 3c403a40fb3b980432b76ad3b64ca0124753283b Mon Sep 17 00:00:00 2001 From: Pursche Date: Wed, 31 Dec 2025 01:43:20 +0100 Subject: [PATCH] Refactored DescriptorSets Made descriptor sets way more more performant Added DescriptorReflection to ShaderCookers output of ShaderPacks Changed ShaderCooker to compile .slang files instead of .hlsl Removed old DescriptorSetBuilder in favor of new DescriptorHandlerVK Removed ModelDesc (stupidly old unused code) Added Math functions for u32 Added a few tracy zones --- Source/Base/Base/Math/Math.h | 15 + Source/Base/Base/Memory/Bytebuffer.cpp | 1 + Source/Base/Base/Memory/Bytebuffer.h | 11 +- Source/Base/Base/Platform.h | 8 +- .../Novus/ShaderPack/ShaderPack.cpp | 155 +++- .../FileFormat/Novus/ShaderPack/ShaderPack.h | 100 +++ Source/Renderer/Renderer/BackendDispatch.cpp | 2 +- Source/Renderer/Renderer/CommandList.cpp | 16 +- Source/Renderer/Renderer/CommandList.h | 2 +- .../Renderer/Commands/BindDescriptorSet.h | 4 +- Source/Renderer/Renderer/DescriptorSet.cpp | 271 +++++-- Source/Renderer/Renderer/DescriptorSet.h | 75 +- .../Renderer/DescriptorSetResource.cpp | 435 +++------- .../Renderer/Renderer/DescriptorSetResource.h | 22 +- Source/Renderer/Renderer/DescriptorType.h | 14 + .../Renderer/Descriptors/ComputeShaderDesc.h | 2 +- .../Renderer/Descriptors/DescriptorSetDesc.h | 17 + .../Renderer/Renderer/Descriptors/ModelDesc.h | 32 - .../Renderer/Descriptors/PixelShaderDesc.h | 2 +- .../Renderer/Descriptors/VertexShaderDesc.h | 2 +- .../Renderer/Renderer/RenderGraphBuilder.cpp | 12 +- .../Renderer/RenderGraphResources.cpp | 24 +- .../Renderer/Renderer/RenderGraphResources.h | 4 +- Source/Renderer/Renderer/Renderer.cpp | 8 +- Source/Renderer/Renderer/Renderer.h | 62 +- .../Vulkan/Backend/DescriptorAllocatorVK.cpp | 348 -------- .../Vulkan/Backend/DescriptorAllocatorVK.h | 46 -- .../Vulkan/Backend/DescriptorHandlerVK.cpp | 387 +++++++++ .../Vulkan/Backend/DescriptorHandlerVK.h | 55 ++ .../Vulkan/Backend/DescriptorSetBuilderVK.cpp | 763 ------------------ .../Vulkan/Backend/DescriptorSetBuilderVK.h | 163 ---- .../Vulkan/Backend/FormatConverterVK.cpp | 48 ++ .../Vulkan/Backend/FormatConverterVK.h | 8 + .../Vulkan/Backend/PipelineHandlerVK.cpp | 223 ++--- .../Vulkan/Backend/PipelineHandlerVK.h | 17 +- .../Vulkan/Backend/RenderDeviceVK.cpp | 14 +- .../Renderers/Vulkan/Backend/RenderDeviceVK.h | 23 +- .../Vulkan/Backend/ShaderHandlerVK.cpp | 44 +- .../Vulkan/Backend/ShaderHandlerVK.h | 59 +- .../Renderers/Vulkan/Backend/SwapChainVK.h | 4 +- .../Vulkan/Backend/TextureHandlerVK.cpp | 138 +++- .../Vulkan/Backend/TextureHandlerVK.h | 8 +- .../Renderer/Renderers/Vulkan/RendererVK.cpp | 574 +++++-------- .../Renderer/Renderers/Vulkan/RendererVK.h | 73 +- Source/Renderer/Renderer/ShaderEntry.h | 5 + Source/Renderer/Renderer/Window.cpp | 7 +- .../ShaderCooker/ShaderCompiler.cpp | 18 +- .../ShaderCooker/ShaderCooker/SlangBridge.cpp | 241 +++++- 48 files changed, 2050 insertions(+), 2512 deletions(-) create mode 100644 Source/Renderer/Renderer/DescriptorType.h create mode 100644 Source/Renderer/Renderer/Descriptors/DescriptorSetDesc.h delete mode 100644 Source/Renderer/Renderer/Descriptors/ModelDesc.h delete mode 100644 Source/Renderer/Renderer/Renderers/Vulkan/Backend/DescriptorAllocatorVK.cpp delete mode 100644 Source/Renderer/Renderer/Renderers/Vulkan/Backend/DescriptorAllocatorVK.h create mode 100644 Source/Renderer/Renderer/Renderers/Vulkan/Backend/DescriptorHandlerVK.cpp create mode 100644 Source/Renderer/Renderer/Renderers/Vulkan/Backend/DescriptorHandlerVK.h delete mode 100644 Source/Renderer/Renderer/Renderers/Vulkan/Backend/DescriptorSetBuilderVK.cpp delete mode 100644 Source/Renderer/Renderer/Renderers/Vulkan/Backend/DescriptorSetBuilderVK.h diff --git a/Source/Base/Base/Math/Math.h b/Source/Base/Base/Math/Math.h index 1ccec7cd..939ee744 100644 --- a/Source/Base/Base/Math/Math.h +++ b/Source/Base/Base/Math/Math.h @@ -123,6 +123,16 @@ namespace Math return (a >= b) ? a : b; } + inline u32 Min(u32 a, u32 b) + { + return (a <= b) ? a : b; + } + + inline u32 Max(u32 a, u32 b) + { + return (a >= b) ? a : b; + } + inline size_t Min(size_t a, size_t b) { return (a <= b) ? a : b; @@ -143,6 +153,11 @@ namespace Math return Max(Min(x, max), min); } + inline u32 Clamp(u32 x, u32 min, u32 max) + { + return Max(Min(x, max), min); + } + inline size_t Clamp(size_t x, size_t min, size_t max) { return Max(Min(x, max), min); diff --git a/Source/Base/Base/Memory/Bytebuffer.cpp b/Source/Base/Base/Memory/Bytebuffer.cpp index ad6effdf..86cf8b10 100644 --- a/Source/Base/Base/Memory/Bytebuffer.cpp +++ b/Source/Base/Base/Memory/Bytebuffer.cpp @@ -15,6 +15,7 @@ SharedPool Bytebuffer::_byteBuffer524288; SharedPool Bytebuffer::_byteBuffer1048576; SharedPool Bytebuffer::_byteBuffer8388608; SharedPool Bytebuffer::_byteBuffer16777216; +SharedPool Bytebuffer::_byteBuffer67108864; SharedPool Bytebuffer::_byteBuffer209715200; std::shared_ptr Bytebuffer::BorrowRuntime(size_t size) diff --git a/Source/Base/Base/Memory/Bytebuffer.h b/Source/Base/Base/Memory/Bytebuffer.h index 4afab063..afaadefa 100644 --- a/Source/Base/Base/Memory/Bytebuffer.h +++ b/Source/Base/Base/Memory/Bytebuffer.h @@ -692,6 +692,14 @@ class Bytebuffer return buffer; } + else if constexpr (size <= 67108864) + { + std::shared_ptr buffer = _byteBuffer67108864.acquireOrCreate(nullptr, 67108864); + buffer->size = size; + buffer->Reset(); + + return buffer; + } else if constexpr (size <= 209715200) // This is used for the Data Extractor, largest observed file in WOTLK is 65MB, however in BFA this has been observed to be 150MB { std::shared_ptr buffer = _byteBuffer209715200.acquireOrCreate(nullptr, 209715200); @@ -721,7 +729,8 @@ class Bytebuffer static SharedPool _byteBuffer524288; static SharedPool _byteBuffer1048576; static SharedPool _byteBuffer8388608; - static SharedPool _byteBuffer16777216; + static SharedPool _byteBuffer16777216; + static SharedPool _byteBuffer67108864; static SharedPool _byteBuffer209715200; class RuntimePool diff --git a/Source/Base/Base/Platform.h b/Source/Base/Base/Platform.h index a3d06a71..b734db86 100644 --- a/Source/Base/Base/Platform.h +++ b/Source/Base/Base/Platform.h @@ -68,5 +68,11 @@ static_assert(false, "Please add PRAGMA_ENABLE_OPTIMIZATION/PRAGMA_DISABLE_OPTIM #ifndef strcpy_s #define strcpy_s(dest, count) strcpy((dest), (count)) #endif // strcpy_s -#define ARRAYSIZE(arr) (sizeof(arr)/sizeof(arr[0])) #endif + +#ifndef ARRAY_COUNT +#define ARRAY_COUNT(arr) (sizeof(arr)/sizeof(arr[0])) +#endif + +#define STATIC_ASSERT_MATCHING_ARRAY(arrA, arrB) static_assert(ARRAY_COUNT(arrA) == ARRAY_COUNT(arrB), "Array count mismatch: " #arrA " and " #arrB) +#define STATIC_ASSERT_MATCHING_ENUM_ARRAY(enumType, arr) static_assert((static_cast(enumType::COUNT) + 1) == ARRAY_COUNT(arr), "Enum and array count mismatch: " #enumType " and " #arr) \ No newline at end of file diff --git a/Source/FileFormat/FileFormat/Novus/ShaderPack/ShaderPack.cpp b/Source/FileFormat/FileFormat/Novus/ShaderPack/ShaderPack.cpp index ba2886bd..ca50e80d 100644 --- a/Source/FileFormat/FileFormat/Novus/ShaderPack/ShaderPack.cpp +++ b/Source/FileFormat/FileFormat/Novus/ShaderPack/ShaderPack.cpp @@ -7,6 +7,31 @@ namespace FileFormat { + std::string DescriptorReflection::ToString() const + { + std::string result = "DescriptorReflection: { "; + result += "Binding: " + std::to_string(binding) + ", "; + result += "Name: " + name + ", "; + result += "Type: " + std::string(DescriptorTypeReflectionNames[static_cast(type)]) + ", "; + result += "SubType: " + std::string(DescriptorTypeReflectionNames[static_cast(subType)]) + ", "; + result += "Count: " + std::to_string(count); + result += " }"; + return result; + } + + DescriptorSetReflection& ShaderReflection::GetDescriptorSetBySlot(u32 slot) + { + if (!descriptorSets.contains(slot)) + { + DescriptorSetReflection descriptorSetReflection; + descriptorSetReflection.slot = slot; + + descriptorSets[slot] = descriptorSetReflection; + } + + return descriptorSets[slot]; + } + ShaderRef* ShaderPack::GetShaderRef(std::shared_ptr& buffer, u32 shaderIndex) { if (shaderIndex >= manifest.numShaders) @@ -18,6 +43,79 @@ namespace FileFormat return shaderRef; } + bool ShaderPack::GetShaderReflection(std::shared_ptr& buffer, u32 shaderIndex, ShaderReflection& reflection) + { + ShaderRef* shaderRef = GetShaderRef(buffer, shaderIndex); + if (shaderRef == nullptr || shaderRef->reflectionOffset == 0 || shaderRef->reflectionSize == 0) + return false; + + u64 readOffset = buffer->readData; + + buffer->readData = shaderRef->reflectionOffset; + u8 numDescriptorSets; + if (!buffer->GetU8(numDescriptorSets)) + return false; + + reflection.descriptorSets.reserve(numDescriptorSets); + + for(u32 i = 0; i < numDescriptorSets; i++) + { + u8 setSlot; + u8 numDescriptors; + + if (!buffer->GetU8(setSlot)) + return false; + + if (!buffer->GetU8(numDescriptors)) + return false; + + DescriptorSetReflection& descriptorSet = reflection.descriptorSets[setSlot]; + descriptorSet.slot = setSlot; + descriptorSet.descriptors.reserve(numDescriptors); + + for (u32 j = 0; j < numDescriptors; j++) + { + u8 binding; + std::string name; + u8 type; + u8 subType; + u16 count; + u8 accessType; + bool isUsed; + u32 byteOffset; + u32 byteSize; + + bool failed = false; + failed |= !buffer->GetU8(binding); + failed |= !buffer->GetString(name); + failed |= !buffer->GetU8(type); + failed |= !buffer->GetU8(subType); + failed |= !buffer->GetU16(count); + failed |= !buffer->GetU8(accessType); + failed |= !buffer->Get(isUsed); + failed |= !buffer->GetU32(byteOffset); + failed |= !buffer->GetU32(byteSize); + + if (failed) + return false; + + DescriptorReflection& descriptor = descriptorSet.descriptors[binding]; + descriptor.binding = binding; + descriptor.name = std::move(name); + descriptor.type = static_cast(type); + descriptor.subType = static_cast(subType); + descriptor.count = count; + descriptor.accessType = static_cast(accessType); + descriptor.isUsed = isUsed; + descriptor.byteOffset = byteOffset; + descriptor.byteSize = byteSize; + } + } + + buffer->readData = readOffset; + return true; + } + u8* ShaderPack::GetShaderDataPtr(std::shared_ptr& buffer, u32 shaderOffset) { if (shaderOffset >= buffer->writtenData) @@ -39,12 +137,16 @@ namespace FileFormat manifest.numShaders = static_cast(shaders.size()); NC_ASSERT(shaders.size() > 0, "ShaderPack must have at least one shader"); - // Write the Header and manifest to file - output.write(reinterpret_cast(&header), sizeof(header)); - output.write(reinterpret_cast(&manifest), sizeof(manifest)); + std::shared_ptr buffer = Bytebuffer::Borrow<67108864>(); + + // Write the Header and manifest to buffer + buffer->Put(header); + buffer->Put(manifest); // Write the ShaderRefs to file - u64 dataOffset = static_cast(output.tellp()) + (sizeof(ShaderRef) * manifest.numShaders); + u64 baseShaderRefOffset = buffer->writtenData; + u64 dataOffset = baseShaderRefOffset + (sizeof(ShaderRef) * manifest.numShaders); + ShaderRef shaderRef; for (u32 i = 0; i < shaders.size(); i++) { @@ -52,16 +154,57 @@ namespace FileFormat shaderRef.dataOffset = dataOffset; shaderRef.dataSize = shaders[i].size; - output.write(reinterpret_cast(&shaderRef), sizeof(ShaderRef)); + buffer->Put(shaderRef); dataOffset += shaders[i].size; } // Write the shader blobs to file for (u32 i = 0; i < shaders.size(); i++) { - output.write(reinterpret_cast(shaders[i].data), shaders[i].size); + buffer->PutBytes(shaders[i].data, shaders[i].size); } + // Write the reflection data to file + for (u32 i = 0; i < shaders.size(); i++) + { + u64 reflectionDataStartOffset = static_cast(buffer->writtenData); + + const ShaderInMemory& shader = shaders[i]; + + // Write reflection data + u8 numDescriptorSets = static_cast(shader.reflection.descriptorSets.size()); + buffer->PutU8(numDescriptorSets); + for(const auto& [setSlot, descriptorSet] : shader.reflection.descriptorSets) + { + buffer->PutU8(descriptorSet.slot); + + u8 numDescriptors = static_cast(descriptorSet.descriptors.size()); + buffer->PutU8(numDescriptors); + for (const auto& [binding, descriptor] : descriptorSet.descriptors) + { + buffer->PutU8(descriptor.binding); + buffer->PutString(descriptor.name); + buffer->PutU8(static_cast(descriptor.type)); + buffer->PutU8(static_cast(descriptor.subType)); + buffer->PutU16(descriptor.count); + buffer->PutU8(static_cast(descriptor.accessType)); + buffer->Put(descriptor.isUsed); + buffer->PutU32(descriptor.byteOffset); + buffer->PutU32(descriptor.byteSize); + } + } + + u64 reflectionDataEndOffset = static_cast(buffer->writtenData); + + // Patch ShaderRef with reflection data offset and size + u64 shaderRefOffset = baseShaderRefOffset + (i * sizeof(ShaderRef)); + ShaderRef* shaderRefInBuffer = reinterpret_cast(buffer->GetDataPointer() + shaderRefOffset); + shaderRefInBuffer->reflectionOffset = reflectionDataStartOffset; + shaderRefInBuffer->reflectionSize = static_cast(reflectionDataEndOffset - reflectionDataStartOffset); + } + + output.write(reinterpret_cast(buffer->GetDataPointer()), buffer->writtenData); + output.close(); return true; diff --git a/Source/FileFormat/FileFormat/Novus/ShaderPack/ShaderPack.h b/Source/FileFormat/FileFormat/Novus/ShaderPack/ShaderPack.h index 3af23b6e..d56a9254 100644 --- a/Source/FileFormat/FileFormat/Novus/ShaderPack/ShaderPack.h +++ b/Source/FileFormat/FileFormat/Novus/ShaderPack/ShaderPack.h @@ -5,11 +5,105 @@ #include #include +#include #include namespace FileFormat { static const std::string SHADER_PACK_EXTENSION = ".shaderpack"; + enum class DescriptorTypeReflection : u8 + { + Unknown, + + Array, // If this is the type, we have a subType that tells us what type of array it is + + ByteAddressBuffer, + ConstantBuffer, + SamplerState, + StructuredBuffer, + Texture, + TextureArray, + + COUNT + }; + inline const char* DescriptorTypeReflectionNames[] = + { + "Unknown", + + "Array", + + "ByteAddressBuffer", + "ConstantBuffer", + "SamplerState", + "StructuredBuffer", + "Texture", + "TextureArray", + + "COUNT" + }; + STATIC_ASSERT_MATCHING_ENUM_ARRAY(DescriptorTypeReflection, DescriptorTypeReflectionNames); + + enum class DescriptorAccessTypeReflection : u8 + { + None, + Read, + ReadWrite, + RasterOrdered, + Append, + Consume, + Write, + Feedback, + + COUNT + }; + inline const char* DescriptorAccessTypeReflectionNames[] = + { + "None", + "Read", + "ReadWrite", + "RasterOrdered", + "Append", + "Consume", + "Write", + "ResourceAccessFeedback", + + "COUNT" + }; + STATIC_ASSERT_MATCHING_ENUM_ARRAY(DescriptorAccessTypeReflection, DescriptorAccessTypeReflectionNames); + + struct DescriptorReflection + { + public: + std::string ToString() const; + + public: + u32 binding; + std::string name; + DescriptorTypeReflection type; + DescriptorTypeReflection subType; // For arrays + u32 count; // For arrays + + DescriptorAccessTypeReflection accessType; + bool isUsed; + u32 byteOffset; + u32 byteSize; + }; + + struct DescriptorSetReflection + { + public: + u32 slot; + robin_hood::unordered_map descriptors; + }; + + struct ShaderReflection + { + DescriptorSetReflection& GetDescriptorSetBySlot(u32 slot); + + public: + robin_hood::unordered_map descriptorSets; + }; + struct ShaderPackManifest { public: @@ -30,6 +124,9 @@ namespace FileFormat u64 dataOffset = 0; u32 dataSize = 0; + + u64 reflectionOffset = 0; + u32 reflectionSize = 0; }; struct ShaderInMemory @@ -37,6 +134,8 @@ namespace FileFormat public: u32 permutationNameHash; + ShaderReflection reflection; + u8* data = nullptr; u32 size = 0; }; @@ -50,6 +149,7 @@ namespace FileFormat u32 GetNumShaders() const { return manifest.numShaders; } ShaderRef* GetShaderRef(std::shared_ptr& buffer, u32 shaderIndex); + bool GetShaderReflection(std::shared_ptr& buffer, u32 shaderIndex, ShaderReflection& reflection); u8* GetShaderDataPtr(std::shared_ptr& buffer, u32 shaderIndex); public: diff --git a/Source/Renderer/Renderer/BackendDispatch.cpp b/Source/Renderer/Renderer/BackendDispatch.cpp index 4b8becfe..b977277b 100644 --- a/Source/Renderer/Renderer/BackendDispatch.cpp +++ b/Source/Renderer/Renderer/BackendDispatch.cpp @@ -246,7 +246,7 @@ namespace Renderer { ZoneScopedC(tracy::Color::Red3); const Commands::BindDescriptorSet* actualData = static_cast(data); - renderer->BindDescriptorSet(commandList, actualData->slot, actualData->descriptors, actualData->numDescriptors, actualData->bufferPermissions); + renderer->BindDescriptorSet(commandList, actualData->set, actualData->bufferPermissions); } void BackendDispatch::SetDepthBias(Renderer* renderer, CommandListID commandList, const void* data) diff --git a/Source/Renderer/Renderer/CommandList.cpp b/Source/Renderer/Renderer/CommandList.cpp index 5ba9791b..e52f8fb6 100644 --- a/Source/Renderer/Renderer/CommandList.cpp +++ b/Source/Renderer/Renderer/CommandList.cpp @@ -290,23 +290,13 @@ namespace Renderer Commands::EndTimeQuery::DISPATCH_FUNCTION(_renderer, _immediateCommandList, command); #endif } - - void CommandList::BindDescriptorSet(DescriptorSetSlot slot, DescriptorSetResource resource, u32 frameIndex) + + void CommandList::BindDescriptorSet(DescriptorSetResource resource, u32 frameIndex) { DescriptorSet* descriptorSet = _resources->GetDescriptorSet(resource.GetID()); - const std::vector& descriptors = descriptorSet->GetDescriptors(); - size_t numDescriptors = descriptors.size(); - Commands::BindDescriptorSet* command = AddCommand(); - command->slot = slot; - - // Make a copy of the current state of this DescriptorSets descriptors, this uses our per-frame stack allocator so it's gonna be fast and not leak - command->descriptors = Memory::Allocator::NewArray(_allocator, numDescriptors); - memcpy(command->descriptors, descriptors.data(), sizeof(Descriptor) * numDescriptors); - - command->numDescriptors = static_cast(numDescriptors); - + command->set = descriptorSet; command->bufferPermissions = &_resources->GetBufferPermissions(_currentPassIndex); #if COMMANDLIST_DEBUG_IMMEDIATE_MODE diff --git a/Source/Renderer/Renderer/CommandList.h b/Source/Renderer/Renderer/CommandList.h index a4f126d8..6e7095a9 100644 --- a/Source/Renderer/Renderer/CommandList.h +++ b/Source/Renderer/Renderer/CommandList.h @@ -86,7 +86,7 @@ namespace Renderer void BeginTimeQuery(TimeQueryID timeQueryID); void EndTimeQuery(TimeQueryID timeQueryID); - void BindDescriptorSet(DescriptorSetSlot slot, DescriptorSetResource resource, u32 frameIndex); + void BindDescriptorSet(DescriptorSetResource resource, u32 frameIndex); void SetDepthBias(f32 constantFactor, f32 clamp, f32 slopeFactor); void SetScissorRect(u32 left, u32 right, u32 top, u32 bottom); diff --git a/Source/Renderer/Renderer/Commands/BindDescriptorSet.h b/Source/Renderer/Renderer/Commands/BindDescriptorSet.h index b2f41292..7f528e4d 100644 --- a/Source/Renderer/Renderer/Commands/BindDescriptorSet.h +++ b/Source/Renderer/Renderer/Commands/BindDescriptorSet.h @@ -13,9 +13,7 @@ namespace Renderer { static const BackendDispatchFunction DISPATCH_FUNCTION; - DescriptorSetSlot slot; - Descriptor* descriptors; - u32 numDescriptors; + DescriptorSet* set; const TrackedBufferBitSets* bufferPermissions; }; diff --git a/Source/Renderer/Renderer/DescriptorSet.cpp b/Source/Renderer/Renderer/DescriptorSet.cpp index 558f2040..be1c8a1a 100644 --- a/Source/Renderer/Renderer/DescriptorSet.cpp +++ b/Source/Renderer/Renderer/DescriptorSet.cpp @@ -1,143 +1,240 @@ #include "DescriptorSet.h" -#include "RenderGraphResources.h" +#include "DescriptorType.h" #include "Renderer.h" +#include "RenderGraphResources.h" + +#include namespace Renderer { - void DescriptorSet::RegisterPipeline(Renderer* renderer, ComputePipelineID pipelineID) + void VerifyDescriptorMatch(const FileFormat::DescriptorReflection& a, const FileFormat::DescriptorReflection& b) { - renderer->GetDescriptorMetaFromPipeline(_metaInfo, pipelineID, _slot); + if (a.name != b.name) + { + NC_LOG_CRITICAL("Descriptor name mismatch in combined descriptor set reflection: '{}' != '{}'", a.name, b.name); + } + if (a.type != b.type) + { + NC_LOG_CRITICAL("Descriptor type mismatch in combined descriptor set reflection for descriptor '{}'", a.name); + } + if (a.subType != b.subType) + { + NC_LOG_CRITICAL("Descriptor subType mismatch in combined descriptor set reflection for descriptor '{}'", a.name); + } + if (a.count != b.count) + { + NC_LOG_CRITICAL("Descriptor count mismatch in combined descriptor set reflection for descriptor '{}'", a.name); + } } - void DescriptorSet::RegisterPipeline(Renderer* renderer, GraphicsPipelineID pipelineID) + void DescriptorSet::RegisterPipeline(Renderer* renderer, ComputePipelineID pipelineID) { - renderer->GetDescriptorMetaFromPipeline(_metaInfo, pipelineID, _slot); - } + ZoneScoped; + u32 slotIndex = static_cast(_slot); - void DescriptorSet::Bind(StringUtils::StringHash nameHash, BufferID bufferID) - { - NC_ASSERT(!_locked, "DescriptorSet : Tried to Bind a BufferID to a DescriptorSet that is currently in use by a RenderPass. Please use the DescriptorSetResource"); + const ComputePipelineDesc& pipelineDesc = renderer->GetDesc(pipelineID); + const ComputeShaderDesc& shaderDesc = renderer->GetDesc(pipelineDesc.computeShader); + + const FileFormat::ShaderReflection& reflection = shaderDesc.shaderEntry->reflection; - for (u32 i = 0; i < _boundDescriptors.size(); i++) + if (!reflection.descriptorSets.contains(slotIndex)) { - if (nameHash == _boundDescriptors[i].nameHash) + return; + } + + const FileFormat::DescriptorSetReflection& descriptorSet = reflection.descriptorSets.at(slotIndex); + for(const auto& [bindingIndex, descriptor] : descriptorSet.descriptors) + { + if (_combinedReflection.descriptors.contains(bindingIndex)) + { + VerifyDescriptorMatch(_combinedReflection.descriptors[bindingIndex], descriptor); + } + else { - _boundDescriptors[i].descriptorType = DescriptorType::DESCRIPTOR_TYPE_BUFFER; - _boundDescriptors[i].bufferID = bufferID; - return; + _combinedReflection.descriptors[bindingIndex] = descriptor; + u32 nameHash = StringUtils::fnv1a_32(descriptor.name.c_str(), descriptor.name.size()); + _nameHashToBindingIndex[nameHash] = bindingIndex; } } - - Descriptor& boundDescriptor = _boundDescriptors.emplace_back(); - boundDescriptor.nameHash = nameHash; - boundDescriptor.descriptorType = DESCRIPTOR_TYPE_BUFFER; - boundDescriptor.bufferID = bufferID; } - void DescriptorSet::BindArray(StringUtils::StringHash nameHash, BufferID bufferID, u32 arrayIndex) + void DescriptorSet::RegisterPipeline(Renderer* renderer, GraphicsPipelineID pipelineID) { - NC_ASSERT(!_locked, "DescriptorSet : Tried to BindArray a BufferID to a DescriptorSet that is currently in use by a RenderPass. Please use the DescriptorSetResource"); + ZoneScoped; + u32 slotIndex = static_cast(_slot); - for (u32 i = 0; i < _boundDescriptors.size(); i++) + const GraphicsPipelineDesc& pipelineDesc = renderer->GetDesc(pipelineID); + + // Vertex { - if (nameHash == _boundDescriptors[i].nameHash && arrayIndex == _boundDescriptors[i].arrayIndex) + const VertexShaderDesc& shaderDesc = renderer->GetDesc(pipelineDesc.states.vertexShader); + const FileFormat::ShaderReflection& reflection = shaderDesc.shaderEntry->reflection; + if (reflection.descriptorSets.contains(slotIndex)) { - _boundDescriptors[i].descriptorType = DescriptorType::DESCRIPTOR_TYPE_BUFFER_ARRAY; - _boundDescriptors[i].bufferID = bufferID; - _boundDescriptors[i].arrayIndex = arrayIndex; - - return; + const FileFormat::DescriptorSetReflection& descriptorSet = reflection.descriptorSets.at(slotIndex); + for (const auto& [bindingIndex, descriptor] : descriptorSet.descriptors) + { + if (_combinedReflection.descriptors.contains(bindingIndex)) + { + VerifyDescriptorMatch(_combinedReflection.descriptors[bindingIndex], descriptor); + } + else + { + _combinedReflection.descriptors[bindingIndex] = descriptor; + u32 nameHash = StringUtils::fnv1a_32(descriptor.name.c_str(), descriptor.name.size()); + _nameHashToBindingIndex[nameHash] = bindingIndex; + } + } + } + } + + // Pixel + if (pipelineDesc.states.pixelShader != PixelShaderID::Invalid()) + { + const PixelShaderDesc& shaderDesc = renderer->GetDesc(pipelineDesc.states.pixelShader); + const FileFormat::ShaderReflection& reflection = shaderDesc.shaderEntry->reflection; + if (reflection.descriptorSets.contains(slotIndex)) + { + const FileFormat::DescriptorSetReflection& descriptorSet = reflection.descriptorSets.at(slotIndex); + for (const auto& [bindingIndex, descriptor] : descriptorSet.descriptors) + { + if (_combinedReflection.descriptors.contains(bindingIndex)) + { + VerifyDescriptorMatch(_combinedReflection.descriptors[bindingIndex], descriptor); + } + else + { + _combinedReflection.descriptors[bindingIndex] = descriptor; + u32 nameHash = StringUtils::fnv1a_32(descriptor.name.c_str(), descriptor.name.size()); + _nameHashToBindingIndex[nameHash] = bindingIndex; + } + } } } + } + + void DescriptorSet::Init(Renderer* renderer) + { + ZoneScoped; + _renderer = renderer; - Descriptor& boundDescriptor = _boundDescriptors.emplace_back(); - boundDescriptor.nameHash = nameHash; - boundDescriptor.descriptorType = DESCRIPTOR_TYPE_BUFFER_ARRAY; - boundDescriptor.bufferID = bufferID; - boundDescriptor.arrayIndex = arrayIndex; + DescriptorSetDesc desc; + desc.reflection = &_combinedReflection; + + _descriptorSetID = renderer->CreateDescriptorSet(desc); + _initialized = true; } - void DescriptorSet::Bind(StringUtils::StringHash nameHash, SamplerID samplerID) + void DescriptorSet::Bind(StringUtils::StringHash nameHash, BufferID bufferID, bool optional) { - NC_ASSERT(!_locked, "DescriptorSet : Tried to Bind a SamplerID to a DescriptorSet that is currently in use by a RenderPass. Please use the DescriptorSetResource"); + ZoneScoped; + if (!_initialized) + { + NC_LOG_CRITICAL("DescriptorSet : Tried to Bind to a DescriptorSet that has not been initialized yet."); + } - for (u32 i = 0; i < _boundDescriptors.size(); i++) + if (optional && !HasBinding(nameHash)) { - if (nameHash == _boundDescriptors[i].nameHash) - { - _boundDescriptors[i].descriptorType = DescriptorType::DESCRIPTOR_TYPE_SAMPLER; - _boundDescriptors[i].samplerID = samplerID; - return; - } + return; } - Descriptor& boundDescriptor = _boundDescriptors.emplace_back(); - boundDescriptor.nameHash = nameHash; - boundDescriptor.descriptorType = DESCRIPTOR_TYPE_SAMPLER; - boundDescriptor.samplerID = samplerID; + u32 bindingIndex = GetBindingIndex(nameHash); + FileFormat::DescriptorReflection& descriptorReflection = GetDescriptorReflection(bindingIndex); // TODO: Add verification stuff + + u32 frameIndexCount = _renderer->GetFrameIndexCount(); + for(u32 i = 0; i < frameIndexCount; i++) + { + _renderer->BindDescriptor(_descriptorSetID, bindingIndex, bufferID, DescriptorType::StorageBuffer, i); + } } - void DescriptorSet::BindArray(StringUtils::StringHash nameHash, SamplerID samplerID, u32 arrayIndex) + void DescriptorSet::Bind(StringUtils::StringHash nameHash, SamplerID samplerID, bool optional) { - NC_ASSERT(!_locked, "DescriptorSet : Tried to BindArray a SamplerID to a DescriptorSet that is currently in use by a RenderPass. Please use the DescriptorSetResource"); + ZoneScoped; + if (!_initialized) + { + NC_LOG_CRITICAL("DescriptorSet : Tried to Bind to a DescriptorSet that has not been initialized yet."); + } - for (u32 i = 0; i < _boundDescriptors.size(); i++) + if (optional && !HasBinding(nameHash)) { - if (nameHash == _boundDescriptors[i].nameHash && arrayIndex == _boundDescriptors[i].arrayIndex) - { - _boundDescriptors[i].descriptorType = DescriptorType::DESCRIPTOR_TYPE_SAMPLER_ARRAY; - _boundDescriptors[i].samplerID = samplerID; - _boundDescriptors[i].arrayIndex = arrayIndex; + return; + } - return; - } + u32 bindingIndex = GetBindingIndex(nameHash); + //FileFormat::DescriptorReflection& descriptorReflection = GetDescriptorReflection(bindingIndex); // TODO: Add verification stuff + + u32 frameIndexCount = _renderer->GetFrameIndexCount(); + for (u32 i = 0; i < frameIndexCount; i++) + { + _renderer->BindDescriptor(_descriptorSetID, bindingIndex, samplerID, i); + } + } + + void DescriptorSet::BindArray(StringUtils::StringHash nameHash, SamplerID samplerID, u32 arrayIndex, bool optional) + { + ZoneScoped; + if (!_initialized) + { + NC_LOG_CRITICAL("DescriptorSet : Tried to Bind to a DescriptorSet that has not been initialized yet."); + } + + if (optional && !HasBinding(nameHash)) + { + return; } - Descriptor& boundDescriptor = _boundDescriptors.emplace_back(); - boundDescriptor.nameHash = nameHash; - boundDescriptor.descriptorType = DESCRIPTOR_TYPE_SAMPLER_ARRAY; - boundDescriptor.samplerID = samplerID; - boundDescriptor.arrayIndex = arrayIndex; + u32 bindingIndex = GetBindingIndex(nameHash); + //FileFormat::DescriptorReflection& descriptorReflection = GetDescriptorReflection(bindingIndex); // TODO: Add verification stuff + + u32 frameIndexCount = _renderer->GetFrameIndexCount(); + for (u32 i = 0; i < frameIndexCount; i++) + { + _renderer->BindDescriptorArray(_descriptorSetID, bindingIndex, samplerID, arrayIndex, i); + } } - void DescriptorSet::Bind(StringUtils::StringHash nameHash, TextureID textureID) + void DescriptorSet::Bind(StringUtils::StringHash nameHash, TextureArrayID textureArrayID, bool optional) { - NC_ASSERT(!_locked, "DescriptorSet : Tried to Bind a TextureID to a DescriptorSet that is currently in use by a RenderPass. Please use the DescriptorSetResource"); + ZoneScoped; + if (!_initialized) + { + NC_LOG_CRITICAL("DescriptorSet : Tried to Bind to a DescriptorSet that has not been initialized yet."); + } - for (u32 i = 0; i < _boundDescriptors.size(); i++) + if (optional && !HasBinding(nameHash)) { - if (nameHash == _boundDescriptors[i].nameHash) - { - _boundDescriptors[i].descriptorType = DescriptorType::DESCRIPTOR_TYPE_TEXTURE; - _boundDescriptors[i].textureID = textureID; - return; - } + return; } - Descriptor& boundDescriptor = _boundDescriptors.emplace_back(); - boundDescriptor.nameHash = nameHash; - boundDescriptor.descriptorType = DESCRIPTOR_TYPE_TEXTURE; - boundDescriptor.textureID = textureID; + u32 bindingIndex = GetBindingIndex(nameHash); + FileFormat::DescriptorReflection& descriptorReflection = GetDescriptorReflection(bindingIndex); // TODO: Add verification stuff + + _renderer->BindDescriptor(_descriptorSetID, bindingIndex, textureArrayID); } - void DescriptorSet::Bind(StringUtils::StringHash nameHash, TextureArrayID textureArrayID) + bool DescriptorSet::HasBinding(StringUtils::StringHash nameHash) const { - NC_ASSERT(!_locked, "DescriptorSet : Tried to Bind a TextureArrayID to a DescriptorSet that is currently in use by a RenderPass. Please use the DescriptorSetResource"); + return _nameHashToBindingIndex.find(nameHash.computedHash) != _nameHashToBindingIndex.end(); + } - for (u32 i = 0; i < _boundDescriptors.size(); i++) + u32 DescriptorSet::GetBindingIndex(StringUtils::StringHash nameHash) const + { + if (!HasBinding(nameHash)) { - if (nameHash == _boundDescriptors[i].nameHash) - { - _boundDescriptors[i].descriptorType = DescriptorType::DESCRIPTOR_TYPE_TEXTURE_ARRAY; - _boundDescriptors[i].textureArrayID = textureArrayID; + NC_LOG_CRITICAL("DescriptorSet::Bind: Tried to bind to a descriptor namehash '{}' that does not exist in the combined reflection for this DescriptorSet, are you trying to bind to a non existing binding in the shader?", nameHash.computedHash); + } - return; - } + return _nameHashToBindingIndex.at(nameHash.computedHash); + } + + FileFormat::DescriptorReflection& DescriptorSet::GetDescriptorReflection(u32 bindingIndex) + { + if (_combinedReflection.descriptors.find(bindingIndex) == _combinedReflection.descriptors.end()) + { + NC_LOG_CRITICAL("DescriptorSet::GetDescriptorReflection: Tried to get descriptor reflection for binding index '{}' that does not exist in the combined reflection for this DescriptorSet", bindingIndex); } - Descriptor& boundDescriptor = _boundDescriptors.emplace_back(); - boundDescriptor.nameHash = nameHash; - boundDescriptor.descriptorType = DESCRIPTOR_TYPE_TEXTURE_ARRAY; - boundDescriptor.textureArrayID = textureArrayID; + return _combinedReflection.descriptors[bindingIndex]; } } \ No newline at end of file diff --git a/Source/Renderer/Renderer/DescriptorSet.h b/Source/Renderer/Renderer/DescriptorSet.h index 9036d2d5..eecc5dc1 100644 --- a/Source/Renderer/Renderer/DescriptorSet.h +++ b/Source/Renderer/Renderer/DescriptorSet.h @@ -4,6 +4,7 @@ #include "Descriptors/BufferDesc.h" #include "Descriptors/ComputePipelineDesc.h" #include "Descriptors/DepthImageDesc.h" +#include "Descriptors/DescriptorSetDesc.h" #include "Descriptors/GraphicsPipelineDesc.h" #include "Descriptors/ImageDesc.h" #include "Descriptors/SamplerDesc.h" @@ -13,50 +14,18 @@ #include #include +#include + namespace Renderer { class Renderer; class RenderGraphResources; - enum DescriptorType - { - DESCRIPTOR_TYPE_BUFFER, - DESCRIPTOR_TYPE_BUFFER_ARRAY, - DESCRIPTOR_TYPE_SAMPLER, - DESCRIPTOR_TYPE_SAMPLER_ARRAY, - DESCRIPTOR_TYPE_TEXTURE, - DESCRIPTOR_TYPE_TEXTURE_ARRAY, - DESCRIPTOR_TYPE_TEXTURE_WRITE, - DESCRIPTOR_TYPE_TEXTURE_READ_WRITE, - DESCRIPTOR_TYPE_IMAGE, - DESCRIPTOR_TYPE_IMAGE_ARRAY, - DESCRIPTOR_TYPE_DEPTH_IMAGE, - DESCRIPTOR_TYPE_DEPTH_IMAGE_ARRAY, - DESCRIPTOR_TYPE_STORAGE_IMAGE, - DESCRIPTOR_TYPE_STORAGE_IMAGE_ARRAY, - }; - - struct Descriptor - { - u32 nameHash; - u32 imageMipLevel; - u32 count = 1; - u32 arrayIndex = 0; - DescriptorType descriptorType; - - TextureID textureID; - ImageID imageID; - DepthImageID depthImageID; - SamplerID samplerID; - TextureArrayID textureArrayID; - BufferID bufferID; - }; - enum DescriptorSetSlot { - DEBUG, + // 1 indexed because we let 0 be the push constants, it's not technically correct but we get nice error checking if we do this + DEBUG = 1, GLOBAL, - TILES, LIGHT, TERRAIN, MODEL, @@ -70,7 +39,6 @@ namespace Renderer { case DEBUG: return "DEBUG"; case GLOBAL: return "GLOBAL"; - case TILES: return "TILES"; case LIGHT: return "LIGHT"; case TERRAIN: return "TERRAIN"; case MODEL: return "MODEL"; @@ -87,34 +55,45 @@ namespace Renderer public: public: - DescriptorSet(DescriptorSetSlot slot) : _slot(slot) {}; + DescriptorSet(DescriptorSetSlot slot) : _slot(slot) + { + _combinedReflection.slot = static_cast(slot); + }; void RegisterPipeline(Renderer* renderer, ComputePipelineID pipelineID); void RegisterPipeline(Renderer* renderer, GraphicsPipelineID pipelineID); + void Init(Renderer* renderer); + bool IsInitialized() const { return _initialized; } - void Bind(StringUtils::StringHash nameHash, BufferID bufferID); - void BindArray(StringUtils::StringHash nameHash, BufferID bufferID, u32 arrayIndex); - - void Bind(StringUtils::StringHash nameHash, SamplerID samplerID); - void BindArray(StringUtils::StringHash nameHash, SamplerID samplerID, u32 arrayIndex); + void Bind(StringUtils::StringHash nameHash, BufferID bufferID, bool optional = false); - void Bind(StringUtils::StringHash nameHash, TextureID textureID); + void Bind(StringUtils::StringHash nameHash, SamplerID samplerID, bool optional = false); + void BindArray(StringUtils::StringHash nameHash, SamplerID samplerID, u32 arrayIndex, bool optional = false); - void Bind(StringUtils::StringHash nameHash, TextureArrayID textureArrayID); + void Bind(StringUtils::StringHash nameHash, TextureArrayID textureArrayID, bool optional = false); - const std::vector& GetDescriptors() const { return _boundDescriptors; } + DescriptorSetID GetID() const { return _descriptorSetID; } + DescriptorSetSlot GetSlot() const { return _slot; } private: - std::vector& GetMutableDescriptors() { return _boundDescriptors; } + bool HasBinding(StringUtils::StringHash nameHash) const; + u32 GetBindingIndex(StringUtils::StringHash nameHash) const; + FileFormat::DescriptorReflection& GetDescriptorReflection(u32 bindingIndex); void Lock() { _locked = true; } void Unlock() { _locked = false; } private: + Renderer* _renderer = nullptr; + bool _initialized = false; + DescriptorSetSlot _slot; DescriptorMetaInfo _metaInfo; - std::vector _boundDescriptors; + FileFormat::DescriptorSetReflection _combinedReflection; + robin_hood::unordered_map _nameHashToBindingIndex; + DescriptorSetID _descriptorSetID; + bool _locked = false; friend class DescriptorSetResource; diff --git a/Source/Renderer/Renderer/DescriptorSetResource.cpp b/Source/Renderer/Renderer/DescriptorSetResource.cpp index cc8aca61..524eb9dd 100644 --- a/Source/Renderer/Renderer/DescriptorSetResource.cpp +++ b/Source/Renderer/Renderer/DescriptorSetResource.cpp @@ -1,18 +1,21 @@ #include "DescriptorSetResource.h" -#include #include +#include +#include + +#include namespace Renderer { DescriptorSetResource::DescriptorSetResource() - : _id(DescriptorSetID::Invalid()) + : _id(DescriptorSetResourceID::Invalid()) , _renderGraphResources(nullptr) { } - DescriptorSetResource::DescriptorSetResource(DescriptorSetID id, RenderGraphResources& renderGraphResources) + DescriptorSetResource::DescriptorSetResource(DescriptorSetResourceID id, RenderGraphResources& renderGraphResources) : _id(id) , _renderGraphResources(&renderGraphResources) { @@ -21,427 +24,217 @@ namespace Renderer void DescriptorSetResource::Bind(StringUtils::StringHash nameHash, ImageResource resource, u32 mipLevel) const { + ZoneScoped; ImageID imageID = _renderGraphResources->GetImage(resource); DescriptorSet* descriptorSet = _renderGraphResources->GetDescriptorSet(_id); - - std::vector& boundDescriptors = descriptorSet->GetMutableDescriptors(); - - for (u32 i = 0; i < boundDescriptors.size(); i++) + if (!descriptorSet->_initialized) { - if (nameHash == boundDescriptors[i].nameHash) - { - boundDescriptors[i].descriptorType = DescriptorType::DESCRIPTOR_TYPE_IMAGE; - boundDescriptors[i].imageID = imageID; - boundDescriptors[i].imageMipLevel = mipLevel; - return; - } + NC_LOG_CRITICAL("DescriptorSet : Tried to Bind to a DescriptorSet that has not been initialized yet."); } - Descriptor& boundDescriptor = boundDescriptors.emplace_back(); - boundDescriptor.nameHash = nameHash; - boundDescriptor.descriptorType = DESCRIPTOR_TYPE_IMAGE; - boundDescriptor.imageID = imageID; - boundDescriptor.imageMipLevel = mipLevel; - } - - void DescriptorSetResource::BindArray(StringUtils::StringHash nameHash, ImageResource resource, u32 mipLevel, u32 arrayIndex) const - { - ImageID imageID = _renderGraphResources->GetImage(resource); - DescriptorSet* descriptorSet = _renderGraphResources->GetDescriptorSet(_id); + DescriptorSetID descriptorSetID = descriptorSet->GetID(); - std::vector& boundDescriptors = descriptorSet->GetMutableDescriptors(); + u32 bindingIndex = descriptorSet->GetBindingIndex(nameHash.computedHash); - for (u32 i = 0; i < boundDescriptors.size(); i++) + // Verify non-mutable access type + FileFormat::DescriptorReflection& descriptorReflection = descriptorSet->GetDescriptorReflection(bindingIndex); + if (descriptorReflection.accessType != FileFormat::DescriptorAccessTypeReflection::Read) { - if (nameHash == boundDescriptors[i].nameHash && arrayIndex == boundDescriptors[i].arrayIndex) - { - boundDescriptors[i].descriptorType = DescriptorType::DESCRIPTOR_TYPE_IMAGE_ARRAY; - boundDescriptors[i].imageID = imageID; - boundDescriptors[i].imageMipLevel = mipLevel; - boundDescriptors[i].arrayIndex = arrayIndex; - - return; - } + NC_LOG_CRITICAL("DescriptorSetResource::Bind: Tried to bind non-mutable ImageResources to a descriptor namehash '{}' that is not a read-only descriptor", nameHash.computedHash); } - Descriptor& boundDescriptor = boundDescriptors.emplace_back(); - boundDescriptor.nameHash = nameHash; - boundDescriptor.descriptorType = DESCRIPTOR_TYPE_IMAGE_ARRAY; - boundDescriptor.imageID = imageID; - boundDescriptor.imageMipLevel = mipLevel; - boundDescriptor.arrayIndex = arrayIndex; + u32 frameIndex = descriptorSet->_renderer->GetCurrentFrameIndex(); + descriptorSet->_renderer->BindDescriptor(descriptorSetID, bindingIndex, imageID, mipLevel, DescriptorType::SampledImage, frameIndex); } void DescriptorSetResource::Bind(StringUtils::StringHash nameHash, ImageMutableResource resource, u32 mipLevel) const { + ZoneScoped; ImageID imageID = _renderGraphResources->GetImage(resource); DescriptorSet* descriptorSet = _renderGraphResources->GetDescriptorSet(_id); - - std::vector& boundDescriptors = descriptorSet->GetMutableDescriptors(); - - for (u32 i = 0; i < boundDescriptors.size(); i++) + if (!descriptorSet->_initialized) { - if (nameHash == boundDescriptors[i].nameHash) - { - boundDescriptors[i].descriptorType = DescriptorType::DESCRIPTOR_TYPE_IMAGE; - boundDescriptors[i].imageID = imageID; - boundDescriptors[i].imageMipLevel = mipLevel; - return; - } + NC_LOG_CRITICAL("DescriptorSet : Tried to Bind to a DescriptorSet that has not been initialized yet."); } - Descriptor& boundDescriptor = boundDescriptors.emplace_back(); - boundDescriptor.nameHash = nameHash; - boundDescriptor.descriptorType = DESCRIPTOR_TYPE_IMAGE; - boundDescriptor.imageID = imageID; - boundDescriptor.imageMipLevel = mipLevel; + DescriptorSetID descriptorSetID = descriptorSet->GetID(); + + u32 bindingIndex = descriptorSet->GetBindingIndex(nameHash.computedHash); + + FileFormat::DescriptorReflection& descriptorReflection = descriptorSet->GetDescriptorReflection(bindingIndex); + DescriptorType descriptorType = (descriptorReflection.accessType == FileFormat::DescriptorAccessTypeReflection::Read) ? DescriptorType::SampledImage : DescriptorType::StorageImage; + + u32 frameIndex = descriptorSet->_renderer->GetCurrentFrameIndex(); + descriptorSet->_renderer->BindDescriptor(descriptorSetID, bindingIndex, imageID, mipLevel, descriptorType, frameIndex); } - void DescriptorSetResource::BindArray(StringUtils::StringHash nameHash, ImageMutableResource resource, u32 mipLevel, u32 arrayIndex) const + void DescriptorSetResource::Bind(StringUtils::StringHash nameHash, ImageMutableResource resource, u32 mipLevel, u32 mipCount) const { + ZoneScoped; ImageID imageID = _renderGraphResources->GetImage(resource); DescriptorSet* descriptorSet = _renderGraphResources->GetDescriptorSet(_id); - - std::vector& boundDescriptors = descriptorSet->GetMutableDescriptors(); - - for (u32 i = 0; i < boundDescriptors.size(); i++) + if (!descriptorSet->_initialized) { - if (nameHash == boundDescriptors[i].nameHash && arrayIndex == boundDescriptors[i].arrayIndex) - { - boundDescriptors[i].descriptorType = DescriptorType::DESCRIPTOR_TYPE_IMAGE_ARRAY; - boundDescriptors[i].imageID = imageID; - boundDescriptors[i].imageMipLevel = mipLevel; - boundDescriptors[i].arrayIndex = arrayIndex; - - return; - } + NC_LOG_CRITICAL("DescriptorSet : Tried to Bind to a DescriptorSet that has not been initialized yet."); } - Descriptor& boundDescriptor = boundDescriptors.emplace_back(); - boundDescriptor.nameHash = nameHash; - boundDescriptor.descriptorType = DESCRIPTOR_TYPE_IMAGE_ARRAY; - boundDescriptor.imageID = imageID; - boundDescriptor.imageMipLevel = mipLevel; - boundDescriptor.arrayIndex = arrayIndex; + DescriptorSetID descriptorSetID = descriptorSet->GetID(); + + u32 bindingIndex = descriptorSet->GetBindingIndex(nameHash.computedHash); + + FileFormat::DescriptorReflection& descriptorReflection = descriptorSet->GetDescriptorReflection(bindingIndex); + DescriptorType descriptorType = (descriptorReflection.accessType == FileFormat::DescriptorAccessTypeReflection::Read) ? DescriptorType::SampledImage : DescriptorType::StorageImage; + + u32 frameIndex = descriptorSet->_renderer->GetCurrentFrameIndex(); + descriptorSet->_renderer->BindDescriptorArray(descriptorSetID, bindingIndex, imageID, mipLevel, mipCount, descriptorType, frameIndex); } void DescriptorSetResource::Bind(StringUtils::StringHash nameHash, DepthImageResource resource) const { + ZoneScoped; DepthImageID imageID = _renderGraphResources->GetImage(resource); DescriptorSet* descriptorSet = _renderGraphResources->GetDescriptorSet(_id); - - std::vector& boundDescriptors = descriptorSet->GetMutableDescriptors(); - - for (u32 i = 0; i < boundDescriptors.size(); i++) + if (!descriptorSet->_initialized) { - if (nameHash == boundDescriptors[i].nameHash) - { - boundDescriptors[i].descriptorType = DescriptorType::DESCRIPTOR_TYPE_DEPTH_IMAGE; - boundDescriptors[i].depthImageID = imageID; - return; - } + NC_LOG_CRITICAL("DescriptorSet : Tried to Bind to a DescriptorSet that has not been initialized yet."); } - Descriptor& boundDescriptor = boundDescriptors.emplace_back(); - boundDescriptor.nameHash = nameHash; - boundDescriptor.descriptorType = DESCRIPTOR_TYPE_DEPTH_IMAGE; - boundDescriptor.depthImageID = imageID; - } - - void DescriptorSetResource::BindArray(StringUtils::StringHash nameHash, DepthImageResource resource, u32 arrayIndex) const - { - DepthImageID imageID = _renderGraphResources->GetImage(resource); - DescriptorSet* descriptorSet = _renderGraphResources->GetDescriptorSet(_id); + DescriptorSetID descriptorSetID = descriptorSet->GetID(); - std::vector& boundDescriptors = descriptorSet->GetMutableDescriptors(); + u32 bindingIndex = descriptorSet->GetBindingIndex(nameHash.computedHash); - for (u32 i = 0; i < boundDescriptors.size(); i++) + // Verify non-mutable access type + FileFormat::DescriptorReflection& descriptorReflection = descriptorSet->GetDescriptorReflection(bindingIndex); + if (descriptorReflection.accessType != FileFormat::DescriptorAccessTypeReflection::Read) { - if (nameHash == boundDescriptors[i].nameHash && arrayIndex == boundDescriptors[i].arrayIndex) - { - boundDescriptors[i].descriptorType = DescriptorType::DESCRIPTOR_TYPE_DEPTH_IMAGE_ARRAY; - boundDescriptors[i].depthImageID = imageID; - boundDescriptors[i].arrayIndex = arrayIndex; - - return; - } + NC_LOG_CRITICAL("DescriptorSetResource::Bind: Tried to bind non-mutable DepthImageResource to a descriptor namehash '{}' that is not a read-only descriptor", nameHash.computedHash); } - Descriptor& boundDescriptor = boundDescriptors.emplace_back(); - boundDescriptor.nameHash = nameHash; - boundDescriptor.descriptorType = DESCRIPTOR_TYPE_DEPTH_IMAGE_ARRAY; - boundDescriptor.depthImageID = imageID; - boundDescriptor.arrayIndex = arrayIndex; + u32 frameIndex = descriptorSet->_renderer->GetCurrentFrameIndex(); + descriptorSet->_renderer->BindDescriptor(descriptorSetID, bindingIndex, imageID, DescriptorType::SampledImage, frameIndex); } - void DescriptorSetResource::Bind(StringUtils::StringHash nameHash, DepthImageMutableResource resource) const + void DescriptorSetResource::BindArray(StringUtils::StringHash nameHash, DepthImageResource resource, u32 arrayIndex) const { + ZoneScoped; DepthImageID imageID = _renderGraphResources->GetImage(resource); DescriptorSet* descriptorSet = _renderGraphResources->GetDescriptorSet(_id); - - std::vector& boundDescriptors = descriptorSet->GetMutableDescriptors(); - - for (u32 i = 0; i < boundDescriptors.size(); i++) + if (!descriptorSet->_initialized) { - if (nameHash == boundDescriptors[i].nameHash) - { - boundDescriptors[i].descriptorType = DescriptorType::DESCRIPTOR_TYPE_DEPTH_IMAGE; - boundDescriptors[i].depthImageID = imageID; - return; - } + NC_LOG_CRITICAL("DescriptorSet : Tried to Bind to a DescriptorSet that has not been initialized yet."); } - Descriptor& boundDescriptor = boundDescriptors.emplace_back(); - boundDescriptor.nameHash = nameHash; - boundDescriptor.descriptorType = DESCRIPTOR_TYPE_DEPTH_IMAGE; - boundDescriptor.depthImageID = imageID; - } + DescriptorSetID descriptorSetID = descriptorSet->GetID(); - void DescriptorSetResource::BindArray(StringUtils::StringHash nameHash, DepthImageMutableResource resource, u32 arrayIndex) const - { - DepthImageID imageID = _renderGraphResources->GetImage(resource); - DescriptorSet* descriptorSet = _renderGraphResources->GetDescriptorSet(_id); - - std::vector& boundDescriptors = descriptorSet->GetMutableDescriptors(); + u32 bindingIndex = descriptorSet->GetBindingIndex(nameHash.computedHash); - for (u32 i = 0; i < boundDescriptors.size(); i++) + // Verify non-mutable access type + FileFormat::DescriptorReflection& descriptorReflection = descriptorSet->GetDescriptorReflection(bindingIndex); + if (descriptorReflection.accessType != FileFormat::DescriptorAccessTypeReflection::Read) { - if (nameHash == boundDescriptors[i].nameHash && arrayIndex == boundDescriptors[i].arrayIndex) - { - boundDescriptors[i].descriptorType = DescriptorType::DESCRIPTOR_TYPE_DEPTH_IMAGE_ARRAY; - boundDescriptors[i].depthImageID = imageID; - boundDescriptors[i].arrayIndex = arrayIndex; - - return; - } + NC_LOG_CRITICAL("DescriptorSetResource::Bind: Tried to bind non-mutable DepthImageResource to a descriptor namehash '{}' that is not a read-only descriptor", nameHash.computedHash); } - Descriptor& boundDescriptor = boundDescriptors.emplace_back(); - boundDescriptor.nameHash = nameHash; - boundDescriptor.descriptorType = DESCRIPTOR_TYPE_DEPTH_IMAGE_ARRAY; - boundDescriptor.depthImageID = imageID; - boundDescriptor.arrayIndex = arrayIndex; + u32 frameIndex = descriptorSet->_renderer->GetCurrentFrameIndex(); + descriptorSet->_renderer->BindDescriptorArray(descriptorSetID, bindingIndex, imageID, arrayIndex, DescriptorType::SampledImage, frameIndex); } - void DescriptorSetResource::BindStorage(StringUtils::StringHash nameHash, ImageMutableResource resource, u32 mipLevel, u32 mipCount) const + void DescriptorSetResource::BindArray(StringUtils::StringHash nameHash, DepthImageMutableResource resource, u32 arrayIndex) const { - ImageID imageID = _renderGraphResources->GetImage(resource); + ZoneScoped; + DepthImageID imageID = _renderGraphResources->GetImage(resource); DescriptorSet* descriptorSet = _renderGraphResources->GetDescriptorSet(_id); - - std::vector& boundDescriptors = descriptorSet->GetMutableDescriptors(); - - for (u32 i = 0; i < boundDescriptors.size(); i++) + if (!descriptorSet->_initialized) { - if (nameHash == boundDescriptors[i].nameHash) - { - boundDescriptors[i].descriptorType = DescriptorType::DESCRIPTOR_TYPE_STORAGE_IMAGE; - boundDescriptors[i].imageID = imageID; - boundDescriptors[i].imageMipLevel = mipLevel; - boundDescriptors[i].count = mipCount; - return; - } + NC_LOG_CRITICAL("DescriptorSet : Tried to Bind to a DescriptorSet that has not been initialized yet."); } - Descriptor& boundDescriptor = boundDescriptors.emplace_back(); - boundDescriptor.nameHash = nameHash; - boundDescriptor.descriptorType = DESCRIPTOR_TYPE_STORAGE_IMAGE; - boundDescriptor.imageID = imageID; - boundDescriptor.imageMipLevel = mipLevel; - boundDescriptor.count = mipCount; - } - - void DescriptorSetResource::BindStorageArray(StringUtils::StringHash nameHash, ImageMutableResource resource, u32 mipLevel, u32 mipCount) const - { - ImageID imageID = _renderGraphResources->GetImage(resource); - DescriptorSet* descriptorSet = _renderGraphResources->GetDescriptorSet(_id); + DescriptorSetID descriptorSetID = descriptorSet->GetID(); - std::vector& boundDescriptors = descriptorSet->GetMutableDescriptors(); + u32 bindingIndex = descriptorSet->GetBindingIndex(nameHash.computedHash); - for (u32 i = 0; i < boundDescriptors.size(); i++) - { - if (nameHash == boundDescriptors[i].nameHash) - { - boundDescriptors[i].descriptorType = DescriptorType::DESCRIPTOR_TYPE_STORAGE_IMAGE_ARRAY; - boundDescriptors[i].imageID = imageID; - boundDescriptors[i].imageMipLevel = mipLevel; - boundDescriptors[i].count = mipCount; - return; - } - } + FileFormat::DescriptorReflection& descriptorReflection = descriptorSet->GetDescriptorReflection(bindingIndex); + DescriptorType descriptorType = (descriptorReflection.accessType == FileFormat::DescriptorAccessTypeReflection::Read) ? DescriptorType::SampledImage : DescriptorType::StorageImage; - Descriptor& boundDescriptor = boundDescriptors.emplace_back(); - boundDescriptor.nameHash = nameHash; - boundDescriptor.descriptorType = DESCRIPTOR_TYPE_STORAGE_IMAGE_ARRAY; - boundDescriptor.imageID = imageID; - boundDescriptor.imageMipLevel = mipLevel; - boundDescriptor.count = mipCount; + u32 frameIndex = descriptorSet->_renderer->GetCurrentFrameIndex(); + descriptorSet->_renderer->BindDescriptorArray(descriptorSetID, bindingIndex, imageID, arrayIndex, descriptorType, frameIndex); } void DescriptorSetResource::Bind(StringUtils::StringHash nameHash, BufferResource resource) { + ZoneScoped; BufferID bufferID = _renderGraphResources->GetBuffer(resource); DescriptorSet* descriptorSet = _renderGraphResources->GetDescriptorSet(_id); - - std::vector& boundDescriptors = descriptorSet->GetMutableDescriptors(); - - for (u32 i = 0; i < boundDescriptors.size(); i++) + if (!descriptorSet->_initialized) { - if (nameHash == boundDescriptors[i].nameHash) - { - boundDescriptors[i].descriptorType = DescriptorType::DESCRIPTOR_TYPE_BUFFER; - boundDescriptors[i].bufferID = bufferID; - return; - } + NC_LOG_CRITICAL("DescriptorSet : Tried to Bind to a DescriptorSet that has not been initialized yet."); } - Descriptor& boundDescriptor = boundDescriptors.emplace_back(); - boundDescriptor.nameHash = nameHash; - boundDescriptor.descriptorType = DESCRIPTOR_TYPE_BUFFER; - boundDescriptor.bufferID = bufferID; - } - - void DescriptorSetResource::BindArray(StringUtils::StringHash nameHash, BufferResource resource, u32 arrayIndex) - { - BufferID bufferID = _renderGraphResources->GetBuffer(resource); - DescriptorSet* descriptorSet = _renderGraphResources->GetDescriptorSet(_id); + DescriptorSetID descriptorSetID = descriptorSet->GetID(); - std::vector& boundDescriptors = descriptorSet->GetMutableDescriptors(); + u32 bindingIndex = descriptorSet->GetBindingIndex(nameHash.computedHash); - for (u32 i = 0; i < boundDescriptors.size(); i++) - { - if (nameHash == boundDescriptors[i].nameHash && arrayIndex == boundDescriptors[i].arrayIndex) - { - boundDescriptors[i].descriptorType = DescriptorType::DESCRIPTOR_TYPE_BUFFER_ARRAY; - boundDescriptors[i].bufferID = bufferID; - boundDescriptors[i].arrayIndex = arrayIndex; - - return; - } - } + FileFormat::DescriptorReflection& descriptorReflection = descriptorSet->GetDescriptorReflection(bindingIndex); - Descriptor& boundDescriptor = boundDescriptors.emplace_back(); - boundDescriptor.nameHash = nameHash; - boundDescriptor.descriptorType = DESCRIPTOR_TYPE_BUFFER_ARRAY; - boundDescriptor.bufferID = bufferID; - boundDescriptor.arrayIndex = arrayIndex; + u32 frameIndex = descriptorSet->_renderer->GetCurrentFrameIndex(); + descriptorSet->_renderer->BindDescriptor(descriptorSetID, bindingIndex, bufferID, DescriptorType::StorageBuffer, frameIndex); } void DescriptorSetResource::Bind(StringUtils::StringHash nameHash, BufferMutableResource resource) { + ZoneScoped; BufferID bufferID = _renderGraphResources->GetBuffer(resource); DescriptorSet* descriptorSet = _renderGraphResources->GetDescriptorSet(_id); - - std::vector& boundDescriptors = descriptorSet->GetMutableDescriptors(); - - for (u32 i = 0; i < boundDescriptors.size(); i++) + if (!descriptorSet->_initialized) { - if (nameHash == boundDescriptors[i].nameHash) - { - boundDescriptors[i].descriptorType = DescriptorType::DESCRIPTOR_TYPE_BUFFER; - boundDescriptors[i].bufferID = bufferID; - return; - } + NC_LOG_CRITICAL("DescriptorSet : Tried to Bind to a DescriptorSet that has not been initialized yet."); } - Descriptor& boundDescriptor = boundDescriptors.emplace_back(); - boundDescriptor.nameHash = nameHash; - boundDescriptor.descriptorType = DESCRIPTOR_TYPE_BUFFER; - boundDescriptor.bufferID = bufferID; - } - - void DescriptorSetResource::BindArray(StringUtils::StringHash nameHash, BufferMutableResource resource, u32 arrayIndex) - { - BufferID bufferID = _renderGraphResources->GetBuffer(resource); - DescriptorSet* descriptorSet = _renderGraphResources->GetDescriptorSet(_id); + DescriptorSetID descriptorSetID = descriptorSet->GetID(); - std::vector& boundDescriptors = descriptorSet->GetMutableDescriptors(); + u32 bindingIndex = descriptorSet->GetBindingIndex(nameHash.computedHash); - for (u32 i = 0; i < boundDescriptors.size(); i++) - { - if (nameHash == boundDescriptors[i].nameHash && arrayIndex == boundDescriptors[i].arrayIndex) - { - boundDescriptors[i].descriptorType = DescriptorType::DESCRIPTOR_TYPE_BUFFER_ARRAY; - boundDescriptors[i].bufferID = bufferID; - boundDescriptors[i].arrayIndex = arrayIndex; - - return; - } - } + FileFormat::DescriptorReflection& descriptorReflection = descriptorSet->GetDescriptorReflection(bindingIndex); - Descriptor& boundDescriptor = boundDescriptors.emplace_back(); - boundDescriptor.nameHash = nameHash; - boundDescriptor.descriptorType = DESCRIPTOR_TYPE_BUFFER_ARRAY; - boundDescriptor.bufferID = bufferID; - boundDescriptor.arrayIndex = arrayIndex; + u32 frameIndex = descriptorSet->_renderer->GetCurrentFrameIndex(); + descriptorSet->_renderer->BindDescriptor(descriptorSetID, bindingIndex, bufferID, DescriptorType::StorageBuffer, frameIndex); } - void DescriptorSetResource::BindRead(StringUtils::StringHash nameHash, TextureID textureID) + void DescriptorSetResource::Bind(StringUtils::StringHash nameHash, TextureID textureID, u32 mipLevel) { + ZoneScoped; DescriptorSet* descriptorSet = _renderGraphResources->GetDescriptorSet(_id); - - std::vector& boundDescriptors = descriptorSet->GetMutableDescriptors(); - - for (u32 i = 0; i < boundDescriptors.size(); i++) + if (!descriptorSet->_initialized) { - if (nameHash == boundDescriptors[i].nameHash) - { - boundDescriptors[i].descriptorType = DescriptorType::DESCRIPTOR_TYPE_TEXTURE; - boundDescriptors[i].textureID = textureID; - return; - } + NC_LOG_CRITICAL("DescriptorSet : Tried to Bind to a DescriptorSet that has not been initialized yet."); } - Descriptor& boundDescriptor = boundDescriptors.emplace_back(); - boundDescriptor.nameHash = nameHash; - boundDescriptor.descriptorType = DESCRIPTOR_TYPE_TEXTURE; - boundDescriptor.textureID = textureID; - } + u32 bindingIndex = descriptorSet->GetBindingIndex(nameHash.computedHash); + FileFormat::DescriptorReflection& descriptorReflection = descriptorSet->GetDescriptorReflection(bindingIndex); - void DescriptorSetResource::BindReadWrite(StringUtils::StringHash nameHash, TextureID textureID) - { - DescriptorSet* descriptorSet = _renderGraphResources->GetDescriptorSet(_id); - - std::vector& boundDescriptors = descriptorSet->GetMutableDescriptors(); + DescriptorType descriptorType = (descriptorReflection.accessType == FileFormat::DescriptorAccessTypeReflection::Read) ? DescriptorType::SampledImage : DescriptorType::StorageImage; - for (u32 i = 0; i < boundDescriptors.size(); i++) - { - if (nameHash == boundDescriptors[i].nameHash) - { - boundDescriptors[i].descriptorType = DescriptorType::DESCRIPTOR_TYPE_TEXTURE_READ_WRITE; - boundDescriptors[i].textureID = textureID; - return; - } - } - - Descriptor& boundDescriptor = boundDescriptors.emplace_back(); - boundDescriptor.nameHash = nameHash; - boundDescriptor.descriptorType = DESCRIPTOR_TYPE_TEXTURE_READ_WRITE; - boundDescriptor.textureID = textureID; + DescriptorSetID descriptorSetID = descriptorSet->GetID(); + u32 frameIndex = descriptorSet->_renderer->GetCurrentFrameIndex(); + descriptorSet->_renderer->BindDescriptor(descriptorSetID, bindingIndex, textureID, mipLevel, descriptorType, frameIndex); } - void DescriptorSetResource::BindWrite(StringUtils::StringHash nameHash, TextureID textureID, u32 mipLevel, u32 mipCount) + void DescriptorSetResource::Bind(StringUtils::StringHash nameHash, TextureID textureID, u32 mipLevel, u32 mipCount) { + ZoneScoped; DescriptorSet* descriptorSet = _renderGraphResources->GetDescriptorSet(_id); - - std::vector& boundDescriptors = descriptorSet->GetMutableDescriptors(); - - for (u32 i = 0; i < boundDescriptors.size(); i++) + if (!descriptorSet->_initialized) { - if (nameHash == boundDescriptors[i].nameHash) - { - boundDescriptors[i].descriptorType = DescriptorType::DESCRIPTOR_TYPE_TEXTURE_WRITE; - boundDescriptors[i].textureID = textureID; - boundDescriptors[i].imageMipLevel = mipLevel; - boundDescriptors[i].count = mipCount; - return; - } + NC_LOG_CRITICAL("DescriptorSet : Tried to Bind to a DescriptorSet that has not been initialized yet."); } - Descriptor& boundDescriptor = boundDescriptors.emplace_back(); - boundDescriptor.nameHash = nameHash; - boundDescriptor.descriptorType = DESCRIPTOR_TYPE_TEXTURE_WRITE; - boundDescriptor.textureID = textureID; - boundDescriptor.imageMipLevel = mipLevel; - boundDescriptor.count = mipCount; + u32 bindingIndex = descriptorSet->GetBindingIndex(nameHash.computedHash); + FileFormat::DescriptorReflection& descriptorReflection = descriptorSet->GetDescriptorReflection(bindingIndex); + + DescriptorType descriptorType = (descriptorReflection.accessType == FileFormat::DescriptorAccessTypeReflection::Read) ? DescriptorType::SampledImage : DescriptorType::StorageImage; + + DescriptorSetID descriptorSetID = descriptorSet->GetID(); + u32 frameIndex = descriptorSet->_renderer->GetCurrentFrameIndex(); + descriptorSet->_renderer->BindDescriptorArray(descriptorSetID, bindingIndex, textureID, mipLevel, mipCount, descriptorType, frameIndex); } } \ No newline at end of file diff --git a/Source/Renderer/Renderer/DescriptorSetResource.h b/Source/Renderer/Renderer/DescriptorSetResource.h index 6f69193d..6d436cf4 100644 --- a/Source/Renderer/Renderer/DescriptorSetResource.h +++ b/Source/Renderer/Renderer/DescriptorSetResource.h @@ -11,46 +11,38 @@ namespace Renderer class DescriptorSet; class RenderGraphResources; - STRONG_TYPEDEF(DescriptorSetID, u16); + STRONG_TYPEDEF(DescriptorSetResourceID, u16); class DescriptorSetResource { public: DescriptorSetResource(); - DescriptorSetResource(DescriptorSetID id, RenderGraphResources& renderGraphResources); + DescriptorSetResource(DescriptorSetResourceID id, RenderGraphResources& renderGraphResources); // Image resources void Bind(StringUtils::StringHash nameHash, ImageResource resource, u32 mipLevel = 0) const; - void BindArray(StringUtils::StringHash nameHash, ImageResource resource, u32 mipLevel, u32 arrayIndex) const; void Bind(StringUtils::StringHash nameHash, ImageMutableResource resource, u32 mipLevel = 0) const; - void BindArray(StringUtils::StringHash nameHash, ImageMutableResource resource, u32 mipLevel, u32 arrayIndex) const; + void Bind(StringUtils::StringHash nameHash, ImageMutableResource resource, u32 mipLevel, u32 mipCount) const; void Bind(StringUtils::StringHash nameHash, DepthImageResource resource) const; void BindArray(StringUtils::StringHash nameHash, DepthImageResource resource, u32 arrayIndex) const; - void Bind(StringUtils::StringHash nameHash, DepthImageMutableResource resource) const; void BindArray(StringUtils::StringHash nameHash, DepthImageMutableResource resource, u32 arrayIndex) const; - void BindStorage(StringUtils::StringHash nameHash, ImageMutableResource resource, u32 mipLevel = 0, u32 mipCount = 1) const; - void BindStorageArray(StringUtils::StringHash nameHash, ImageMutableResource resource, u32 mipLevel = 0, u32 mipCount = 1) const; - // Buffer resources void Bind(StringUtils::StringHash nameHash, BufferResource resource); - void BindArray(StringUtils::StringHash nameHash, BufferResource resource, u32 arrayIndex); void Bind(StringUtils::StringHash nameHash, BufferMutableResource resource); - void BindArray(StringUtils::StringHash nameHash, BufferMutableResource resource, u32 arrayIndex); // Texture - void BindRead(StringUtils::StringHash nameHash, TextureID textureID); - void BindReadWrite(StringUtils::StringHash nameHash, TextureID textureID); - void BindWrite(StringUtils::StringHash nameHash, TextureID textureID, u32 mipLevel = 0, u32 mipCount = 1); + void Bind(StringUtils::StringHash nameHash, TextureID textureID, u32 mipLevel = 0); + void Bind(StringUtils::StringHash nameHash, TextureID textureID, u32 mipLevel, u32 mipCount); - DescriptorSetID GetID() { return _id; } + DescriptorSetResourceID GetID() { return _id; } private: - DescriptorSetID _id; + DescriptorSetResourceID _id; RenderGraphResources* _renderGraphResources; }; diff --git a/Source/Renderer/Renderer/DescriptorType.h b/Source/Renderer/Renderer/DescriptorType.h new file mode 100644 index 00000000..203482b2 --- /dev/null +++ b/Source/Renderer/Renderer/DescriptorType.h @@ -0,0 +1,14 @@ +#pragma once +#include + +namespace Renderer +{ + enum class DescriptorType : u8 + { + UniformBuffer, + StorageBuffer, + + SampledImage, + StorageImage, // Writeable + }; +} \ No newline at end of file diff --git a/Source/Renderer/Renderer/Descriptors/ComputeShaderDesc.h b/Source/Renderer/Renderer/Descriptors/ComputeShaderDesc.h index 626aadab..d76abebd 100644 --- a/Source/Renderer/Renderer/Descriptors/ComputeShaderDesc.h +++ b/Source/Renderer/Renderer/Descriptors/ComputeShaderDesc.h @@ -10,7 +10,7 @@ namespace Renderer struct ComputeShaderDesc { // Load already in memory - ShaderEntry shaderEntry; + const ShaderEntry* shaderEntry = nullptr; // Load by file void AddPermutationField(const std::string& key, const std::string& value) diff --git a/Source/Renderer/Renderer/Descriptors/DescriptorSetDesc.h b/Source/Renderer/Renderer/Descriptors/DescriptorSetDesc.h new file mode 100644 index 00000000..065a914e --- /dev/null +++ b/Source/Renderer/Renderer/Descriptors/DescriptorSetDesc.h @@ -0,0 +1,17 @@ +#pragma once +#include + +#include + +#include + +namespace Renderer +{ + struct DescriptorSetDesc + { + FileFormat::DescriptorSetReflection* reflection; + }; + + // Lets strong-typedef an ID type with the underlying type of u16 + STRONG_TYPEDEF(DescriptorSetID, u16); +} \ No newline at end of file diff --git a/Source/Renderer/Renderer/Descriptors/ModelDesc.h b/Source/Renderer/Renderer/Descriptors/ModelDesc.h deleted file mode 100644 index ae47e2b0..00000000 --- a/Source/Renderer/Renderer/Descriptors/ModelDesc.h +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once -#include -#include - -#include - -namespace Renderer -{ - struct Vertex - { - vec3 pos; - vec3 normal; - vec2 texCoord; - }; - - struct ModelDesc - { - std::string path; - }; - - struct PrimitiveModelDesc - { - std::vector vertices; - std::vector indices; - - std::string debugName; - }; - - // Lets strong-typedef an ID type with the underlying type of u16 - STRONG_TYPEDEF(ModelID, u16); - -} \ No newline at end of file diff --git a/Source/Renderer/Renderer/Descriptors/PixelShaderDesc.h b/Source/Renderer/Renderer/Descriptors/PixelShaderDesc.h index afd5b937..bf295099 100644 --- a/Source/Renderer/Renderer/Descriptors/PixelShaderDesc.h +++ b/Source/Renderer/Renderer/Descriptors/PixelShaderDesc.h @@ -10,7 +10,7 @@ namespace Renderer struct PixelShaderDesc { // Load already in memory - ShaderEntry shaderEntry; + const ShaderEntry* shaderEntry = nullptr; // Load by file void AddPermutationField(const std::string& key, const std::string& value) diff --git a/Source/Renderer/Renderer/Descriptors/VertexShaderDesc.h b/Source/Renderer/Renderer/Descriptors/VertexShaderDesc.h index 2f10eec6..fc25580f 100644 --- a/Source/Renderer/Renderer/Descriptors/VertexShaderDesc.h +++ b/Source/Renderer/Renderer/Descriptors/VertexShaderDesc.h @@ -10,7 +10,7 @@ namespace Renderer struct VertexShaderDesc { // Load already in memory - ShaderEntry shaderEntry; + const ShaderEntry* shaderEntry = nullptr; // Load by file void AddPermutationField(const std::string& key, const std::string& value) diff --git a/Source/Renderer/Renderer/RenderGraphBuilder.cpp b/Source/Renderer/Renderer/RenderGraphBuilder.cpp index 0d5cfd5f..fb1cf78a 100644 --- a/Source/Renderer/Renderer/RenderGraphBuilder.cpp +++ b/Source/Renderer/Renderer/RenderGraphBuilder.cpp @@ -64,7 +64,7 @@ namespace Renderer for (ImageMutableResource resource : colorClears) { ImageID imageID = _resources.GetImage(resource); - const ImageDesc& imageDesc = _renderer->GetImageDesc(imageID); + const ImageDesc& imageDesc = _renderer->GetDesc(imageID); ImageComponentType imageComponentType = ToImageComponentType(imageDesc.format); @@ -94,7 +94,7 @@ namespace Renderer { DepthImageID imageID = _resources.GetImage(resource); - const DepthImageDesc& imageDesc = _renderer->GetImageDesc(imageID); + const DepthImageDesc& imageDesc = _renderer->GetDesc(imageID); commandList.Clear(resource, imageDesc.depthClearValue); commandList.ImageBarrier(resource); @@ -296,8 +296,8 @@ namespace Renderer } // Lock the DescriptorSets so we have to go through the DescriptorSetResource - const DynamicArray& usedDescriptorSets = _resources.GetUsedDescriptorSetIDs(currentPassIndex); - for (DescriptorSetID descriptorSetID : usedDescriptorSets) + const DynamicArray& usedDescriptorSets = _resources.GetUsedDescriptorSetIDs(currentPassIndex); + for (DescriptorSetResourceID descriptorSetID : usedDescriptorSets) { DescriptorSet* descriptorSet = _resources.GetDescriptorSet(descriptorSetID); descriptorSet->Lock(); @@ -309,8 +309,8 @@ namespace Renderer void RenderGraphBuilder::PostPass(CommandList& /*commandList*/, u32 currentPassIndex, const std::string& passName) { // Unlock the DescriptorSets so we can use them again - const DynamicArray& usedDescriptorSets = _resources.GetUsedDescriptorSetIDs(currentPassIndex); - for (DescriptorSetID descriptorSetID : usedDescriptorSets) + const DynamicArray& usedDescriptorSets = _resources.GetUsedDescriptorSetIDs(currentPassIndex); + for (DescriptorSetResourceID descriptorSetID : usedDescriptorSets) { DescriptorSet* descriptorSet = _resources.GetDescriptorSet(descriptorSetID); descriptorSet->Unlock(); diff --git a/Source/Renderer/Renderer/RenderGraphResources.cpp b/Source/Renderer/Renderer/RenderGraphResources.cpp index 2e1f40aa..70d597d5 100644 --- a/Source/Renderer/Renderer/RenderGraphResources.cpp +++ b/Source/Renderer/Renderer/RenderGraphResources.cpp @@ -31,7 +31,7 @@ namespace Renderer TrackedBufferBitSets bufferPermissions; - DynamicArray descriptorSetIDs; + DynamicArray descriptorSetIDs; }; struct RenderGraphResourcesData : IRenderGraphResourcesData @@ -121,22 +121,22 @@ namespace Renderer const ImageDesc& RenderGraphResources::GetImageDesc(ImageResource resource) { ImageID imageID = GetImage(resource); - return _renderer->GetImageDesc(imageID); + return _renderer->GetDesc(imageID); } const ImageDesc& RenderGraphResources::GetImageDesc(ImageMutableResource resource) { ImageID imageID = GetImage(resource); - return _renderer->GetImageDesc(imageID); + return _renderer->GetDesc(imageID); } const DepthImageDesc& RenderGraphResources::GetImageDesc(DepthImageResource resource) { DepthImageID imageID = GetImage(resource); - return _renderer->GetImageDesc(imageID); + return _renderer->GetDesc(imageID); } const DepthImageDesc& RenderGraphResources::GetImageDesc(DepthImageMutableResource resource) { DepthImageID imageID = GetImage(resource); - return _renderer->GetImageDesc(imageID); + return _renderer->GetDesc(imageID); } uvec2 RenderGraphResources::GetImageDimensions(ImageResource resource, u32 mipLevel) @@ -204,9 +204,9 @@ namespace Renderer return data->trackedBuffers[static_cast(resource)]; } - DescriptorSet* RenderGraphResources::GetDescriptorSet(DescriptorSetID descriptorSetID) + DescriptorSet* RenderGraphResources::GetDescriptorSet(DescriptorSetResourceID descriptorSetID) { - NC_ASSERT(descriptorSetID != DescriptorSetID::Invalid(), "RenderGraphResources : GetDescriptorSet tried to get image of invalid DescriptorSetResourceID"); + NC_ASSERT(descriptorSetID != DescriptorSetResourceID::Invalid(), "RenderGraphResources : GetDescriptorSet tried to get image of invalid DescriptorSetResourceID"); RenderGraphResourcesData* data = static_cast(_data); return data->trackedDescriptorSets[static_cast(descriptorSetID)]; @@ -266,21 +266,21 @@ namespace Renderer { RenderGraphResourcesData* data = static_cast(_data); - DescriptorSetID id = DescriptorSetID::Invalid(); + DescriptorSetResourceID id = DescriptorSetResourceID::Invalid(); for (u32 i = 0; i < data->trackedDescriptorSets.Count(); i++) { DescriptorSet* trackedDescriptorSet = data->trackedDescriptorSets[i]; if (trackedDescriptorSet == &descriptorSet) { - id = DescriptorSetID(i); + id = DescriptorSetResourceID(i); break; } } - if (id == DescriptorSetID::Invalid()) + if (id == DescriptorSetResourceID::Invalid()) { - id = DescriptorSetID(static_cast(data->trackedDescriptorSets.Count())); + id = DescriptorSetResourceID(static_cast(data->trackedDescriptorSets.Count())); data->trackedDescriptorSets.Insert(&descriptorSet); } @@ -616,7 +616,7 @@ namespace Renderer return data->trackedPasses[passIndex].bufferPermissions; } - const DynamicArray& RenderGraphResources::GetUsedDescriptorSetIDs(u32 passIndex) + const DynamicArray& RenderGraphResources::GetUsedDescriptorSetIDs(u32 passIndex) { RenderGraphResourcesData* data = static_cast(_data); diff --git a/Source/Renderer/Renderer/RenderGraphResources.h b/Source/Renderer/Renderer/RenderGraphResources.h index 0fc0cef4..d9a7b0b0 100644 --- a/Source/Renderer/Renderer/RenderGraphResources.h +++ b/Source/Renderer/Renderer/RenderGraphResources.h @@ -100,7 +100,7 @@ namespace Renderer BufferID GetBuffer(BufferResource resource); BufferID GetBuffer(BufferMutableResource resource); - DescriptorSet* GetDescriptorSet(DescriptorSetID resource); + DescriptorSet* GetDescriptorSet(DescriptorSetResourceID resource); ImageResource GetResource(ImageID id); DepthImageResource GetResource(DepthImageID id); @@ -131,7 +131,7 @@ namespace Renderer const TrackedBufferBitSets& GetBufferPermissions(u32 passIndex); - const DynamicArray& GetUsedDescriptorSetIDs(u32 passIndex); + const DynamicArray& GetUsedDescriptorSetIDs(u32 passIndex); const DynamicArray& GetPassAccesses(ImageID imageID); const DynamicArray& GetPassAccesses(DepthImageID imageID); diff --git a/Source/Renderer/Renderer/Renderer.cpp b/Source/Renderer/Renderer/Renderer.cpp index 988d8939..84401942 100644 --- a/Source/Renderer/Renderer/Renderer.cpp +++ b/Source/Renderer/Renderer/Renderer.cpp @@ -4,24 +4,26 @@ #include +#include + namespace Renderer { Renderer::~Renderer() { } - void Renderer::SetGetShaderEntryCallback(const std::function& callback) + void Renderer::SetGetShaderEntryCallback(const std::function& callback) { _getShaderEntryCallback = callback; } - const ShaderEntry& Renderer::GetShaderEntry(u32 shaderNameHash) + const ShaderEntry* Renderer::GetShaderEntry(u32 shaderNameHash, const std::string& debugName) { if (!_getShaderEntryCallback) { NC_LOG_CRITICAL("Renderer::GetShaderEntry called but no callback is set!"); } - return _getShaderEntryCallback(shaderNameHash); + return _getShaderEntryCallback(shaderNameHash, debugName); } void Renderer::SetGetBlitPipelineCallback(const std::function& callback) diff --git a/Source/Renderer/Renderer/Renderer.h b/Source/Renderer/Renderer/Renderer.h index dd9c3913..f4f4804e 100644 --- a/Source/Renderer/Renderer/Renderer.h +++ b/Source/Renderer/Renderer/Renderer.h @@ -3,6 +3,7 @@ #include "DescriptorMeta.h" #include "DescriptorSet.h" +#include "DescriptorType.h" #include "RenderStates.h" #include "ShaderEntry.h" @@ -12,6 +13,7 @@ #include "Descriptors/ComputePipelineDesc.h" #include "Descriptors/ComputeShaderDesc.h" #include "Descriptors/DepthImageDesc.h" +#include "Descriptors/DescriptorSetDesc.h" #include "Descriptors/GraphicsPipelineDesc.h" #include "Descriptors/ImageDesc.h" #include "Descriptors/PixelShaderDesc.h" @@ -24,6 +26,16 @@ #include "Descriptors/UploadBuffer.h" #include "Descriptors/VertexShaderDesc.h" +namespace FileFormat +{ + struct ShaderReflection; +} + +namespace Memory +{ + class Allocator; +} + namespace Novus { class Window; @@ -34,11 +46,6 @@ namespace tracy struct SourceLocationData; } -namespace Memory -{ - class Allocator; -} - struct FfxInterface; struct FfxCacaoContext; @@ -58,7 +65,7 @@ namespace Renderer virtual void Deinit() = 0; virtual void SetShaderSourceDirectory(const std::string& path) = 0; - virtual void SetGetShaderEntryCallback(const std::function& callback); + virtual void SetGetShaderEntryCallback(const std::function& callback); virtual void SetGetBlitPipelineCallback(const std::function& callback); virtual void ReloadShaders(bool forceRecompileAll) = 0; virtual void ClearUploadBuffers() = 0; @@ -84,6 +91,8 @@ namespace Renderer virtual SamplerID CreateSampler(SamplerDesc& sampler) = 0; virtual SemaphoreID CreateNSemaphore() = 0; + virtual DescriptorSetID CreateDescriptorSet(const DescriptorSetDesc& desc) = 0; + virtual GraphicsPipelineID CreatePipeline(GraphicsPipelineDesc& desc) = 0; virtual ComputePipelineID CreatePipeline(ComputePipelineDesc& desc) = 0; @@ -106,8 +115,21 @@ namespace Renderer virtual void UnloadTexture(TextureID textureID) = 0; virtual void UnloadTexturesInArray(TextureArrayID textureArrayID, u32 unloadStartIndex) = 0; + // Descriptor binding + virtual void BindDescriptor(DescriptorSetID descriptorSetID, u32 bindingIndex, BufferID bufferID, DescriptorType type, u32 frameIndex) = 0; + virtual void BindDescriptor(DescriptorSetID descriptorSetID, u32 bindingIndex, ImageID imageID, u32 mipLevel, DescriptorType type, u32 frameIndex) = 0; + virtual void BindDescriptorArray(DescriptorSetID descriptorSetID, u32 bindingIndex, ImageID imageID, u32 mipLevel, u32 mipCount, DescriptorType type, u32 frameIndex) = 0; + virtual void BindDescriptor(DescriptorSetID descriptorSetID, u32 bindingIndex, DepthImageID imageID, DescriptorType type, u32 frameIndex) = 0; + virtual void BindDescriptorArray(DescriptorSetID descriptorSetID, u32 bindingIndex, DepthImageID imageID, u32 arrayIndex, DescriptorType type, u32 frameIndex) = 0; + virtual void BindDescriptor(DescriptorSetID descriptorSetID, u32 bindingIndex, SamplerID samplerID, u32 frameIndex) = 0; + virtual void BindDescriptorArray(DescriptorSetID descriptorSetID, u32 bindingIndex, SamplerID samplerID, u32 arrayIndex, u32 frameIndex) = 0; + virtual void BindDescriptor(DescriptorSetID descriptorSetID, u32 bindingIndex, TextureID textureID, u32 mipLevel, DescriptorType type, u32 frameIndex) = 0; + virtual void BindDescriptorArray(DescriptorSetID descriptorSetID, u32 bindingIndex, TextureID textureID, u32 mipLevel, u32 mipCount, DescriptorType type, u32 frameIndex) = 0; + virtual void BindDescriptor(DescriptorSetID descriptorSetID, u32 bindingIndex, TextureArrayID textureArrayID) = 0; + // Misc virtual u32 AddTextureToArray(TextureID textureID, TextureArrayID textureArrayID) = 0; + virtual void FlushTextureArrayDescriptors(TextureArrayID textureArrayID) = 0; // Command List Functions virtual CommandListID BeginCommandList() = 0; @@ -154,7 +176,7 @@ namespace Renderer virtual void SetIndexBuffer(CommandListID commandListID, BufferID bufferID, IndexFormat indexFormat) = 0; virtual void SetBuffer(CommandListID commandListID, u32 slot, BufferID buffer) = 0; - virtual void BindDescriptorSet(CommandListID commandListID, DescriptorSetSlot slot, Descriptor* descriptors, u32 numDescriptors, const TrackedBufferBitSets* bufferPermissions) = 0; + virtual void BindDescriptorSet(CommandListID commandListID, DescriptorSet* descriptorSet, const TrackedBufferBitSets* bufferPermissions) = 0; virtual void MarkFrameStart(CommandListID commandListID, u32 frameIndex) = 0; virtual void BeginTrace(CommandListID commandListID, const tracy::SourceLocationData* sourceLocation) = 0; @@ -207,17 +229,29 @@ namespace Renderer const std::vector& GetFrameTimeQueries() { return _frameTimeQueries; } + // ID to Descriptor + virtual TextureBaseDesc GetDesc(TextureID textureID) = 0; + + virtual const ImageDesc& GetDesc(ImageID ID) = 0; + virtual const DepthImageDesc& GetDesc(DepthImageID ID) = 0; + + virtual const ComputePipelineDesc& GetDesc(ComputePipelineID ID) = 0; + virtual const GraphicsPipelineDesc& GetDesc(GraphicsPipelineID ID) = 0; + + virtual const ComputeShaderDesc& GetDesc(ComputeShaderID ID) = 0; + virtual const VertexShaderDesc& GetDesc(VertexShaderID ID) = 0; + virtual const PixelShaderDesc& GetDesc(PixelShaderID ID) = 0; + // Utils virtual void FlushGPU() = 0; virtual f32 FlipFrame(u32 frameIndex) = 0; // Returns time waited in seconds + virtual u32 GetCurrentFrameIndex() = 0; + virtual u32 GetFrameIndexCount() = 0; + virtual void ResetTimeQueries(u32 frameIndex) = 0; virtual TextureID GetTextureID(TextureArrayID textureArrayID, u32 index) = 0; - virtual TextureBaseDesc GetTextureDesc(TextureID textureID) = 0; - - virtual const ImageDesc& GetImageDesc(ImageID ID) = 0; - virtual const DepthImageDesc& GetImageDesc(DepthImageID ID) = 0; virtual uvec2 GetImageDimensions(const ImageID id, u32 mipLevel = 0) = 0; virtual uvec2 GetImageDimensions(const DepthImageID id) = 0; @@ -241,13 +275,11 @@ namespace Renderer virtual bool HasExtendedTextureSupport() = 0; - virtual void GetDescriptorMetaFromPipeline(DescriptorMetaInfo& metaInfo, GraphicsPipelineID pipeline, DescriptorSetSlot slot) = 0; - virtual void GetDescriptorMetaFromPipeline(DescriptorMetaInfo& metaInfo, ComputePipelineID pipeline, DescriptorSetSlot slot) = 0; + const ShaderEntry* GetShaderEntry(u32 shaderNameHash, const std::string& debugName); protected: Renderer() {}; // Pure virtual class, disallow creation of it - const ShaderEntry& GetShaderEntry(u32 shaderNameHash); const GraphicsPipelineID GetBlitPipeline(u32 shaderNameHash); void BeginExecutingCommandlist() { _isExecutingCommandlist = true; }; @@ -258,7 +290,7 @@ namespace Renderer std::vector _frameTimeQueries; std::vector> _onRenderSizeChangedCallbacks; - std::function _getShaderEntryCallback; + std::function _getShaderEntryCallback; std::function _getBlitPipelineCallback; friend class RenderGraph; diff --git a/Source/Renderer/Renderer/Renderers/Vulkan/Backend/DescriptorAllocatorVK.cpp b/Source/Renderer/Renderer/Renderers/Vulkan/Backend/DescriptorAllocatorVK.cpp deleted file mode 100644 index 6c934ea7..00000000 --- a/Source/Renderer/Renderer/Renderers/Vulkan/Backend/DescriptorAllocatorVK.cpp +++ /dev/null @@ -1,348 +0,0 @@ -#include "DescriptorAllocatorVK.h" -#include "RenderDeviceVK.h" - -#include - -#include -#include -#include - -namespace Renderer -{ - namespace Backend - { - bool IsMemoryError(VkResult result) - { - switch (result) - { - case VK_ERROR_FRAGMENTED_POOL: - case VK_ERROR_OUT_OF_POOL_MEMORY: - return true; - - default: - return false; - } - } - - struct DescriptorAllocatorVK - { - VkDescriptorPool pool; - }; - - struct PoolStorage - { - std::vector _usableAllocators; - std::vector _fullAllocators; - }; - - struct PoolSize - { - VkDescriptorType type; - f32 multiplier; - }; - - struct PoolSizes - { - std::vector sizes = - { - { VK_DESCRIPTOR_TYPE_SAMPLER, 4.0f}, - { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1.0f}, - { VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 10.0f}, - { VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1.0f}, - { VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1.0f}, - { VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1.0f}, - { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2.0f}, - { VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 2.0f}, - { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1.0f}, - { VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, 1.0f}, - { VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1.0f} - }; - }; - - class DescriptorAllocatorPoolVKImpl : public DescriptorAllocatorPoolVK - { - public: - virtual ~DescriptorAllocatorPoolVKImpl(); - - void SetPoolSizeMultiplier(VkDescriptorType type, f32 multiplier) override final; - void Flip() override final; - DescriptorAllocatorHandleVK GetAllocator() override final; - - void ReturnAllocator(DescriptorAllocatorHandleVK& handle, bool isFull); - VkDescriptorPool CreatePool(i32 count, VkDescriptorPoolCreateFlags flags); - - RenderDeviceVK* _device; - PoolSizes _poolSizes; - - i32 _frameIndex; - i32 _numFrames; - - std::mutex _poolMutex; - - // Zero is for static pool, next is for frame indexing - std::vector> _descriptorPools; - - // Fully cleared allocators - std::vector _clearAllocators; - }; - - DescriptorAllocatorPoolVK* DescriptorAllocatorPoolVK::Create(RenderDeviceVK* device, i32 numFrames) - { - DescriptorAllocatorPoolVKImpl* impl = new DescriptorAllocatorPoolVKImpl(); - - impl->_device = device; - impl->_frameIndex = 0; - impl->_numFrames = numFrames; - - for (i32 i = 0; i < numFrames; i++) - { - impl->_descriptorPools.push_back(std::make_unique()); - } - - return impl; - } - - DescriptorAllocatorHandleVK::~DescriptorAllocatorHandleVK() - { - DescriptorAllocatorPoolVKImpl* implPool = static_cast(ownerPool); - if (implPool) - { - implPool->ReturnAllocator(*this, false); - } - } - - DescriptorAllocatorHandleVK::DescriptorAllocatorHandleVK(DescriptorAllocatorHandleVK&& other) - { - Return(); - - vkPool = other.vkPool; - poolID = other.poolID; - ownerPool = other.ownerPool; - - other.ownerPool = nullptr; - other.poolID = -1; - other.vkPool = VkDescriptorPool(); - } - - DescriptorAllocatorHandleVK& DescriptorAllocatorHandleVK::operator=(DescriptorAllocatorHandleVK&& other) - { - Return(); - - vkPool = other.vkPool; - poolID = other.poolID; - ownerPool = other.ownerPool; - - other.ownerPool = nullptr; - other.poolID = -1; - other.vkPool = VkDescriptorPool(); - - return *this; - } - - void DescriptorAllocatorHandleVK::Return() - { - DescriptorAllocatorPoolVKImpl* implPool = static_cast(ownerPool); - if (implPool) - { - implPool->ReturnAllocator(*this, false); - } - - vkPool = VkDescriptorPool{}; - poolID = -1; - ownerPool = nullptr; - } - - bool DescriptorAllocatorHandleVK::Allocate(const VkDescriptorSetLayout& layout, VkDescriptorSet& set, void* next) - { - DescriptorAllocatorPoolVKImpl* implPool = static_cast(ownerPool); - - VkDescriptorSetAllocateInfo allocInfo; - allocInfo.pNext = next; - allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; - allocInfo.descriptorPool = vkPool; - allocInfo.descriptorSetCount = 1; - allocInfo.pSetLayouts = &layout; - - VkResult result = vkAllocateDescriptorSets(implPool->_device->_device, &allocInfo, &set); - if (result != VK_SUCCESS) - { - // We allocate pools on memory error - if (IsMemoryError(result)) - { - // Out of space, we need to reallocate - implPool->ReturnAllocator(*this, true); - - DescriptorAllocatorHandleVK newHandle = implPool->GetAllocator(); - - vkPool = newHandle.vkPool; - poolID = newHandle.poolID; - - newHandle.vkPool = VkDescriptorPool{}; - newHandle.poolID = -1; - newHandle.ownerPool = nullptr; - - return Allocate(layout, set); - } - else - { - NC_LOG_CRITICAL("Could not allocate descriptor set"); - return false; - } - } - - return true; - } - - VkDescriptorPool DescriptorAllocatorPoolVKImpl::CreatePool(i32 count, VkDescriptorPoolCreateFlags flags) - { - std::vector sizes; - sizes.reserve(_poolSizes.sizes.size()); - - for (auto size : _poolSizes.sizes) - { - sizes.push_back({ size.type, u32(size.multiplier * count) }); - } - - VkDescriptorPoolCreateInfo poolInfo = {}; - poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; - poolInfo.flags = flags; - poolInfo.maxSets = count; - poolInfo.poolSizeCount = static_cast(sizes.size()); - poolInfo.pPoolSizes = sizes.data(); - - VkDescriptorPool descriptorPool; - VkResult result = vkCreateDescriptorPool(_device->_device, &poolInfo, nullptr, &descriptorPool); - - if (result != VK_SUCCESS) - { - NC_LOG_CRITICAL("Could not create descriptor pool"); - } - - return descriptorPool; - } - - DescriptorAllocatorPoolVKImpl::~DescriptorAllocatorPoolVKImpl() - { - for (DescriptorAllocatorVK allocator : _clearAllocators) - { - vkDestroyDescriptorPool(_device->_device, allocator.pool, nullptr); - } - for (auto&& storage : _descriptorPools) - { - for (DescriptorAllocatorVK allocator : storage->_fullAllocators) - { - vkDestroyDescriptorPool(_device->_device, allocator.pool, nullptr); - } - for (DescriptorAllocatorVK allocator : storage->_usableAllocators) - { - vkDestroyDescriptorPool(_device->_device, allocator.pool, nullptr); - } - } - } - - void DescriptorAllocatorPoolVKImpl::Flip() - { - _frameIndex = (_frameIndex + 1) % _numFrames; - - for (auto allocator : _descriptorPools[_frameIndex]->_fullAllocators) - { - vkResetDescriptorPool(_device->_device, allocator.pool, VkDescriptorPoolResetFlags{ 0 }); - - _clearAllocators.push_back(allocator); - } - - for (auto allocator : _descriptorPools[_frameIndex]->_usableAllocators) - { - vkResetDescriptorPool(_device->_device, allocator.pool, VkDescriptorPoolResetFlags{ 0 }); - - _clearAllocators.push_back(allocator); - } - - _descriptorPools[_frameIndex]->_fullAllocators.clear(); - _descriptorPools[_frameIndex]->_usableAllocators.clear(); - } - - void DescriptorAllocatorPoolVKImpl::SetPoolSizeMultiplier(VkDescriptorType type, f32 multiplier) - { - for (auto& size : _poolSizes.sizes) - { - if (size.type == type) - { - size.multiplier = multiplier; - return; - } - } - - // Not found, so add it - PoolSize newSize; - newSize.type = type; - newSize.multiplier = multiplier; - _poolSizes.sizes.push_back(newSize); - } - - void DescriptorAllocatorPoolVKImpl::ReturnAllocator(DescriptorAllocatorHandleVK& handle, bool isFull) - { - std::lock_guard lock(_poolMutex); - - if (isFull) - { - _descriptorPools[handle.poolID]->_fullAllocators.push_back(DescriptorAllocatorVK{ handle.vkPool }); - } - else - { - _descriptorPools[handle.poolID]->_usableAllocators.push_back(DescriptorAllocatorVK{ handle.vkPool }); - } - } - - DescriptorAllocatorHandleVK DescriptorAllocatorPoolVKImpl::GetAllocator() - { - std::lock_guard lock(_poolMutex); - - bool foundAllocator = false; - i32 poolIndex = _frameIndex; - - DescriptorAllocatorVK allocator; - - // Try to reuse an allocated pool - if (_clearAllocators.size() != 0) - { - allocator = _clearAllocators.back(); - _clearAllocators.pop_back(); - foundAllocator = true; - } - else - { - if (_descriptorPools[poolIndex]->_usableAllocators.size() > 0) - { - allocator = _descriptorPools[poolIndex]->_usableAllocators.back(); - _descriptorPools[poolIndex]->_usableAllocators.pop_back(); - foundAllocator = true; - } - } - - // Need a new pool - if (!foundAllocator) - { - // Static pool has to be free-able - VkDescriptorPoolCreateFlags flags = 0; - if (poolIndex == 0) - { - flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT; - } - - VkDescriptorPool newPool = CreatePool(2000, flags); - allocator.pool = newPool; - - foundAllocator = true; - } - - DescriptorAllocatorHandleVK newHandle; - newHandle.ownerPool = this; - newHandle.poolID = poolIndex; - newHandle.vkPool = allocator.pool; - - return newHandle; - } - - } -} \ No newline at end of file diff --git a/Source/Renderer/Renderer/Renderers/Vulkan/Backend/DescriptorAllocatorVK.h b/Source/Renderer/Renderer/Renderers/Vulkan/Backend/DescriptorAllocatorVK.h deleted file mode 100644 index 13760f4a..00000000 --- a/Source/Renderer/Renderer/Renderers/Vulkan/Backend/DescriptorAllocatorVK.h +++ /dev/null @@ -1,46 +0,0 @@ -#pragma once -#include - -#include - -namespace Renderer -{ - namespace Backend - { - class RenderDeviceVK; - class DescriptorAllocatorPoolVK; - - struct DescriptorAllocatorHandleVK - { - friend struct DescriptorAllocatorVK; - DescriptorAllocatorHandleVK() = default; - DescriptorAllocatorHandleVK& operator=(const DescriptorAllocatorHandleVK&) = delete; - - ~DescriptorAllocatorHandleVK(); - DescriptorAllocatorHandleVK(DescriptorAllocatorHandleVK&& other); - DescriptorAllocatorHandleVK& operator=(DescriptorAllocatorHandleVK&& other); - - // Return this handle to the pool, will make this handle orphaned - void Return(); - - // Allocate new descriptor, handle has to be valid - // Will mutate the handle if it requires a new vkDescriptorPool - bool Allocate(const VkDescriptorSetLayout& layout, VkDescriptorSet& set, void* pNext = nullptr); - - DescriptorAllocatorPoolVK* ownerPool{ nullptr }; - VkDescriptorPool vkPool; - i8 poolID; - }; - - class DescriptorAllocatorPoolVK - { - public: - static DescriptorAllocatorPoolVK* Create(RenderDeviceVK* device, i32 numFrames = 3); - - virtual void SetPoolSizeMultiplier(VkDescriptorType type, f32 multiplier) = 0; - - virtual void Flip() = 0; - virtual DescriptorAllocatorHandleVK GetAllocator() = 0; - }; - } -} \ No newline at end of file diff --git a/Source/Renderer/Renderer/Renderers/Vulkan/Backend/DescriptorHandlerVK.cpp b/Source/Renderer/Renderer/Renderers/Vulkan/Backend/DescriptorHandlerVK.cpp new file mode 100644 index 00000000..4ac8c389 --- /dev/null +++ b/Source/Renderer/Renderer/Renderers/Vulkan/Backend/DescriptorHandlerVK.cpp @@ -0,0 +1,387 @@ +#include "DescriptorHandlerVK.h" +#include "TextureHandlerVK.h" +#include "RenderDeviceVK.h" +#include "FormatConverterVK.h" + +#include +#include + +#include + +namespace Renderer +{ + namespace Backend + { + VkDescriptorPoolSize poolSizes[] = + { + { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1000 }, + { VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 40000 }, + { VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1000 }, + { VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1000 }, + { VK_DESCRIPTOR_TYPE_SAMPLER, 100 } + }; + constexpr u32 maxDescriptorSets = 128; + + struct DescriptorSet + { + DescriptorSetDesc desc; + + VkDescriptorSet sets[RenderDeviceVK::FRAME_INDEX_COUNT]; + VkDescriptorSetLayout layout; + }; + + struct DescriptorHandlerData : public IDescriptorHandlerData + { + // Pool data + VkDescriptorPool permanentPool; + //VkDescriptorPool framePools[RenderDeviceVK::FRAME_INDEX_COUNT]; // TODO + + std::vector descriptorSets; + }; + + void DescriptorHandlerVK::Init(RenderDeviceVK* device, TextureHandlerVK* textureHandler) + { + ZoneScoped; + _device = device; + _textureHandler = textureHandler; + _data = new DescriptorHandlerData(); + + CreateDescriptorPool(); + } + + DescriptorSetID DescriptorHandlerVK::CreateDescriptorSet(const DescriptorSetDesc& desc) + { + ZoneScoped; + DescriptorHandlerData& data = *static_cast(_data); + + DescriptorSetID id = DescriptorSetID(static_cast(data.descriptorSets.size())); + DescriptorSet& descriptorSet = data.descriptorSets.emplace_back(); + descriptorSet.desc = desc; + + CreateDescriptorSet(descriptorSet); + + return id; + } + + VkDescriptorSet DescriptorHandlerVK::GetVkDescriptorSet(DescriptorSetID descriptorSetID, u32 frameIndex) + { + DescriptorHandlerData& data = *static_cast(_data); + + DescriptorSetID::type id = static_cast(descriptorSetID); + if (id >= data.descriptorSets.size()) + { + NC_LOG_CRITICAL("DescriptorHandlerVK::GetVkDescriptorSet: Invalid DescriptorSetID {}", id); + } + + return data.descriptorSets[id].sets[frameIndex]; + } + + VkDescriptorSetLayout DescriptorHandlerVK::GetVkDescriptorSetLayout(DescriptorSetID descriptorSetID) + { + DescriptorHandlerData& data = *static_cast(_data); + + DescriptorSetID::type id = static_cast(descriptorSetID); + if (id >= data.descriptorSets.size()) + { + NC_LOG_CRITICAL("DescriptorHandlerVK::GetVkDescriptorSetLayout: Invalid DescriptorSetID {}", id); + } + + return data.descriptorSets[id].layout; + } + + void DescriptorHandlerVK::CreateDescriptorPool() + { + ZoneScoped; + DescriptorHandlerData& data = *static_cast(_data); + + VkDescriptorPoolCreateInfo poolInfo{ VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO }; + poolInfo.maxSets = maxDescriptorSets; + poolInfo.poolSizeCount = ARRAY_COUNT(poolSizes); + poolInfo.pPoolSizes = poolSizes; + poolInfo.flags = VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT; + + vkCreateDescriptorPool(_device->_device, &poolInfo, nullptr, &data.permanentPool); + } + + void DescriptorHandlerVK::CreateDescriptorSet(DescriptorSet& descriptorSet) + { + ZoneScoped; + DescriptorHandlerData& data = *static_cast(_data); + u32 numSupportedTextures = _device->HasExtendedTextureSupport() ? 8192 : 4096; + + // Init bindings + u32 numReflectedDescriptors = static_cast(descriptorSet.desc.reflection->descriptors.size()); + std::vector bindings; + bindings.reserve(numReflectedDescriptors); + + std::vector bindingFlags; + bindingFlags.reserve(numReflectedDescriptors); + + bool hasVariableBinding = false; + + for (auto& [_, descriptor] : descriptorSet.desc.reflection->descriptors) + { + VkDescriptorBindingFlags flags = VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT; + u32 count = descriptor.count; + + VkDescriptorType vkDescType = FormatConverterVK::ToVkDescriptorType(descriptor); + bool isTextureType = vkDescType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE || vkDescType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + bool isTextureArray = isTextureType && (count != 1); + + if (isTextureArray) + { + flags |= VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT; + + if (count == 0) + { + count = numSupportedTextures; + hasVariableBinding = true; + flags |= VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT; + } + } + + VkDescriptorSetLayoutBinding binding{}; + binding.binding = descriptor.binding; + binding.descriptorType = FormatConverterVK::ToVkDescriptorType(descriptor); + binding.descriptorCount = count; + binding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT | VK_SHADER_STAGE_COMPUTE_BIT; + binding.pImmutableSamplers = nullptr; + bindings.push_back(binding); + bindingFlags.push_back(flags); + } + + // Create layout + VkDescriptorSetLayoutBindingFlagsCreateInfo flagsInfo{ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO }; + flagsInfo.bindingCount = static_cast(bindingFlags.size()); + flagsInfo.pBindingFlags = bindingFlags.data(); + + VkDescriptorSetLayoutCreateInfo layoutInfo{ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO }; + layoutInfo.pNext = &flagsInfo; + layoutInfo.bindingCount = static_cast(bindings.size()); + layoutInfo.pBindings = bindings.data(); + layoutInfo.flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT; + + VkResult result = vkCreateDescriptorSetLayout(_device->_device, &layoutInfo, nullptr, &descriptorSet.layout); + if (result != VK_SUCCESS) + { + NC_LOG_CRITICAL("DescriptorHandlerVK::CreateDescriptorSet: Failed to create descriptor set layout!"); + } + + // Create descriptor set + VkDescriptorSetVariableDescriptorCountAllocateInfo variableCountInfo{ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO }; + variableCountInfo.descriptorSetCount = 1; + variableCountInfo.pDescriptorCounts = &numSupportedTextures; + + VkDescriptorSetAllocateInfo allocInfo{ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO }; + if (hasVariableBinding) + { + allocInfo.pNext = &variableCountInfo; + } + allocInfo.descriptorPool = data.permanentPool; + allocInfo.descriptorSetCount = 1; + allocInfo.pSetLayouts = &descriptorSet.layout; + + for (u32 i = 0; i < RenderDeviceVK::FRAME_INDEX_COUNT; i++) + { + result = vkAllocateDescriptorSets(_device->_device, &allocInfo, &descriptorSet.sets[i]); + if (result != VK_SUCCESS) + { + NC_LOG_CRITICAL("DescriptorHandlerVK::CreateDescriptorSet: Failed to allocate descriptor set! You probably need to increase maxDescriptorSets."); + } + } + } + + void DescriptorHandlerVK::BindDescriptor(DescriptorSetID setID, u32 binding, VkBuffer buffer, DescriptorType type, u32 frameIndex) + { + ZoneScoped; + VkDescriptorBufferInfo bufferInfo{}; + bufferInfo.buffer = buffer; + bufferInfo.offset = 0; + bufferInfo.range = VK_WHOLE_SIZE; + + VkWriteDescriptorSet descriptorWrite{ VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET }; + descriptorWrite.dstSet = GetVkDescriptorSet(setID, frameIndex); + descriptorWrite.dstBinding = binding; + descriptorWrite.descriptorCount = 1; + descriptorWrite.descriptorType = FormatConverterVK::ToVkDescriptorType(type); + descriptorWrite.pBufferInfo = &bufferInfo; + + vkUpdateDescriptorSets(_device->_device, 1, &descriptorWrite, 0, nullptr); + } + + void DescriptorHandlerVK::BindDescriptor(DescriptorSetID setID, u32 binding, VkImageView image, DescriptorType type, bool isRT, u32 frameIndex) + { + ZoneScoped; + VkDescriptorImageInfo imageInfo{}; + imageInfo.imageView = image; + imageInfo.imageLayout = (!isRT && type == DescriptorType::SampledImage) ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : VK_IMAGE_LAYOUT_GENERAL; + + VkWriteDescriptorSet write{ VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET }; + write.dstSet = GetVkDescriptorSet(setID, frameIndex); + write.dstBinding = binding; + write.descriptorCount = 1; + write.descriptorType = FormatConverterVK::ToVkDescriptorType(type); + write.pImageInfo = &imageInfo; + + vkUpdateDescriptorSets(_device->_device, 1, &write, 0, nullptr); + } + + void DescriptorHandlerVK::BindDescriptorArray(DescriptorSetID setID, u32 binding, VkImageView image, u32 arrayOffset, DescriptorType type, bool isRT, u32 frameIndex) + { + ZoneScoped; + VkDescriptorImageInfo imageInfo{}; + imageInfo.imageView = image; + imageInfo.imageLayout = (!isRT && type == DescriptorType::SampledImage) ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : VK_IMAGE_LAYOUT_GENERAL; + + VkWriteDescriptorSet write{ VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET }; + write.dstSet = GetVkDescriptorSet(setID, frameIndex); + write.dstBinding = binding; + write.dstArrayElement = arrayOffset; + write.descriptorCount = 1; + write.descriptorType = FormatConverterVK::ToVkDescriptorType(type); + write.pImageInfo = &imageInfo; + + vkUpdateDescriptorSets(_device->_device, 1, &write, 0, nullptr); + } + + void DescriptorHandlerVK::BindDescriptorArray(DescriptorSetID setID, u32 binding, std::vector& images, u32 arrayOffset, DescriptorType type, bool isRT, u32 frameIndex) + { + ZoneScoped; + u32 count = static_cast(images.size()); + + VkImageLayout layout = (!isRT && type == DescriptorType::SampledImage) + ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL + : VK_IMAGE_LAYOUT_GENERAL; + + std::vector imageInfos(count); + for (u32 i = 0; i < count; ++i) + { + imageInfos[i].sampler = VK_NULL_HANDLE; + imageInfos[i].imageView = images[i]; + imageInfos[i].imageLayout = layout; + } + + VkWriteDescriptorSet write{ VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET }; + write.dstSet = GetVkDescriptorSet(setID, frameIndex); + write.dstBinding = binding; + write.dstArrayElement = arrayOffset; + write.descriptorCount = count; + write.descriptorType = FormatConverterVK::ToVkDescriptorType(type); + write.pImageInfo = imageInfos.data(); + + vkUpdateDescriptorSets(_device->_device, 1, &write, 0, nullptr); + } + + void DescriptorHandlerVK::BindDescriptor(DescriptorSetID setID, u32 binding, VkSampler sampler, u32 frameIndex) + { + ZoneScoped; + VkDescriptorImageInfo samplerInfo{}; + samplerInfo.sampler = sampler; + + VkWriteDescriptorSet write{ VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET }; + write.dstSet = GetVkDescriptorSet(setID, frameIndex); + write.dstBinding = binding; + write.descriptorCount = 1; + write.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER; + write.pImageInfo = &samplerInfo; + + vkUpdateDescriptorSets(_device->_device, 1, &write, 0, nullptr); + } + + void DescriptorHandlerVK::BindDescriptorArray(DescriptorSetID setID, u32 binding, VkSampler sampler, u32 arrayIndex, u32 frameIndex) + { + ZoneScoped; + VkDescriptorImageInfo samplerInfo{}; + samplerInfo.sampler = sampler; + + VkWriteDescriptorSet write{ VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET }; + write.dstSet = GetVkDescriptorSet(setID, frameIndex); + write.dstBinding = binding; + write.dstArrayElement = arrayIndex; + write.descriptorCount = 1; + write.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER; + write.pImageInfo = &samplerInfo; + + vkUpdateDescriptorSets(_device->_device, 1, &write, 0, nullptr); + } + + void DescriptorHandlerVK::BindDescriptor(DescriptorSetID setID, u32 binding, TextureArrayID textureArrayID) + { + ZoneScoped; + // Register this binding so future texture array updates can propagate to this descriptor set + _textureHandler->RegisterTextureArrayBinding(textureArrayID, setID, binding); + + const SafeVector& textureIDs = _textureHandler->GetTextureIDsInArray(textureArrayID); + + u32 numTextures = static_cast(textureIDs.Size()); + + // Only update the descriptor if there are textures in the array + if (numTextures == 0) + { + return; + } + + std::vector imageInfos(numTextures); + + for(u32 i = 0; i < numTextures; i++) + { + TextureID textureID = textureIDs.ReadGetUnsafe(i); + VkImageView imageView = _textureHandler->GetImageView(textureID); + + imageInfos[i].imageView = imageView; + imageInfos[i].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + imageInfos[i].sampler = VK_NULL_HANDLE; + } + + std::vector writes(RenderDeviceVK::FRAME_INDEX_COUNT); + for(u32 i = 0; i < RenderDeviceVK::FRAME_INDEX_COUNT; i++) + { + VkWriteDescriptorSet& write = writes[i]; + write = { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET }; + write.dstSet = GetVkDescriptorSet(setID, i); + write.dstBinding = binding; + write.dstArrayElement = 0; + write.descriptorCount = numTextures; + write.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; + write.pImageInfo = imageInfos.data(); + } + + vkUpdateDescriptorSets(_device->_device, static_cast(writes.size()), writes.data(), 0, nullptr); + } + + void DescriptorHandlerVK::UpdateTextureArrayDescriptors(DescriptorSetID setID, u32 binding, const TextureID* textureIDs, u32 startIndex, u32 count) + { + ZoneScoped; + if (count == 0) + { + return; + } + + std::vector imageInfos(count); + + for (u32 i = 0; i < count; i++) + { + VkImageView imageView = _textureHandler->GetImageView(textureIDs[i]); + + imageInfos[i].imageView = imageView; + imageInfos[i].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + imageInfos[i].sampler = VK_NULL_HANDLE; + } + + std::vector writes(RenderDeviceVK::FRAME_INDEX_COUNT); + for (u32 i = 0; i < RenderDeviceVK::FRAME_INDEX_COUNT; i++) + { + VkWriteDescriptorSet& write = writes[i]; + write = { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET }; + write.dstSet = GetVkDescriptorSet(setID, i); + write.dstBinding = binding; + write.dstArrayElement = startIndex; + write.descriptorCount = count; + write.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; + write.pImageInfo = imageInfos.data(); + } + + vkUpdateDescriptorSets(_device->_device, static_cast(writes.size()), writes.data(), 0, nullptr); + } + } +} \ No newline at end of file diff --git a/Source/Renderer/Renderer/Renderers/Vulkan/Backend/DescriptorHandlerVK.h b/Source/Renderer/Renderer/Renderers/Vulkan/Backend/DescriptorHandlerVK.h new file mode 100644 index 00000000..bc956580 --- /dev/null +++ b/Source/Renderer/Renderer/Renderers/Vulkan/Backend/DescriptorHandlerVK.h @@ -0,0 +1,55 @@ +#pragma once +#include "Renderer/Descriptors/DescriptorSetDesc.h" +#include "Renderer/Descriptors/TextureDesc.h" +#include "Renderer/Descriptors/TextureArrayDesc.h" +#include "Renderer/DescriptorType.h" + +#include +#include + +#include + +namespace Renderer +{ + namespace Backend + { + class RenderDeviceVK; + class TextureHandlerVK; + struct DescriptorSet; + + struct IDescriptorHandlerData {}; + + class DescriptorHandlerVK + { + public: + void Init(RenderDeviceVK* device, TextureHandlerVK* textureHandler); + + DescriptorSetID CreateDescriptorSet(const DescriptorSetDesc& desc); + + void BindDescriptor(DescriptorSetID setID, u32 binding, VkBuffer buffer, DescriptorType type, u32 frameIndex); + void BindDescriptor(DescriptorSetID setID, u32 binding, VkImageView image, DescriptorType type, bool isRT, u32 frameIndex); + void BindDescriptorArray(DescriptorSetID setID, u32 binding, VkImageView image, u32 arrayOffset, DescriptorType type, bool isRT, u32 frameIndex); + void BindDescriptorArray(DescriptorSetID setID, u32 binding, std::vector& images, u32 arrayOffset, DescriptorType type, bool isRT, u32 frameIndex); + void BindDescriptor(DescriptorSetID setID, u32 binding, VkSampler sampler, u32 frameIndex); + void BindDescriptorArray(DescriptorSetID setID, u32 binding, VkSampler sampler, u32 arrayIndex, u32 frameIndex); + void BindDescriptor(DescriptorSetID setID, u32 binding, TextureArrayID textureArrayID); // Texture arrays don't take a frameIndex for simplicity, we don't expect them to change per-frame + + // Updates only a range of descriptors in a texture array binding (for incremental updates) + void UpdateTextureArrayDescriptors(DescriptorSetID setID, u32 binding, const TextureID* textureIDs, u32 startIndex, u32 count); + + VkDescriptorSet GetVkDescriptorSet(DescriptorSetID descriptorSetID, u32 frameIndex); + VkDescriptorSetLayout GetVkDescriptorSetLayout(DescriptorSetID descriptorSetID); + + private: + void CreateDescriptorPool(); + + void CreateDescriptorSet(DescriptorSet& descriptorSet); + + private: + RenderDeviceVK* _device; + TextureHandlerVK* _textureHandler; + + IDescriptorHandlerData* _data; + }; + } +} \ No newline at end of file diff --git a/Source/Renderer/Renderer/Renderers/Vulkan/Backend/DescriptorSetBuilderVK.cpp b/Source/Renderer/Renderer/Renderers/Vulkan/Backend/DescriptorSetBuilderVK.cpp deleted file mode 100644 index d5e42879..00000000 --- a/Source/Renderer/Renderer/Renderers/Vulkan/Backend/DescriptorSetBuilderVK.cpp +++ /dev/null @@ -1,763 +0,0 @@ -#include "DescriptorSetBuilderVK.h" -#include "BufferHandlerVK.h" -#include "PipelineHandlerVK.h" -#include "RenderDeviceVK.h" -#include "ShaderHandlerVK.h" -#include "Renderer/RenderSettings.h" -#include "Renderer/TrackedBufferBitSets.h" - -#include -#include - -#include -#include - -namespace Renderer -{ - namespace Backend - { - DescriptorSetBuilderVK::DescriptorSetBuilderVK(Memory::Allocator* allocator, GraphicsPipelineID pipelineID, PipelineHandlerVK* pipelineHandler, ShaderHandlerVK* shaderHandler, BufferHandlerVK* bufferHandler, DescriptorMegaPoolVK* parentPool) - : _allocator(allocator) - { - _pipelineType = PipelineType::Graphics; - _pipelineHandler = pipelineHandler; - _shaderHandler = shaderHandler; - _bufferHandler = bufferHandler; - _parentPool = parentPool; - _graphicsPipelineID = pipelineID; - } - - DescriptorSetBuilderVK::DescriptorSetBuilderVK(Memory::Allocator* allocator, ComputePipelineID pipelineID, PipelineHandlerVK* pipelineHandler, ShaderHandlerVK* shaderHandler, BufferHandlerVK* bufferHandler, DescriptorMegaPoolVK* parentPool) - : _allocator(allocator) - { - _pipelineType = PipelineType::Compute; - _pipelineHandler = pipelineHandler; - _shaderHandler = shaderHandler; - _bufferHandler = bufferHandler; - _parentPool = parentPool; - _computePipelineID = pipelineID; - } - - void DescriptorSetBuilderVK::InitReflectData() - { - ZoneScoped; - - if (_pipelineType == PipelineType::Graphics) - { - // Graphics pipeline - GraphicsPipelineDesc desc = _pipelineHandler->GetDescriptor(_graphicsPipelineID); - - if (desc.states.vertexShader != VertexShaderID::Invalid()) - { - const Backend::BindReflection& bindReflection = _shaderHandler->GetBindReflection(desc.states.vertexShader); - _bindInfos.insert(_bindInfos.end(), bindReflection.dataBindings.begin(), bindReflection.dataBindings.end()); - } - if (desc.states.pixelShader != PixelShaderID::Invalid()) - { - const BindReflection& bindReflection = _shaderHandler->GetBindReflection(desc.states.pixelShader); - - // Loop over all new databindings - for (const BindInfo& dataBinding : bindReflection.dataBindings) - { - bool found = false; - // Loop over our current databindings - for (BindInfo& bindInfo : _bindInfos) - { - // If they occupy the same descriptor space - if (dataBinding.set == bindInfo.set && - dataBinding.binding == bindInfo.binding) - { - // If the name, descriptorType and count matches as well we assume it matches and is fine - if (dataBinding.nameHash == bindInfo.nameHash && - dataBinding.descriptorType == bindInfo.descriptorType && - dataBinding.count == bindInfo.count) - { - // Just add our stageflags to it - bindInfo.stageFlags |= dataBinding.stageFlags; - } - else - { - // Else somethings is really bad, lets fatal log - NC_LOG_CRITICAL("Vertex Shader and Pixel Shader tries to use the same descriptor set and binding, but they don't seem to match"); - } - found = true; - break; - } - } - - // If we didn't find a match, add it to our bindInfos - if (!found) - { - _bindInfos.push_back(dataBinding); - } - } - } - } - else - { - // Compute pipeline - ComputePipelineDesc desc = _pipelineHandler->GetDescriptor(_computePipelineID); - - const Backend::BindReflection& bindReflection = _shaderHandler->GetBindReflection(desc.computeShader); - _bindInfos.insert(_bindInfos.end(), bindReflection.dataBindings.begin(), bindReflection.dataBindings.end()); - } - - for(u32 i = 0; i < _bindInfos.size(); i++) - { - _hashedNameToBindInfoIndex.insert_or_assign(_bindInfos[i].nameHash, i); - } - - } - - void DescriptorSetBuilderVK::SetBufferPermissions(const TrackedBufferBitSets* bufferPermissions) - { - ZoneScoped; - - _bufferPermissions = bufferPermissions; - - u32 numBitSets = _bufferPermissions->GetNumBufferSets(); - _bufferReadAccesses = Memory::Allocator::New(_allocator, _allocator, numBitSets); - _bufferWriteAccesses = Memory::Allocator::New(_allocator, _allocator, numBitSets); - _bufferAccesses = Memory::Allocator::New(_allocator, _allocator, numBitSets); - } - - void DescriptorSetBuilderVK::BindSampler(i32 set, i32 binding, VkDescriptorImageInfo& imageInfo) - { - ZoneScoped; - - for (auto& imageWrite : _imageWrites) - { - if (imageWrite.dstBinding == binding && imageWrite.dstSet == set) - { - imageWrite.imageInfo = imageInfo; - return; - } - } - - ImageWriteDescriptor newWrite; - newWrite.dstSet = set; - newWrite.dstBinding = binding; - newWrite.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER; - newWrite.imageInfo = imageInfo; - - _imageWrites.push_back(newWrite); - } - - void DescriptorSetBuilderVK::BindSampler(u32 nameHash, VkDescriptorImageInfo& imageInfo) - { - ZoneScoped; - - NC_ASSERT(imageInfo.sampler != nullptr, "DescriptorSetBuilderVK : BindSampler was passed an imageInfo with a nullptr sampler"); - - if (!_hashedNameToBindInfoIndex.contains(nameHash)) - return; - - u32 bindInfoIndex = _hashedNameToBindInfoIndex[nameHash]; - BindInfo& bindInfo = _bindInfos[bindInfoIndex]; - - BindSampler(bindInfo.set, bindInfo.binding, imageInfo); - } - - void DescriptorSetBuilderVK::BindSamplerArrayIndex(i32 set, i32 binding, u32 arrayIndex, VkDescriptorImageInfo& imageInfo) - { - ZoneScoped; - - for (auto& imageWrite : _imageWrites) - { - if (imageWrite.dstBinding == binding && imageWrite.dstSet == set && imageWrite.dstArrayIndex == arrayIndex) - { - imageWrite.imageInfo = imageInfo; - return; - } - } - - ImageWriteDescriptor newWrite; - newWrite.dstSet = set; - newWrite.dstBinding = binding; - newWrite.dstArrayIndex = arrayIndex; - newWrite.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER; - newWrite.imageInfo = imageInfo; - - _imageWrites.push_back(newWrite); - } - - void DescriptorSetBuilderVK::BindSamplerArrayIndex(u32 nameHash, VkDescriptorImageInfo& imageInfo, u32 arrayIndex) - { - ZoneScoped; - - if (!_hashedNameToBindInfoIndex.contains(nameHash)) - return; - - u32 bindInfoIndex = _hashedNameToBindInfoIndex[nameHash]; - BindInfo& bindInfo = _bindInfos[bindInfoIndex]; - - BindSamplerArrayIndex(bindInfo.set, bindInfo.binding, arrayIndex, imageInfo); - } - - void DescriptorSetBuilderVK::BindImage(i32 set, i32 binding, const VkDescriptorImageInfo& imageInfo, bool imageWrite) - { - ZoneScoped; - - for (auto& imageWrite : _imageWrites) - { - if (imageWrite.dstBinding == binding && imageWrite.dstSet == set) - { - imageWrite.imageInfo = imageInfo; - return; - } - } - - ImageWriteDescriptor newWrite; - newWrite.dstSet = set; - newWrite.dstBinding = binding; - newWrite.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; - newWrite.imageInfo = imageInfo; - if (imageWrite) - { - newWrite.imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - } - - _imageWrites.push_back(newWrite); - } - - void DescriptorSetBuilderVK::BindImage(u32 nameHash, const VkDescriptorImageInfo& imageInfo) - { - ZoneScoped; - - if (!_hashedNameToBindInfoIndex.contains(nameHash)) - return; - - u32 bindInfoIndex = _hashedNameToBindInfoIndex[nameHash]; - BindInfo& bindInfo = _bindInfos[bindInfoIndex]; - - BindImage(bindInfo.set, bindInfo.binding, imageInfo); - } - - void DescriptorSetBuilderVK::BindImageArray(i32 set, i32 binding, VkDescriptorImageInfo* images, i32 count) - { - ZoneScoped; - - for (auto& imageWrite : _imageWrites) - { - if (imageWrite.dstBinding == binding && imageWrite.dstSet == set) - { - imageWrite.imageArray = images; - imageWrite.imageCount = count; - return; - } - } - - ImageWriteDescriptor newWrite; - newWrite.dstSet = set; - newWrite.dstBinding = binding; - newWrite.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; - newWrite.imageArray = images; - newWrite.imageCount = count; - - _imageWrites.push_back(newWrite); - } - - void DescriptorSetBuilderVK::BindImageArray(u32 nameHash, VkDescriptorImageInfo* images, i32 count) - { - ZoneScoped; - - if (!_hashedNameToBindInfoIndex.contains(nameHash)) - return; - - u32 bindInfoIndex = _hashedNameToBindInfoIndex[nameHash]; - BindInfo& bindInfo = _bindInfos[bindInfoIndex]; - - BindImageArray(bindInfo.set, bindInfo.binding, images, count); - } - - void DescriptorSetBuilderVK::BindImageArrayIndex(i32 set, i32 binding, u32 arrayIndex, const VkDescriptorImageInfo& imageInfo, bool imageWrite) - { - ZoneScoped; - - for (auto& imageWrite : _imageWrites) - { - if (imageWrite.dstBinding == binding && imageWrite.dstSet == set && imageWrite.dstArrayIndex == arrayIndex) - { - imageWrite.imageInfo = imageInfo; - return; - } - } - - ImageWriteDescriptor newWrite; - newWrite.dstSet = set; - newWrite.dstBinding = binding; - newWrite.dstArrayIndex = arrayIndex; - newWrite.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; - newWrite.imageInfo = imageInfo; - if (imageWrite) - { - newWrite.imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - } - - _imageWrites.push_back(newWrite); - } - - void DescriptorSetBuilderVK::BindImageArrayIndex(u32 nameHash, const VkDescriptorImageInfo& imageInfo, u32 arrayIndex) - { - ZoneScoped; - - if (!_hashedNameToBindInfoIndex.contains(nameHash)) - return; - - u32 bindInfoIndex = _hashedNameToBindInfoIndex[nameHash]; - BindInfo& bindInfo = _bindInfos[bindInfoIndex]; - - BindImageArrayIndex(bindInfo.set, bindInfo.binding, arrayIndex, imageInfo); - } - - void DescriptorSetBuilderVK::BindStorageImage(i32 set, i32 binding, VkDescriptorImageInfo* imageInfos, i32 count) - { - ZoneScoped; - - ImageWriteDescriptor newWrite; - newWrite.dstSet = set; - newWrite.dstBinding = binding; - newWrite.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; - - if (count == 1) - { - for (auto& imageWrite : _imageWrites) - { - if (imageWrite.dstBinding == binding && imageWrite.dstSet == set) - { - imageWrite.imageInfo = imageInfos[0]; - return; - } - } - - newWrite.imageInfo = imageInfos[0]; - } - else - { - for (auto& imageWrite : _imageWrites) - { - if (imageWrite.dstBinding == binding && imageWrite.dstSet == set) - { - imageWrite.imageArray = imageInfos; - newWrite.imageCount = count; - return; - } - } - - newWrite.imageArray = imageInfos; - newWrite.imageCount = count; - } - - _imageWrites.push_back(newWrite); - } - - void DescriptorSetBuilderVK::BindStorageImage(u32 nameHash, VkDescriptorImageInfo* imageInfos, i32 count) - { - ZoneScoped; - - if (!_hashedNameToBindInfoIndex.contains(nameHash)) - return; - - u32 bindInfoIndex = _hashedNameToBindInfoIndex[nameHash]; - BindInfo& bindInfo = _bindInfos[bindInfoIndex]; - - BindStorageImage(bindInfo.set, bindInfo.binding, imageInfos, count); - } - - void DescriptorSetBuilderVK::BindStorageImageArray(u32 nameHash, VkDescriptorImageInfo* imageInfos, i32 count) - { - ZoneScoped; - - if (!_hashedNameToBindInfoIndex.contains(nameHash)) - return; - - u32 bindInfoIndex = _hashedNameToBindInfoIndex[nameHash]; - BindInfo& bindInfo = _bindInfos[bindInfoIndex]; - - BindStorageImageArray(bindInfo.set, bindInfo.binding, imageInfos, count); - } - - void DescriptorSetBuilderVK::BindStorageImageArray(i32 set, i32 binding, VkDescriptorImageInfo* imageInfos, i32 count) - { - ZoneScoped; - - for (auto& imageWrite : _imageWrites) - { - if (imageWrite.dstBinding == binding && imageWrite.dstSet == set) - { - imageWrite.imageArray = imageInfos; - imageWrite.imageCount = count; - return; - } - } - - ImageWriteDescriptor newWrite; - newWrite.dstSet = set; - newWrite.dstBinding = binding; - newWrite.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; - newWrite.imageArray = imageInfos; - newWrite.imageCount = count; - - _imageWrites.push_back(newWrite); - } - - void DescriptorSetBuilderVK::BindBuffer(i32 set, i32 binding, const VkDescriptorBufferInfo& bufferInfo, VkDescriptorType bufferType) - { - ZoneScoped; - - for (auto& bufferWrite : _bufferWrites) - { - if (bufferWrite.dstBinding == binding && bufferWrite.dstSet == set) - { - bufferWrite.bufferInfo = bufferInfo; - bufferWrite.descriptorType = bufferType; - return; - } - } - - BufferWriteDescriptor newWrite; - newWrite.dstSet = set; - newWrite.dstBinding = binding; - newWrite.descriptorType = bufferType; - newWrite.bufferInfo = bufferInfo; - - _bufferWrites.push_back(newWrite); - } - - void DescriptorSetBuilderVK::BindBuffer(u32 nameHash, const VkDescriptorBufferInfo& bufferInfo, BufferID bufferID) - { - ZoneScoped; - - if (!_hashedNameToBindInfoIndex.contains(nameHash)) - return; - - u32 bindInfoIndex = _hashedNameToBindInfoIndex[nameHash]; - BindInfo& bindInfo = _bindInfos[bindInfoIndex]; - - BindBuffer(bindInfo.set, bindInfo.binding, bufferInfo, bindInfo.descriptorType); - - BufferID::type bufferIndex = static_cast(bufferID); - - _bufferAccesses->Set(bufferIndex); - if (bindInfo.isWrite) - { - _bufferWriteAccesses->Set(bufferIndex); - } - else - { - _bufferReadAccesses->Set(bufferIndex); - } - - _bufferIndexToBindInfoIndex[bufferIndex] = bindInfoIndex; - } - - void DescriptorSetBuilderVK::BindBufferArrayIndex(i32 set, i32 binding, u32 arrayIndex, const VkDescriptorBufferInfo& bufferInfo, VkDescriptorType bufferType) - { - ZoneScoped; - - for (auto& bufferWrite : _bufferWrites) - { - if (bufferWrite.dstBinding == binding && bufferWrite.dstSet == set && bufferWrite.dstArrayIndex == arrayIndex) - { - bufferWrite.bufferInfo = bufferInfo; - bufferWrite.descriptorType = bufferType; - return; - } - } - - BufferWriteDescriptor newWrite; - newWrite.dstSet = set; - newWrite.dstBinding = binding; - newWrite.dstArrayIndex = arrayIndex; - newWrite.descriptorType = bufferType; - newWrite.bufferInfo = bufferInfo; - - _bufferWrites.push_back(newWrite); - } - - void DescriptorSetBuilderVK::BindBufferArrayIndex(u32 nameHash, const VkDescriptorBufferInfo& bufferInfo, u32 arrayIndex, BufferID bufferID) - { - ZoneScoped; - - if (!_hashedNameToBindInfoIndex.contains(nameHash)) - return; - - u32 bindInfoIndex = _hashedNameToBindInfoIndex[nameHash]; - BindInfo& bindInfo = _bindInfos[bindInfoIndex]; - - BindBufferArrayIndex(bindInfo.set, bindInfo.binding, arrayIndex, bufferInfo, bindInfo.descriptorType); - - BufferID::type bufferIndex = static_cast(bufferID); - - _bufferAccesses->Set(bufferIndex); - if (bindInfo.isWrite) - { - _bufferWriteAccesses->Set(bufferIndex); - } - else - { - _bufferReadAccesses->Set(bufferIndex); - } - - _bufferIndexToBindInfoIndex[bufferIndex] = bindInfoIndex; - } - - void DescriptorSetBuilderVK::BindRayStructure(i32 set, i32 binding, const VkWriteDescriptorSetAccelerationStructureKHR& info) - { - ZoneScoped; - - for (auto& bufferWrite : _bufferWrites) - { - if (bufferWrite.dstBinding == binding && bufferWrite.dstSet == set) - { - bufferWrite.accelinfo = info; - return; - } - } - - BufferWriteDescriptor newWrite; - newWrite.dstSet = set; - newWrite.dstBinding = binding; - newWrite.descriptorType = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR; - newWrite.accelinfo = info; - - _bufferWrites.push_back(newWrite); - } - - void DescriptorSetBuilderVK::BindRayStructure(u32 nameHash, const VkWriteDescriptorSetAccelerationStructureKHR& info) - { - ZoneScoped; - - if (!_hashedNameToBindInfoIndex.contains(nameHash)) - return; - - u32 bindInfoIndex = _hashedNameToBindInfoIndex[nameHash]; - BindInfo& bindInfo = _bindInfos[bindInfoIndex]; - - BindRayStructure(bindInfo.set, bindInfo.binding, info); - } - - void DescriptorSetBuilderVK::UpdateDescriptorSet(i32 set, VkDescriptorSet& descriptor, RenderDeviceVK& device) - { - ZoneScoped; - - std::vector descriptorWrites; - descriptorWrites.reserve(20); - - for (ImageWriteDescriptor& imageWrite : _imageWrites) - { - if (imageWrite.dstSet == set) - { - VkWriteDescriptorSet newWrite = {}; - newWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - newWrite.pNext = nullptr; - - newWrite.dstBinding = imageWrite.dstBinding; - newWrite.dstSet = descriptor; - newWrite.descriptorCount = 1; - newWrite.descriptorType = imageWrite.descriptorType; - newWrite.pImageInfo = &imageWrite.imageInfo; - - //special case for the image arrays - if (imageWrite.imageArray != nullptr) - { - newWrite.descriptorCount = imageWrite.imageCount; - newWrite.pImageInfo = imageWrite.imageArray; - } - // special case for image arrays that only write to individual indices - if (imageWrite.dstArrayIndex != -1) - { - newWrite.dstArrayElement = imageWrite.dstArrayIndex; - } - - descriptorWrites.push_back(newWrite); - } - } - - for (BufferWriteDescriptor& bufferWrite : _bufferWrites) - { - if (bufferWrite.dstSet == set) - { - VkWriteDescriptorSet newWrite = {}; - newWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - newWrite.pNext = nullptr; - - newWrite.dstBinding = bufferWrite.dstBinding; - newWrite.dstSet = descriptor; - newWrite.descriptorCount = 1; - newWrite.descriptorType = bufferWrite.descriptorType; - newWrite.pBufferInfo = &bufferWrite.bufferInfo; - - if (bufferWrite.descriptorType == VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR) - { - newWrite.pBufferInfo = nullptr; - newWrite.pNext = &bufferWrite.accelinfo; - } - if (bufferWrite.dstArrayIndex != -1) - { - newWrite.dstArrayElement = bufferWrite.dstArrayIndex; - } - - descriptorWrites.push_back(newWrite); - } - } - - vkUpdateDescriptorSets(device._device, static_cast(descriptorWrites.size()), descriptorWrites.data(), 0, nullptr); - } - - VkDescriptorSet DescriptorSetBuilderVK::BuildDescriptorSet(i32 set, DescriptorLifetime lifetime) - { - ZoneScoped; - - VkDescriptorSetLayout* layout; - if (_pipelineType == PipelineType::Graphics) - { - layout = &_pipelineHandler->GetDescriptorSetLayout(_graphicsPipelineID, set); - } - else - { - layout = &_pipelineHandler->GetDescriptorSetLayout(_computePipelineID, set); - } - - void* next = nullptr; - u32 counts[1]; - counts[0] = Settings::MAX_TEXTURES; - - VkDescriptorSetVariableDescriptorCountAllocateInfo setCounts = {}; - setCounts.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO; - setCounts.pNext = nullptr; - setCounts.descriptorSetCount = 1; - setCounts.pDescriptorCounts = counts; - - for (const ImageWriteDescriptor& imageWrite : _imageWrites) - { - if (imageWrite.descriptorType != VK_DESCRIPTOR_TYPE_STORAGE_IMAGE && imageWrite.imageArray != nullptr && imageWrite.dstSet == set) - { - counts[0] = imageWrite.imageCount; - next = &setCounts; - } - } - - if (_bufferPermissions) - { - ValidateAccesses(); - } - - VkDescriptorSet newSet = _parentPool->AllocateDescriptor(*layout, lifetime, next); - UpdateDescriptorSet(set, newSet, *_parentPool->_device); - return newSet; - } - - void DescriptorSetBuilderVK::ValidateAccesses() - { - ZoneScoped; - - bool didError = false; - - const BitSet& readPermissions = _bufferPermissions->GetReadBitSet(); - if (!_bufferReadAccesses->IsSubsetOf(readPermissions)) - { - NC_LOG_INFO("\n\n--- READS ---"); - - BitSet* subtracted = _bufferReadAccesses->NewBitwiseUnset(readPermissions); - - subtracted->ForEachSetBit([&](u32 set, u32 bit) - { - u32 bufferIndex = set * 64 + bit; - BufferID bufferID = BufferID(bufferIndex); - - const std::string& bufferName = _bufferHandler->GetBufferName(bufferID); - - u32 bindInfoIndex = _bufferIndexToBindInfoIndex[bufferIndex]; - BindInfo& bindInfo = _bindInfos[bindInfoIndex]; - - NC_LOG_ERROR("DescriptorSetBuilderVK : Tried to read from BufferID {} (Buffer Name: {}, Binding Name: {}), but RenderPass does not have READ access for that", bufferIndex, bufferName, bindInfo.name); - didError = true; - }); - } - - const BitSet& writePermissions = _bufferPermissions->GetWriteBitSet(); - if (!_bufferWriteAccesses->IsSubsetOf(writePermissions)) - { - NC_LOG_INFO("\n\n--- WRITES ---"); - - BitSet* subtracted = _bufferWriteAccesses->NewBitwiseUnset(writePermissions); - - subtracted->ForEachSetBit([&](u32 set, u32 bit) - { - u32 bufferIndex = set * 64 + bit; - BufferID bufferID = BufferID(bufferIndex); - - const std::string& bufferName = _bufferHandler->GetBufferName(bufferID); - - u32 bindInfoIndex = _bufferIndexToBindInfoIndex[bufferIndex]; - BindInfo& bindInfo = _bindInfos[bindInfoIndex]; - - NC_LOG_ERROR("DescriptorSetBuilderVK : Tried to write to BufferID {} (Buffer Name: {}, Binding Name: {}), but RenderPass does not have WRITE access for that", bufferIndex, bufferName, bindInfo.name); - didError = true; - }); - } - - bool isGraphics = _pipelineType == PipelineType::Graphics; - const BitSet& shaderStagePermissions = (isGraphics) ? _bufferPermissions->GetGraphicsBitSet() : _bufferPermissions->GetComputeBitSet(); - if (!_bufferAccesses->IsSubsetOf(shaderStagePermissions)) - { - std::string stageName = (isGraphics) ? "GRAPHICS" : "COMPUTE"; - NC_LOG_INFO("\n\n--- {} ---", stageName); - - BitSet* subtracted = _bufferAccesses->NewBitwiseUnset(shaderStagePermissions); - - subtracted->ForEachSetBit([&](u32 set, u32 bit) - { - u32 bufferIndex = set * 64 + bit; - BufferID bufferID = BufferID(bufferIndex); - - const std::string& bufferName = _bufferHandler->GetBufferName(bufferID); - - u32 bindInfoIndex = _bufferIndexToBindInfoIndex[bufferIndex]; - BindInfo& bindInfo = _bindInfos[bindInfoIndex]; - - NC_LOG_ERROR("DescriptorSetBuilderVK : Tried to use BufferID {} (Buffer Name: {}, Binding Name: {}) in a {} pipeline, but RenderPass does not have access for that", bufferIndex, bufferName, bindInfo.name, stageName); - didError = true; - }); - } - - if (didError) - { - NC_LOG_CRITICAL("DescriptorSetBuilderVK : ValidateAccesses failed to validate the RenderPass"); - } - } - - VkDescriptorSet DescriptorMegaPoolVK::AllocateDescriptor(VkDescriptorSetLayout layout, DescriptorLifetime lifetime, void* next) - { - if (lifetime == DescriptorLifetime::Static) - { - VkDescriptorSet set; - _staticHandle.Allocate(layout, set, next); - return set; - } - else - { - VkDescriptorSet set; - _dynamicHandle.Allocate(layout, set, next); - return set; - } - } - - void DescriptorMegaPoolVK::Init(i32 numFrames, RenderDeviceVK* device) - { - _device = device; - - _dynamicAllocatorPool = DescriptorAllocatorPoolVK::Create(device, numFrames); - _staticAllocatorPool = DescriptorAllocatorPoolVK::Create(device, 1); - _dynamicHandle = _dynamicAllocatorPool->GetAllocator(); - _staticHandle = _staticAllocatorPool->GetAllocator(); - } - - void DescriptorMegaPoolVK::SetFrame(i32 frameNumber) - { - _dynamicAllocatorPool->Flip(); - _dynamicHandle = _dynamicAllocatorPool->GetAllocator(); - } - } -} \ No newline at end of file diff --git a/Source/Renderer/Renderer/Renderers/Vulkan/Backend/DescriptorSetBuilderVK.h b/Source/Renderer/Renderer/Renderers/Vulkan/Backend/DescriptorSetBuilderVK.h deleted file mode 100644 index decdfe71..00000000 --- a/Source/Renderer/Renderer/Renderers/Vulkan/Backend/DescriptorSetBuilderVK.h +++ /dev/null @@ -1,163 +0,0 @@ -#pragma once -#include "DescriptorAllocatorVK.h" -#include "ShaderHandlerVK.h" -#include "Renderer/Descriptors/GraphicsPipelineDesc.h" -#include "Renderer/Descriptors/ComputePipelineDesc.h" -#include "Renderer/Descriptors/BufferDesc.h" - -#include - -#include -#include - -#include - -namespace Memory -{ - class Allocator; -} - -class BitSet; - -namespace Renderer -{ - class TrackedBufferBitSets; - - namespace Backend - { - class RenderDeviceVK; - class PipelineHandlerVK; - class ShaderHandlerVK; - class BufferHandlerVK; - - enum class DescriptorLifetime - { - Static, - PerFrame - }; - - struct DescriptorMegaPoolVK; - - class DescriptorSetBuilderVK - { - public: - DescriptorSetBuilderVK(::Memory::Allocator* allocator, GraphicsPipelineID pipelineID, PipelineHandlerVK* pipelineHandler, ShaderHandlerVK* shaderHandler, BufferHandlerVK* bufferHandler, DescriptorMegaPoolVK* parentPool); - DescriptorSetBuilderVK(::Memory::Allocator* allocator, ComputePipelineID pipelineID, PipelineHandlerVK* pipelineHandler, ShaderHandlerVK* shaderHandler, BufferHandlerVK* bufferHandler, DescriptorMegaPoolVK* parentPool); - - void InitReflectData(); - void SetBufferPermissions(const TrackedBufferBitSets* bufferPermissions); - - void BindSampler(i32 set, i32 binding, VkDescriptorImageInfo& imageInfo); - void BindSampler(u32 nameHash, VkDescriptorImageInfo& imageInfo); - - void BindSamplerArrayIndex(i32 set, i32 binding, u32 arrayIndex, VkDescriptorImageInfo& imageInfo); - void BindSamplerArrayIndex(u32 nameHash, VkDescriptorImageInfo& imageInfo, u32 arrayIndex); - - void BindImage(i32 set, i32 binding, const VkDescriptorImageInfo& imageInfo, bool imageWrite = false); - void BindImage(u32 nameHash, const VkDescriptorImageInfo& imageInfo); - - void BindImageArray(i32 set, i32 binding, VkDescriptorImageInfo* images, i32 count); - void BindImageArray(u32 nameHash, VkDescriptorImageInfo* images, i32 count); - - void BindImageArrayIndex(i32 set, i32 binding, u32 arrayIndex, const VkDescriptorImageInfo& imageInfo, bool imageWrite = false); - void BindImageArrayIndex(u32 nameHash, const VkDescriptorImageInfo& imageInfo, u32 arrayIndex); - - void BindStorageImage(i32 set, i32 binding, VkDescriptorImageInfo* imageInfos, i32 count); - void BindStorageImage(u32 nameHash, VkDescriptorImageInfo* imageInfos, i32 count); - - void BindStorageImageArray(i32 set, i32 binding, VkDescriptorImageInfo* imageInfos, i32 count); - void BindStorageImageArray(u32 nameHash, VkDescriptorImageInfo* imageInfos, i32 count); - - void BindBuffer(i32 set, i32 binding, const VkDescriptorBufferInfo& bufferInfo, VkDescriptorType bufferType); - void BindBuffer(u32 nameHash, const VkDescriptorBufferInfo& bufferInfo, BufferID bufferID); - - void BindBufferArrayIndex(i32 set, i32 binding, u32 arrayIndex, const VkDescriptorBufferInfo& bufferInfo, VkDescriptorType bufferType); - void BindBufferArrayIndex(u32 nameHash, const VkDescriptorBufferInfo& bufferInfo, u32 arrayIndex, BufferID bufferID); - - void BindRayStructure(i32 set, i32 binding, const VkWriteDescriptorSetAccelerationStructureKHR& info); - void BindRayStructure(u32 nameHash, const VkWriteDescriptorSetAccelerationStructureKHR& info); - - void UpdateDescriptorSet(i32 set, VkDescriptorSet& descriptor, RenderDeviceVK& device); - VkDescriptorSet BuildDescriptorSet(i32 set, DescriptorLifetime lifetime); - - private: - void ValidateAccesses(); - - private: - enum class PipelineType - { - Graphics, - Compute, - }; - - struct ImageWriteDescriptor - { - int dstSet; - int dstBinding; - int dstArrayIndex = -1; - VkDescriptorType descriptorType; - VkDescriptorImageInfo imageInfo; - VkDescriptorImageInfo* imageArray{ nullptr }; - int imageCount; - }; - - struct BufferWriteDescriptor - { - int dstSet; - int dstBinding; - int dstArrayIndex = -1; - VkDescriptorType descriptorType; - VkDescriptorBufferInfo bufferInfo; - VkWriteDescriptorSetAccelerationStructureKHR accelinfo; - }; - - private: - ::Memory::Allocator* _allocator; - - PipelineHandlerVK* _pipelineHandler; - ShaderHandlerVK* _shaderHandler; - BufferHandlerVK* _bufferHandler; - DescriptorMegaPoolVK* _parentPool; - - PipelineType _pipelineType; - - GraphicsPipelineID _graphicsPipelineID; - ComputePipelineID _computePipelineID; - - std::vector _bindInfos; - robin_hood::unordered_map _hashedNameToBindInfoIndex; - robin_hood::unordered_map _bufferIndexToBindInfoIndex; - - std::vector _imageWrites; - std::vector _bufferWrites; - - const TrackedBufferBitSets* _bufferPermissions = nullptr; - BitSet* _bufferAccesses = nullptr; - BitSet* _bufferReadAccesses = nullptr; - BitSet* _bufferWriteAccesses = nullptr; - }; - - struct DescriptorAllocator - { - i32 maxDescriptors; - i32 current_descriptors; - VkDescriptorPool pool; - }; - - struct DescriptorMegaPoolVK - { - VkDescriptorSet AllocateDescriptor(VkDescriptorSetLayout layout, DescriptorLifetime lifetime, void* next = nullptr); - - void Init(i32 numFrames, RenderDeviceVK* device); - void SetFrame(i32 frameNumber); - - DescriptorAllocatorHandleVK _dynamicHandle; - DescriptorAllocatorHandleVK _staticHandle; - - DescriptorAllocatorPoolVK* _dynamicAllocatorPool; - DescriptorAllocatorPoolVK* _staticAllocatorPool; - - RenderDeviceVK* _device; - }; - } -} \ No newline at end of file diff --git a/Source/Renderer/Renderer/Renderers/Vulkan/Backend/FormatConverterVK.cpp b/Source/Renderer/Renderer/Renderers/Vulkan/Backend/FormatConverterVK.cpp index 55cb4383..de568331 100644 --- a/Source/Renderer/Renderer/Renderers/Vulkan/Backend/FormatConverterVK.cpp +++ b/Source/Renderer/Renderer/Renderers/Vulkan/Backend/FormatConverterVK.cpp @@ -2,6 +2,8 @@ #include +#include + namespace Renderer { namespace Backend @@ -549,6 +551,52 @@ namespace Renderer return VkPrimitiveTopology::VK_PRIMITIVE_TOPOLOGY_POINT_LIST; } + VkDescriptorType FormatConverterVK::ToVkDescriptorType(const FileFormat::DescriptorReflection& descriptor) + { + FileFormat::DescriptorTypeReflection type = descriptor.type; + if (type == FileFormat::DescriptorTypeReflection::Array) + { + type = descriptor.subType; + } + + switch (type) + { + case FileFormat::DescriptorTypeReflection::ByteAddressBuffer: + case FileFormat::DescriptorTypeReflection::StructuredBuffer: + return VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + + case FileFormat::DescriptorTypeReflection::ConstantBuffer: + return VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + + case FileFormat::DescriptorTypeReflection::SamplerState: + return VK_DESCRIPTOR_TYPE_SAMPLER; + + case FileFormat::DescriptorTypeReflection::Texture: + case FileFormat::DescriptorTypeReflection::TextureArray: + if (descriptor.accessType == FileFormat::DescriptorAccessTypeReflection::Read) + return VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; + else + return VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; + } + + NC_LOG_CRITICAL("This should never hit, did we forget to update this function after adding more descriptor types?"); + return VK_DESCRIPTOR_TYPE_MAX_ENUM; + } + + VkDescriptorType FormatConverterVK::ToVkDescriptorType(DescriptorType type) + { + switch(type) + { + case DescriptorType::UniformBuffer: return VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + case DescriptorType::StorageBuffer: return VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + case DescriptorType::SampledImage: return VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; + case DescriptorType::StorageImage: return VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; + default: + NC_LOG_CRITICAL("This should never hit, did we forget to update this function after adding more descriptor types?"); + } + return VK_DESCRIPTOR_TYPE_MAX_ENUM; + } + bool FormatConverterVK::ToAnisotropyEnabled(SamplerFilter filter) { switch (filter) diff --git a/Source/Renderer/Renderer/Renderers/Vulkan/Backend/FormatConverterVK.h b/Source/Renderer/Renderer/Renderers/Vulkan/Backend/FormatConverterVK.h index 69a71715..aae86219 100644 --- a/Source/Renderer/Renderer/Renderers/Vulkan/Backend/FormatConverterVK.h +++ b/Source/Renderer/Renderer/Renderers/Vulkan/Backend/FormatConverterVK.h @@ -1,11 +1,17 @@ #pragma once #include "Renderer/DescriptorMeta.h" +#include "Renderer/DescriptorType.h" #include "Renderer/RenderStates.h" #include #include +namespace FileFormat +{ + struct DescriptorReflection; +} + namespace Renderer { namespace Backend @@ -33,6 +39,8 @@ namespace Renderer static VkBorderColor ToVkBorderColor(StaticBorderColor borderColor); static VkIndexType ToVkIndexType(IndexFormat indexFormat); static VkPrimitiveTopology ToVkPrimitiveTopology(PrimitiveTopology topology); + static VkDescriptorType ToVkDescriptorType(const FileFormat::DescriptorReflection& descriptor); + static VkDescriptorType ToVkDescriptorType(DescriptorType type); static bool ToAnisotropyEnabled(SamplerFilter filter); static u32 ToByteSize(const InputFormat format); diff --git a/Source/Renderer/Renderer/Renderers/Vulkan/Backend/PipelineHandlerVK.cpp b/Source/Renderer/Renderer/Renderers/Vulkan/Backend/PipelineHandlerVK.cpp index 3db574bb..0fd928e5 100644 --- a/Source/Renderer/Renderer/Renderers/Vulkan/Backend/PipelineHandlerVK.cpp +++ b/Source/Renderer/Renderer/Renderers/Vulkan/Backend/PipelineHandlerVK.cpp @@ -4,7 +4,6 @@ #include "ShaderHandlerVK.h" #include "ImageHandlerVK.h" #include "SpirvReflect.h" -#include "DescriptorSetBuilderVK.h" #include "DebugMarkerUtilVK.h" #include @@ -39,8 +38,6 @@ namespace Renderer std::vector descriptorSetLayouts; std::vector pushConstantRanges; - - DescriptorSetBuilderVK* descriptorSetBuilder; }; struct ComputePipelineCacheDesc @@ -60,8 +57,6 @@ namespace Renderer std::vector descriptorSetLayouts; std::vector pushConstantRanges; - - DescriptorSetBuilderVK* descriptorSetBuilder; }; struct PipelineHandlerVKData : IPipelineHandlerVKData @@ -100,12 +95,7 @@ namespace Renderer pipeline.descriptorSetLayoutDatas.clear(); pipeline.pushConstantRanges.clear(); - delete pipeline.descriptorSetBuilder; - CreatePipelineInternal(pipeline, pipeline.desc, pipeline.numRenderTargets); - - pipeline.descriptorSetBuilder = new DescriptorSetBuilderVK(_allocator, GraphicsPipelineID(i), this, _shaderHandler, _bufferHandler, _device->_descriptorMegaPool); - pipeline.descriptorSetBuilder->InitReflectData(); } for (u32 i = 0; i < data.computePipelines.size(); i++) @@ -123,12 +113,7 @@ namespace Renderer pipeline.descriptorSetLayoutDatas.clear(); pipeline.pushConstantRanges.clear(); - delete pipeline.descriptorSetBuilder; - CreatePipelineInternal(pipeline, pipeline.desc); - - pipeline.descriptorSetBuilder = new DescriptorSetBuilderVK(_allocator, ComputePipelineID(i), this, _shaderHandler, _bufferHandler, _device->_descriptorMegaPool); - pipeline.descriptorSetBuilder->InitReflectData(); } } @@ -169,12 +154,8 @@ namespace Renderer CreatePipelineInternal(pipeline, desc, numAttachments); GraphicsPipelineID pipelineID = GraphicsPipelineID(static_cast(nextID)); - pipeline.descriptorSetBuilder = new DescriptorSetBuilderVK(_allocator, pipelineID, this, _shaderHandler, _bufferHandler, _device->_descriptorMegaPool); - data.graphicsPipelines.push_back(pipeline); - pipeline.descriptorSetBuilder->InitReflectData(); // Needs to happen after push_back - return pipelineID; } @@ -198,34 +179,30 @@ namespace Renderer CreatePipelineInternal(pipeline, desc); ComputePipelineID pipelineID = ComputePipelineID(static_cast(nextID)); - pipeline.descriptorSetBuilder = new DescriptorSetBuilderVK(_allocator, pipelineID, this, _shaderHandler, _bufferHandler, _device->_descriptorMegaPool); - data.computePipelines.push_back(pipeline); - pipeline.descriptorSetBuilder->InitReflectData(); // Needs to happen after push_back - return pipelineID; } - const GraphicsPipelineDesc& PipelineHandlerVK::GetDescriptor(GraphicsPipelineID id) + const GraphicsPipelineDesc& PipelineHandlerVK::GetDesc(GraphicsPipelineID id) { PipelineHandlerVKData& data = static_cast(*_data); return data.graphicsPipelines[static_cast(id)].desc; } - const ComputePipelineDesc& PipelineHandlerVK::GetDescriptor(ComputePipelineID id) + const ComputePipelineDesc& PipelineHandlerVK::GetDesc(ComputePipelineID id) { PipelineHandlerVKData& data = static_cast(*_data); return data.computePipelines[static_cast(id)].desc; } - GraphicsPipelineDesc& PipelineHandlerVK::GetMutableDescriptor(GraphicsPipelineID id) + GraphicsPipelineDesc& PipelineHandlerVK::GetMutableDesc(GraphicsPipelineID id) { PipelineHandlerVKData& data = static_cast(*_data); return data.graphicsPipelines[static_cast(id)].desc; } - ComputePipelineDesc& PipelineHandlerVK::GetMutableDescriptor(ComputePipelineID id) + ComputePipelineDesc& PipelineHandlerVK::GetMutableDesc(ComputePipelineID id) { PipelineHandlerVKData& data = static_cast(*_data); return data.computePipelines[static_cast(id)].desc; @@ -321,108 +298,6 @@ namespace Renderer return data.computePipelines[static_cast(id)].pipelineLayout; } - DescriptorSetBuilderVK& PipelineHandlerVK::GetDescriptorSetBuilder(GraphicsPipelineID id) - { - PipelineHandlerVKData& data = static_cast(*_data); - return *data.graphicsPipelines[static_cast(id)].descriptorSetBuilder; - } - - DescriptorSetBuilderVK& PipelineHandlerVK::GetDescriptorSetBuilder(ComputePipelineID id) - { - PipelineHandlerVKData& data = static_cast(*_data); - return *data.computePipelines[static_cast(id)].descriptorSetBuilder; - } - - void AddDescriptorMetaEntry(DescriptorMetaInfo& metaInfo, Backend::BindInfo bindInfo, DescriptorSetSlot slot) - { - u32 nameHash = bindInfo.nameHash; - u32 bindingIndex = bindInfo.binding; - DescriptorMetaType type = FormatConverterVK::ToDescriptorMetaType(bindInfo.descriptorType); - u32 setSlot = bindInfo.set; - - if (setSlot != static_cast(slot)) - { - return; - } - - NC_ASSERT(type != DescriptorMetaType::UNIFORM_BUFFER_DYNAMIC, "Shader is using useless Uniform Buffer Dynamic descriptor"); - NC_ASSERT(type != DescriptorMetaType::STORAGE_BUFFER_DYNAMIC, "Shader is using useless Storage Buffer Dynamic descriptor"); - NC_ASSERT(type != DescriptorMetaType::INPUT_ATTACHMENT, "Shader is using useless Input Attachment descriptor"); - - // If we already have a binding with this name, we need to make sure it matches - if (metaInfo.nameHashToDescriptorIndex.contains(nameHash)) - { - u32 existingIndex = metaInfo.nameHashToDescriptorIndex[nameHash]; - DescriptorMeta& existingMeta = metaInfo.descriptors[existingIndex]; - NC_ASSERT(existingMeta.nameHash == nameHash, "DescriptorMeta nameHash mismatch"); - NC_ASSERT(existingMeta.bindingIndex == bindingIndex, "DescriptorMeta bindingIndex mismatch"); - return; - } - - // If we already have a binding with this binding index, we need to make sure it matches - if (metaInfo.bindingIndexToDescriptorIndex.contains(bindingIndex)) - { - u32 existingIndex = metaInfo.bindingIndexToDescriptorIndex[bindingIndex]; - DescriptorMeta& existingMeta = metaInfo.descriptors[existingIndex]; - NC_ASSERT(existingMeta.nameHash == nameHash, "DescriptorMeta nameHash mismatch"); - NC_ASSERT(existingMeta.bindingIndex == bindingIndex, "DescriptorMeta bindingIndex mismatch"); - return; - } - - // If we didn't have it yet, add it - DescriptorMeta meta = { - .name = bindInfo.name, - .nameHash = nameHash, - .bindingIndex = bindingIndex, - .type = type - }; - u32 descriptorIndex = static_cast(metaInfo.descriptors.size()); - metaInfo.descriptors.push_back(meta); - metaInfo.nameHashToDescriptorIndex[meta.nameHash] = descriptorIndex; - metaInfo.bindingIndexToDescriptorIndex[meta.bindingIndex] = descriptorIndex; - } - - void PipelineHandlerVK::GetDescriptorMetaFromPipeline(DescriptorMetaInfo& metaInfo, GraphicsPipelineID pipelineID, DescriptorSetSlot slot) - { - PipelineHandlerVKData& data = static_cast(*_data); - auto& pipeline = data.graphicsPipelines[static_cast(pipelineID)]; - - if (pipeline.desc.states.vertexShader != VertexShaderID::Invalid()) - { - const BindReflection& bindReflection = _shaderHandler->GetBindReflection(pipeline.desc.states.vertexShader); - - for(auto& bindInfo : bindReflection.dataBindings) - { - AddDescriptorMetaEntry(metaInfo, bindInfo, slot); - } - } - if (pipeline.desc.states.pixelShader != PixelShaderID::Invalid()) - { - const BindReflection& bindReflection = _shaderHandler->GetBindReflection(pipeline.desc.states.pixelShader); - - for (auto& bindInfo : bindReflection.dataBindings) - { - AddDescriptorMetaEntry(metaInfo, bindInfo, slot); - } - } - } - - void PipelineHandlerVK::GetDescriptorMetaFromPipeline(DescriptorMetaInfo& metaInfo, ComputePipelineID pipelineID, DescriptorSetSlot slot) - { - PipelineHandlerVKData& data = static_cast(*_data); - auto& pipeline = data.computePipelines[static_cast(pipelineID)]; - - if (pipeline.desc.computeShader != ComputeShaderID::Invalid()) - { - const BindReflection& bindReflection = _shaderHandler->GetBindReflection(pipeline.desc.computeShader); - - for (auto& bindInfo : bindReflection.dataBindings) - { - AddDescriptorMetaEntry(metaInfo, bindInfo, slot); - } - } - } - u64 PipelineHandlerVK::CalculateCacheDescHash(const GraphicsPipelineDesc& desc) { GraphicsPipelineCacheDesc cacheDesc = {}; @@ -494,18 +369,20 @@ namespace Renderer void PipelineHandlerVK::CreatePipelineInternal(GraphicsPipeline& pipeline, const GraphicsPipelineDesc& desc, u32 numAttachments) { + u32 numSupportedTextures = _device->HasExtendedTextureSupport() ? 8192 : 4096; + // -- Get Reflection data from shader -- std::vector bindInfos; std::vector bindInfoPushConstants; if (desc.states.vertexShader != VertexShaderID::Invalid()) { - const BindReflection& bindReflection = _shaderHandler->GetBindReflection(desc.states.vertexShader); + const BindReflection& bindReflection = _shaderHandler->GetFullBindReflection(desc.states.vertexShader); bindInfos.insert(bindInfos.end(), bindReflection.dataBindings.begin(), bindReflection.dataBindings.end()); bindInfoPushConstants.insert(bindInfoPushConstants.end(), bindReflection.pushConstants.begin(), bindReflection.pushConstants.end()); } if (desc.states.pixelShader != PixelShaderID::Invalid()) { - const BindReflection& bindReflection = _shaderHandler->GetBindReflection(desc.states.pixelShader); + const BindReflection& bindReflection = _shaderHandler->GetFullBindReflection(desc.states.pixelShader); // Loop over all new databindings for (const BindInfo& dataBinding : bindReflection.dataBindings) @@ -555,10 +432,16 @@ namespace Renderer layoutBinding.binding = bindInfo.binding; layoutBinding.descriptorType = bindInfo.descriptorType; - layoutBinding.descriptorCount = bindInfo.count; + layoutBinding.descriptorCount = (bindInfo.count == 0) ? numSupportedTextures : bindInfo.count; layoutBinding.stageFlags = bindInfo.stageFlags; layout.bindings.push_back(layoutBinding); + + bool isTextureType = bindInfo.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE || + bindInfo.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + bool isTextureArray = isTextureType && (bindInfo.count == 0 || bindInfo.count > 1); + layout.isTextureArray.push_back(isTextureArray); + layout.isVariableBinding.push_back(bindInfo.count == 0); } size_t numDescriptorSets = pipeline.descriptorSetLayoutDatas.size(); @@ -566,10 +449,31 @@ namespace Renderer for (size_t i = 0; i < numDescriptorSets; i++) { - pipeline.descriptorSetLayoutDatas[i].createInfo.bindingCount = static_cast(pipeline.descriptorSetLayoutDatas[i].bindings.size()); - pipeline.descriptorSetLayoutDatas[i].createInfo.pBindings = pipeline.descriptorSetLayoutDatas[i].bindings.data(); + DescriptorSetLayoutData& layoutData = pipeline.descriptorSetLayoutDatas[i]; + + std::vector bindingFlags(layoutData.bindings.size(), VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT); + for (size_t j = 0; j < layoutData.bindings.size(); j++) + { + if (layoutData.isTextureArray[j]) + { + bindingFlags[j] |= VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT; + } + if (layoutData.isVariableBinding[j]) + { + bindingFlags[j] |= VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT; + } + } - if (vkCreateDescriptorSetLayout(_device->_device, &pipeline.descriptorSetLayoutDatas[i].createInfo, nullptr, &pipeline.descriptorSetLayouts[i]) != VK_SUCCESS) + VkDescriptorSetLayoutBindingFlagsCreateInfo flagsInfo{ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO }; + flagsInfo.bindingCount = static_cast(bindingFlags.size()); + flagsInfo.pBindingFlags = bindingFlags.data(); + + layoutData.createInfo.pNext = &flagsInfo; + layoutData.createInfo.bindingCount = static_cast(layoutData.bindings.size()); + layoutData.createInfo.pBindings = layoutData.bindings.data(); + layoutData.createInfo.flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT; + + if (vkCreateDescriptorSetLayout(_device->_device, &layoutData.createInfo, nullptr, &pipeline.descriptorSetLayouts[i]) != VK_SUCCESS) { NC_LOG_CRITICAL("Failed to create descriptor set layout!"); } @@ -856,26 +760,29 @@ namespace Renderer void PipelineHandlerVK::CreatePipelineInternal(ComputePipeline& pipeline, const ComputePipelineDesc& desc) { + u32 numSupportedTextures = _device->HasExtendedTextureSupport() ? 8192 : 4096; + std::vector bindInfos; std::vector bindInfoPushConstants; - - const BindReflection& bindReflection = _shaderHandler->GetBindReflection(desc.computeShader); + const BindReflection& bindReflection = _shaderHandler->GetFullBindReflection(desc.computeShader); bindInfos.insert(bindInfos.end(), bindReflection.dataBindings.begin(), bindReflection.dataBindings.end()); bindInfoPushConstants.insert(bindInfoPushConstants.end(), bindReflection.pushConstants.begin(), bindReflection.pushConstants.end()); - for (BindInfo& bindInfo : bindInfos) { DescriptorSetLayoutData& layout = GetDescriptorSet(bindInfo.set, pipeline.descriptorSetLayoutDatas); VkDescriptorSetLayoutBinding layoutBinding = {}; - layoutBinding.binding = bindInfo.binding; layoutBinding.descriptorType = bindInfo.descriptorType; - layoutBinding.descriptorCount = bindInfo.count; + layoutBinding.descriptorCount = (bindInfo.count == 0) ? numSupportedTextures : bindInfo.count; layoutBinding.stageFlags = bindInfo.stageFlags; - layout.bindings.push_back(layoutBinding); - } + bool isTextureType = bindInfo.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE || + bindInfo.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + bool isTextureArray = isTextureType && (bindInfo.count == 0 || bindInfo.count > 1); + layout.isTextureArray.push_back(isTextureArray); + layout.isVariableBinding.push_back(bindInfo.count == 0); + } for (BindInfoPushConstant& pushConstant : bindInfoPushConstants) { VkPushConstantRange& range = pipeline.pushConstantRanges.emplace_back(); @@ -883,29 +790,47 @@ namespace Renderer range.size = pushConstant.size; range.stageFlags = pushConstant.stageFlags; } - size_t numDescriptorSets = pipeline.descriptorSetLayoutDatas.size(); pipeline.descriptorSetLayouts.resize(numDescriptorSets); - for (size_t i = 0; i < numDescriptorSets; i++) { - pipeline.descriptorSetLayoutDatas[i].createInfo.bindingCount = static_cast(pipeline.descriptorSetLayoutDatas[i].bindings.size()); - pipeline.descriptorSetLayoutDatas[i].createInfo.pBindings = pipeline.descriptorSetLayoutDatas[i].bindings.data(); + DescriptorSetLayoutData& layoutData = pipeline.descriptorSetLayoutDatas[i]; - if (vkCreateDescriptorSetLayout(_device->_device, &pipeline.descriptorSetLayoutDatas[i].createInfo, nullptr, &pipeline.descriptorSetLayouts[i]) != VK_SUCCESS) + // Build binding flags + std::vector bindingFlags(layoutData.bindings.size(), VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT); + for (size_t j = 0; j < layoutData.bindings.size(); j++) + { + if (layoutData.isTextureArray[j]) + { + bindingFlags[j] |= VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT; + } + if (layoutData.isVariableBinding[j]) + { + bindingFlags[j] |= VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT; + } + } + + VkDescriptorSetLayoutBindingFlagsCreateInfo flagsInfo{ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO }; + flagsInfo.bindingCount = static_cast(bindingFlags.size()); + flagsInfo.pBindingFlags = bindingFlags.data(); + + layoutData.createInfo.pNext = &flagsInfo; + layoutData.createInfo.bindingCount = static_cast(layoutData.bindings.size()); + layoutData.createInfo.pBindings = layoutData.bindings.data(); + layoutData.createInfo.flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT; + + if (vkCreateDescriptorSetLayout(_device->_device, &layoutData.createInfo, nullptr, &pipeline.descriptorSetLayouts[i]) != VK_SUCCESS) { NC_LOG_CRITICAL("Failed to create descriptor set layout!"); } DebugMarkerUtilVK::SetObjectName(_device->_device, (uint64_t)pipeline.descriptorSetLayouts[i], VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT, desc.debugName.c_str()); } - VkPipelineLayoutCreateInfo pipelineLayoutInfo = {}; pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; pipelineLayoutInfo.setLayoutCount = static_cast(pipeline.descriptorSetLayouts.size()); pipelineLayoutInfo.pSetLayouts = pipeline.descriptorSetLayouts.data(); pipelineLayoutInfo.pushConstantRangeCount = static_cast(pipeline.pushConstantRanges.size()); // Optional pipelineLayoutInfo.pPushConstantRanges = pipeline.pushConstantRanges.data(); - if (vkCreatePipelineLayout(_device->_device, &pipelineLayoutInfo, nullptr, &pipeline.pipelineLayout) != VK_SUCCESS) { NC_LOG_CRITICAL("Failed to create pipeline layout!"); diff --git a/Source/Renderer/Renderer/Renderers/Vulkan/Backend/PipelineHandlerVK.h b/Source/Renderer/Renderer/Renderers/Vulkan/Backend/PipelineHandlerVK.h index d05539bd..7b29655e 100644 --- a/Source/Renderer/Renderer/Renderers/Vulkan/Backend/PipelineHandlerVK.h +++ b/Source/Renderer/Renderer/Renderers/Vulkan/Backend/PipelineHandlerVK.h @@ -23,7 +23,6 @@ namespace Renderer class ShaderHandlerVK; class ImageHandlerVK; class BufferHandlerVK; - class DescriptorSetBuilderVK; struct GraphicsPipeline; struct ComputePipeline; @@ -31,6 +30,8 @@ namespace Renderer { VkDescriptorSetLayoutCreateInfo createInfo; std::vector bindings; + std::vector isTextureArray; + std::vector isVariableBinding; }; struct IPipelineHandlerVKData {}; @@ -47,12 +48,12 @@ namespace Renderer GraphicsPipelineID CreatePipeline(const GraphicsPipelineDesc& desc); ComputePipelineID CreatePipeline(const ComputePipelineDesc& desc); - const GraphicsPipelineDesc& GetDescriptor(GraphicsPipelineID id); - const ComputePipelineDesc& GetDescriptor(ComputePipelineID id); + const GraphicsPipelineDesc& GetDesc(GraphicsPipelineID id); + const ComputePipelineDesc& GetDesc(ComputePipelineID id); // Be careful with these - GraphicsPipelineDesc& GetMutableDescriptor(GraphicsPipelineID id); - ComputePipelineDesc& GetMutableDescriptor(ComputePipelineID id); + GraphicsPipelineDesc& GetMutableDesc(GraphicsPipelineID id); + ComputePipelineDesc& GetMutableDesc(ComputePipelineID id); VkPipeline GetPipeline(GraphicsPipelineID id); VkPipeline GetPipeline(ComputePipelineID id); @@ -77,12 +78,6 @@ namespace Renderer VkPipelineLayout& GetPipelineLayout(GraphicsPipelineID id); VkPipelineLayout& GetPipelineLayout(ComputePipelineID id); - DescriptorSetBuilderVK& GetDescriptorSetBuilder(GraphicsPipelineID id); - DescriptorSetBuilderVK& GetDescriptorSetBuilder(ComputePipelineID id); - - void GetDescriptorMetaFromPipeline(DescriptorMetaInfo& metaInfo, GraphicsPipelineID pipeline, DescriptorSetSlot slot); - void GetDescriptorMetaFromPipeline(DescriptorMetaInfo& metaInfo, ComputePipelineID pipeline, DescriptorSetSlot slot); - private: u64 CalculateCacheDescHash(const GraphicsPipelineDesc& desc); u64 CalculateCacheDescHash(const ComputePipelineDesc& desc); diff --git a/Source/Renderer/Renderer/Renderers/Vulkan/Backend/RenderDeviceVK.cpp b/Source/Renderer/Renderer/Renderers/Vulkan/Backend/RenderDeviceVK.cpp index 195ca6e4..d4f2147d 100644 --- a/Source/Renderer/Renderer/Renderers/Vulkan/Backend/RenderDeviceVK.cpp +++ b/Source/Renderer/Renderer/Renderers/Vulkan/Backend/RenderDeviceVK.cpp @@ -1,7 +1,6 @@ #include "RenderDeviceVK.h" #include "DebugMarkerUtilVK.h" -#include "DescriptorSetBuilderVK.h" #include "ImageHandlerVK.h" #include "SemaphoreHandlerVK.h" #include "SwapChainVK.h" @@ -79,7 +78,6 @@ namespace Renderer { // TODO: All cleanup - delete _descriptorMegaPool; delete _imguiContext; } @@ -166,9 +164,6 @@ namespace Renderer CreateCommandPool(); CreateTracyContext(); - _descriptorMegaPool = new DescriptorMegaPoolVK(); - _descriptorMegaPool->Init(FRAME_INDEX_COUNT, this); - fnVkCmdDrawIndirectCountKHR = (PFN_vkCmdDrawIndirectCountKHR)vkGetDeviceProcAddr(_device, "vkCmdDrawIndirectCountKHR"); fnVkCmdDrawIndexedIndirectCountKHR = (PFN_vkCmdDrawIndexedIndirectCountKHR)vkGetDeviceProcAddr(_device, "vkCmdDrawIndexedIndirectCountKHR"); @@ -407,6 +402,11 @@ namespace Renderer descriptorIndexingFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES_EXT; descriptorIndexingFeatures.runtimeDescriptorArray = true; descriptorIndexingFeatures.shaderSampledImageArrayNonUniformIndexing = true; + descriptorIndexingFeatures.descriptorBindingPartiallyBound = true; + descriptorIndexingFeatures.descriptorBindingSampledImageUpdateAfterBind = true; + descriptorIndexingFeatures.descriptorBindingStorageBufferUpdateAfterBind = true; + descriptorIndexingFeatures.descriptorBindingStorageImageUpdateAfterBind = true; + descriptorIndexingFeatures.descriptorBindingVariableDescriptorCount = true; descriptorIndexingFeatures.pNext = &shaderSubgroupFeatures; VkPhysicalDeviceShaderAtomicInt64FeaturesKHR atomicInt64Features = {}; @@ -1426,8 +1426,8 @@ namespace Renderer NC_LOG_CRITICAL("Tried to use a format that wasn't uncompressed or used BC compression, what is this? id: {}", static_cast::type>(format)); } - curWidth = Math::Max(1, curWidth / 2); - curHeight = Math::Max(1, curHeight / 2); + curWidth = Math::Max(1u, curWidth / 2); + curHeight = Math::Max(1u, curHeight / 2); } vkCmdCopyBufferToImage( diff --git a/Source/Renderer/Renderer/Renderers/Vulkan/Backend/RenderDeviceVK.h b/Source/Renderer/Renderer/Renderers/Vulkan/Backend/RenderDeviceVK.h index a553a074..4653886b 100644 --- a/Source/Renderer/Renderer/Renderers/Vulkan/Backend/RenderDeviceVK.h +++ b/Source/Renderer/Renderer/Renderers/Vulkan/Backend/RenderDeviceVK.h @@ -31,7 +31,6 @@ namespace Renderer struct SwapChainVK; class ImageHandlerVK; class SemaphoreHandlerVK; - struct DescriptorMegaPoolVK; struct QueueFamilyIndices { @@ -73,6 +72,8 @@ namespace Renderer const std::string& GetGPUName() { return _gpuName; } ImageFormat GetSwapChainImageFormat() { return _swapChainFormats[0]; } + static const u32 FRAME_INDEX_COUNT = 2; + private: void InitOnce(); @@ -128,7 +129,6 @@ namespace Renderer uvec2 _mainWindowSize; vec2 _renderSize = vec2(1, 1); - static const u32 FRAME_INDEX_COUNT = 2; static bool _initialized; u32 _frameIndex; @@ -157,26 +157,25 @@ namespace Renderer VmaAllocator _allocator; - DescriptorMegaPoolVK* _descriptorMegaPool; - tracy::VkCtx* _tracyContext = nullptr; ImguiContext* _imguiContext = nullptr; - friend class ::Renderer::RendererVK; friend class BufferHandlerVK; + friend class CommandListHandlerVK; + friend struct DescriptorAllocatorHandleVK; + friend class DescriptorAllocatorPoolVKImpl; + friend class DescriptorSetBuilderVK; + friend class DescriptorHandlerVK; + friend class FidelityFXHandlerVK; friend class ImageHandlerVK; - friend class TextureHandlerVK; friend class ModelHandlerVK; - friend class ShaderHandlerVK; friend class PipelineHandlerVK; - friend class CommandListHandlerVK; + friend class ::Renderer::RendererVK; friend class SamplerHandlerVK; friend class SemaphoreHandlerVK; + friend class ShaderHandlerVK; + friend class TextureHandlerVK; friend class TimeQueryHandlerVK; friend class UploadBufferHandlerVK; - friend struct DescriptorAllocatorHandleVK; - friend class DescriptorAllocatorPoolVKImpl; - friend class DescriptorSetBuilderVK; - friend class FidelityFXHandlerVK; }; } } diff --git a/Source/Renderer/Renderer/Renderers/Vulkan/Backend/ShaderHandlerVK.cpp b/Source/Renderer/Renderer/Renderers/Vulkan/Backend/ShaderHandlerVK.cpp index 9daeb49b..0851f15e 100644 --- a/Source/Renderer/Renderer/Renderers/Vulkan/Backend/ShaderHandlerVK.cpp +++ b/Source/Renderer/Renderer/Renderers/Vulkan/Backend/ShaderHandlerVK.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -92,7 +93,7 @@ namespace Renderer ZoneScoped; VertexShaderID shaderID; bool wasCached; - if (desc.shaderEntry.shaderData != nullptr && desc.shaderEntry.shaderSize != 0) + if (desc.shaderEntry != nullptr) { shaderID = LoadShaderFromMemory(desc.shaderEntry, _vertexShaderStore, wasCached); } @@ -113,7 +114,7 @@ namespace Renderer ZoneScoped; PixelShaderID shaderID; bool wasCached; - if (desc.shaderEntry.shaderData != nullptr && desc.shaderEntry.shaderSize != 0) + if (desc.shaderEntry != nullptr) { shaderID = LoadShaderFromMemory(desc.shaderEntry, _pixelShaderStore, wasCached); } @@ -135,7 +136,7 @@ namespace Renderer ComputeShaderID shaderID; bool wasCached; - if (desc.shaderEntry.shaderData != nullptr && desc.shaderEntry.shaderSize != 0) + if (desc.shaderEntry != nullptr) { shaderID = LoadShaderFromMemory(desc.shaderEntry, _computeShaderStore, wasCached); } @@ -151,7 +152,7 @@ namespace Renderer return shaderID; } - void ShaderHandlerVK::ReflectShader(const uint32_t* shaderData, size_t shaderSize, BindReflection& bindReflection, const std::string& shaderPath) + void ShaderHandlerVK::ReflectUsedBindings(const uint32_t* shaderData, size_t shaderSize, BindReflection& bindReflection, const std::string& shaderPath) { // Reflect descriptor sets SpvReflectShaderModule reflectModule; @@ -233,6 +234,41 @@ namespace Renderer } } + void ShaderHandlerVK::ReflectFullBindings(const ShaderEntry* shaderEntry, BindReflection& bindReflection) + { + const FileFormat::ShaderReflection& reflection = shaderEntry->reflection; + + for (const auto& [set, descriptorSet] : reflection.descriptorSets) + { + for (const auto& [binding, descriptor] : descriptorSet.descriptors) + { + if (set == 0) + { + BindInfoPushConstant pushConstant; + pushConstant.offset = descriptor.byteOffset; + pushConstant.size = descriptor.byteSize; + pushConstant.stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT | VK_SHADER_STAGE_COMPUTE_BIT; + + bindReflection.pushConstants.push_back(pushConstant); + } + else + { + BindInfo bindInfo; + bindInfo.name = descriptor.name; + bindInfo.nameHash = StringUtils::fnv1a_32(descriptor.name.c_str(), descriptor.name.length()); + bindInfo.descriptorType = FormatConverterVK::ToVkDescriptorType(descriptor); + bindInfo.set = set; + bindInfo.binding = binding; + bindInfo.count = descriptor.count; + bindInfo.stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT | VK_SHADER_STAGE_COMPUTE_BIT; + bindInfo.isUsed = descriptor.isUsed; + bindInfo.isWrite = (descriptor.accessType == FileFormat::DescriptorAccessTypeReflection::ReadWrite || descriptor.accessType == FileFormat::DescriptorAccessTypeReflection::Write); + bindReflection.dataBindings.push_back(bindInfo); + } + } + } + } + void ShaderHandlerVK::ReadFile(const std::string& filename, ShaderBinary& binary) { ZoneScoped; diff --git a/Source/Renderer/Renderer/Renderers/Vulkan/Backend/ShaderHandlerVK.h b/Source/Renderer/Renderer/Renderers/Vulkan/Backend/ShaderHandlerVK.h index ab660a13..bc87e990 100644 --- a/Source/Renderer/Renderer/Renderers/Vulkan/Backend/ShaderHandlerVK.h +++ b/Source/Renderer/Renderer/Renderers/Vulkan/Backend/ShaderHandlerVK.h @@ -40,6 +40,9 @@ namespace Renderer u32 count; u32 stageFlags; + u32 offset; + u32 size; + bool isUsed = false; bool isWrite = false; }; @@ -72,21 +75,40 @@ namespace Renderer PixelShaderID LoadShader(const PixelShaderDesc& desc); ComputeShaderID LoadShader(const ComputeShaderDesc& desc); + const VertexShaderDesc& GetDesc(const VertexShaderID id) { return _vertexShaderStore.descs[static_cast(id)]; } + const PixelShaderDesc& GetDesc(const PixelShaderID id) { return _pixelShaderStore.descs[static_cast(id)]; } + const ComputeShaderDesc& GetDesc(const ComputeShaderID id) { return _computeShaderStore.descs[static_cast(id)]; } + VkShaderModule GetShaderModule(const VertexShaderID id) { return _vertexShaderStore.shaders[static_cast(id)].module; } VkShaderModule GetShaderModule(const PixelShaderID id) { return _pixelShaderStore.shaders[static_cast(id)].module; } VkShaderModule GetShaderModule(const ComputeShaderID id) { return _computeShaderStore.shaders[static_cast(id)].module; } - const BindReflection& GetBindReflection(const VertexShaderID id) + // Reflection of only what this shader uses + const BindReflection& GetUsedBindReflection(const VertexShaderID id) { - return _vertexShaderStore.shaders[static_cast(id)].bindReflection; + return _vertexShaderStore.shaders[static_cast(id)].usedBindReflection; } - const BindReflection& GetBindReflection(const PixelShaderID id) + const BindReflection& GetUsedBindReflection(const PixelShaderID id) { - return _pixelShaderStore.shaders[static_cast(id)].bindReflection; + return _pixelShaderStore.shaders[static_cast(id)].usedBindReflection; + } + const BindReflection& GetUsedBindReflection(const ComputeShaderID id) + { + return _computeShaderStore.shaders[static_cast(id)].usedBindReflection; + } + + // Full reflection of all descriptors in the shader even if not used + const BindReflection& GetFullBindReflection(const VertexShaderID id) + { + return _vertexShaderStore.shaders[static_cast(id)].fullBindReflection; + } + const BindReflection& GetFullBindReflection(const PixelShaderID id) + { + return _pixelShaderStore.shaders[static_cast(id)].fullBindReflection; } - const BindReflection& GetBindReflection(const ComputeShaderID id) + const BindReflection& GetFullBindReflection(const ComputeShaderID id) { - return _computeShaderStore.shaders[static_cast(id)].bindReflection; + return _computeShaderStore.shaders[static_cast(id)].fullBindReflection; } private: @@ -101,7 +123,8 @@ namespace Renderer VkShaderModule module; ShaderBinary spirv; - BindReflection bindReflection; + BindReflection usedBindReflection; + BindReflection fullBindReflection; }; struct ShaderStoreBase @@ -165,7 +188,9 @@ namespace Renderer shader.module = CreateShaderModule(data, size, shaderPath); shader.permutationFields = permutationFields; - ReflectShader(data, size, shader.bindReflection, shaderPath); + ReflectUsedBindings(data, size, shader.usedBindReflection, shaderPath); + // TODO: Somehow get the full reflection if you're not using shaderpacks, because the descriptorsets are gonna need it. This codepath is broken for now. + NC_LOG_CRITICAL("ShaderHandlerVK::LoadShaderFromFile - Loading shaders from file without shaderpacks is currently not supported!"); u32 permutationPathHash = StringUtils::fnv1a_32(permutationPath.c_str(), permutationPath.length()); shaderStore.hashToIndex[permutationPathHash] = static_cast(id); @@ -175,13 +200,13 @@ namespace Renderer } template - T LoadShaderFromMemory(const ShaderEntry& shaderEntry, ShaderStoreBase& shaderStore, bool& wasCached) + T LoadShaderFromMemory(const ShaderEntry* shaderEntry, ShaderStoreBase& shaderStore, bool& wasCached) { size_t id; using idType = type_safe::underlying_type; // If shader is already loaded, return ID of already loaded version - if (TryFindExistingShader(shaderEntry.permutationNameHash, shaderStore, id)) + if (TryFindExistingShader(shaderEntry->permutationNameHash, shaderStore, id)) { wasCached = true; return T(static_cast(id)); @@ -191,19 +216,21 @@ namespace Renderer assert(id < T::MaxValue()); Shader& shader = shaderStore.shaders.emplace_back(); - u32* data = reinterpret_cast(shaderEntry.shaderData); - const u32 size = shaderEntry.shaderSize; - shader.module = CreateShaderModule(data, size, shaderEntry.debugName); + u32* data = reinterpret_cast(shaderEntry->shaderData); + const u32 size = shaderEntry->shaderSize; + shader.module = CreateShaderModule(data, size, shaderEntry->debugName); - ReflectShader(data, size, shader.bindReflection, shaderEntry.debugName); + ReflectUsedBindings(data, size, shader.usedBindReflection, shaderEntry->debugName); + ReflectFullBindings(shaderEntry, shader.fullBindReflection); - shaderStore.hashToIndex[shaderEntry.permutationNameHash] = static_cast(id); + shaderStore.hashToIndex[shaderEntry->permutationNameHash] = static_cast(id); wasCached = false; return T(static_cast(id)); } - void ReflectShader(const uint32_t* shaderData, size_t shaderSize, BindReflection& bindReflection, const std::string& shaderPath); + void ReflectUsedBindings(const uint32_t* shaderData, size_t shaderSize, BindReflection& bindReflection, const std::string& shaderPath); + void ReflectFullBindings(const ShaderEntry* shaderEntry, BindReflection& bindReflection); void ReadFile(const std::string& filename, ShaderBinary& binary); VkShaderModule CreateShaderModule(const uint32_t* shaderData, size_t shaderSize, const std::string& debugName); diff --git a/Source/Renderer/Renderer/Renderers/Vulkan/Backend/SwapChainVK.h b/Source/Renderer/Renderer/Renderers/Vulkan/Backend/SwapChainVK.h index 8c7398c1..8e80d25c 100644 --- a/Source/Renderer/Renderer/Renderers/Vulkan/Backend/SwapChainVK.h +++ b/Source/Renderer/Renderer/Renderers/Vulkan/Backend/SwapChainVK.h @@ -112,8 +112,8 @@ namespace Renderer { VkExtent2D actualExtent = { (uint32_t)windowSize.x, (uint32_t)windowSize.y }; - actualExtent.width = Math::Max(capabilities.minImageExtent.width, Math::Min((int)capabilities.maxImageExtent.width, (int)actualExtent.width)); - actualExtent.height = Math::Max(capabilities.minImageExtent.height, Math::Min((int)capabilities.maxImageExtent.height, (int)actualExtent.height)); + actualExtent.width = Math::Max(capabilities.minImageExtent.width, Math::Min(capabilities.maxImageExtent.width, actualExtent.width)); + actualExtent.height = Math::Max(capabilities.minImageExtent.height, Math::Min(capabilities.maxImageExtent.height, actualExtent.height)); return actualExtent; } diff --git a/Source/Renderer/Renderer/Renderers/Vulkan/Backend/TextureHandlerVK.cpp b/Source/Renderer/Renderer/Renderers/Vulkan/Backend/TextureHandlerVK.cpp index 2f49965d..fd322008 100644 --- a/Source/Renderer/Renderer/Renderers/Vulkan/Backend/TextureHandlerVK.cpp +++ b/Source/Renderer/Renderer/Renderers/Vulkan/Backend/TextureHandlerVK.cpp @@ -4,6 +4,7 @@ #include "FormatConverterVK.h" #include "DebugMarkerUtilVK.h" #include "BufferHandlerVK.h" +#include "DescriptorHandlerVK.h" #include "UploadBufferHandlerVK.h" #include "SamplerHandlerVK.h" @@ -60,6 +61,12 @@ namespace Renderer bool layoutUndefined = true; }; + struct TextureArrayBinding + { + DescriptorSetID descriptorSetID; + u32 bindingIndex; + }; + struct TextureArray { u32 size; @@ -68,6 +75,9 @@ namespace Renderer SafeVector* textureHashes = nullptr; robin_hood::unordered_map* textureIDToArrayIndex; robin_hood::unordered_set ownedTextureIDs; + + std::vector registeredBindings; + u32 lastFlushedCount = 0; // Track how many textures were in last descriptor update }; struct TextureHandlerVKData : ITextureHandlerVKData @@ -79,11 +89,12 @@ namespace Renderer SafeVector textureArrays; }; - void TextureHandlerVK::Init(RenderDeviceVK* device, BufferHandlerVK* bufferHandler, UploadBufferHandlerVK* uploadBufferHandler, SamplerHandlerVK* samplerHandler) + void TextureHandlerVK::Init(RenderDeviceVK* device, BufferHandlerVK* bufferHandler, DescriptorHandlerVK* descriptorHandler, UploadBufferHandlerVK* uploadBufferHandler, SamplerHandlerVK* samplerHandler) { _data = new TextureHandlerVKData(); _device = device; _bufferHandler = bufferHandler; + _descriptorHandler = descriptorHandler; _uploadBufferHandler = uploadBufferHandler; _samplerHandler = samplerHandler; } @@ -144,6 +155,47 @@ namespace Renderer vkFreeDescriptorSets(_device->_device, _device->_imguiContext->imguiPool, static_cast(data.descriptorsToFree.size()), data.descriptorsToFree.data()); data.descriptorsToFree.clear(); } + + // Flush texture array updates - only update newly added textures + if (_descriptorHandler != nullptr) + { + data.textureArrays.WriteLock( + [&](std::vector& textureArrays) + { + for (size_t i = 0; i < textureArrays.size(); i++) + { + TextureArray& textureArray = textureArrays[i]; + + u32 currentCount = static_cast(textureArray.textures->Size()); + if (currentCount <= textureArray.lastFlushedCount) + { + continue; // No new textures to flush + } + + u32 newTexturesCount = currentCount - textureArray.lastFlushedCount; + u32 startIndex = textureArray.lastFlushedCount; + + // Update all registered descriptor sets with only the new textures + textureArray.textures->ReadLock( + [&](const std::vector& textures) + { + const TextureID* textureIDs = textures.data() + startIndex; + + for (const auto& binding : textureArray.registeredBindings) + { + _descriptorHandler->UpdateTextureArrayDescriptors( + binding.descriptorSetID, + binding.bindingIndex, + textureIDs, + startIndex, + newTexturesCount); + } + }); + + textureArray.lastFlushedCount = currentCount; + } + }); + } } TextureID TextureHandlerVK::LoadTexture(const TextureDesc& desc) @@ -301,6 +353,9 @@ namespace Renderer textureArray.textureHashes->Resize(unloadStartIndex); textureArray.textures->Resize(unloadStartIndex); + + // Update lastFlushedCount so subsequent loads in the same frame get flushed correctly + textureArray.lastFlushedCount = Math::Min(textureArray.lastFlushedCount, unloadStartIndex); }); } @@ -330,6 +385,83 @@ namespace Renderer return TextureArrayID(static_cast(nextHandle)); } + void TextureHandlerVK::RegisterTextureArrayBinding(TextureArrayID textureArrayID, DescriptorSetID descriptorSetID, u32 bindingIndex) + { + TextureHandlerVKData& data = static_cast(*_data); + TextureArrayID::type id = static_cast(textureArrayID); + + if (data.textureArrays.Size() <= id) + { + NC_LOG_CRITICAL("TextureHandlerVK::RegisterTextureArrayBinding: Tried to register binding for invalid TextureArrayID: {0}", id); + } + + data.textureArrays.WriteLock( + [&](std::vector& textureArrays) + { + TextureArray& textureArray = textureArrays[id]; + + // Check if this binding already exists + for (const auto& binding : textureArray.registeredBindings) + { + if (binding.descriptorSetID == descriptorSetID && binding.bindingIndex == bindingIndex) + { + return; // Already registered + } + } + + TextureArrayBinding newBinding; + newBinding.descriptorSetID = descriptorSetID; + newBinding.bindingIndex = bindingIndex; + textureArray.registeredBindings.push_back(newBinding); + }); + } + + void TextureHandlerVK::FlushTextureArrayDescriptors(TextureArrayID textureArrayID) + { + TextureHandlerVKData& data = static_cast(*_data); + TextureArrayID::type id = static_cast(textureArrayID); + + if (data.textureArrays.Size() <= id) + { + NC_LOG_CRITICAL("TextureHandlerVK::RegisterTextureArrayBinding: Tried to register binding for invalid TextureArrayID: {0}", id); + } + + data.textureArrays.WriteLock( + [&](std::vector& textureArrays) + { + TextureArray& textureArray = textureArrays[id]; + + u32 currentCount = static_cast(textureArray.textures->Size()); + if (currentCount <= textureArray.lastFlushedCount) + { + return; // No new textures to flush + } + + u32 newTexturesCount = currentCount - textureArray.lastFlushedCount; + u32 startIndex = textureArray.lastFlushedCount; + + // Update all registered descriptor sets with only the new textures + textureArray.textures->ReadLock( + [&](const std::vector& textures) + { + const TextureID* textureIDs = textures.data() + startIndex; + + for (const auto& binding : textureArray.registeredBindings) + { + _descriptorHandler->UpdateTextureArrayDescriptors( + binding.descriptorSetID, + binding.bindingIndex, + textureIDs, + startIndex, + newTexturesCount); + } + }); + + textureArray.lastFlushedCount = currentCount; + + }); + } + TextureID TextureHandlerVK::CreateDataTexture(const DataTextureDesc& desc) { TextureHandlerVKData& data = static_cast(*_data); @@ -362,8 +494,8 @@ namespace Renderer for (i32 i = 0; i < desc.mipLevels; ++i) { // For each mip level, calculate the reduced dimensions. - u32 mipWidth = Math::Max(1u, desc.width >> i); - u32 mipHeight = Math::Max(1u, desc.height >> i); + u32 mipWidth = Math::Max(1, desc.width >> i); + u32 mipHeight = Math::Max(1, desc.height >> i); mipUploadSize += static_cast(static_cast(mipWidth) * static_cast(mipHeight) * FormatTexelSize(FormatConverterVK::ToVkFormat(texture->desc.format))); } texture->uploadSize = mipUploadSize; diff --git a/Source/Renderer/Renderer/Renderers/Vulkan/Backend/TextureHandlerVK.h b/Source/Renderer/Renderer/Renderers/Vulkan/Backend/TextureHandlerVK.h index 68af7477..b10ca7a3 100644 --- a/Source/Renderer/Renderer/Renderers/Vulkan/Backend/TextureHandlerVK.h +++ b/Source/Renderer/Renderer/Renderers/Vulkan/Backend/TextureHandlerVK.h @@ -1,4 +1,5 @@ #pragma once +#include "Renderer/Descriptors/DescriptorSetDesc.h" #include "Renderer/Descriptors/SamplerDesc.h" #include "Renderer/Descriptors/TextureDesc.h" #include "Renderer/Descriptors/TextureArrayDesc.h" @@ -19,6 +20,7 @@ namespace Renderer class BufferHandlerVK; class UploadBufferHandlerVK; class SamplerHandlerVK; + class DescriptorHandlerVK; struct Texture; struct ITextureHandlerVKData {}; @@ -26,11 +28,14 @@ namespace Renderer class TextureHandlerVK { public: - void Init(RenderDeviceVK* device, BufferHandlerVK* bufferHandler, UploadBufferHandlerVK* uploadBufferHandler, SamplerHandlerVK* samplerHandler); + void Init(RenderDeviceVK* device, BufferHandlerVK* bufferHandler, DescriptorHandlerVK* descriptorHandler, UploadBufferHandlerVK* uploadBufferHandler, SamplerHandlerVK* samplerHandler); void InitDebugTexture(); void FlipFrame(u32 frameIndex); + void RegisterTextureArrayBinding(TextureArrayID textureArrayID, DescriptorSetID descriptorSetID, u32 bindingIndex); + void FlushTextureArrayDescriptors(TextureArrayID textureArrayID); + TextureID LoadTexture(const TextureDesc& desc); TextureID LoadTextureIntoArray(const TextureDesc& desc, TextureArrayID textureArrayID, u32& arrayIndex, bool allowDuplicates); @@ -85,6 +90,7 @@ namespace Renderer RenderDeviceVK* _device; BufferHandlerVK* _bufferHandler; + DescriptorHandlerVK* _descriptorHandler = nullptr; UploadBufferHandlerVK* _uploadBufferHandler; SamplerHandlerVK* _samplerHandler; diff --git a/Source/Renderer/Renderer/Renderers/Vulkan/RendererVK.cpp b/Source/Renderer/Renderer/Renderers/Vulkan/RendererVK.cpp index aebf4fd5..027c9865 100644 --- a/Source/Renderer/Renderer/Renderers/Vulkan/RendererVK.cpp +++ b/Source/Renderer/Renderer/Renderers/Vulkan/RendererVK.cpp @@ -1,22 +1,21 @@ #include "RendererVK.h" #include "Renderer/Window.h" -#include "Backend/RenderDeviceVK.h" #include "Backend/BufferHandlerVK.h" +#include "Backend/CommandListHandlerVK.h" +#include "Backend/DebugMarkerUtilVK.h" +#include "Backend/DescriptorHandlerVK.h" +#include "Backend/FormatConverterVK.h" #include "Backend/ImageHandlerVK.h" -#include "Backend/TextureHandlerVK.h" -#include "Backend/ShaderHandlerVK.h" #include "Backend/PipelineHandlerVK.h" -#include "Backend/CommandListHandlerVK.h" +#include "Backend/RenderDeviceVK.h" #include "Backend/SamplerHandlerVK.h" #include "Backend/SemaphoreHandlerVK.h" -#include "Backend/UploadBufferHandlerVK.h" +#include "Backend/ShaderHandlerVK.h" #include "Backend/SwapChainVK.h" -#include "Backend/DebugMarkerUtilVK.h" -#include "Backend/DescriptorSetBuilderVK.h" -#include "Backend/FormatConverterVK.h" -#include "Backend/DebugMarkerUtilVK.h" +#include "Backend/TextureHandlerVK.h" #include "Backend/TimeQueryHandlerVK.h" +#include "Backend/UploadBufferHandlerVK.h" #include #include @@ -31,32 +30,36 @@ namespace Renderer { RendererVK::RendererVK(Novus::Window* window) : _device(new Backend::RenderDeviceVK(window)) + , _presentDescriptorSet(DescriptorSetSlot::PER_PASS) { _frameAllocator.Init(64 * 1024 * 1024, "Renderer Allocator"); // Create handlers _bufferHandler = new Backend::BufferHandlerVK(); + _commandListHandler = new Backend::CommandListHandlerVK(); + _descriptorHandler = new Backend::DescriptorHandlerVK(); _imageHandler = new Backend::ImageHandlerVK(); - _textureHandler = new Backend::TextureHandlerVK(); - _shaderHandler = new Backend::ShaderHandlerVK(); _pipelineHandler = new Backend::PipelineHandlerVK(); - _commandListHandler = new Backend::CommandListHandlerVK(); _samplerHandler = new Backend::SamplerHandlerVK(); _semaphoreHandler = new Backend::SemaphoreHandlerVK(); - _uploadBufferHandler = new Backend::UploadBufferHandlerVK(); + _shaderHandler = new Backend::ShaderHandlerVK(); + _textureHandler = new Backend::TextureHandlerVK(); _timeQueryHandler = new Backend::TimeQueryHandlerVK(); + _uploadBufferHandler = new Backend::UploadBufferHandlerVK(); // Init _device->Init(); + _bufferHandler->Init(_device); - _imageHandler->Init(_device, _samplerHandler); - _textureHandler->Init(_device, _bufferHandler, _uploadBufferHandler, _samplerHandler); - _shaderHandler->Init(_device); - _timeQueryHandler->Init(_device); - _pipelineHandler->Init(&_frameAllocator, _device, _shaderHandler, _imageHandler, _bufferHandler); + _descriptorHandler->Init(_device, _textureHandler); _commandListHandler->Init(_device); _samplerHandler->Init(_device); _semaphoreHandler->Init(_device); + _shaderHandler->Init(_device); + _timeQueryHandler->Init(_device); + _imageHandler->Init(_device, _samplerHandler); + _pipelineHandler->Init(&_frameAllocator, _device, _shaderHandler, _imageHandler, _bufferHandler); + _textureHandler->Init(_device, _bufferHandler, _descriptorHandler, _uploadBufferHandler, _samplerHandler); _uploadBufferHandler->Init(this, _device, _bufferHandler, _textureHandler, _semaphoreHandler, _commandListHandler); } @@ -174,6 +177,11 @@ namespace Renderer return _semaphoreHandler->CreateNSemaphore(); } + DescriptorSetID RendererVK::CreateDescriptorSet(const DescriptorSetDesc& desc) + { + return _descriptorHandler->CreateDescriptorSet(desc); + } + GraphicsPipelineID RendererVK::CreatePipeline(GraphicsPipelineDesc& desc) { return _pipelineHandler->CreatePipeline(desc); @@ -243,11 +251,128 @@ namespace Renderer _textureHandler->UnloadTexturesInArray(textureArrayID, unloadStartIndex); } + void RendererVK::BindDescriptor(DescriptorSetID descriptorSetID, u32 bindingIndex, BufferID bufferID, DescriptorType type, u32 frameIndex) + { + VkBuffer buffer = _bufferHandler->GetBuffer(bufferID); + _descriptorHandler->BindDescriptor(descriptorSetID, bindingIndex, buffer, type, frameIndex); + } + + void RendererVK::BindDescriptor(DescriptorSetID descriptorSetID, u32 bindingIndex, ImageID imageID, u32 mipLevel, DescriptorType type, u32 frameIndex) + { + VkImageView imageView = _imageHandler->GetColorView(imageID, mipLevel); + _descriptorHandler->BindDescriptor(descriptorSetID, bindingIndex, imageView, type, true, frameIndex); + } + + void RendererVK::BindDescriptorArray(DescriptorSetID descriptorSetID, u32 bindingIndex, ImageID imageID, u32 mipLevel, u32 mipCount, DescriptorType type, u32 frameIndex) + { + std::vector imageViews; + for (u32 i = 0; i < mipCount; i++) + { + u32 mip = mipLevel + i; + VkImageView imageView = _imageHandler->GetColorView(imageID, mip); + imageViews.push_back(imageView); + } + _descriptorHandler->BindDescriptorArray(descriptorSetID, bindingIndex, imageViews, 0, type, true, frameIndex); + } + + void RendererVK::BindDescriptor(DescriptorSetID descriptorSetID, u32 bindingIndex, DepthImageID imageID, DescriptorType type, u32 frameIndex) + { + VkImageView imageView = _imageHandler->GetDepthView(imageID); + _descriptorHandler->BindDescriptor(descriptorSetID, bindingIndex, imageView, type, true, frameIndex); + } + + void RendererVK::BindDescriptorArray(DescriptorSetID descriptorSetID, u32 bindingIndex, DepthImageID imageID, u32 arrayIndex, DescriptorType type, u32 frameIndex) + { + VkImageView imageView = _imageHandler->GetDepthView(imageID); + _descriptorHandler->BindDescriptorArray(descriptorSetID, bindingIndex, imageView, arrayIndex, type, true, frameIndex); + } + + void RendererVK::BindDescriptor(DescriptorSetID descriptorSetID, u32 bindingIndex, SamplerID samplerID, u32 frameIndex) + { + VkSampler sampler = _samplerHandler->GetSampler(samplerID); + _descriptorHandler->BindDescriptor(descriptorSetID, bindingIndex, sampler, frameIndex); + } + + void RendererVK::BindDescriptorArray(DescriptorSetID descriptorSetID, u32 bindingIndex, SamplerID samplerID, u32 arrayIndex, u32 frameIndex) + { + VkSampler sampler = _samplerHandler->GetSampler(samplerID); + _descriptorHandler->BindDescriptorArray(descriptorSetID, bindingIndex, sampler, arrayIndex, frameIndex); + } + + void RendererVK::BindDescriptor(DescriptorSetID descriptorSetID, u32 bindingIndex, TextureID textureID, u32 mipLevel, DescriptorType type, u32 frameIndex) + { + VkImageView imageView = _textureHandler->GetImageView(textureID, mipLevel); + _descriptorHandler->BindDescriptor(descriptorSetID, bindingIndex, imageView, type, false, frameIndex); + } + + void RendererVK::BindDescriptorArray(DescriptorSetID descriptorSetID, u32 bindingIndex, TextureID textureID, u32 mipLevel, u32 mipCount, DescriptorType type, u32 frameIndex) + { + std::vector imageViews; + for (u32 i = 0; i < mipCount; i++) + { + u32 mip = mipLevel + i; + VkImageView imageView = _textureHandler->GetImageView(textureID, mip); + imageViews.push_back(imageView); + } + + _descriptorHandler->BindDescriptorArray(descriptorSetID, bindingIndex, imageViews, 0, type, false, frameIndex); + } + + void RendererVK::BindDescriptor(DescriptorSetID descriptorSetID, u32 bindingIndex, TextureArrayID textureArrayID) + { + _descriptorHandler->BindDescriptor(descriptorSetID, bindingIndex, textureArrayID); + } + u32 RendererVK::AddTextureToArray(TextureID textureID, TextureArrayID textureArrayID) { return _textureHandler->AddTextureToArray(textureID, textureArrayID); } + void RendererVK::FlushTextureArrayDescriptors(TextureArrayID textureArrayID) + { + _textureHandler->FlushTextureArrayDescriptors(textureArrayID); + } + + TextureBaseDesc RendererVK::GetDesc(TextureID textureID) + { + return _textureHandler->GetTextureDesc(textureID); + } + + const ImageDesc& RendererVK::GetDesc(ImageID ID) + { + return _imageHandler->GetImageDesc(ID); + } + + const DepthImageDesc& RendererVK::GetDesc(DepthImageID ID) + { + return _imageHandler->GetImageDesc(ID); + } + + const ComputePipelineDesc& RendererVK::GetDesc(ComputePipelineID ID) + { + return _pipelineHandler->GetDesc(ID); + } + + const GraphicsPipelineDesc& RendererVK::GetDesc(GraphicsPipelineID ID) + { + return _pipelineHandler->GetDesc(ID); + } + + const ComputeShaderDesc& RendererVK::GetDesc(ComputeShaderID ID) + { + return _shaderHandler->GetDesc(ID); + } + + const VertexShaderDesc& RendererVK::GetDesc(VertexShaderID ID) + { + return _shaderHandler->GetDesc(ID); + } + + const PixelShaderDesc& RendererVK::GetDesc(PixelShaderID ID) + { + return _shaderHandler->GetDesc(ID); + } + static VmaBudget sBudgets[16] = { { 0 } }; void RendererVK::FlushGPU() @@ -258,6 +383,7 @@ namespace Renderer f32 RendererVK::FlipFrame(u32 frameIndex) { ZoneScopedC(tracy::Color::Red3); + _frameIndex = frameIndex; // Reset old commandbuffers _commandListHandler->FlipFrame(); @@ -311,29 +437,24 @@ namespace Renderer return timeWaited; } - void RendererVK::ResetTimeQueries(u32 frameIndex) - { - _frameTimeQueries.clear(); - } - - TextureID RendererVK::GetTextureID(TextureArrayID textureArrayID, u32 index) + u32 RendererVK::GetCurrentFrameIndex() { - return _textureHandler->GetTextureIDInArray(textureArrayID, index); + return _frameIndex; } - TextureBaseDesc RendererVK::GetTextureDesc(TextureID textureID) + u32 RendererVK::GetFrameIndexCount() { - return _textureHandler->GetTextureDesc(textureID); + return _device->FRAME_INDEX_COUNT; } - const ImageDesc& RendererVK::GetImageDesc(ImageID ID) + void RendererVK::ResetTimeQueries(u32 frameIndex) { - return _imageHandler->GetImageDesc(ID); + _frameTimeQueries.clear(); } - const DepthImageDesc& RendererVK::GetImageDesc(DepthImageID ID) + TextureID RendererVK::GetTextureID(TextureArrayID textureArrayID, u32 index) { - return _imageHandler->GetImageDesc(ID); + return _textureHandler->GetTextureIDInArray(textureArrayID, index); } uvec2 RendererVK::GetImageDimensions(const ImageID id, u32 mipLevel) @@ -668,7 +789,7 @@ namespace Renderer } uvec2 extent = desc.extent; - if (extent == uvec2(0)) + if (extent == uvec2(0) && desc.renderTargets[0] != ImageMutableResource::Invalid()) { extent = _imageHandler->GetDimensions(desc.MutableResourceToImageID(desc.renderTargets[0]), 0); } @@ -1233,243 +1354,6 @@ namespace Renderer return false; } - void RendererVK::BindDescriptor(Backend::DescriptorSetBuilderVK& builder, Descriptor& descriptor) - { - if (descriptor.descriptorType == DescriptorType::DESCRIPTOR_TYPE_BUFFER) - { - ZoneScopedN("Buffer"); - VkDescriptorBufferInfo bufferInfo = {}; - bufferInfo.buffer = _bufferHandler->GetBuffer(descriptor.bufferID); - bufferInfo.range = _bufferHandler->GetBufferSize(descriptor.bufferID); - - builder.BindBuffer(descriptor.nameHash, bufferInfo, descriptor.bufferID); - } - else if (descriptor.descriptorType == DescriptorType::DESCRIPTOR_TYPE_BUFFER_ARRAY) - { - ZoneScopedN("BufferArray"); - VkDescriptorBufferInfo bufferInfo = {}; - bufferInfo.buffer = _bufferHandler->GetBuffer(descriptor.bufferID); - bufferInfo.range = _bufferHandler->GetBufferSize(descriptor.bufferID); - - builder.BindBufferArrayIndex(descriptor.nameHash, bufferInfo, descriptor.arrayIndex, descriptor.bufferID); - } - else if (descriptor.descriptorType == DescriptorType::DESCRIPTOR_TYPE_SAMPLER) - { - ZoneScopedN("Sampler"); - VkDescriptorImageInfo imageInfo = {}; - imageInfo.sampler = _samplerHandler->GetSampler(descriptor.samplerID); - - builder.BindSampler(descriptor.nameHash, imageInfo); - } - else if (descriptor.descriptorType == DescriptorType::DESCRIPTOR_TYPE_SAMPLER_ARRAY) - { - ZoneScopedN("SamplerArray"); - VkDescriptorImageInfo imageInfo = {}; - imageInfo.sampler = _samplerHandler->GetSampler(descriptor.samplerID); - - builder.BindSamplerArrayIndex(descriptor.nameHash, imageInfo, descriptor.arrayIndex); - } - else if (descriptor.descriptorType == DescriptorType::DESCRIPTOR_TYPE_TEXTURE) - { - ZoneScopedN("Texture"); - VkDescriptorImageInfo imageInfo = {}; - imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - imageInfo.imageView = _textureHandler->GetImageView(descriptor.textureID); - - builder.BindImage(descriptor.nameHash, imageInfo); - } - else if (descriptor.descriptorType == DescriptorType::DESCRIPTOR_TYPE_TEXTURE_ARRAY) - { - ZoneScopedN("TextureArray"); - const SafeVector& textureIDs = _textureHandler->GetTextureIDsInArray(descriptor.textureArrayID); - - u32 textureArraySize = _textureHandler->GetTextureArraySize(descriptor.textureArrayID); - - VkDescriptorImageInfo* imageInfos = Memory::Allocator::NewArray(&_frameAllocator, textureArraySize); - u32 numImageInfos = 0; - - u32 numTextures = static_cast(textureIDs.Size()); - - // From 0 to numTextures, add our actual textures - bool texturesAreOnionTextures = false; - - textureIDs.ReadLock( - [&](const std::vector textures) - { - for (auto textureID : textures) - { - VkDescriptorImageInfo& imageInfo = imageInfos[numImageInfos++]; - imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - imageInfo.imageView = _textureHandler->GetImageView(textureID); - imageInfo.sampler = VK_NULL_HANDLE; - - texturesAreOnionTextures = _textureHandler->IsOnionTexture(textureID); - } - }); - - // from numTextures to textureArraySize, add debug texture - VkDescriptorImageInfo imageInfoDebugTexture; - imageInfoDebugTexture.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - - if (texturesAreOnionTextures) - { - imageInfoDebugTexture.imageView = _textureHandler->GetDebugOnionTextureImageView(); - } - else - { - imageInfoDebugTexture.imageView = _textureHandler->GetDebugTextureImageView(); - } - - imageInfoDebugTexture.sampler = VK_NULL_HANDLE; - - for (u32 i = numTextures; i < textureArraySize; i++) - { - VkDescriptorImageInfo& imageInfo = imageInfos[numImageInfos++]; - imageInfo = imageInfoDebugTexture; - } - - builder.BindImageArray(descriptor.nameHash, imageInfos, textureArraySize); - } - else if (descriptor.descriptorType == DescriptorType::DESCRIPTOR_TYPE_TEXTURE_WRITE) - { - ZoneScopedN("TextureWrite"); - VkDescriptorImageInfo* imageInfos = Memory::Allocator::NewArray(&_frameAllocator, descriptor.count); - u32 numImageInfos = 0; - - TextureBaseDesc textureDesc = _textureHandler->GetTextureDesc(descriptor.textureID); - - for (u32 i = 0; i < descriptor.count; i++) - { - u32 mipLevel = descriptor.imageMipLevel + i; - - if ((i32)mipLevel < textureDesc.mipLevels) - { - VkDescriptorImageInfo& imageInfo = imageInfos[numImageInfos++]; - imageInfo.imageLayout = VK_IMAGE_LAYOUT_GENERAL; - imageInfo.imageView = _textureHandler->GetImageView(descriptor.textureID, mipLevel); - imageInfo.sampler = VK_NULL_HANDLE; - } - else - { - // Any imageInfos pointing to mips we don't have should point to the last mip - VkDescriptorImageInfo& imageInfo = imageInfos[numImageInfos++]; - imageInfo.imageLayout = VK_IMAGE_LAYOUT_GENERAL; - imageInfo.imageView = _textureHandler->GetImageView(descriptor.textureID, textureDesc.mipLevels - 1); - imageInfo.sampler = VK_NULL_HANDLE; - } - } - - builder.BindStorageImage(descriptor.nameHash, imageInfos, static_cast(descriptor.count)); - } - else if (descriptor.descriptorType == DescriptorType::DESCRIPTOR_TYPE_TEXTURE_READ_WRITE) - { - ZoneScopedN("TextureReadWrite"); - VkDescriptorImageInfo imageInfo = {}; - imageInfo.imageLayout = VK_IMAGE_LAYOUT_GENERAL; - imageInfo.imageView = _textureHandler->GetImageView(descriptor.textureID); - - builder.BindImage(descriptor.nameHash, imageInfo); - } - else if (descriptor.descriptorType == DescriptorType::DESCRIPTOR_TYPE_IMAGE) - { - ZoneScopedN("Image"); - VkDescriptorImageInfo imageInfo = {}; - imageInfo.imageLayout = VK_IMAGE_LAYOUT_GENERAL; - imageInfo.imageView = _imageHandler->GetColorView(descriptor.imageID,descriptor.imageMipLevel); - - builder.BindImage(descriptor.nameHash, imageInfo); - } - else if (descriptor.descriptorType == DescriptorType::DESCRIPTOR_TYPE_IMAGE_ARRAY) - { - ZoneScopedN("ImageArray"); - VkDescriptorImageInfo imageInfo = {}; - imageInfo.imageLayout = VK_IMAGE_LAYOUT_GENERAL; - imageInfo.imageView = _imageHandler->GetColorView(descriptor.imageID, descriptor.imageMipLevel); - - builder.BindImageArrayIndex(descriptor.nameHash, imageInfo, descriptor.arrayIndex); - } - else if (descriptor.descriptorType == DescriptorType::DESCRIPTOR_TYPE_DEPTH_IMAGE) - { - ZoneScopedN("DepthImage"); - VkDescriptorImageInfo imageInfo = {}; - imageInfo.imageLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL; - imageInfo.imageView = _imageHandler->GetDepthView(descriptor.depthImageID); - - builder.BindImage(descriptor.nameHash, imageInfo); - } - else if (descriptor.descriptorType == DescriptorType::DESCRIPTOR_TYPE_DEPTH_IMAGE_ARRAY) - { - ZoneScopedN("DepthImageArray"); - VkDescriptorImageInfo imageInfo = {}; - imageInfo.imageLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL; - imageInfo.imageView = _imageHandler->GetDepthView(descriptor.depthImageID); - - builder.BindImageArrayIndex(descriptor.nameHash, imageInfo, descriptor.arrayIndex); - } - else if (descriptor.descriptorType == DescriptorType::DESCRIPTOR_TYPE_STORAGE_IMAGE) - { - ZoneScopedN("StorageImage"); - VkDescriptorImageInfo* imageInfos = Memory::Allocator::NewArray(&_frameAllocator, descriptor.count); - u32 numImageInfos = 0; - - const ImageDesc& imageDesc = _imageHandler->GetImageDesc(descriptor.imageID); - - for (u32 i = 0; i < descriptor.count; i++) - { - u32 mipLevel = descriptor.imageMipLevel + i; - - if (mipLevel < imageDesc.mipLevels) - { - VkDescriptorImageInfo& imageInfo = imageInfos[numImageInfos++]; - imageInfo.imageLayout = VK_IMAGE_LAYOUT_GENERAL; - imageInfo.imageView = _imageHandler->GetColorView(descriptor.imageID, mipLevel); - imageInfo.sampler = VK_NULL_HANDLE; - } - else - { - // Any imageInfos pointing to mips we don't have should point to the last mip - VkDescriptorImageInfo& imageInfo = imageInfos[numImageInfos++]; - imageInfo.imageLayout = VK_IMAGE_LAYOUT_GENERAL; - imageInfo.imageView = _imageHandler->GetColorView(descriptor.imageID, imageDesc.mipLevels - 1); - imageInfo.sampler = VK_NULL_HANDLE; - } - } - - builder.BindStorageImage(descriptor.nameHash, imageInfos, static_cast(descriptor.count)); - } - else if (descriptor.descriptorType == DescriptorType::DESCRIPTOR_TYPE_STORAGE_IMAGE_ARRAY) - { - ZoneScopedN("StorageImageArray"); - VkDescriptorImageInfo* imageInfos = Memory::Allocator::NewArray(&_frameAllocator, descriptor.count); - u32 numImageInfos = 0; - - const ImageDesc& imageDesc = _imageHandler->GetImageDesc(descriptor.imageID); - - for (u32 i = 0; i < descriptor.count; i++) - { - u32 mipLevel = descriptor.imageMipLevel + i; - - if (mipLevel < imageDesc.mipLevels) - { - VkDescriptorImageInfo& imageInfo = imageInfos[numImageInfos++]; - imageInfo.imageLayout = VK_IMAGE_LAYOUT_GENERAL; - imageInfo.imageView = _imageHandler->GetColorArrayView(descriptor.imageID, mipLevel); - imageInfo.sampler = VK_NULL_HANDLE; - } - else - { - // Any imageInfos pointing to mips we don't have should point to the last mip - VkDescriptorImageInfo& imageInfo = imageInfos[numImageInfos++]; - imageInfo.imageLayout = VK_IMAGE_LAYOUT_GENERAL; - imageInfo.imageView = _imageHandler->GetColorArrayView(descriptor.imageID, imageDesc.mipLevels - 1); - imageInfo.sampler = VK_NULL_HANDLE; - } - } - - builder.BindStorageImageArray(descriptor.nameHash, imageInfos, static_cast(descriptor.count)); - } - } - void RendererVK::RecreateSwapChain(Backend::SwapChainVK* swapChain) { _device->RecreateSwapChain(_imageHandler, _semaphoreHandler, swapChain); @@ -1502,7 +1386,7 @@ namespace Renderer destroyList.buffers.clear(); } - void RendererVK::BindDescriptorSet(CommandListID commandListID, DescriptorSetSlot slot, Descriptor* descriptors, u32 numDescriptors, const TrackedBufferBitSets* bufferPermissions) + void RendererVK::BindDescriptorSet(CommandListID commandListID, DescriptorSet* descriptorSet, const TrackedBufferBitSets* bufferPermissions) { ZoneScopedNC("RendererVK::BindDescriptorSet", tracy::Color::Red3); @@ -1510,55 +1394,38 @@ namespace Renderer GraphicsPipelineID graphicsPipelineID = _commandListHandler->GetBoundGraphicsPipeline(commandListID); ComputePipelineID computePipelineID = _commandListHandler->GetBoundComputePipeline(commandListID); + DescriptorSetID descriptorSetID = descriptorSet->GetID(); + + VkDescriptorSet vkDescriptorSet = _descriptorHandler->GetVkDescriptorSet(descriptorSetID, _frameIndex); + u32 slot = static_cast(descriptorSet->GetSlot()); + if (graphicsPipelineID != GraphicsPipelineID::Invalid()) { - if (_pipelineHandler->GetNumDescriptorSetLayouts(graphicsPipelineID) <= static_cast(slot)) + /*if (_pipelineHandler->GetNumDescriptorSetLayouts(graphicsPipelineID) <= slot) { return; - } - - Backend::DescriptorSetBuilderVK& builder = _pipelineHandler->GetDescriptorSetBuilder(graphicsPipelineID); - builder.SetBufferPermissions(bufferPermissions); + }*/ - for (u32 i = 0; i < numDescriptors; i++) - { - ZoneScopedNC("BindDescriptor", tracy::Color::Red3); - Descriptor& descriptor = descriptors[i]; - BindDescriptor(builder, descriptor); - } - - VkDescriptorSet descriptorSet = builder.BuildDescriptorSet(static_cast(slot), Backend::DescriptorLifetime::PerFrame); - Backend::DebugMarkerUtilVK::SetObjectName(_device->_device, (u64)descriptorSet, VK_OBJECT_TYPE_DESCRIPTOR_SET, DescriptorSetToName(slot)); + // TODO: Validate buffer permissions VkPipelineLayout pipelineLayout = _pipelineHandler->GetPipelineLayout(graphicsPipelineID); // Bind descriptor set - vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, slot, 1, &descriptorSet, 0, nullptr); - } + vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, slot, 1, &vkDescriptorSet, 0, nullptr); + } else if (computePipelineID != ComputePipelineID::Invalid()) { - if (_pipelineHandler->GetNumDescriptorSetLayouts(computePipelineID) <= static_cast(slot)) + /*if (_pipelineHandler->GetNumDescriptorSetLayouts(computePipelineID) <= slot) { return; - } - - Backend::DescriptorSetBuilderVK& builder = _pipelineHandler->GetDescriptorSetBuilder(computePipelineID); - builder.SetBufferPermissions(bufferPermissions); - - for (u32 i = 0; i < numDescriptors; i++) - { - ZoneScopedNC("BindDescriptor", tracy::Color::Red3); - Descriptor& descriptor = descriptors[i]; - BindDescriptor(builder, descriptor); - } + }*/ - VkDescriptorSet descriptorSet = builder.BuildDescriptorSet(static_cast(slot), Backend::DescriptorLifetime::PerFrame); - Backend::DebugMarkerUtilVK::SetObjectName(_device->_device, (u64)descriptorSet, VK_OBJECT_TYPE_DESCRIPTOR_SET, DescriptorSetToName(slot)); + // TODO: Validate buffer permissions VkPipelineLayout pipelineLayout = _pipelineHandler->GetPipelineLayout(computePipelineID); // Bind descriptor set - vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, slot, 1, &descriptorSet, 0, nullptr); + vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, slot, 1, &vkDescriptorSet, 0, nullptr); } } @@ -1572,9 +1439,6 @@ namespace Renderer // Add a marker specifying the frameIndex Backend::DebugMarkerUtilVK::PushMarker(commandBuffer, Color(1,1,1,1), std::to_string(frameIndex)); Backend::DebugMarkerUtilVK::PopMarker(commandBuffer); - - // Free up any old descriptors - _device->_descriptorMegaPool->SetFrame(frameIndex); } #if !TRACY_ENABLE @@ -1799,36 +1663,27 @@ namespace Renderer GraphicsPipelineID graphicsPipelineID = _commandListHandler->GetBoundGraphicsPipeline(commandListID); + VkShaderStageFlags shaderStageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT | VK_SHADER_STAGE_COMPUTE_BIT; + VkPipelineLayout layout; + if (graphicsPipelineID != GraphicsPipelineID::Invalid()) { - VkShaderStageFlags shaderStageFlags = 0; - - u32 numPushConstantRanges = _pipelineHandler->GetNumPushConstantRanges(graphicsPipelineID); - for (u32 i = 0; i < numPushConstantRanges; i++) + layout = _pipelineHandler->GetPipelineLayout(graphicsPipelineID); + } + else + { + ComputePipelineID computePipelineID = _commandListHandler->GetBoundComputePipeline(commandListID); + if (computePipelineID != ComputePipelineID::Invalid()) { - const VkPushConstantRange& constantRange = _pipelineHandler->GetPushConstantRange(graphicsPipelineID, i); - - if (offset >= constantRange.offset && offset < constantRange.offset + constantRange.size) - { - shaderStageFlags |= constantRange.stageFlags; - } + layout = _pipelineHandler->GetPipelineLayout(computePipelineID); } - - if (shaderStageFlags == 0) + else { - NC_LOG_CRITICAL("RendererVK::PushConstant : shaderStageFlags was 0, did we try to push a constant that doesn't exist?"); + NC_LOG_CRITICAL("Tried to push constants without a bound graphics or compute pipeline"); + return; } - - VkPipelineLayout layout = _pipelineHandler->GetPipelineLayout(graphicsPipelineID); - vkCmdPushConstants(commandBuffer, layout, shaderStageFlags, offset, size, data); - } - - ComputePipelineID computePipelineID = _commandListHandler->GetBoundComputePipeline(commandListID); - if (computePipelineID != ComputePipelineID::Invalid()) - { - VkPipelineLayout layout = _pipelineHandler->GetPipelineLayout(computePipelineID); - vkCmdPushConstants(commandBuffer, layout, VkShaderStageFlagBits::VK_SHADER_STAGE_COMPUTE_BIT, offset, size, data); } + vkCmdPushConstants(commandBuffer, layout, shaderStageFlags, offset, size, data); } void RendererVK::Present(Novus::Window* window, ImageID imageID, SemaphoreID semaphoreID) @@ -1943,55 +1798,32 @@ namespace Renderer BeginRenderPass(commandListID, renderPassDesc); ImageDesc imageDesc = _imageHandler->GetImageDesc(imageID); - ImageComponentType componentType = ToImageComponentType(imageDesc.format); - std::string componentTypeName = ""; - - switch (componentType) - { - case ImageComponentType::FLOAT: - case ImageComponentType::SNORM: - case ImageComponentType::UNORM: - componentTypeName = "float"; - break; - case ImageComponentType::SINT: - componentTypeName = "int"; - break; - case ImageComponentType::UINT: - componentTypeName = "uint"; - break; - - default: - break; - } - - u8 componentCount = ToImageComponentCount(imageDesc.format); - if (componentCount > 1) - { - componentTypeName += std::to_string(componentCount); - } + + std::string componentTypeName = GetTextureTypeName(imageDesc.format); u32 componentTypeNameHash = StringUtils::fnv1a_32(componentTypeName.c_str(), componentTypeName.size()); GraphicsPipelineID pipelineID = GetBlitPipeline(componentTypeNameHash); VkPipelineLayout pipelineLayout = _pipelineHandler->GetPipelineLayout(pipelineID); - Backend::DescriptorSetBuilderVK& builder = _pipelineHandler->GetDescriptorSetBuilder(pipelineID); + + if (!_presentDescriptorSet.IsInitialized()) + { + _presentDescriptorSet.RegisterPipeline(this, pipelineID); + _presentDescriptorSet.Init(this); + } BeginPipeline(commandListID, pipelineID); SetViewport(commandListID, _lastViewport); SetScissorRect(commandListID, _lastScissorRect); - // Set descriptors - VkDescriptorImageInfo samplerInfo = {}; - samplerInfo.sampler = _samplerHandler->GetSampler(samplerID); - builder.BindSampler("_sampler"_h, samplerInfo); - - VkDescriptorImageInfo imageInfo = {}; - imageInfo.imageLayout = VK_IMAGE_LAYOUT_GENERAL; - imageInfo.imageView = _imageHandler->GetColorView(imageID); - builder.BindImage("_texture"_h, imageInfo); - - VkDescriptorSet descriptorSet = builder.BuildDescriptorSet(DescriptorSetSlot::PER_PASS, Backend::DescriptorLifetime::PerFrame); + VkSampler vkSampler = _samplerHandler->GetSampler(samplerID); + VkImageView vkImageView = _imageHandler->GetColorView(imageID); + DescriptorSetID descriptorSetID = _presentDescriptorSet.GetID(); + _descriptorHandler->BindDescriptor(descriptorSetID, 0, vkSampler, frameIndex); + _descriptorHandler->BindDescriptor(descriptorSetID, 1, vkImageView, DescriptorType::SampledImage, false, frameIndex); + + VkDescriptorSet descriptorSet = _descriptorHandler->GetVkDescriptorSet(descriptorSetID, _frameIndex); vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, DescriptorSetSlot::PER_PASS, 1, &descriptorSet, 0, nullptr); struct BlitConstant @@ -2009,7 +1841,7 @@ namespace Renderer blitConstant.channelRedirectors |= (2 << 16); blitConstant.channelRedirectors |= (3 << 24); - vkCmdPushConstants(commandBuffer, pipelineLayout, VkShaderStageFlagBits::VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(BlitConstant), &blitConstant); + vkCmdPushConstants(commandBuffer, pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT | VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(BlitConstant), &blitConstant); vkCmdDraw(commandBuffer, 3, 1, 0, 0); @@ -2224,14 +2056,4 @@ namespace Renderer { return _device->HasExtendedTextureSupport(); } - - void RendererVK::GetDescriptorMetaFromPipeline(DescriptorMetaInfo& metaInfo, GraphicsPipelineID pipeline, DescriptorSetSlot slot) - { - _pipelineHandler->GetDescriptorMetaFromPipeline(metaInfo, pipeline, slot); - } - - void RendererVK::GetDescriptorMetaFromPipeline(DescriptorMetaInfo& metaInfo, ComputePipelineID pipeline, DescriptorSetSlot slot) - { - _pipelineHandler->GetDescriptorMetaFromPipeline(metaInfo, pipeline, slot); - } } diff --git a/Source/Renderer/Renderer/Renderers/Vulkan/RendererVK.h b/Source/Renderer/Renderer/Renderers/Vulkan/RendererVK.h index a040c1be..5e68c449 100644 --- a/Source/Renderer/Renderer/Renderers/Vulkan/RendererVK.h +++ b/Source/Renderer/Renderer/Renderers/Vulkan/RendererVK.h @@ -1,5 +1,5 @@ #pragma once -#include +#include "Renderer/Renderer.h" #include @@ -12,21 +12,21 @@ namespace Renderer { namespace Backend { - class RenderDeviceVK; + struct BindInfo; class BufferHandlerVK; + class CommandListHandlerVK; + class DescriptorHandlerVK; + class DescriptorSetBuilderVK; class ImageHandlerVK; - class TextureHandlerVK; - class ShaderHandlerVK; class PipelineHandlerVK; - class CommandListHandlerVK; + class RenderDeviceVK; class SamplerHandlerVK; class SemaphoreHandlerVK; - class UploadBufferHandlerVK; - class TimeQueryHandlerVK; - struct BindInfo; - class DescriptorSetBuilderVK; + class ShaderHandlerVK; struct SwapChainVK; - class DescriptorSetBuilderVK; + class TextureHandlerVK; + class TimeQueryHandlerVK; + class UploadBufferHandlerVK; } class RendererVK : public Renderer @@ -60,6 +60,8 @@ namespace Renderer [[nodiscard]] SamplerID CreateSampler(SamplerDesc& desc) override; [[nodiscard]] SemaphoreID CreateNSemaphore() override; + [[nodiscard]] DescriptorSetID CreateDescriptorSet(const DescriptorSetDesc& desc) override; + [[nodiscard]] GraphicsPipelineID CreatePipeline(GraphicsPipelineDesc& desc) override; [[nodiscard]] ComputePipelineID CreatePipeline(ComputePipelineDesc& desc) override; @@ -81,9 +83,22 @@ namespace Renderer // Unloading void UnloadTexture(TextureID textureID) override; void UnloadTexturesInArray(TextureArrayID textureArrayID, u32 unloadStartIndex) override; + + // Descriptor binding + void BindDescriptor(DescriptorSetID descriptorSetID, u32 bindingIndex, BufferID bufferID, DescriptorType type, u32 frameIndex) override; + void BindDescriptor(DescriptorSetID descriptorSetID, u32 bindingIndex, ImageID imageID, u32 mipLevel, DescriptorType type, u32 frameIndex) override; + void BindDescriptorArray(DescriptorSetID descriptorSetID, u32 bindingIndex, ImageID imageID, u32 mipLevel, u32 mipCount, DescriptorType type, u32 frameIndex) override; + void BindDescriptor(DescriptorSetID descriptorSetID, u32 bindingIndex, DepthImageID imageID, DescriptorType type, u32 frameIndex) override; + void BindDescriptorArray(DescriptorSetID descriptorSetID, u32 bindingIndex, DepthImageID imageID, u32 arrayIndex, DescriptorType type, u32 frameIndex) override; + void BindDescriptor(DescriptorSetID descriptorSetID, u32 bindingIndex, SamplerID samplerID, u32 frameIndex) override; + void BindDescriptorArray(DescriptorSetID descriptorSetID, u32 bindingIndex, SamplerID samplerID, u32 arrayIndex, u32 frameIndex) override; + void BindDescriptor(DescriptorSetID descriptorSetID, u32 bindingIndex, TextureID textureID, u32 mipLevel, DescriptorType type, u32 frameIndex) override; + void BindDescriptorArray(DescriptorSetID descriptorSetID, u32 bindingIndex, TextureID textureID, u32 mipLevel, u32 mipCount, DescriptorType type, u32 frameIndex) override; + void BindDescriptor(DescriptorSetID descriptorSetID, u32 bindingIndex, TextureArrayID textureArrayID) override; // Misc u32 AddTextureToArray(TextureID textureID, TextureArrayID textureArrayID) override; + void FlushTextureArrayDescriptors(TextureArrayID textureArrayID) override; // Command List Functions [[nodiscard]] CommandListID BeginCommandList() override; @@ -129,7 +144,7 @@ namespace Renderer void SetIndexBuffer(CommandListID commandListID, BufferID bufferID, IndexFormat indexFormat) override; void SetBuffer(CommandListID commandListID, u32 slot, BufferID buffer) override; - void BindDescriptorSet(CommandListID commandListID, DescriptorSetSlot slot, Descriptor* descriptors, u32 numDescriptors, const TrackedBufferBitSets* bufferPermissions) override; + void BindDescriptorSet(CommandListID commandListID, DescriptorSet* descriptorSet, const TrackedBufferBitSets* bufferPermissions) override; void MarkFrameStart(CommandListID commandListID, u32 frameIndex) override; void BeginTrace(CommandListID commandListID, const tracy::SourceLocationData* sourceLocation) override; @@ -173,18 +188,30 @@ namespace Renderer [[nodiscard]] const std::string& GetTimeQueryName(TimeQueryID id) override; [[nodiscard]] f32 GetLastTimeQueryDuration(TimeQueryID id) override; + // ID to Descriptor + [[nodiscard]] TextureBaseDesc GetDesc(TextureID textureID); + + [[nodiscard]] const ImageDesc& GetDesc(ImageID ID); + [[nodiscard]] const DepthImageDesc& GetDesc(DepthImageID ID); + + [[nodiscard]] const ComputePipelineDesc& GetDesc(ComputePipelineID ID); + [[nodiscard]] const GraphicsPipelineDesc& GetDesc(GraphicsPipelineID ID); + + [[nodiscard]] const ComputeShaderDesc& GetDesc(ComputeShaderID ID); + [[nodiscard]] const VertexShaderDesc& GetDesc(VertexShaderID ID); + [[nodiscard]] const PixelShaderDesc& GetDesc(PixelShaderID ID); + // Utils // Flush will wait until any in-flight frames are done void FlushGPU() override; f32 FlipFrame(u32 frameIndex) override; + [[nodiscard]] u32 GetCurrentFrameIndex() override; + [[nodiscard]] u32 GetFrameIndexCount() override; + void ResetTimeQueries(u32 frameIndex) override; [[nodiscard]] TextureID GetTextureID(TextureArrayID textureArrayID, u32 index) override; - [[nodiscard]] TextureBaseDesc GetTextureDesc(TextureID textureID) override; - - [[nodiscard]] const ImageDesc& GetImageDesc(ImageID ID) override; - [[nodiscard]] const DepthImageDesc& GetImageDesc(DepthImageID ID) override; [[nodiscard]] uvec2 GetImageDimensions(const ImageID id, u32 mipLevel = 0) override; [[nodiscard]] uvec2 GetImageDimensions(const DepthImageID id) override; @@ -208,12 +235,8 @@ namespace Renderer bool HasExtendedTextureSupport() override; - void GetDescriptorMetaFromPipeline(DescriptorMetaInfo& metaInfo, GraphicsPipelineID pipeline, DescriptorSetSlot slot) override; - void GetDescriptorMetaFromPipeline(DescriptorMetaInfo& metaInfo, ComputePipelineID pipeline, DescriptorSetSlot slot) override; - private: [[nodiscard]] bool ReflectDescriptorSet(const std::string& name, u32 nameHash, u32 type, i32& set, const std::vector& bindInfos, u32& outBindInfoIndex, VkDescriptorSetLayoutBinding* outDescriptorLayoutBinding); - void BindDescriptor(Backend::DescriptorSetBuilderVK& builder, Descriptor& descriptor); void RecreateSwapChain(Backend::SwapChainVK* swapChain); void CreateDummyPipeline(); @@ -221,20 +244,22 @@ namespace Renderer private: Backend::RenderDeviceVK* _device = nullptr; Backend::BufferHandlerVK* _bufferHandler = nullptr; + Backend::DescriptorHandlerVK* _descriptorHandler = nullptr; + Backend::CommandListHandlerVK* _commandListHandler = nullptr; Backend::ImageHandlerVK* _imageHandler = nullptr; - Backend::TextureHandlerVK* _textureHandler = nullptr; - Backend::ShaderHandlerVK* _shaderHandler = nullptr; Backend::PipelineHandlerVK* _pipelineHandler = nullptr; - Backend::CommandListHandlerVK* _commandListHandler = nullptr; Backend::SamplerHandlerVK* _samplerHandler = nullptr; Backend::SemaphoreHandlerVK* _semaphoreHandler = nullptr; - Backend::UploadBufferHandlerVK* _uploadBufferHandler = nullptr; + Backend::ShaderHandlerVK* _shaderHandler = nullptr; + Backend::TextureHandlerVK* _textureHandler = nullptr; Backend::TimeQueryHandlerVK* _timeQueryHandler = nullptr; + Backend::UploadBufferHandlerVK* _uploadBufferHandler = nullptr; Memory::StackAllocator _frameAllocator; + u32 _frameIndex = 0; GraphicsPipelineID _globalDummyPipeline = GraphicsPipelineID::Invalid(); - //Backend::DescriptorSetBuilderVK* _descriptorSetBuilder = nullptr; + DescriptorSet _presentDescriptorSet; Viewport _lastViewport; ScissorRect _lastScissorRect; diff --git a/Source/Renderer/Renderer/ShaderEntry.h b/Source/Renderer/Renderer/ShaderEntry.h index b6449c6a..9742f0c2 100644 --- a/Source/Renderer/Renderer/ShaderEntry.h +++ b/Source/Renderer/Renderer/ShaderEntry.h @@ -4,6 +4,8 @@ #include #include +#include + #include namespace Renderer @@ -33,7 +35,10 @@ namespace Renderer { std::string debugName; u32 permutationNameHash; + u8* shaderData = nullptr; u32 shaderSize = 0; + + FileFormat::ShaderReflection reflection; }; } \ No newline at end of file diff --git a/Source/Renderer/Renderer/Window.cpp b/Source/Renderer/Renderer/Window.cpp index 910c4385..1562e336 100644 --- a/Source/Renderer/Renderer/Window.cpp +++ b/Source/Renderer/Renderer/Window.cpp @@ -2,6 +2,7 @@ #include +#include #include namespace Novus @@ -59,7 +60,11 @@ namespace Novus bool Window::Update(f32 deltaTime) { - glfwPollEvents(); + { + ZoneScopedN("glfwPollEvents"); + glfwPollEvents(); + } + if (glfwWindowShouldClose(_window)) { diff --git a/Source/ShaderCooker/ShaderCooker/ShaderCompiler.cpp b/Source/ShaderCooker/ShaderCooker/ShaderCompiler.cpp index 5a9bffe2..29195fb6 100644 --- a/Source/ShaderCooker/ShaderCooker/ShaderCompiler.cpp +++ b/Source/ShaderCooker/ShaderCooker/ShaderCompiler.cpp @@ -164,7 +164,7 @@ namespace ShaderCooker std::string path = itr->make_preferred().string(); if (fs::exists(*itr)) { - if (fs::is_regular_file(*itr) && itr->extension() == ".hlsl") + if (fs::is_regular_file(*itr) && itr->extension() == ".slang") { //std::transform(path.begin(), path.end(), path.begin(), ::tolower); u32 strHash = StringUtils::fnv1a_32(path.c_str(), path.length()); @@ -195,7 +195,10 @@ namespace ShaderCooker shader.fileBufferSize = shader.source.length(); if (!Lexer::Process(shader) || !Parser::CheckSyntax(shader) || !Parser::ResolveIncludes(this, shader)) + { _shaders.pop_back(); + _numFailedShaders++; + } else _shaderHashToIndex[strHash] = static_cast(_shaders.size() - 1); } @@ -260,7 +263,7 @@ namespace ShaderCooker if (!shader.hasResolvedIncludes) continue; - if (StringUtils::EndsWith(shader.name, ".inc.hlsl")) + if (StringUtils::EndsWith(shader.name, ".inc.slang")) { _shaderCache->Touch(shader.path); continue; @@ -415,21 +418,26 @@ namespace ShaderCooker void ShaderCompiler::GetPermutationFilename(const Shader& shader, u32 permutationID, const std::string& inputFileName, std::string& filename) { filename = inputFileName; - size_t offset = filename.find_first_of('.'); + // Strip .slang from the extension + size_t offset = filename.find_last_of('.'); + filename = filename.substr(0, offset); + + // Extract the .ps/.vs/.cs into its own string + offset = filename.find_first_of('.'); std::string extension = filename.substr(offset); filename = filename.substr(0, offset); + // Add permutation data to the filename const Permutation& permutation = shader.permutations[permutationID]; - for (u32 i = 0; i < permutation.defines.size(); i++) { const Define& define = permutation.defines[i]; filename += "-" + define.name + define.value; } + // Add back the extension (without .slang) filename += extension; std::replace(filename.begin(), filename.end(), '\\', '/'); } - } diff --git a/Source/ShaderCooker/ShaderCooker/SlangBridge.cpp b/Source/ShaderCooker/ShaderCooker/SlangBridge.cpp index 144556a3..55242ceb 100644 --- a/Source/ShaderCooker/ShaderCooker/SlangBridge.cpp +++ b/Source/ShaderCooker/ShaderCooker/SlangBridge.cpp @@ -231,6 +231,206 @@ namespace ShaderCooker return StringUtils::fnv1a_32(shaderPath.string().c_str(), shaderPath.string().length()); } + FileFormat::DescriptorTypeReflection GetDescriptorTypeReflection(slang::TypeLayoutReflection* typeLayout, u32& count) + { + slang::TypeReflection::Kind kind = typeLayout->getKind(); + switch (kind) + { + case slang::TypeReflection::Kind::ConstantBuffer: + { + return FileFormat::DescriptorTypeReflection::ConstantBuffer; + } + case slang::TypeReflection::Kind::SamplerState: + { + return FileFormat::DescriptorTypeReflection::SamplerState; + } + case slang::TypeReflection::Kind::Resource: + { + SlangResourceShape shape = typeLayout->getResourceShape(); + + switch (shape) + { + case SlangResourceShape::SLANG_BYTE_ADDRESS_BUFFER: + return FileFormat::DescriptorTypeReflection::ByteAddressBuffer; + case SlangResourceShape::SLANG_STRUCTURED_BUFFER: + return FileFormat::DescriptorTypeReflection::StructuredBuffer; + case SlangResourceShape::SLANG_TEXTURE_1D: + case SlangResourceShape::SLANG_TEXTURE_2D: + case SlangResourceShape::SLANG_TEXTURE_3D: + case SlangResourceShape::SLANG_TEXTURE_CUBE: + return FileFormat::DescriptorTypeReflection::Texture; + case SlangResourceShape::SLANG_TEXTURE_1D_ARRAY: + case SlangResourceShape::SLANG_TEXTURE_2D_ARRAY: + case SlangResourceShape::SLANG_TEXTURE_CUBE_ARRAY: + return FileFormat::DescriptorTypeReflection::TextureArray; + default: + NC_LOG_CRITICAL("Unsupported resource shape {0} in GetDescriptorTypeReflection", static_cast(shape)); + } + break; + } + case slang::TypeReflection::Kind::Array: + { + size_t elementCount = typeLayout->getElementCount(); + if (elementCount == ~size_t(0)) + { + // Unbounded array + count = 0; // 0 means it's gonna be unbounded + } + else + { + count = static_cast(elementCount); + } + return FileFormat::DescriptorTypeReflection::Array; + } + } + + NC_LOG_CRITICAL("Unsupported type kind {0} in GetDescriptorTypeReflection", static_cast(kind)); + return FileFormat::DescriptorTypeReflection::Unknown; + } + + FileFormat::DescriptorAccessTypeReflection ToAccessType(SlangResourceAccess access) + { + switch(access) + { + case SLANG_RESOURCE_ACCESS_NONE: + return FileFormat::DescriptorAccessTypeReflection::None; + case SLANG_RESOURCE_ACCESS_READ: + return FileFormat::DescriptorAccessTypeReflection::Read; + case SLANG_RESOURCE_ACCESS_READ_WRITE: + return FileFormat::DescriptorAccessTypeReflection::ReadWrite; + case SLANG_RESOURCE_ACCESS_RASTER_ORDERED: + return FileFormat::DescriptorAccessTypeReflection::RasterOrdered; + case SLANG_RESOURCE_ACCESS_APPEND: + return FileFormat::DescriptorAccessTypeReflection::Append; + case SLANG_RESOURCE_ACCESS_CONSUME: + return FileFormat::DescriptorAccessTypeReflection::Consume; + case SLANG_RESOURCE_ACCESS_WRITE: + return FileFormat::DescriptorAccessTypeReflection::Write; + case SLANG_RESOURCE_ACCESS_FEEDBACK: + return FileFormat::DescriptorAccessTypeReflection::Feedback; + } + + return FileFormat::DescriptorAccessTypeReflection::None; + } + + bool ReflectDescriptors(slang::ProgramLayout* programLayout, Slang::ComPtr entryPointMetadata, FileFormat::ShaderReflection& out) + { + SlangResult result; + bool success = true; + + u32 parameterCount = programLayout->getParameterCount(); + + for (u32 i = 0; i < parameterCount; i++) + { + slang::VariableLayoutReflection* variableLayout = programLayout->getParameterByIndex(i); + slang::TypeLayoutReflection* typeLayout = variableLayout->getTypeLayout(); + + u32 slot = variableLayout->getBindingSpace(); + const char* name = variableLayout->getName(); + u32 binding = variableLayout->getBindingIndex(); + FileFormat::DescriptorAccessTypeReflection accessType = ToAccessType(typeLayout->getResourceAccess()); + bool isUsed; + u32 byteOffset = 0; + u32 byteSize = 0; + + if (slot == 4) + { + volatile int asd = 123; + } + + SlangParameterCategory category = static_cast(variableLayout->getCategory()); + result = entryPointMetadata->isParameterLocationUsed(category, slot, binding, isUsed); + NC_ASSERT(SLANG_SUCCEEDED(result), "Failed to get parameter usage from metadata"); + + u32 count = 1; + FileFormat::DescriptorTypeReflection type = GetDescriptorTypeReflection(typeLayout, count); + FileFormat::DescriptorTypeReflection subType = FileFormat::DescriptorTypeReflection::Unknown; + + // Get byteOffset and byteSize for ConstantBuffer types (push constants) + if (type == FileFormat::DescriptorTypeReflection::ConstantBuffer) + { + byteOffset = static_cast(variableLayout->getOffset(slang::ParameterCategory::Uniform)); + slang::TypeLayoutReflection* elementTypeLayout = typeLayout->getElementTypeLayout(); + if (elementTypeLayout) + { + byteSize = static_cast(elementTypeLayout->getSize(SLANG_PARAMETER_CATEGORY_UNIFORM)); + } + } + + if (slot == 0) + { + if (type != FileFormat::DescriptorTypeReflection::ConstantBuffer) + { + // Slot 0 is reserved for push constants + NC_LOG_ERROR("Descriptor found in slot 0 which is reserved for push constants: {0} (binding {1})\n You probably wanted to use the PER_PASS or PER_DRAW macros", name, binding); + success = false; + continue; + } + if (byteSize == 0) + { + // Slot 0 is reserved for push constants + NC_LOG_ERROR("Push constant buffer has size 0: {0} (binding {1})", name, binding); + success = false; + continue; + } + } + + // Get the subtype if this is an array + if (type == FileFormat::DescriptorTypeReflection::Array) + { + slang::TypeLayoutReflection* elementTypeLayout = typeLayout->getElementTypeLayout(); + subType = GetDescriptorTypeReflection(elementTypeLayout, count); + } + + FileFormat::DescriptorSetReflection& descriptorSet = out.GetDescriptorSetBySlot(slot); + if (descriptorSet.descriptors.contains(binding)) + { + // Make sure the existing descriptor matches + FileFormat::DescriptorReflection& existingDescriptor = descriptorSet.descriptors[binding]; + + if (existingDescriptor.name != name || + existingDescriptor.type != type || + existingDescriptor.subType != subType || + existingDescriptor.count != count || + existingDescriptor.accessType != accessType || + existingDescriptor.isUsed != isUsed || + existingDescriptor.byteOffset != byteOffset || + existingDescriptor.byteSize != byteSize) + { + std::string existingDescriptorStr = existingDescriptor.ToString(); + std::string newDescriptorStr = FileFormat::DescriptorReflection{ .binding = binding, .name = name, .type = type, .subType = subType, .count = count }.ToString(); + NC_LOG_ERROR("Descriptor binding conflict at slot {0}, binding {1}:\nExisting: {2}\nNew: {3}", + slot, + binding, + existingDescriptorStr.c_str(), + newDescriptorStr.c_str()); + + success = false; + } + } + else + { + // New binding + FileFormat::DescriptorReflection descriptor; + descriptor.binding = binding; + descriptor.name = name; + descriptor.type = type; + descriptor.subType = subType; + descriptor.count = count; + descriptor.accessType = accessType; + descriptor.isUsed = isUsed; + descriptor.byteOffset = byteOffset; + descriptor.byteSize = byteSize; + + // TODO: Check so we don't have implicit padding (explicit padding is fine) + + descriptorSet.descriptors[binding] = descriptor; + } + } + + return success; + } + bool SlangBridge::Compile(std::filesystem::path path, const std::string& source, FileFormat::ShaderInMemory& shaderInMemory) { SlangBridgeData* data = static_cast(_data); @@ -246,9 +446,9 @@ namespace ShaderCooker // Set up defines std::vector defines; defines.reserve(32); - defines.push_back({ "DEBUG", "0" }); - defines.push_back({ "GLOBAL", "1" }); - defines.push_back({ "TILES", "2" }); + // 1 indexed because we let 0 be the push constants, it's not technically correct but we get nice error checking if we do this + defines.push_back({ "DEBUG", "1" }); + defines.push_back({ "GLOBAL", "2" }); defines.push_back({ "LIGHT", "3" }); defines.push_back({ "TERRAIN", "4" }); defines.push_back({ "MODEL", "5" }); @@ -359,6 +559,25 @@ namespace ShaderCooker return false; } + Slang::ComPtr entryPointMetadata; + result = linkedProgram->getEntryPointMetadata(0, 0, entryPointMetadata.writeRef(), data->diagnostics.writeRef()); + if (data->diagnostics) + { + std::string diagStr = { (char*)data->diagnostics->getBufferPointer(), data->diagnostics->getBufferSize() }; + NC_LOG_ERROR("[Slang] Get Entrypoint metadata: {0} ({1})", diagStr.c_str(), path.string().c_str()); + } + if (!SLANG_SUCCEEDED(result)) + { + NC_LOG_ERROR("[Slang] Failed to get entrypoint metadata ({0})", path.string().c_str()); + return false; + } + + // Reflect descriptors + if (!ReflectDescriptors(programLayout, entryPointMetadata, shaderInMemory.reflection)) + { + return false; + } + // Copy to output blob shaderInMemory.data = new u8[kernelBlob->getBufferSize()]; memcpy(shaderInMemory.data, kernelBlob->getBufferPointer(), kernelBlob->getBufferSize()); @@ -386,22 +605,22 @@ namespace ShaderCooker } } - // We expect filename to end with .XX.hlsl where XX is the profile of the shader, for example vs for vertex shader, ps for pixel shader, cs for compute etc - // First we remove the .hlsl part of the name - fs::path withoutHlsl = filename.replace_extension(); + // We expect filename to end with .XX.slang where XX is the profile of the shader, for example vs for vertex shader, ps for pixel shader, cs for compute etc + // First we remove the .slang part of the name + fs::path withoutSlang = filename.replace_extension(); - if (!withoutHlsl.has_extension()) + if (!withoutSlang.has_extension()) { - NC_LOG_ERROR("Filename \"{0}\" should end with .XX.hlsl where XX is one of these valid profiles depending on shader type: {1}", filename.string(), validProfiles); + NC_LOG_ERROR("Filename \"{0}\" should end with .XX.slang where XX is one of these valid profiles depending on shader type: {1}", filename.string(), validProfiles); return false; } - std::string extension = withoutHlsl.extension().string().substr(1); // Get the extension (.vs) as a string, then remove the first char which will be the "." + std::string extension = withoutSlang.extension().string().substr(1); // Get the extension (.vs) as a string, then remove the first char which will be the "." if (extension.length() != 2 && extension.length() != 3) { - NC_LOG_ERROR("Filename \"{0}\" should end with .XX.hlsl where XX is one of these valid profiles depending on shader type: {1}", filename.string(), validProfiles); + NC_LOG_ERROR("Filename \"{0}\" should end with .XX.slang where XX is one of these valid profiles depending on shader type: {1}", filename.string(), validProfiles); return false; } @@ -419,7 +638,7 @@ namespace ShaderCooker if (!isValidProfile) { - NC_LOG_ERROR("Filename \"{0}\" should end with .XX.hlsl where XX is one of these valid profiles depending on shader type: {1}", filename.string(), validProfiles); + NC_LOG_ERROR("Filename \"{0}\" should end with .XX.slang where XX is one of these valid profiles depending on shader type: {1}", filename.string(), validProfiles); return false; }