summaryrefslogtreecommitdiffstats
path: root/Graphics/GraphicsEngine
diff options
context:
space:
mode:
authorassiduous <assiduous@diligentgraphics.com>2020-08-23 03:26:49 +0000
committerassiduous <assiduous@diligentgraphics.com>2020-08-23 03:26:49 +0000
commit2771c71fad9cc4311c287ad119d078662ef52c29 (patch)
treea0cf76cd433d6cba40b8a1478ed9d415a2517481 /Graphics/GraphicsEngine
parentD3D12 backend: improved command list version detection (diff)
downloadDiligentCore-2771c71fad9cc4311c287ad119d078662ef52c29.tar.gz
DiligentCore-2771c71fad9cc4311c287ad119d078662ef52c29.zip
Added USAGE_UNIFIED usage type (API 240066)
Diffstat (limited to 'Graphics/GraphicsEngine')
-rw-r--r--Graphics/GraphicsEngine/CMakeLists.txt1
-rw-r--r--Graphics/GraphicsEngine/include/BufferBase.hpp69
-rw-r--r--Graphics/GraphicsEngine/interface/APIInfo.h2
-rw-r--r--Graphics/GraphicsEngine/interface/GraphicsTypes.h27
-rw-r--r--Graphics/GraphicsEngine/src/BufferBase.cpp128
-rw-r--r--Graphics/GraphicsEngine/src/TextureBase.cpp4
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");
+ }
}