From 80299c85521ce03f7478aa8f3203e25f5dba65c1 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 17 Dec 2024 15:58:26 +0100 Subject: [PATCH] Add stride to GPUVertexLayout --- Source/Engine/Graphics/GPUBuffer.cpp | 15 +++++++++++++++ Source/Engine/Graphics/GPUBufferDescription.h | 18 ++++++++++++++++++ .../Graphics/Shaders/GPUVertexLayout.cpp | 18 +++++++++++++++++- .../Engine/Graphics/Shaders/GPUVertexLayout.h | 14 +++++++++++++- .../DirectX/DX11/GPUDeviceDX11.cpp | 6 +++--- .../DirectX/DX12/GPUDeviceDX12.cpp | 6 +++--- .../GraphicsDevice/Null/GPUVertexLayoutNull.h | 2 +- .../GraphicsDevice/Vulkan/GPUDeviceVulkan.cpp | 8 ++++---- 8 files changed, 74 insertions(+), 13 deletions(-) diff --git a/Source/Engine/Graphics/GPUBuffer.cpp b/Source/Engine/Graphics/GPUBuffer.cpp index b0d081d4c..eca708af9 100644 --- a/Source/Engine/Graphics/GPUBuffer.cpp +++ b/Source/Engine/Graphics/GPUBuffer.cpp @@ -6,6 +6,7 @@ #include "GPUBufferDescription.h" #include "PixelFormatExtensions.h" #include "RenderTask.h" +#include "Shaders/GPUVertexLayout.h" #include "Async/Tasks/GPUCopyResourceTask.h" #include "Engine/Core/Utilities.h" #include "Engine/Core/Types/String.h" @@ -75,6 +76,20 @@ GPUBufferDescription GPUBufferDescription::Vertex(GPUVertexLayout* layout, uint3 return desc; } +GPUBufferDescription GPUBufferDescription::Vertex(GPUVertexLayout* layout, uint32 elementsCount, const void* data) +{ + const uint32 stride = layout ? layout->GetStride() : 0; + CHECK_RETURN_DEBUG(stride, GPUBufferDescription()); + return Vertex(layout, stride, elementsCount, data); +} + +GPUBufferDescription GPUBufferDescription::Vertex(GPUVertexLayout* layout, uint32 elementsCount, GPUResourceUsage usage) +{ + const uint32 stride = layout ? layout->GetStride() : 0; + CHECK_RETURN_DEBUG(stride, GPUBufferDescription()); + return Vertex(layout, stride, elementsCount, usage); +} + void GPUBufferDescription::Clear() { Platform::MemoryClear(this, sizeof(GPUBufferDescription)); diff --git a/Source/Engine/Graphics/GPUBufferDescription.h b/Source/Engine/Graphics/GPUBufferDescription.h index adb7f3cf2..4861d626c 100644 --- a/Source/Engine/Graphics/GPUBufferDescription.h +++ b/Source/Engine/Graphics/GPUBufferDescription.h @@ -202,6 +202,24 @@ public: /// The buffer description. static GPUBufferDescription Vertex(GPUVertexLayout* layout, uint32 elementStride, uint32 elementsCount, GPUResourceUsage usage = GPUResourceUsage::Default); + /// + /// Creates vertex buffer description. + /// + /// The vertex buffer layout. + /// The elements count. + /// The data. + /// The buffer description. + static GPUBufferDescription Vertex(GPUVertexLayout* layout, uint32 elementsCount, const void* data); + + /// + /// Creates vertex buffer description. + /// + /// The vertex buffer layout. + /// The elements count. + /// The usage mode. + /// The buffer description. + static GPUBufferDescription Vertex(GPUVertexLayout* layout, uint32 elementsCount, GPUResourceUsage usage = GPUResourceUsage::Default); + /// /// Creates vertex buffer description. /// [Deprecated in v1.10] diff --git a/Source/Engine/Graphics/Shaders/GPUVertexLayout.cpp b/Source/Engine/Graphics/Shaders/GPUVertexLayout.cpp index 6a4b8e677..996a177c2 100644 --- a/Source/Engine/Graphics/Shaders/GPUVertexLayout.cpp +++ b/Source/Engine/Graphics/Shaders/GPUVertexLayout.cpp @@ -5,9 +5,11 @@ #include "Engine/Core/Log.h" #endif #include "Engine/Core/Collections/Dictionary.h" +#include "Engine/Core/Math/Math.h" #include "Engine/Core/Types/Span.h" #include "Engine/Graphics/GPUDevice.h" #include "Engine/Graphics/GPUBuffer.h" +#include "Engine/Graphics/PixelFormatExtensions.h" #if GPU_ENABLE_RESOURCE_NAMING #include "Engine/Scripting/Enums.h" #endif @@ -74,6 +76,20 @@ GPUVertexLayout::GPUVertexLayout() { } +void GPUVertexLayout::SetElements(const Elements& elements, uint32 offsets[GPU_MAX_VS_ELEMENTS]) +{ + _elements = elements; + uint32 strides[GPU_MAX_VB_BINDED] = {}; + for (int32 i = 0; i < elements.Count(); i++) + { + const VertexElement& e = elements[i]; + strides[e.Slot] = Math::Max(strides[e.Slot], offsets[i]); + } + _stride = 0; + for (int32 i = 0; i < GPU_MAX_VB_BINDED; i++) + _stride += strides[i]; +} + GPUVertexLayout* GPUVertexLayout::Get(const Elements& elements) { // Hash input layout @@ -144,7 +160,7 @@ GPUVertexLayout* GPUVertexLayout::Get(const Span& vertexBuffers) anyValid = true; int32 start = elements.Count(); elements.Add(layouts.Layouts[slot]->GetElements()); - for (int32 j = start; j < elements.Count() ;j++) + for (int32 j = start; j < elements.Count(); j++) elements.Get()[j].Slot = (byte)slot; } } diff --git a/Source/Engine/Graphics/Shaders/GPUVertexLayout.h b/Source/Engine/Graphics/Shaders/GPUVertexLayout.h index 8d60573b8..e234b32b1 100644 --- a/Source/Engine/Graphics/Shaders/GPUVertexLayout.h +++ b/Source/Engine/Graphics/Shaders/GPUVertexLayout.h @@ -16,11 +16,15 @@ API_CLASS(Sealed, NoSpawn) class FLAXENGINE_API GPUVertexLayout : public GPUReso DECLARE_SCRIPTING_TYPE_NO_SPAWN(GPUVertexLayout); typedef Array> Elements; -protected: +private: Elements _elements; + uint32 _stride; +protected: GPUVertexLayout(); + void SetElements(const Elements& elements, uint32 offsets[GPU_MAX_VS_ELEMENTS]); + public: /// /// Gets the list of elements used by this layout. @@ -30,6 +34,14 @@ public: return _elements; } + /// + /// Gets the size in bytes of all elements in the layout structure (including their offsets). + /// + API_PROPERTY() FORCE_INLINE uint32 GetStride() const + { + return _stride; + } + /// /// Gets the vertex layout for a given list of elements. Uses internal cache to skip creating layout if it's already exists for a given list. /// diff --git a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.cpp b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.cpp index 4a9e4a6d2..35656606a 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.cpp +++ b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.cpp @@ -152,11 +152,10 @@ GPUVertexLayoutDX11::GPUVertexLayoutDX11(GPUDeviceDX11* device, const Elements& : GPUResourceBase(device, StringView::Empty) , InputElementsCount(elements.Count()) { - _elements = elements; uint32 offsets[GPU_MAX_VB_BINDED] = {}; - for (int32 i = 0; i < _elements.Count(); i++) + for (int32 i = 0; i < elements.Count(); i++) { - const VertexElement& src = _elements.Get()[i]; + const VertexElement& src = elements.Get()[i]; D3D11_INPUT_ELEMENT_DESC& dst = InputElements[i]; uint32& offset = offsets[src.Slot]; if (src.Offset != 0) @@ -169,6 +168,7 @@ GPUVertexLayoutDX11::GPUVertexLayoutDX11(GPUDeviceDX11* device, const Elements& dst.InstanceDataStepRate = src.PerInstance ? 1 : 0; offset += PixelFormatExtensions::SizeInBytes(src.Format); } + SetElements(elements, offsets); } GPUDevice* GPUDeviceDX11::Create() diff --git a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUDeviceDX12.cpp b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUDeviceDX12.cpp index eb252be54..ab4a0ab81 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUDeviceDX12.cpp +++ b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUDeviceDX12.cpp @@ -40,11 +40,10 @@ GPUVertexLayoutDX12::GPUVertexLayoutDX12(GPUDeviceDX12* device, const Elements& : GPUResourceDX12(device, StringView::Empty) , InputElementsCount(elements.Count()) { - _elements = elements; uint32 offsets[GPU_MAX_VB_BINDED] = {}; - for (int32 i = 0; i < _elements.Count(); i++) + for (int32 i = 0; i < elements.Count(); i++) { - const VertexElement& src = _elements.Get()[i]; + const VertexElement& src = elements.Get()[i]; D3D12_INPUT_ELEMENT_DESC& dst = InputElements[i]; uint32& offset = offsets[src.Slot]; if (src.Offset != 0) @@ -57,6 +56,7 @@ GPUVertexLayoutDX12::GPUVertexLayoutDX12(GPUDeviceDX12* device, const Elements& dst.InstanceDataStepRate = src.PerInstance ? 1 : 0; offset += PixelFormatExtensions::SizeInBytes(src.Format); } + SetElements(elements, offsets); } GPUDevice* GPUDeviceDX12::Create() diff --git a/Source/Engine/GraphicsDevice/Null/GPUVertexLayoutNull.h b/Source/Engine/GraphicsDevice/Null/GPUVertexLayoutNull.h index c1b7e96a7..f1a5f0abd 100644 --- a/Source/Engine/GraphicsDevice/Null/GPUVertexLayoutNull.h +++ b/Source/Engine/GraphicsDevice/Null/GPUVertexLayoutNull.h @@ -15,7 +15,7 @@ public: GPUVertexLayoutNull(const Elements& elements) : GPUVertexLayout() { - _elements = elements; + SetElements(elements, {}); } }; diff --git a/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.cpp b/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.cpp index 283b48e67..e5f7f2bcc 100644 --- a/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.cpp +++ b/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.cpp @@ -452,7 +452,6 @@ uint32 GetHash(const FramebufferVulkan::Key& key) GPUVertexLayoutVulkan::GPUVertexLayoutVulkan(GPUDeviceVulkan* device, const Elements& elements) : GPUResourceVulkan(device, StringView::Empty) { - _elements = elements; uint32 offsets[GPU_MAX_VB_BINDED] = {}; for (int32 i = 0; i < GPU_MAX_VB_BINDED; i++) { @@ -462,9 +461,9 @@ GPUVertexLayoutVulkan::GPUVertexLayoutVulkan(GPUDeviceVulkan* device, const Elem binding.inputRate = VK_VERTEX_INPUT_RATE_VERTEX; } uint32 bindingsCount = 0; - for (int32 i = 0; i < _elements.Count(); i++) + for (int32 i = 0; i < elements.Count(); i++) { - const VertexElement& src = _elements.Get()[i]; + const VertexElement& src = elements.Get()[i]; uint32& offset = offsets[src.Slot]; if (src.Offset != 0) offset = src.Offset; @@ -485,11 +484,12 @@ GPUVertexLayoutVulkan::GPUVertexLayoutVulkan(GPUDeviceVulkan* device, const Elem bindingsCount = Math::Max(bindingsCount, (uint32)src.Slot + 1); offset += size; } + SetElements(elements, offsets); RenderToolsVulkan::ZeroStruct(CreateInfo, VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO); CreateInfo.vertexBindingDescriptionCount = bindingsCount; CreateInfo.pVertexBindingDescriptions = Bindings; - CreateInfo.vertexAttributeDescriptionCount = _elements.Count(); + CreateInfo.vertexAttributeDescriptionCount = elements.Count(); CreateInfo.pVertexAttributeDescriptions = Attributes; }