diff options
| author | assiduous <assiduous@diligentgraphics.com> | 2020-08-23 03:26:49 +0000 |
|---|---|---|
| committer | assiduous <assiduous@diligentgraphics.com> | 2020-08-23 03:26:49 +0000 |
| commit | 2771c71fad9cc4311c287ad119d078662ef52c29 (patch) | |
| tree | a0cf76cd433d6cba40b8a1478ed9d415a2517481 /Graphics/GraphicsEngine | |
| parent | D3D12 backend: improved command list version detection (diff) | |
| download | DiligentCore-2771c71fad9cc4311c287ad119d078662ef52c29.tar.gz DiligentCore-2771c71fad9cc4311c287ad119d078662ef52c29.zip | |
Added USAGE_UNIFIED usage type (API 240066)
Diffstat (limited to 'Graphics/GraphicsEngine')
| -rw-r--r-- | Graphics/GraphicsEngine/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | Graphics/GraphicsEngine/include/BufferBase.hpp | 69 | ||||
| -rw-r--r-- | Graphics/GraphicsEngine/interface/APIInfo.h | 2 | ||||
| -rw-r--r-- | Graphics/GraphicsEngine/interface/GraphicsTypes.h | 27 | ||||
| -rw-r--r-- | Graphics/GraphicsEngine/src/BufferBase.cpp | 128 | ||||
| -rw-r--r-- | Graphics/GraphicsEngine/src/TextureBase.cpp | 4 |
6 files changed, 187 insertions, 44 deletions
diff --git a/Graphics/GraphicsEngine/CMakeLists.txt b/Graphics/GraphicsEngine/CMakeLists.txt index c6ec31ae..1de30eab 100644 --- a/Graphics/GraphicsEngine/CMakeLists.txt +++ b/Graphics/GraphicsEngine/CMakeLists.txt @@ -63,6 +63,7 @@ set(INTERFACE set(SOURCE src/APIInfo.cpp + src/BufferBase.cpp src/DefaultShaderSourceStreamFactory.cpp src/EngineMemory.cpp src/FramebufferBase.cpp diff --git a/Graphics/GraphicsEngine/include/BufferBase.hpp b/Graphics/GraphicsEngine/include/BufferBase.hpp index aeee4114..0095cabb 100644 --- a/Graphics/GraphicsEngine/include/BufferBase.hpp +++ b/Graphics/GraphicsEngine/include/BufferBase.hpp @@ -40,6 +40,9 @@ namespace Diligent { +void ValidateBufferInitData(const BufferDesc& Desc, const BufferData* pBuffData); +void ValidateBufferDesc(const BufferDesc& Desc); + /// Template class implementing base functionality for a buffer object /// \tparam BaseInterface - base interface that this class will inheret @@ -58,13 +61,13 @@ class BufferBase : public DeviceObjectBase<BaseInterface, RenderDeviceImplType, public: using TDeviceObjectBase = DeviceObjectBase<BaseInterface, RenderDeviceImplType, BufferDesc>; - /// \param pRefCounters - reference counters object that controls the lifetime of this buffer. + /// \param pRefCounters - reference counters object that controls the lifetime of this buffer. /// \param BuffViewObjAllocator - allocator that is used to allocate memory for the buffer view instances. /// This parameter is only used for debug purposes. - /// \param pDevice - pointer to the device. - /// \param BuffDesc - buffer description. - /// \param bIsDeviceInternal - flag indicating if the buffer is an internal device object and - /// must not keep a strong reference to the device. + /// \param pDevice - pointer to the device. + /// \param BuffDesc - buffer description. + /// \param bIsDeviceInternal - flag indicating if the buffer is an internal device object and + /// must not keep a strong reference to the device. BufferBase(IReferenceCounters* pRefCounters, TBuffViewObjAllocator& BuffViewObjAllocator, RenderDeviceImplType* pDevice, @@ -77,40 +80,7 @@ public: m_pDefaultUAV{nullptr, STDDeleter<BufferViewImplType, TBuffViewObjAllocator>(BuffViewObjAllocator)}, m_pDefaultSRV{nullptr, STDDeleter<BufferViewImplType, TBuffViewObjAllocator>(BuffViewObjAllocator)} { -#define VERIFY_BUFFER(Expr, ...) \ - do \ - { \ - if (!(Expr)) \ - { \ - LOG_ERROR_AND_THROW("Buffer '", this->m_Desc.Name ? this->m_Desc.Name : "", "': ", ##__VA_ARGS__); \ - } \ - } while (false) - - Uint32 AllowedBindFlags = - BIND_VERTEX_BUFFER | BIND_INDEX_BUFFER | BIND_UNIFORM_BUFFER | - BIND_SHADER_RESOURCE | BIND_STREAM_OUTPUT | BIND_UNORDERED_ACCESS | - BIND_INDIRECT_DRAW_ARGS; - const Char* strAllowedBindFlags = - "BIND_VERTEX_BUFFER (1), BIND_INDEX_BUFFER (2), BIND_UNIFORM_BUFFER (4), " - "BIND_SHADER_RESOURCE (8), BIND_STREAM_OUTPUT (16), BIND_UNORDERED_ACCESS (128), " - "BIND_INDIRECT_DRAW_ARGS (256)"; - - VERIFY_BUFFER((BuffDesc.BindFlags & ~AllowedBindFlags) == 0, "Incorrect bind flags specified (", BuffDesc.BindFlags & ~AllowedBindFlags, "). Only the following flags are allowed:\n", strAllowedBindFlags); - - if ((this->m_Desc.BindFlags & BIND_UNORDERED_ACCESS) || - (this->m_Desc.BindFlags & BIND_SHADER_RESOURCE)) - { - VERIFY_BUFFER(this->m_Desc.Mode > BUFFER_MODE_UNDEFINED && this->m_Desc.Mode < BUFFER_MODE_NUM_MODES, GetBufferModeString(this->m_Desc.Mode), " is not a valid mode for a buffer created with BIND_SHADER_RESOURCE or BIND_UNORDERED_ACCESS flags"); - if (this->m_Desc.Mode == BUFFER_MODE_STRUCTURED || this->m_Desc.Mode == BUFFER_MODE_FORMATTED) - { - VERIFY_BUFFER(this->m_Desc.ElementByteStride != 0, "Element stride must not be zero for structured and formatted buffers"); - } - else if (this->m_Desc.Mode == BUFFER_MODE_RAW) - { - } - } - -#undef VERIFY_BUFFER + ValidateBufferDesc(this->m_Desc); Uint64 DeviceQueuesMask = pDevice->GetCommandQueueMask(); DEV_CHECK_ERR((this->m_Desc.CommandQueueMask & DeviceQueuesMask) != 0, "No bits in the command queue mask (0x", std::hex, this->m_Desc.CommandQueueMask, ") correspond to one of ", pDevice->GetCommandQueueCount(), " available device command queues"); @@ -164,6 +134,27 @@ protected: /// Corrects buffer view description and validates view parameters. void CorrectBufferViewDesc(struct BufferViewDesc& ViewDesc); + void DecayUnifiedBuffer() + { + VERIFY_EXPR(this->m_Desc.Usage == USAGE_UNIFIED); + VERIFY_EXPR(this->m_Desc.CPUAccessFlags != CPU_ACCESS_NONE); + if (this->m_Desc.CPUAccessFlags == CPU_ACCESS_WRITE) + { + this->m_Desc.Usage = USAGE_DEFAULT; + this->m_Desc.CPUAccessFlags = CPU_ACCESS_NONE; + } + else if (this->m_Desc.CPUAccessFlags == CPU_ACCESS_READ) + { + this->m_Desc.Usage = USAGE_STAGING; + } + else + { + LOG_ERROR_AND_THROW("Unified buffer '", this->m_Desc.Name, + "' cannot be automatically converted to a non-unified buffer " + "because it uses both CPU_ACCESS_WRITE and CPU_ACCESS_READ flags"); + } + } + #ifdef DILIGENT_DEBUG TBuffViewObjAllocator& m_dbgBuffViewAllocator; #endif diff --git a/Graphics/GraphicsEngine/interface/APIInfo.h b/Graphics/GraphicsEngine/interface/APIInfo.h index 59d3bd30..8d14c8c2 100644 --- a/Graphics/GraphicsEngine/interface/APIInfo.h +++ b/Graphics/GraphicsEngine/interface/APIInfo.h @@ -30,7 +30,7 @@ /// \file /// Diligent API information -#define DILIGENT_API_VERSION 240065 +#define DILIGENT_API_VERSION 240066 #include "../../../Primitives/interface/BasicTypes.h" diff --git a/Graphics/GraphicsEngine/interface/GraphicsTypes.h b/Graphics/GraphicsEngine/interface/GraphicsTypes.h index 41e83d4e..b80a6712 100644 --- a/Graphics/GraphicsEngine/interface/GraphicsTypes.h +++ b/Graphics/GraphicsEngine/interface/GraphicsTypes.h @@ -102,20 +102,39 @@ DILIGENT_TYPED_ENUM(USAGE, Uint8) /// and cannot be accessed at all by the CPU. This type of resource must be initialized /// when it is created, since it cannot be changed after creation. \n /// D3D11 Counterpart: D3D11_USAGE_IMMUTABLE. OpenGL counterpart: GL_STATIC_DRAW + /// \remarks Static buffers do not allow CPU access and must use CPU_ACCESS_NONE flag. USAGE_STATIC = 0, /// A resource that requires read and write access by the GPU and can also be occasionally /// written by the CPU. \n - /// D3D11 Counterpart: D3D11_USAGE_DEFAULT. OpenGL counterpart: GL_DYNAMIC_DRAW + /// D3D11 Counterpart: D3D11_USAGE_DEFAULT. OpenGL counterpart: GL_DYNAMIC_DRAW. + /// \remarks Default buffers do not allow CPU access and must use CPU_ACCESS_NONE flag. USAGE_DEFAULT, /// A resource that can be read by the GPU and written at least once per frame by the CPU. \n /// D3D11 Counterpart: D3D11_USAGE_DYNAMIC. OpenGL counterpart: GL_STREAM_DRAW + /// \remarks Dynamic buffers must use CPU_ACCESS_WRITE flag. USAGE_DYNAMIC, - /// A resource that facilitates transferring data from GPU to CPU. \n - /// D3D11 Counterpart: D3D11_USAGE_STAGING. OpenGL counterpart: GL_DYNAMIC_READ - USAGE_STAGING + /// A resource that facilitates transferring data between GPU and CPU. \n + /// D3D11 Counterpart: D3D11_USAGE_STAGING. OpenGL counterpart: GL_STATIC_READ or + /// GL_STATIC_COPY depending on the CPU access flags. + /// \remarks Staging buffers must use exactly one of CPU_ACCESS_WRITE or CPU_ACCESS_READ flags. + USAGE_STAGING, + + /// A resource residing in a unified memory (e.g. memory shared between CPU and GPU), + /// that can be read and written by GPU and can also be directly accessed by CPU. + /// \remarks Unified buffers must use at least one of CPU_ACCESS_WRITE or CPU_ACCESS_READ flags.\n + /// If it is not possible to create a unified resource, the engine will attempt to create a non-unified + /// resource as below: + /// - If CPU_ACCESS_WRITE flag is specified, default-usage resource will be created. + /// - If CPU_ACCESS_READ flag is specified, staging resource will be created. + /// - If both CPU_ACCESS_WRITE and CPU_ACCESS_READ flags are used, an error will be generated. + /// An application must check the actual usage after the resource has been created. + USAGE_UNIFIED, + + /// Helper value indicating the total number of elements in the enum + USAGE_NUM_USAGES }; /// Allowed CPU access mode flags when mapping a resource diff --git a/Graphics/GraphicsEngine/src/BufferBase.cpp b/Graphics/GraphicsEngine/src/BufferBase.cpp new file mode 100644 index 00000000..106fd671 --- /dev/null +++ b/Graphics/GraphicsEngine/src/BufferBase.cpp @@ -0,0 +1,128 @@ +/* + * Copyright 2019-2020 Diligent Graphics LLC + * Copyright 2015-2019 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#include "pch.h" +#include "Buffer.h" +#include "GraphicsAccessories.hpp" + +namespace Diligent +{ + +#define LOG_BUFFER_ERROR_AND_THROW(...) LOG_ERROR_AND_THROW("Description of buffer '", (Desc.Name ? Desc.Name : ""), "' is invalid: ", ##__VA_ARGS__) +#define VERIFY_BUFFER(Expr, ...) \ + do \ + { \ + if (!(Expr)) \ + { \ + LOG_BUFFER_ERROR_AND_THROW(__VA_ARGS__); \ + } \ + } while (false) + + +void ValidateBufferDesc(const BufferDesc& Desc) +{ + constexpr Uint32 AllowedBindFlags = + BIND_VERTEX_BUFFER | + BIND_INDEX_BUFFER | + BIND_UNIFORM_BUFFER | + BIND_SHADER_RESOURCE | + BIND_STREAM_OUTPUT | + BIND_UNORDERED_ACCESS | + BIND_INDIRECT_DRAW_ARGS; + + VERIFY_BUFFER((Desc.BindFlags & ~AllowedBindFlags) == 0, "the following bind flags are not allowed for a buffer: ", GetBindFlagsString(Desc.BindFlags & ~AllowedBindFlags, ", "), '.'); + + if ((Desc.BindFlags & BIND_UNORDERED_ACCESS) || + (Desc.BindFlags & BIND_SHADER_RESOURCE)) + { + VERIFY_BUFFER(Desc.Mode > BUFFER_MODE_UNDEFINED && Desc.Mode < BUFFER_MODE_NUM_MODES, GetBufferModeString(Desc.Mode), " is not a valid mode for a buffer created with BIND_SHADER_RESOURCE or BIND_UNORDERED_ACCESS flags."); + if (Desc.Mode == BUFFER_MODE_STRUCTURED || Desc.Mode == BUFFER_MODE_FORMATTED) + { + VERIFY_BUFFER(Desc.ElementByteStride != 0, "element stride must not be zero for structured and formatted buffers."); + } + else if (Desc.Mode == BUFFER_MODE_RAW) + { + } + } + + switch (Desc.Usage) + { + case USAGE_STATIC: + case USAGE_DEFAULT: + VERIFY_BUFFER(Desc.CPUAccessFlags == CPU_ACCESS_NONE, "static and default buffers can't have any CPU access flags set."); + break; + + case USAGE_DYNAMIC: + VERIFY_BUFFER(Desc.CPUAccessFlags == CPU_ACCESS_WRITE, "dynamic buffers require CPU_ACCESS_WRITE flag."); + break; + + case USAGE_STAGING: + VERIFY_BUFFER(Desc.CPUAccessFlags == CPU_ACCESS_WRITE || Desc.CPUAccessFlags == CPU_ACCESS_READ, + "exactly one of CPU_ACCESS_WRITE or CPU_ACCESS_READ flags must be specified for a staging buffer."); + VERIFY_BUFFER(Desc.BindFlags == BIND_NONE, + "staging buffers cannot be bound to any part of the graphics pipeline and can't have any bind flags set."); + break; + + case USAGE_UNIFIED: + VERIFY_BUFFER(Desc.CPUAccessFlags != CPU_ACCESS_NONE, + "at least one of CPU_ACCESS_WRITE or CPU_ACCESS_READ flags must be specified for a unified buffer."); + break; + + default: + UNEXPECTED("Unknown usage"); + } +} + +void ValidateBufferInitData(const BufferDesc& Desc, const BufferData* pBuffData) +{ + if (Desc.Usage == USAGE_STATIC && (pBuffData == nullptr || pBuffData->pData == nullptr)) + LOG_BUFFER_ERROR_AND_THROW("initial data must not be null as static buffers must be initialized at creation time."); + + if (Desc.Usage == USAGE_DYNAMIC && pBuffData != nullptr && pBuffData->pData != nullptr) + LOG_BUFFER_ERROR_AND_THROW("initial data must be null for dynamic buffers."); + + if (Desc.Usage == USAGE_STAGING) + { + if (Desc.CPUAccessFlags == CPU_ACCESS_WRITE) + { + VERIFY_BUFFER(pBuffData == nullptr || pBuffData->pData == nullptr, + "CPU-writable staging buffers must be updated via map."); + } + } + else if (Desc.Usage == USAGE_UNIFIED) + { + if (pBuffData != nullptr && pBuffData->pData != nullptr && (Desc.CPUAccessFlags & CPU_ACCESS_WRITE) == 0) + { + LOG_BUFFER_ERROR_AND_THROW("CPU_ACCESS_WRITE flag is required to intialize a unified buffer."); + } + } +} + +#undef VERIFY_BUFFER +#undef LOG_BUFFER_ERROR_AND_THROW + +} // namespace Diligent diff --git a/Graphics/GraphicsEngine/src/TextureBase.cpp b/Graphics/GraphicsEngine/src/TextureBase.cpp index e7073aae..c4e5e999 100644 --- a/Graphics/GraphicsEngine/src/TextureBase.cpp +++ b/Graphics/GraphicsEngine/src/TextureBase.cpp @@ -128,6 +128,10 @@ void ValidateTextureDesc(const TextureDesc& Desc) if ((Desc.CPUAccessFlags & (CPU_ACCESS_READ | CPU_ACCESS_WRITE)) == (CPU_ACCESS_READ | CPU_ACCESS_WRITE)) LOG_TEXTURE_ERROR_AND_THROW("Staging textures must use exactly one of ACESS_READ or ACCESS_WRITE flags"); } + else if (Desc.Usage == USAGE_UNIFIED) + { + LOG_TEXTURE_ERROR_AND_THROW("USAGE_UNIFIED textures are currently not supported"); + } } |
