summaryrefslogtreecommitdiffstats
path: root/Graphics
diff options
context:
space:
mode:
authorEgor Yusov <egor.yusov@gmail.com>2019-03-07 17:02:28 +0000
committerEgor Yusov <egor.yusov@gmail.com>2019-03-07 17:02:28 +0000
commit195dfd3a09bc917135deeb4a4450638ae47997d1 (patch)
tree5b827c7e71cbc34e7e927d8dc10873acefc3d8a1 /Graphics
parentImproved handling input layout elements in the pipeline state (diff)
downloadDiligentCore-195dfd3a09bc917135deeb4a4450638ae47997d1.tar.gz
DiligentCore-195dfd3a09bc917135deeb4a4450638ae47997d1.zip
Improved buffer stride management in PSO
Diffstat (limited to 'Graphics')
-rw-r--r--Graphics/GraphicsEngine/include/PipelineStateBase.h54
-rwxr-xr-xGraphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp3
-rw-r--r--Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp3
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/VAOCache.cpp5
4 files changed, 34 insertions, 31 deletions
diff --git a/Graphics/GraphicsEngine/include/PipelineStateBase.h b/Graphics/GraphicsEngine/include/PipelineStateBase.h
index fc5d8dce..bafdce97 100644
--- a/Graphics/GraphicsEngine/include/PipelineStateBase.h
+++ b/Graphics/GraphicsEngine/include/PipelineStateBase.h
@@ -176,12 +176,13 @@ public:
for (size_t Elem = 0; Elem < InputLayout.NumElements; ++Elem)
pLayoutElements[Elem] = InputLayout.LayoutElements[Elem];
+
+ // Correct description and compute offsets and tight strides
+ std::array<Uint32, MaxBufferSlots> Strides, TightStrides = {};
// Set all strides to an invalid value because an application may want to use 0 stride
- for (auto& Stride : m_Strides)
+ for (auto& Stride : Strides)
Stride = LayoutElement::AutoStride;
- // Correct description and compute offsets and tight strides
- decltype(m_Strides) TightStrides = {};
for (Uint32 i=0; i < InputLayout.NumElements; ++i)
{
auto& LayoutElem = pLayoutElements[i];
@@ -190,9 +191,9 @@ public:
LayoutElem.IsNormalized = false; // Floating point values cannot be normalized
auto BuffSlot = LayoutElem.BufferSlot;
- if (BuffSlot >= m_Strides.size())
+ if (BuffSlot >= Strides.size())
{
- UNEXPECTED("Buffer slot (", BuffSlot, ") exceeds maximum allowed value (", m_Strides.size()-1, ")");
+ UNEXPECTED("Buffer slot (", BuffSlot, ") exceeds maximum allowed value (", Strides.size()-1, ")");
continue;
}
m_BufferSlotsUsed = std::max(m_BufferSlotsUsed, BuffSlot + 1);
@@ -208,14 +209,14 @@ public:
if (LayoutElem.Stride != LayoutElement::AutoStride)
{
// Verify that the value is consistent with the previously specified stride, if any
- if (m_Strides[BuffSlot] != LayoutElement::AutoStride && m_Strides[BuffSlot] != LayoutElem.Stride)
+ if (Strides[BuffSlot] != LayoutElement::AutoStride && Strides[BuffSlot] != LayoutElem.Stride)
{
LOG_ERROR_MESSAGE("Inconsistent strides are specified for buffer slot ", BuffSlot, ". "
"Input element at index ", LayoutElem.InputIndex, " explicitly specifies stride ", LayoutElem.Stride, ", "
- "while current value is ", m_Strides[BuffSlot], ". Specify consistent strides or use "
+ "while current value is ", Strides[BuffSlot], ". Specify consistent strides or use "
"LayoutElement::AutoStride to allow the engine compute strides automatically.");
}
- m_Strides[BuffSlot] = LayoutElem.Stride;
+ Strides[BuffSlot] = LayoutElem.Stride;
}
CurrAutoStride = std::max(CurrAutoStride, LayoutElem.RelativeOffset + LayoutElem.NumComponents * GetValueSize(LayoutElem.ValueType));
@@ -227,26 +228,33 @@ public:
auto BuffSlot = LayoutElem.BufferSlot;
// If no input elements explicitly specified stride for this buffer slot, use automatic stride
- if (m_Strides[BuffSlot] == LayoutElement::AutoStride)
+ if (Strides[BuffSlot] == LayoutElement::AutoStride)
{
- m_Strides[BuffSlot] = TightStrides[BuffSlot];
+ Strides[BuffSlot] = TightStrides[BuffSlot];
}
else
{
- if (m_Strides[BuffSlot] < TightStrides[BuffSlot])
+ if (Strides[BuffSlot] < TightStrides[BuffSlot])
{
- LOG_ERROR_MESSAGE("Stride ", m_Strides[BuffSlot], " explicitly specified for slot ", BuffSlot, " is smaller than the "
+ LOG_ERROR_MESSAGE("Stride ", Strides[BuffSlot], " explicitly specified for slot ", BuffSlot, " is smaller than the "
"minimum stride ", TightStrides[BuffSlot], " required to accomodate all input elements.");
}
}
if (LayoutElem.Stride == LayoutElement::AutoStride)
- LayoutElem.Stride = m_Strides[BuffSlot];
+ LayoutElem.Stride = Strides[BuffSlot];
}
- // Set strides for all unused slots to 0
- for (auto& Stride : m_Strides)
+
+ if (m_BufferSlotsUsed > 0)
{
- if (Stride == LayoutElement::AutoStride)
- Stride = 0;
+ auto* pStridesRawMem = ALLOCATE(GetRawAllocator(), "Raw memory for buffer strides", sizeof(Uint32) * m_BufferSlotsUsed);
+ m_pStrides = reinterpret_cast<Uint32*>(pStridesRawMem);
+
+ // Set strides for all unused slots to 0
+ for (Uint32 i=0; i < m_BufferSlotsUsed; ++i)
+ {
+ auto Stride = Strides[i];
+ m_pStrides[i] = Stride != LayoutElement::AutoStride ? Stride : 0;
+ }
}
Uint64 DeviceQueuesMask = pDevice->GetCommandQueueMask();
@@ -281,13 +289,15 @@ public:
RawAllocator.Free(const_cast<StaticSamplerDesc*>(this->m_Desc.ResourceLayout.StaticSamplers));
if (this->m_Desc.GraphicsPipeline.InputLayout.LayoutElements != nullptr)
RawAllocator.Free(const_cast<LayoutElement*>(this->m_Desc.GraphicsPipeline.InputLayout.LayoutElements));
+ if (m_pStrides != nullptr)
+ RawAllocator.Free(m_pStrides);
}
IMPLEMENT_QUERY_INTERFACE_IN_PLACE( IID_PipelineState, TDeviceObjectBase )
- virtual const Uint32* GetBufferStrides()const
+ Uint32 GetBufferStride(Uint32 BufferSlot)const
{
- return m_Strides.data();
+ return BufferSlot < m_BufferSlotsUsed ? m_pStrides[BufferSlot] : 0;
}
Uint32 GetNumBufferSlotsUsed()const
@@ -329,11 +339,7 @@ protected:
Uint32 m_BufferSlotsUsed = 0;
Uint32 m_NumShaders = 0; ///< Number of shaders that this PSO uses
-
- // The size of this array must be equal to the
- // maximum number of buffer slots, because a layout
- // element can refer to any input slot
- std::array<Uint32, MaxBufferSlots> m_Strides = {}; // TODO: rework this
+ Uint32* m_pStrides = nullptr;
StringPool m_StringPool;
RefCntAutoPtr<IShader> m_pVS; ///< Strong reference to the vertex shader
diff --git a/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp
index f177586d..df4a59c3 100755
--- a/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp
+++ b/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp
@@ -687,13 +687,12 @@ namespace Diligent
bool BindVBs = m_NumVertexStreams != m_NumCommittedD3D11VBs;
- const auto* Strides = pPipelineStateD3D11->GetBufferStrides();
for (UINT Slot = 0; Slot < m_NumVertexStreams; ++Slot)
{
auto& CurrStream = m_VertexStreams[Slot];
auto* pBuffD3D11Impl = CurrStream.pBuffer.RawPtr();
ID3D11Buffer* pd3d11Buffer = pBuffD3D11Impl ? pBuffD3D11Impl->m_pd3d11Buffer : nullptr;
- auto Stride = Strides[Slot];
+ auto Stride = pPipelineStateD3D11->GetBufferStride(Slot);
auto Offset = CurrStream.Offset;
// It is safe to perform raw pointer check because device context keeps
diff --git a/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp
index a1d9db3f..353b9676 100644
--- a/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp
+++ b/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp
@@ -319,7 +319,6 @@ namespace Diligent
// Do not initialize array with zeroes for performance reasons
D3D12_VERTEX_BUFFER_VIEW VBViews[MaxBufferSlots];// = {}
VERIFY( m_NumVertexStreams <= MaxBufferSlots, "Too many buffers are being set" );
- const auto *Strides = m_pPipelineState->GetBufferStrides();
DEV_CHECK_ERR( m_NumVertexStreams >= m_pPipelineState->GetNumBufferSlotsUsed(), "Currently bound pipeline state '", m_pPipelineState->GetDesc().Name, "' expects ", m_pPipelineState->GetNumBufferSlotsUsed(), " input buffer slots, but only ", m_NumVertexStreams, " is bound");
bool DynamicBufferPresent = false;
for( UINT Buff = 0; Buff < m_NumVertexStreams; ++Buff )
@@ -342,7 +341,7 @@ namespace Diligent
//GraphicsCtx.AddReferencedObject(pd3d12Resource);
VBView.BufferLocation = pBufferD3D12->GetGPUAddress(this) + CurrStream.Offset;
- VBView.StrideInBytes = Strides[Buff];
+ VBView.StrideInBytes = m_pPipelineState->GetBufferStride(Buff);
// Note that for a dynamic buffer, what we use here is the size of the buffer itself, not the upload heap buffer!
VBView.SizeInBytes = pBufferD3D12->GetDesc().uiSizeInBytes - CurrStream.Offset;
}
diff --git a/Graphics/GraphicsEngineOpenGL/src/VAOCache.cpp b/Graphics/GraphicsEngineOpenGL/src/VAOCache.cpp
index fece99b3..b9d2237b 100644
--- a/Graphics/GraphicsEngineOpenGL/src/VAOCache.cpp
+++ b/Graphics/GraphicsEngineOpenGL/src/VAOCache.cpp
@@ -90,7 +90,6 @@ const GLObjectWrappers::GLVertexArrayObj& VAOCache::GetVAO( IPipelineState *pPSO
const auto &InputLayout = pPSOGL->GetDesc().GraphicsPipeline.InputLayout;
const LayoutElement *LayoutElems = InputLayout.LayoutElements;
Uint32 NumElems = InputLayout.NumElements;
- const Uint32 *Strides = pPSOGL->GetBufferStrides();
// Construct the key
VAOCacheKey Key(pPSO, pIndexBuffer);
@@ -115,7 +114,7 @@ const GLObjectWrappers::GLVertexArrayObj& VAOCache::GetVAO( IPipelineState *pPSO
Key.NumUsedSlots = MaxUsedSlot;
auto &CurrStream = VertexStreams[BuffSlot];
- auto Stride = Strides[BuffSlot];
+ auto Stride = pPSOGL->GetBufferStride(BuffSlot);
auto &pCurrBuf = VertexBuffers[BuffSlot];
auto &CurrStreamKey = Key.Streams[BuffSlot];
if (pCurrBuf == nullptr)
@@ -179,7 +178,7 @@ const GLObjectWrappers::GLVertexArrayObj& VAOCache::GetVAO( IPipelineState *pPSO
// Get buffer through the strong reference. Note that we are not
// using pointers stored in the key for safety
auto &CurrStream = VertexStreams[BuffSlot];
- auto Stride = Strides[BuffSlot];
+ auto Stride = pPSOGL->GetBufferStride(BuffSlot);
auto *pBuff = VertexBuffers[BuffSlot];
VERIFY( pBuff != nullptr, "Vertex buffer is null" );
const BufferGLImpl *pBufferOGL = static_cast<const BufferGLImpl*>( pBuff );