diff --git a/Source/Engine/GraphicsDevice/Vulkan/GPUBufferVulkan.cpp b/Source/Engine/GraphicsDevice/Vulkan/GPUBufferVulkan.cpp index 2acd2712c..ad16fbdbc 100644 --- a/Source/Engine/GraphicsDevice/Vulkan/GPUBufferVulkan.cpp +++ b/Source/Engine/GraphicsDevice/Vulkan/GPUBufferVulkan.cpp @@ -48,7 +48,6 @@ void GPUBufferViewVulkan::DescriptorAsUniformTexelBuffer(GPUContextVulkan* conte { ASSERT_LOW_LAYER(View != VK_NULL_HANDLE); bufferView = &View; - context->AddBufferBarrier(Owner, VK_ACCESS_SHADER_READ_BIT); } @@ -58,7 +57,13 @@ void GPUBufferViewVulkan::DescriptorAsStorageBuffer(GPUContextVulkan* context, V buffer = Buffer; offset = 0; range = Size; + context->AddBufferBarrier(Owner, VK_ACCESS_SHADER_READ_BIT); +} +void GPUBufferViewVulkan::DescriptorAsStorageTexelBuffer(GPUContextVulkan* context, const VkBufferView*& bufferView) +{ + ASSERT_LOW_LAYER(View != VK_NULL_HANDLE); + bufferView = &View; context->AddBufferBarrier(Owner, VK_ACCESS_SHADER_READ_BIT); } @@ -103,7 +108,7 @@ bool GPUBufferVulkan::OnInit() bufferInfo.usage |= VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; if (_desc.Flags & GPUBufferFlags::IndexBuffer) bufferInfo.usage |= VK_BUFFER_USAGE_INDEX_BUFFER_BIT; - if (IsStaging()) + if (IsStaging() || _desc.Flags & GPUBufferFlags::UnorderedAccess) bufferInfo.usage |= VK_BUFFER_USAGE_TRANSFER_SRC_BIT; // Create buffer diff --git a/Source/Engine/GraphicsDevice/Vulkan/GPUBufferVulkan.h b/Source/Engine/GraphicsDevice/Vulkan/GPUBufferVulkan.h index 2949c2725..4173be92f 100644 --- a/Source/Engine/GraphicsDevice/Vulkan/GPUBufferVulkan.h +++ b/Source/Engine/GraphicsDevice/Vulkan/GPUBufferVulkan.h @@ -50,6 +50,7 @@ public: // [DescriptorOwnerResourceVulkan] void DescriptorAsUniformTexelBuffer(GPUContextVulkan* context, const VkBufferView*& bufferView) override; void DescriptorAsStorageBuffer(GPUContextVulkan* context, VkBuffer& buffer, VkDeviceSize& offset, VkDeviceSize& range) override; + void DescriptorAsStorageTexelBuffer(GPUContextVulkan* context, const VkBufferView*& bufferView) override; }; /// @@ -80,7 +81,6 @@ public: /// /// Gets the Vulkan buffer handle. /// - /// The buffer handle. FORCE_INLINE VkBuffer GetHandle() const { return _buffer; @@ -89,7 +89,6 @@ public: /// /// Gets the Vulkan memory allocation handle. /// - /// The memory allocation handle. FORCE_INLINE VmaAllocation GetAllocation() const { return _allocation; diff --git a/Source/Engine/GraphicsDevice/Vulkan/GPUContextVulkan.cpp b/Source/Engine/GraphicsDevice/Vulkan/GPUContextVulkan.cpp index aafa7b6a6..13cb2333f 100644 --- a/Source/Engine/GraphicsDevice/Vulkan/GPUContextVulkan.cpp +++ b/Source/Engine/GraphicsDevice/Vulkan/GPUContextVulkan.cpp @@ -491,6 +491,20 @@ void GPUContextVulkan::UpdateDescriptorSets(const SpirvShaderDescriptorInfo& des needsWrite |= dsWriter.WriteStorageBuffer(descriptorIndex, buffer, offset, range); break; } + case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: + { + // Unordered Access (Buffer) + auto ua = handles[descriptor.Slot]; + if (!ua) + { + const auto dummy = _device->HelperResources.GetDummyBuffer(); + ua = (DescriptorOwnerResourceVulkan*)dummy->View()->GetNativePtr(); + } + const VkBufferView* bufferView; + ua->DescriptorAsStorageTexelBuffer(this, bufferView); + needsWrite |= dsWriter.WriteStorageTexelBuffer(descriptorIndex, bufferView); + break; + } case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: { // Constant Buffer @@ -916,6 +930,8 @@ void GPUContextVulkan::BindUA(int32 slot, GPUResourceView* view) void GPUContextVulkan::BindVB(const Span& vertexBuffers, const uint32* vertexBuffersOffsets) { + if (vertexBuffers.Length() == 0) + return; const auto cmdBuffer = _cmdBufferManager->GetCmdBuffer(); VkBuffer buffers[GPU_MAX_VB_BINDED]; VkDeviceSize offsets[GPU_MAX_VB_BINDED]; diff --git a/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.cpp b/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.cpp index 6f1c4a8de..d4624c017 100644 --- a/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.cpp +++ b/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.cpp @@ -146,9 +146,7 @@ static VKAPI_ATTR VkBool32 VKAPI_PTR DebugUtilsCallback(VkDebugUtilsMessageSever case 3: // Attachment 2 not written by fragment shader case 5: // SPIR-V module not valid: MemoryBarrier: Vulkan specification requires Memory Semantics to have one of the following bits set: Acquire, Release, AcquireRelease or SequentiallyConsistent case -1666394502: // After query pool creation, each query must be reset before it is used. Queries must also be reset between uses. -#if PLATFORM_ANDROID case 602160055: // Attachment 4 not written by fragment shader; undefined values will be written to attachment. TODO: investigate it for PS_GBuffer shader from Deferred material with USE_LIGHTMAP=1 -#endif return VK_FALSE; } break; @@ -156,11 +154,8 @@ static VKAPI_ATTR VkBool32 VKAPI_PTR DebugUtilsCallback(VkDebugUtilsMessageSever switch (callbackData->messageIdNumber) { case 0: // Vertex shader writes to output location 0.0 which is not consumed by fragment shader -#if PLATFORM_ANDROID - // TODO: implement preTransform for Android to improve swapchain presentation performance - case 558591440: // preTransform doesn't match the currentTransform returned by vkGetPhysicalDeviceSurfaceCapabilitiesKHR, the presentation engine will transform the image content as part of the presentation operation. + case 558591440: // preTransform doesn't match the currentTransform returned by vkGetPhysicalDeviceSurfaceCapabilitiesKHR, the presentation engine will transform the image content as part of the presentation operation. TODO: implement preTransform for Android to improve swapchain presentation performance case 101294395: // Vertex shader writes to output location 0.0 which is not consumed by fragment shader -#endif return VK_FALSE; } break; @@ -231,6 +226,7 @@ static VKAPI_ATTR VkBool32 VKAPI_PTR DebugUtilsCallback(VkDebugUtilsMessageSever return VK_FALSE; } + #endif void SetupDebugLayerCallback() @@ -1705,7 +1701,7 @@ bool GPUDeviceVulkan::Init() limits.HasGeometryShaders = false; // TODO: add geometry shaders support for Vulkan limits.HasInstancing = true; limits.HasVolumeTextureRendering = true; - limits.HasDrawIndirect = true; + limits.HasDrawIndirect = PhysicalDeviceLimits.maxDrawIndirectCount >= 1; limits.HasAppendConsumeBuffers = false; // TODO: add Append Consume buffers support for Vulkan limits.HasSeparateRenderTargetBlendState = true; limits.HasDepthAsSRV = true; diff --git a/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.h b/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.h index ba972932b..f7da7d30a 100644 --- a/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.h +++ b/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.h @@ -799,7 +799,7 @@ public: } /// - /// Gets the storage image descriptor. + /// Gets the storage image descriptor (VK_DESCRIPTOR_TYPE_STORAGE_IMAGE). /// /// The GPU context. Can be sued to add memory barriers to the pipeline before binding the descriptor to the pipeline. /// The image view. @@ -810,7 +810,7 @@ public: } /// - /// Gets the uniform texel buffer descriptor. + /// Gets the uniform texel buffer descriptor (VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER). /// /// The GPU context. Can be sued to add memory barriers to the pipeline before binding the descriptor to the pipeline. /// The buffer view. @@ -820,7 +820,7 @@ public: } /// - /// Gets the storage buffer descriptor. + /// Gets the storage buffer descriptor (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER). /// /// The GPU context. Can be sued to add memory barriers to the pipeline before binding the descriptor to the pipeline. /// The buffer. @@ -832,7 +832,17 @@ public: } /// - /// Gets the dynamic uniform buffer descriptor. + /// Gets the storage texel buffer descriptor (VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER). + /// + /// The GPU context. Can be sued to add memory barriers to the pipeline before binding the descriptor to the pipeline. + /// The buffer view. + virtual void DescriptorAsStorageTexelBuffer(GPUContextVulkan* context, const VkBufferView*& bufferView) + { + CRASH; + } + + /// + /// Gets the dynamic uniform buffer descriptor (VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC). /// /// The GPU context. Can be sued to add memory barriers to the pipeline before binding the descriptor to the pipeline. /// The buffer. diff --git a/Source/Engine/GraphicsDevice/Vulkan/RenderToolsVulkan.h b/Source/Engine/GraphicsDevice/Vulkan/RenderToolsVulkan.h index ec5d882bc..1380d221d 100644 --- a/Source/Engine/GraphicsDevice/Vulkan/RenderToolsVulkan.h +++ b/Source/Engine/GraphicsDevice/Vulkan/RenderToolsVulkan.h @@ -79,7 +79,7 @@ public: stageFlags = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; break; case VK_ACCESS_INDIRECT_COMMAND_READ_BIT: - stageFlags = VK_PIPELINE_STAGE_TRANSFER_BIT; + stageFlags = VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT; break; case VK_ACCESS_TRANSFER_WRITE_BIT: stageFlags = VK_PIPELINE_STAGE_TRANSFER_BIT; diff --git a/Source/Engine/Renderer/Utils/BitonicSort.cpp b/Source/Engine/Renderer/Utils/BitonicSort.cpp index 3858a7fae..a9478034d 100644 --- a/Source/Engine/Renderer/Utils/BitonicSort.cpp +++ b/Source/Engine/Renderer/Utils/BitonicSort.cpp @@ -157,6 +157,17 @@ void BitonicSort::Sort(GPUContext* context, GPUBuffer* sortingKeysBuffer, GPUBuf if (sortedIndicesBuffer) { // Copy indices to another buffer +#if !BUILD_RELEASE + switch (sortedIndicesBuffer->GetDescription().Format) + { + case PixelFormat::R32_UInt: + case PixelFormat::R16_UInt: + case PixelFormat::R8_UInt: + break; + default: + LOG(Warning, "Invalid format {0} of sortedIndicesBuffer for BitonicSort. It needs to be UInt type.", (int32)sortedIndicesBuffer->GetDescription().Format); + } +#endif context->BindSR(1, sortingKeysBuffer->View()); context->BindUA(0, sortedIndicesBuffer->View()); // TODO: use indirect dispatch to match the items count for copy diff --git a/Source/Engine/ShadersCompilation/Vulkan/ShaderCompilerVulkan.cpp b/Source/Engine/ShadersCompilation/Vulkan/ShaderCompilerVulkan.cpp index ac6d9d43b..998cc4291 100644 --- a/Source/Engine/ShadersCompilation/Vulkan/ShaderCompilerVulkan.cpp +++ b/Source/Engine/ShadersCompilation/Vulkan/ShaderCompilerVulkan.cpp @@ -234,6 +234,13 @@ SpirvShaderResourceType GetTextureType(const glslang::TSampler& sampler) } } +bool IsUavType(const glslang::TType& type) +{ + if (type.getQualifier().isReadOnly()) + return false; + return (type.getBasicType() == glslang::EbtSampler && type.getSampler().isImage()) || (type.getQualifier().storage == glslang::EvqBuffer); +} + class DescriptorsCollector { public: @@ -295,10 +302,20 @@ public: } else if (type.getSampler().dim == glslang::EsdBuffer) { - // Buffer SRV - descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER; - resourceType = SpirvShaderResourceType::Buffer; - resourceBindingType = SpirvShaderResourceBindingType::SRV; + if (IsUavType(type)) + { + // Buffer UAV + descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; + resourceType = SpirvShaderResourceType::Buffer; + resourceBindingType = SpirvShaderResourceBindingType::UAV; + } + else + { + // Buffer SRV + descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER; + resourceType = SpirvShaderResourceType::Buffer; + resourceBindingType = SpirvShaderResourceBindingType::SRV; + } } else if (type.isTexture()) {