Fix GPU particles on Vulkan

#478
This commit is contained in:
Wojtek Figat
2021-05-17 13:41:08 +02:00
parent ec806a2009
commit 0a25b71437
8 changed files with 74 additions and 20 deletions

View File

@@ -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

View File

@@ -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;
};
/// <summary>
@@ -80,7 +81,6 @@ public:
/// <summary>
/// Gets the Vulkan buffer handle.
/// </summary>
/// <returns>The buffer handle.</returns>
FORCE_INLINE VkBuffer GetHandle() const
{
return _buffer;
@@ -89,7 +89,6 @@ public:
/// <summary>
/// Gets the Vulkan memory allocation handle.
/// </summary>
/// <returns>The memory allocation handle.</returns>
FORCE_INLINE VmaAllocation GetAllocation() const
{
return _allocation;

View File

@@ -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<GPUBuffer*>& 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];

View File

@@ -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;

View File

@@ -799,7 +799,7 @@ public:
}
/// <summary>
/// Gets the storage image descriptor.
/// Gets the storage image descriptor (VK_DESCRIPTOR_TYPE_STORAGE_IMAGE).
/// </summary>
/// <param name="context">The GPU context. Can be sued to add memory barriers to the pipeline before binding the descriptor to the pipeline.</param>
/// <param name="imageView">The image view.</param>
@@ -810,7 +810,7 @@ public:
}
/// <summary>
/// Gets the uniform texel buffer descriptor.
/// Gets the uniform texel buffer descriptor (VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER).
/// </summary>
/// <param name="context">The GPU context. Can be sued to add memory barriers to the pipeline before binding the descriptor to the pipeline.</param>
/// <param name="bufferView">The buffer view.</param>
@@ -820,7 +820,7 @@ public:
}
/// <summary>
/// Gets the storage buffer descriptor.
/// Gets the storage buffer descriptor (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER).
/// </summary>
/// <param name="context">The GPU context. Can be sued to add memory barriers to the pipeline before binding the descriptor to the pipeline.</param>
/// <param name="buffer">The buffer.</param>
@@ -832,7 +832,17 @@ public:
}
/// <summary>
/// Gets the dynamic uniform buffer descriptor.
/// Gets the storage texel buffer descriptor (VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER).
/// </summary>
/// <param name="context">The GPU context. Can be sued to add memory barriers to the pipeline before binding the descriptor to the pipeline.</param>
/// <param name="bufferView">The buffer view.</param>
virtual void DescriptorAsStorageTexelBuffer(GPUContextVulkan* context, const VkBufferView*& bufferView)
{
CRASH;
}
/// <summary>
/// Gets the dynamic uniform buffer descriptor (VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC).
/// </summary>
/// <param name="context">The GPU context. Can be sued to add memory barriers to the pipeline before binding the descriptor to the pipeline.</param>
/// <param name="buffer">The buffer.</param>

View File

@@ -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;

View File

@@ -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

View File

@@ -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())
{