From db5cfe224b9ff00234b29ff097262bc7377b90c4 Mon Sep 17 00:00:00 2001 From: assiduous Date: Thu, 5 Nov 2020 21:43:17 -0800 Subject: Refactored BufferBase --- Graphics/GraphicsEngine/include/BufferBase.hpp | 179 +++++++++---------------- Graphics/GraphicsEngine/src/BufferBase.cpp | 51 ++++++- 2 files changed, 112 insertions(+), 118 deletions(-) (limited to 'Graphics/GraphicsEngine') diff --git a/Graphics/GraphicsEngine/include/BufferBase.hpp b/Graphics/GraphicsEngine/include/BufferBase.hpp index 605bc2ed..0ccbc0aa 100644 --- a/Graphics/GraphicsEngine/include/BufferBase.hpp +++ b/Graphics/GraphicsEngine/include/BufferBase.hpp @@ -42,8 +42,15 @@ namespace Diligent { -void ValidateBufferInitData(const BufferDesc& Desc, const BufferData* pBuffData); -void ValidateBufferDesc(const BufferDesc& Desc, const DeviceCaps& deviceCaps); +/// Validates buffer description and throws an exception in case of an error. +void ValidateBufferDesc(const BufferDesc& Desc, const DeviceCaps& deviceCaps) noexcept(false); + +/// Validates initial buffer data parameters and throws an exception in case of an error. +void ValidateBufferInitData(const BufferDesc& Desc, const BufferData* pBuffData) noexcept(false); + +/// Validates and corrects buffer view description; throws an exception in case of an error. +void ValidateAndCorrectBufferViewDesc(const BufferDesc& BuffDesc, BufferViewDesc& ViewDesc) noexcept(false); + /// Template class implementing base functionality for a buffer object @@ -93,10 +100,31 @@ public: /// Implementation of IBuffer::CreateView(); calls CreateViewInternal() virtual function /// that creates buffer view for the specific engine implementation. - virtual void DILIGENT_CALL_TYPE CreateView(const struct BufferViewDesc& ViewDesc, IBufferView** ppView) override; + virtual void DILIGENT_CALL_TYPE CreateView(const struct BufferViewDesc& ViewDesc, IBufferView** ppView) override + { + DEV_CHECK_ERR(ViewDesc.ViewType != BUFFER_VIEW_UNDEFINED, "Buffer view type is not specified"); + if (ViewDesc.ViewType == BUFFER_VIEW_SHADER_RESOURCE) + DEV_CHECK_ERR(this->m_Desc.BindFlags & BIND_SHADER_RESOURCE, "Attempting to create SRV for buffer '", this->m_Desc.Name, "' that was not created with BIND_SHADER_RESOURCE flag"); + else if (ViewDesc.ViewType == BUFFER_VIEW_UNORDERED_ACCESS) + DEV_CHECK_ERR(this->m_Desc.BindFlags & BIND_UNORDERED_ACCESS, "Attempting to create UAV for buffer '", this->m_Desc.Name, "' that was not created with BIND_UNORDERED_ACCESS flag"); + else + UNEXPECTED("Unexpected buffer view type"); + + CreateViewInternal(ViewDesc, ppView, false); + } + /// Implementation of IBuffer::GetDefaultView(). - virtual IBufferView* DILIGENT_CALL_TYPE GetDefaultView(BUFFER_VIEW_TYPE ViewType) override; + virtual IBufferView* DILIGENT_CALL_TYPE GetDefaultView(BUFFER_VIEW_TYPE ViewType) override + { + switch (ViewType) + { + case BUFFER_VIEW_SHADER_RESOURCE: return m_pDefaultSRV.get(); + case BUFFER_VIEW_UNORDERED_ACCESS: return m_pDefaultUAV.get(); + default: UNEXPECTED("Unknown view type"); return nullptr; + } + } + /// Creates default buffer views. @@ -105,7 +133,37 @@ public: /// - Creates default unordered access view addressing the entire buffer if Diligent::BIND_UNORDERED_ACCESS flag is set /// /// The function calls CreateViewInternal(). - void CreateDefaultViews(); + void CreateDefaultViews() + { + // Create default views for structured and raw buffers. For formatted buffers we do not know the view format, so + // cannot create views. + + if (this->m_Desc.BindFlags & BIND_UNORDERED_ACCESS && (this->m_Desc.Mode == BUFFER_MODE_STRUCTURED || this->m_Desc.Mode == BUFFER_MODE_RAW)) + { + BufferViewDesc ViewDesc; + ViewDesc.ViewType = BUFFER_VIEW_UNORDERED_ACCESS; + auto UAVName = FormatString("Default UAV of buffer '", this->m_Desc.Name, '\''); + ViewDesc.Name = UAVName.c_str(); + + IBufferView* pUAV = nullptr; + CreateViewInternal(ViewDesc, &pUAV, true); + m_pDefaultUAV.reset(static_cast(pUAV)); + VERIFY(m_pDefaultUAV->GetDesc().ViewType == BUFFER_VIEW_UNORDERED_ACCESS, "Unexpected view type"); + } + + if (this->m_Desc.BindFlags & BIND_SHADER_RESOURCE && (this->m_Desc.Mode == BUFFER_MODE_STRUCTURED || this->m_Desc.Mode == BUFFER_MODE_RAW)) + { + BufferViewDesc ViewDesc; + ViewDesc.ViewType = BUFFER_VIEW_SHADER_RESOURCE; + auto SRVName = FormatString("Default SRV of buffer '", this->m_Desc.Name, '\''); + ViewDesc.Name = SRVName.c_str(); + + IBufferView* pSRV = nullptr; + CreateViewInternal(ViewDesc, &pSRV, true); + m_pDefaultSRV.reset(static_cast(pSRV)); + VERIFY(m_pDefaultSRV->GetDesc().ViewType == BUFFER_VIEW_SHADER_RESOURCE, "Unexpected view type"); + } + } virtual void DILIGENT_CALL_TYPE SetState(RESOURCE_STATE State) override final { @@ -133,9 +191,6 @@ protected: /// Pure virtual function that creates buffer view for the specific engine implementation. virtual void CreateViewInternal(const struct BufferViewDesc& ViewDesc, IBufferView** ppView, bool bIsDefaultView) = 0; - /// Corrects buffer view description and validates view parameters. - void CorrectBufferViewDesc(struct BufferViewDesc& ViewDesc); - #ifdef DILIGENT_DEBUG TBuffViewObjAllocator& m_dbgBuffViewAllocator; #endif @@ -149,112 +204,4 @@ protected: std::unique_ptr> m_pDefaultSRV; }; - - - -template -void BufferBase::CreateView(const struct BufferViewDesc& ViewDesc, IBufferView** ppView) -{ - DEV_CHECK_ERR(ViewDesc.ViewType != BUFFER_VIEW_UNDEFINED, "Buffer view type is not specified"); - if (ViewDesc.ViewType == BUFFER_VIEW_SHADER_RESOURCE) - DEV_CHECK_ERR(this->m_Desc.BindFlags & BIND_SHADER_RESOURCE, "Attempting to create SRV for buffer '", this->m_Desc.Name, "' that was not created with BIND_SHADER_RESOURCE flag"); - else if (ViewDesc.ViewType == BUFFER_VIEW_UNORDERED_ACCESS) - DEV_CHECK_ERR(this->m_Desc.BindFlags & BIND_UNORDERED_ACCESS, "Attempting to create UAV for buffer '", this->m_Desc.Name, "' that was not created with BIND_UNORDERED_ACCESS flag"); - else - UNEXPECTED("Unexpected buffer view type"); - - CreateViewInternal(ViewDesc, ppView, false); -} - - -template -void BufferBase::CorrectBufferViewDesc(struct BufferViewDesc& ViewDesc) -{ - if (ViewDesc.ByteWidth == 0) - { - DEV_CHECK_ERR(this->m_Desc.uiSizeInBytes > ViewDesc.ByteOffset, "Byte offset (", ViewDesc.ByteOffset, ") exceeds buffer size (", this->m_Desc.uiSizeInBytes, ")"); - ViewDesc.ByteWidth = this->m_Desc.uiSizeInBytes - ViewDesc.ByteOffset; - } - if (ViewDesc.ByteOffset + ViewDesc.ByteWidth > this->m_Desc.uiSizeInBytes) - LOG_ERROR_AND_THROW("Buffer view range [", ViewDesc.ByteOffset, ", ", ViewDesc.ByteOffset + ViewDesc.ByteWidth, ") is out of the buffer boundaries [0, ", this->m_Desc.uiSizeInBytes, ")."); - if ((this->m_Desc.BindFlags & BIND_UNORDERED_ACCESS) || - (this->m_Desc.BindFlags & BIND_SHADER_RESOURCE)) - { - if (this->m_Desc.Mode == BUFFER_MODE_STRUCTURED || this->m_Desc.Mode == BUFFER_MODE_FORMATTED) - { - VERIFY(this->m_Desc.ElementByteStride != 0, "Element byte stride is zero"); - if ((ViewDesc.ByteOffset % this->m_Desc.ElementByteStride) != 0) - LOG_ERROR_AND_THROW("Buffer view byte offset (", ViewDesc.ByteOffset, ") is not multiple of element byte stride (", this->m_Desc.ElementByteStride, ")."); - if ((ViewDesc.ByteWidth % this->m_Desc.ElementByteStride) != 0) - LOG_ERROR_AND_THROW("Buffer view byte width (", ViewDesc.ByteWidth, ") is not multiple of element byte stride (", this->m_Desc.ElementByteStride, ")."); - } - - if (this->m_Desc.Mode == BUFFER_MODE_FORMATTED && ViewDesc.Format.ValueType == VT_UNDEFINED) - LOG_ERROR_AND_THROW("Format must be specified when creating a view of a formatted buffer"); - - if (this->m_Desc.Mode == BUFFER_MODE_FORMATTED || (this->m_Desc.Mode == BUFFER_MODE_RAW && ViewDesc.Format.ValueType != VT_UNDEFINED)) - { - if (ViewDesc.Format.NumComponents <= 0 || ViewDesc.Format.NumComponents > 4) - LOG_ERROR_AND_THROW("Incorrect number of components (", Uint32{ViewDesc.Format.NumComponents}, "). 1, 2, 3, or 4 are allowed values"); - if (ViewDesc.Format.ValueType == VT_FLOAT32 || ViewDesc.Format.ValueType == VT_FLOAT16) - ViewDesc.Format.IsNormalized = false; - auto ViewElementStride = GetValueSize(ViewDesc.Format.ValueType) * Uint32{ViewDesc.Format.NumComponents}; - if (this->m_Desc.Mode == BUFFER_MODE_RAW && this->m_Desc.ElementByteStride == 0) - LOG_ERROR_AND_THROW("To enable formatted views of a raw buffer, element byte must be specified during buffer initialization"); - if (ViewElementStride != this->m_Desc.ElementByteStride) - LOG_ERROR_AND_THROW("Buffer element byte stride (", this->m_Desc.ElementByteStride, ") is not consistent with the size (", ViewElementStride, ") defined by the format of the view (", GetBufferFormatString(ViewDesc.Format), ')'); - } - - if (this->m_Desc.Mode == BUFFER_MODE_RAW && ViewDesc.Format.ValueType == VT_UNDEFINED) - { - if ((ViewDesc.ByteOffset % 16) != 0) - LOG_ERROR_AND_THROW("When creating a RAW view, the offset of the first element from the start of the buffer (", ViewDesc.ByteOffset, ") must be a multiple of 16 bytes"); - } - } -} - -template -IBufferView* BufferBase::GetDefaultView(BUFFER_VIEW_TYPE ViewType) -{ - switch (ViewType) - { - case BUFFER_VIEW_SHADER_RESOURCE: return m_pDefaultSRV.get(); - case BUFFER_VIEW_UNORDERED_ACCESS: return m_pDefaultUAV.get(); - default: UNEXPECTED("Unknown view type"); return nullptr; - } -} - -template -void BufferBase::CreateDefaultViews() -{ - // Create default views for structured and raw buffers. For formatted buffers we do not know the view format, so - // cannot create views. - - if (this->m_Desc.BindFlags & BIND_UNORDERED_ACCESS && (this->m_Desc.Mode == BUFFER_MODE_STRUCTURED || this->m_Desc.Mode == BUFFER_MODE_RAW)) - { - BufferViewDesc ViewDesc; - ViewDesc.ViewType = BUFFER_VIEW_UNORDERED_ACCESS; - auto UAVName = FormatString("Default UAV of buffer '", this->m_Desc.Name, '\''); - ViewDesc.Name = UAVName.c_str(); - - IBufferView* pUAV = nullptr; - CreateViewInternal(ViewDesc, &pUAV, true); - m_pDefaultUAV.reset(static_cast(pUAV)); - VERIFY(m_pDefaultUAV->GetDesc().ViewType == BUFFER_VIEW_UNORDERED_ACCESS, "Unexpected view type"); - } - - if (this->m_Desc.BindFlags & BIND_SHADER_RESOURCE && (this->m_Desc.Mode == BUFFER_MODE_STRUCTURED || this->m_Desc.Mode == BUFFER_MODE_RAW)) - { - BufferViewDesc ViewDesc; - ViewDesc.ViewType = BUFFER_VIEW_SHADER_RESOURCE; - auto SRVName = FormatString("Default SRV of buffer '", this->m_Desc.Name, '\''); - ViewDesc.Name = SRVName.c_str(); - - IBufferView* pSRV = nullptr; - CreateViewInternal(ViewDesc, &pSRV, true); - m_pDefaultSRV.reset(static_cast(pSRV)); - VERIFY(m_pDefaultSRV->GetDesc().ViewType == BUFFER_VIEW_SHADER_RESOURCE, "Unexpected view type"); - } -} - } // namespace Diligent diff --git a/Graphics/GraphicsEngine/src/BufferBase.cpp b/Graphics/GraphicsEngine/src/BufferBase.cpp index 88ed62d9..5156764b 100644 --- a/Graphics/GraphicsEngine/src/BufferBase.cpp +++ b/Graphics/GraphicsEngine/src/BufferBase.cpp @@ -42,7 +42,7 @@ namespace Diligent } while (false) -void ValidateBufferDesc(const BufferDesc& Desc, const DeviceCaps& deviceCaps) +void ValidateBufferDesc(const BufferDesc& Desc, const DeviceCaps& deviceCaps) noexcept(false) { static_assert(BIND_FLAGS_LAST == 0x400L, "Please update this function to handle the new bind flags"); @@ -114,7 +114,7 @@ void ValidateBufferDesc(const BufferDesc& Desc, const DeviceCaps& deviceCaps) } } -void ValidateBufferInitData(const BufferDesc& Desc, const BufferData* pBuffData) +void ValidateBufferInitData(const BufferDesc& Desc, const BufferData* pBuffData) noexcept(false) { if (Desc.Usage == USAGE_IMMUTABLE && (pBuffData == nullptr || pBuffData->pData == nullptr)) LOG_BUFFER_ERROR_AND_THROW("initial data must not be null as immutable buffers must be initialized at creation time."); @@ -142,4 +142,51 @@ void ValidateBufferInitData(const BufferDesc& Desc, const BufferData* pBuffData) #undef VERIFY_BUFFER #undef LOG_BUFFER_ERROR_AND_THROW +void ValidateAndCorrectBufferViewDesc(const BufferDesc& BuffDesc, BufferViewDesc& ViewDesc) noexcept(false) +{ + if (ViewDesc.ByteWidth == 0) + { + DEV_CHECK_ERR(BuffDesc.uiSizeInBytes > ViewDesc.ByteOffset, "Byte offset (", ViewDesc.ByteOffset, ") exceeds buffer size (", BuffDesc.uiSizeInBytes, ")"); + ViewDesc.ByteWidth = BuffDesc.uiSizeInBytes - ViewDesc.ByteOffset; + } + + if (ViewDesc.ByteOffset + ViewDesc.ByteWidth > BuffDesc.uiSizeInBytes) + LOG_ERROR_AND_THROW("Buffer view range [", ViewDesc.ByteOffset, ", ", ViewDesc.ByteOffset + ViewDesc.ByteWidth, ") is out of the buffer boundaries [0, ", BuffDesc.uiSizeInBytes, ")."); + + if ((BuffDesc.BindFlags & BIND_UNORDERED_ACCESS) || + (BuffDesc.BindFlags & BIND_SHADER_RESOURCE)) + { + if (BuffDesc.Mode == BUFFER_MODE_STRUCTURED || BuffDesc.Mode == BUFFER_MODE_FORMATTED) + { + VERIFY(BuffDesc.ElementByteStride != 0, "Element byte stride is zero"); + if ((ViewDesc.ByteOffset % BuffDesc.ElementByteStride) != 0) + LOG_ERROR_AND_THROW("Buffer view byte offset (", ViewDesc.ByteOffset, ") is not a multiple of element byte stride (", BuffDesc.ElementByteStride, ")."); + if ((ViewDesc.ByteWidth % BuffDesc.ElementByteStride) != 0) + LOG_ERROR_AND_THROW("Buffer view byte width (", ViewDesc.ByteWidth, ") is not a multiple of element byte stride (", BuffDesc.ElementByteStride, ")."); + } + + if (BuffDesc.Mode == BUFFER_MODE_FORMATTED && ViewDesc.Format.ValueType == VT_UNDEFINED) + LOG_ERROR_AND_THROW("Format must be specified when creating a view of a formatted buffer"); + + if (BuffDesc.Mode == BUFFER_MODE_FORMATTED || (BuffDesc.Mode == BUFFER_MODE_RAW && ViewDesc.Format.ValueType != VT_UNDEFINED)) + { + if (ViewDesc.Format.NumComponents <= 0 || ViewDesc.Format.NumComponents > 4) + LOG_ERROR_AND_THROW("Incorrect number of components (", Uint32{ViewDesc.Format.NumComponents}, "). 1, 2, 3, or 4 are allowed values"); + if (ViewDesc.Format.ValueType == VT_FLOAT32 || ViewDesc.Format.ValueType == VT_FLOAT16) + ViewDesc.Format.IsNormalized = false; + auto ViewElementStride = GetValueSize(ViewDesc.Format.ValueType) * Uint32{ViewDesc.Format.NumComponents}; + if (BuffDesc.Mode == BUFFER_MODE_RAW && BuffDesc.ElementByteStride == 0) + LOG_ERROR_AND_THROW("To enable formatted views of a raw buffer, element byte must be specified during buffer initialization"); + if (ViewElementStride != BuffDesc.ElementByteStride) + LOG_ERROR_AND_THROW("Buffer element byte stride (", BuffDesc.ElementByteStride, ") is not consistent with the size (", ViewElementStride, ") defined by the format of the view (", GetBufferFormatString(ViewDesc.Format), ')'); + } + + if (BuffDesc.Mode == BUFFER_MODE_RAW && ViewDesc.Format.ValueType == VT_UNDEFINED) + { + if ((ViewDesc.ByteOffset % 16) != 0) + LOG_ERROR_AND_THROW("When creating a RAW view, the offset of the first element from the start of the buffer (", ViewDesc.ByteOffset, ") must be a multiple of 16 bytes"); + } + } +} + } // namespace Diligent -- cgit v1.2.3