summaryrefslogtreecommitdiffstats
path: root/Graphics/GraphicsEngineVulkan
diff options
context:
space:
mode:
authorEgor Yusov <egor.yusov@gmail.com>2019-11-24 23:34:48 +0000
committerEgor Yusov <egor.yusov@gmail.com>2019-11-24 23:34:48 +0000
commitcc038e873634fef5ca4c861e375bf8a39ef372ae (patch)
tree33ec16a8b26332fef3892bee0ecb942684ac411e /Graphics/GraphicsEngineVulkan
parentclang-formatted headers of GraphicsEngineVulkan project (diff)
downloadDiligentCore-cc038e873634fef5ca4c861e375bf8a39ef372ae.tar.gz
DiligentCore-cc038e873634fef5ca4c861e375bf8a39ef372ae.zip
clang-formatted cpp files of GraphiceEngineVulkan project
Diffstat (limited to 'Graphics/GraphicsEngineVulkan')
-rw-r--r--Graphics/GraphicsEngineVulkan/include/CommandPoolManager.h31
-rw-r--r--Graphics/GraphicsEngineVulkan/src/BufferViewVkImpl.cpp20
-rw-r--r--Graphics/GraphicsEngineVulkan/src/BufferVkImpl.cpp218
-rw-r--r--Graphics/GraphicsEngineVulkan/src/CommandPoolManager.cpp38
-rw-r--r--Graphics/GraphicsEngineVulkan/src/CommandQueueVkImpl.cpp52
-rw-r--r--Graphics/GraphicsEngineVulkan/src/DescriptorPoolManager.cpp66
-rw-r--r--Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp3711
-rw-r--r--Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp220
-rw-r--r--Graphics/GraphicsEngineVulkan/src/FenceVkImpl.cpp31
-rw-r--r--Graphics/GraphicsEngineVulkan/src/FramebufferCache.cpp48
-rw-r--r--Graphics/GraphicsEngineVulkan/src/GenerateMipsVkHelper.cpp727
-rw-r--r--Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp206
-rw-r--r--Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp286
-rw-r--r--Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp274
-rw-r--r--Graphics/GraphicsEngineVulkan/src/RenderPassCache.cpp25
-rw-r--r--Graphics/GraphicsEngineVulkan/src/SamplerVkImpl.cpp48
-rw-r--r--Graphics/GraphicsEngineVulkan/src/ShaderResourceBindingVkImpl.cpp42
-rw-r--r--Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp149
-rw-r--r--Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp437
-rw-r--r--Graphics/GraphicsEngineVulkan/src/ShaderVariableVk.cpp89
-rw-r--r--Graphics/GraphicsEngineVulkan/src/ShaderVkImpl.cpp44
-rw-r--r--Graphics/GraphicsEngineVulkan/src/SwapChainVkImpl.cpp270
-rw-r--r--Graphics/GraphicsEngineVulkan/src/TextureViewVkImpl.cpp22
-rw-r--r--Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp349
-rw-r--r--Graphics/GraphicsEngineVulkan/src/VulkanDynamicHeap.cpp151
-rw-r--r--Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp356
-rw-r--r--Graphics/GraphicsEngineVulkan/src/VulkanUploadHeap.cpp57
-rw-r--r--Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanCommandBuffer.cpp203
-rw-r--r--Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanCommandBufferPool.cpp152
-rw-r--r--Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanDebug.cpp1034
-rw-r--r--Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanFencePool.cpp68
-rw-r--r--Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanInstance.cpp388
-rw-r--r--Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanLogicalDevice.cpp887
-rw-r--r--Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanMemoryManager.cpp79
-rw-r--r--Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp277
35 files changed, 5703 insertions, 5352 deletions
diff --git a/Graphics/GraphicsEngineVulkan/include/CommandPoolManager.h b/Graphics/GraphicsEngineVulkan/include/CommandPoolManager.h
index c28d1838..525d1d60 100644
--- a/Graphics/GraphicsEngineVulkan/include/CommandPoolManager.h
+++ b/Graphics/GraphicsEngineVulkan/include/CommandPoolManager.h
@@ -37,11 +37,11 @@ class RenderDeviceVkImpl;
class CommandPoolManager
{
public:
- CommandPoolManager(RenderDeviceVkImpl& DeviceVkImpl,
+ CommandPoolManager(RenderDeviceVkImpl& DeviceVkImpl,
std::string Name,
- uint32_t queueFamilyIndex,
- VkCommandPoolCreateFlags flags)noexcept;
-
+ uint32_t queueFamilyIndex,
+ VkCommandPoolCreateFlags flags) noexcept;
+
// clang-format off
CommandPoolManager (const CommandPoolManager&) = delete;
CommandPoolManager ( CommandPoolManager&&) = delete;
@@ -52,31 +52,34 @@ public:
~CommandPoolManager();
// Allocates Vulkan command pool.
- VulkanUtilities::CommandPoolWrapper AllocateCommandPool(const char *DebugName = nullptr);
-
+ VulkanUtilities::CommandPoolWrapper AllocateCommandPool(const char* DebugName = nullptr);
+
void SafeReleaseCommandPool(VulkanUtilities::CommandPoolWrapper&& CmdPool, Uint32 CmdQueueIndex, Uint64 FenceValue);
void DestroyPools();
#ifdef DEVELOPMENT
- int32_t GetAllocatedPoolCount()const{return m_AllocatedPoolCounter;}
+ int32_t GetAllocatedPoolCount() const
+ {
+ return m_AllocatedPoolCounter;
+ }
#endif
private:
// Returns command pool to the list of available pools. The GPU must have finished using the pool
void FreeCommandPool(VulkanUtilities::CommandPoolWrapper&& CmdPool);
- RenderDeviceVkImpl& m_DeviceVkImpl;
- const std::string m_Name;
- const uint32_t m_QueueFamilyIndex;
- const VkCommandPoolCreateFlags m_CmdPoolFlags;
+ RenderDeviceVkImpl& m_DeviceVkImpl;
+ const std::string m_Name;
+ const uint32_t m_QueueFamilyIndex;
+ const VkCommandPoolCreateFlags m_CmdPoolFlags;
- std::mutex m_Mutex;
- std::deque< VulkanUtilities::CommandPoolWrapper, STDAllocatorRawMem<VulkanUtilities::CommandPoolWrapper> > m_CmdPools;
+ std::mutex m_Mutex;
+ std::deque<VulkanUtilities::CommandPoolWrapper, STDAllocatorRawMem<VulkanUtilities::CommandPoolWrapper>> m_CmdPools;
#ifdef DEVELOPMENT
std::atomic_int32_t m_AllocatedPoolCounter;
#endif
};
-}
+} // namespace Diligent
diff --git a/Graphics/GraphicsEngineVulkan/src/BufferViewVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/BufferViewVkImpl.cpp
index eb9b4001..74cd8ab7 100644
--- a/Graphics/GraphicsEngineVulkan/src/BufferViewVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/BufferViewVkImpl.cpp
@@ -29,12 +29,13 @@
namespace Diligent
{
-BufferViewVkImpl::BufferViewVkImpl( IReferenceCounters* pRefCounters,
- RenderDeviceVkImpl* pDevice,
- const BufferViewDesc& ViewDesc,
- IBuffer* pBuffer,
- VulkanUtilities::BufferViewWrapper&& BuffView,
- bool bIsDefaultView ) :
+BufferViewVkImpl::BufferViewVkImpl(IReferenceCounters* pRefCounters,
+ RenderDeviceVkImpl* pDevice,
+ const BufferViewDesc& ViewDesc,
+ IBuffer* pBuffer,
+ VulkanUtilities::BufferViewWrapper&& BuffView,
+ bool bIsDefaultView) :
+ // clang-format off
TBufferViewBase
{
pRefCounters,
@@ -44,6 +45,7 @@ BufferViewVkImpl::BufferViewVkImpl( IReferenceCounters* pRefCou
bIsDefaultView
},
m_BuffView{std::move(BuffView)}
+// clang-format on
{
}
@@ -52,9 +54,9 @@ BufferViewVkImpl::~BufferViewVkImpl()
m_pDevice->SafeReleaseDeviceObject(std::move(m_BuffView), m_pBuffer->GetDesc().CommandQueueMask);
}
-IMPLEMENT_QUERY_INTERFACE( BufferViewVkImpl, IID_BufferViewVk, TBufferViewBase )
+IMPLEMENT_QUERY_INTERFACE(BufferViewVkImpl, IID_BufferViewVk, TBufferViewBase)
-const BufferVkImpl* BufferViewVkImpl::GetBufferVk()const
+const BufferVkImpl* BufferViewVkImpl::GetBufferVk() const
{
return ValidatedCast<const BufferVkImpl>(m_pBuffer);
}
@@ -64,4 +66,4 @@ BufferVkImpl* BufferViewVkImpl::GetBufferVk()
return ValidatedCast<BufferVkImpl>(m_pBuffer);
}
-}
+} // namespace Diligent
diff --git a/Graphics/GraphicsEngineVulkan/src/BufferVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/BufferVkImpl.cpp
index 8f96a003..3a878440 100644
--- a/Graphics/GraphicsEngineVulkan/src/BufferVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/BufferVkImpl.cpp
@@ -36,11 +36,12 @@
namespace Diligent
{
-BufferVkImpl :: BufferVkImpl(IReferenceCounters* pRefCounters,
- FixedBlockMemoryAllocator& BuffViewObjMemAllocator,
- RenderDeviceVkImpl* pRenderDeviceVk,
- const BufferDesc& BuffDesc,
- const BufferData* pBuffData /*= nullptr*/) :
+BufferVkImpl::BufferVkImpl(IReferenceCounters* pRefCounters,
+ FixedBlockMemoryAllocator& BuffViewObjMemAllocator,
+ RenderDeviceVkImpl* pRenderDeviceVk,
+ const BufferDesc& BuffDesc,
+ const BufferData* pBuffData /*= nullptr*/) :
+ // clang-format off
TBufferBase
{
pRefCounters,
@@ -50,38 +51,39 @@ BufferVkImpl :: BufferVkImpl(IReferenceCounters* pRefCounters,
false
},
m_DynamicAllocations{STD_ALLOCATOR_RAW_MEM(VulkanDynamicAllocation, GetRawAllocator(), "Allocator for vector<VulkanDynamicAllocation>")}
+// clang-format on
{
-#define LOG_BUFFER_ERROR_AND_THROW(...) LOG_ERROR_AND_THROW("Buffer \"", BuffDesc.Name ? BuffDesc.Name : "", "\": ", ##__VA_ARGS__);
+#define LOG_BUFFER_ERROR_AND_THROW(...) LOG_ERROR_AND_THROW("Buffer \"", BuffDesc.Name ? BuffDesc.Name : "", "\": ", ##__VA_ARGS__)
- if( m_Desc.Usage == USAGE_STATIC && (pBuffData == nullptr || pBuffData->pData == nullptr) )
- LOG_BUFFER_ERROR_AND_THROW("Static buffer must be initialized with data at creation time")
+ if (m_Desc.Usage == USAGE_STATIC && (pBuffData == nullptr || pBuffData->pData == nullptr))
+ LOG_BUFFER_ERROR_AND_THROW("Static buffer must be initialized with data at creation time");
- if( m_Desc.Usage == USAGE_DYNAMIC && pBuffData != nullptr && pBuffData->pData != nullptr )
- LOG_BUFFER_ERROR_AND_THROW("Dynamic buffer must be initialized via Map()")
+ if (m_Desc.Usage == USAGE_DYNAMIC && pBuffData != nullptr && pBuffData->pData != nullptr)
+ LOG_BUFFER_ERROR_AND_THROW("Dynamic buffer must be initialized via Map()");
if (m_Desc.Usage == USAGE_STAGING)
{
if (m_Desc.CPUAccessFlags != CPU_ACCESS_WRITE && m_Desc.CPUAccessFlags != CPU_ACCESS_READ)
- LOG_BUFFER_ERROR_AND_THROW("Exactly one of the CPU_ACCESS_WRITE or CPU_ACCESS_READ flags must be specified for a cpu-accessible buffer")
+ LOG_BUFFER_ERROR_AND_THROW("Exactly one of the CPU_ACCESS_WRITE or CPU_ACCESS_READ flags must be specified for a cpu-accessible buffer");
if (m_Desc.CPUAccessFlags == CPU_ACCESS_WRITE)
{
if (pBuffData != nullptr && pBuffData->pData != nullptr)
- LOG_BUFFER_ERROR_AND_THROW("CPU-writable staging buffers must be updated via map")
+ LOG_BUFFER_ERROR_AND_THROW("CPU-writable staging buffers must be updated via map");
}
}
const auto& LogicalDevice = pRenderDeviceVk->GetLogicalDevice();
- const auto& DeviceLimits = pRenderDeviceVk->GetPhysicalDevice().GetProperties().limits;
- m_DynamicOffsetAlignment = std::max(Uint32{4}, static_cast<Uint32>(DeviceLimits.optimalBufferCopyOffsetAlignment));
+ const auto& DeviceLimits = pRenderDeviceVk->GetPhysicalDevice().GetProperties().limits;
+ m_DynamicOffsetAlignment = std::max(Uint32{4}, static_cast<Uint32>(DeviceLimits.optimalBufferCopyOffsetAlignment));
VkBufferCreateInfo VkBuffCI = {};
- VkBuffCI.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
- VkBuffCI.pNext = nullptr;
- VkBuffCI.flags = 0; // VK_BUFFER_CREATE_SPARSE_BINDING_BIT, VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT, VK_BUFFER_CREATE_SPARSE_ALIASED_BIT
- VkBuffCI.size = m_Desc.uiSizeInBytes;
+ VkBuffCI.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
+ VkBuffCI.pNext = nullptr;
+ VkBuffCI.flags = 0; // VK_BUFFER_CREATE_SPARSE_BINDING_BIT, VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT, VK_BUFFER_CREATE_SPARSE_ALIASED_BIT
+ VkBuffCI.size = m_Desc.uiSizeInBytes;
VkBuffCI.usage =
- VK_BUFFER_USAGE_TRANSFER_SRC_BIT | // The buffer can be used as the source of a transfer command
+ VK_BUFFER_USAGE_TRANSFER_SRC_BIT | // The buffer can be used as the source of a transfer command
VK_BUFFER_USAGE_TRANSFER_DST_BIT; // The buffer can be used as the destination of a transfer command
if (m_Desc.BindFlags & BIND_UNORDERED_ACCESS)
{
@@ -89,15 +91,15 @@ BufferVkImpl :: BufferVkImpl(IReferenceCounters* pRefCounters,
// HLSL formatted buffers are mapped to GLSL storage buffers:
//
// RWBuffer<uint4> RWBuff
- //
+ //
// |
// V
- //
+ //
// layout(std140, binding = 3) buffer RWBuff
// {
// uvec4 data[];
// }g_RWBuff;
- //
+ //
// So we have to set both VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT and VK_BUFFER_USAGE_STORAGE_BUFFER_BIT bits
VkBuffCI.usage |= VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
@@ -110,7 +112,7 @@ BufferVkImpl :: BufferVkImpl(IReferenceCounters* pRefCounters,
if (m_Desc.BindFlags & BIND_SHADER_RESOURCE)
{
// VkBuffCI.usage |= m_Desc.Mode == BUFFER_MODE_FORMATTED ? VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT : VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
- // HLSL buffer SRVs are mapped to storge buffers in GLSL, so we need to set both
+ // HLSL buffer SRVs are mapped to storge buffers in GLSL, so we need to set both
// VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT and VK_BUFFER_USAGE_STORAGE_BUFFER_BIT flags
VkBuffCI.usage |= VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
@@ -128,16 +130,16 @@ BufferVkImpl :: BufferVkImpl(IReferenceCounters* pRefCounters,
VkBuffCI.usage |= VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
// Each element of pDynamicOffsets parameter of vkCmdBindDescriptorSets function which corresponds to a descriptor
- // binding with type VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC must be a multiple of
+ // binding with type VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC must be a multiple of
// VkPhysicalDeviceLimits::minUniformBufferOffsetAlignment (13.2.5)
m_DynamicOffsetAlignment = std::max(m_DynamicOffsetAlignment, static_cast<Uint32>(DeviceLimits.minUniformBufferOffsetAlignment));
}
- if(m_Desc.Usage == USAGE_DYNAMIC)
+ if (m_Desc.Usage == USAGE_DYNAMIC)
{
auto CtxCount = 1 + pRenderDeviceVk->GetNumDeferredContexts();
m_DynamicAllocations.reserve(CtxCount);
- for(Uint32 ctx=0; ctx < CtxCount; ++ctx)
+ for (Uint32 ctx = 0; ctx < CtxCount; ++ctx)
m_DynamicAllocations.emplace_back();
}
@@ -146,32 +148,33 @@ BufferVkImpl :: BufferVkImpl(IReferenceCounters* pRefCounters,
// Dynamic constant/vertex/index buffers are suballocated in the upload heap when Map() is called.
// Dynamic buffers with SRV or UAV flags need to be allocated in GPU-only memory
constexpr RESOURCE_STATE State = static_cast<RESOURCE_STATE>(
- RESOURCE_STATE_VERTEX_BUFFER |
- RESOURCE_STATE_INDEX_BUFFER |
- RESOURCE_STATE_CONSTANT_BUFFER |
- RESOURCE_STATE_SHADER_RESOURCE |
- RESOURCE_STATE_COPY_SOURCE |
- RESOURCE_STATE_INDIRECT_ARGUMENT);
+ RESOURCE_STATE_VERTEX_BUFFER |
+ RESOURCE_STATE_INDEX_BUFFER |
+ RESOURCE_STATE_CONSTANT_BUFFER |
+ RESOURCE_STATE_SHADER_RESOURCE |
+ RESOURCE_STATE_COPY_SOURCE |
+ RESOURCE_STATE_INDIRECT_ARGUMENT);
SetState(State);
#ifdef _DEBUG
{
- VkAccessFlags AccessFlags = VK_ACCESS_INDIRECT_COMMAND_READ_BIT |
- VK_ACCESS_INDEX_READ_BIT |
- VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT |
- VK_ACCESS_UNIFORM_READ_BIT |
- VK_ACCESS_SHADER_READ_BIT |
- VK_ACCESS_TRANSFER_READ_BIT;
+ VkAccessFlags AccessFlags =
+ VK_ACCESS_INDIRECT_COMMAND_READ_BIT |
+ VK_ACCESS_INDEX_READ_BIT |
+ VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT |
+ VK_ACCESS_UNIFORM_READ_BIT |
+ VK_ACCESS_SHADER_READ_BIT |
+ VK_ACCESS_TRANSFER_READ_BIT;
VERIFY_EXPR(ResourceStateFlagsToVkAccessFlags(State) == AccessFlags);
}
#endif
}
else
{
- VkBuffCI.sharingMode = VK_SHARING_MODE_EXCLUSIVE; // sharing mode of the buffer when it will be accessed by multiple queue families.
- VkBuffCI.queueFamilyIndexCount = 0; // number of entries in the pQueueFamilyIndices array
- VkBuffCI.pQueueFamilyIndices = nullptr; // list of queue families that will access this buffer
- // (ignored if sharingMode is not VK_SHARING_MODE_CONCURRENT).
+ VkBuffCI.sharingMode = VK_SHARING_MODE_EXCLUSIVE; // sharing mode of the buffer when it will be accessed by multiple queue families.
+ VkBuffCI.queueFamilyIndexCount = 0; // number of entries in the pQueueFamilyIndices array
+ VkBuffCI.pQueueFamilyIndices = nullptr; // list of queue families that will access this buffer
+ // (ignored if sharingMode is not VK_SHARING_MODE_CONCURRENT).
m_VulkanBuffer = LogicalDevice.CreateBuffer(VkBuffCI, m_Desc.Name);
@@ -183,21 +186,21 @@ BufferVkImpl :: BufferVkImpl(IReferenceCounters* pRefCounters,
else
BufferMemoryFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
- VERIFY( IsPowerOfTwo(MemReqs.alignment), "Alignment is not power of 2!");
+ VERIFY(IsPowerOfTwo(MemReqs.alignment), "Alignment is not power of 2!");
m_MemoryAllocation = pRenderDeviceVk->AllocateMemory(MemReqs, BufferMemoryFlags);
auto AlignedOffset = Align(VkDeviceSize{m_MemoryAllocation.UnalignedOffset}, MemReqs.alignment);
VERIFY(m_MemoryAllocation.Size >= MemReqs.size + (AlignedOffset - m_MemoryAllocation.UnalignedOffset), "Size of memory allocation is too small");
auto Memory = m_MemoryAllocation.Page->GetVkMemory();
- auto err = LogicalDevice.BindBufferMemory(m_VulkanBuffer, Memory, AlignedOffset);
+ auto err = LogicalDevice.BindBufferMemory(m_VulkanBuffer, Memory, AlignedOffset);
CHECK_VK_ERROR_AND_THROW(err, "Failed to bind buffer memory");
- bool bInitializeBuffer = (pBuffData != nullptr && pBuffData->pData != nullptr && pBuffData->DataSize > 0);
- RESOURCE_STATE InitialState = RESOURCE_STATE_UNDEFINED;
- if( bInitializeBuffer )
+ bool bInitializeBuffer = (pBuffData != nullptr && pBuffData->pData != nullptr && pBuffData->DataSize > 0);
+ RESOURCE_STATE InitialState = RESOURCE_STATE_UNDEFINED;
+ if (bInitializeBuffer)
{
VkBufferCreateInfo VkStaginBuffCI = VkBuffCI;
- VkStaginBuffCI.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
+ VkStaginBuffCI.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
std::string StagingBufferName = "Upload buffer for '";
StagingBufferName += m_Desc.Name;
@@ -205,13 +208,13 @@ BufferVkImpl :: BufferVkImpl(IReferenceCounters* pRefCounters,
VulkanUtilities::BufferWrapper StagingBuffer = LogicalDevice.CreateBuffer(VkStaginBuffCI, StagingBufferName.c_str());
VkMemoryRequirements StagingBufferMemReqs = LogicalDevice.GetBufferMemoryRequirements(StagingBuffer);
- VERIFY( IsPowerOfTwo(StagingBufferMemReqs.alignment), "Alignment is not power of 2!");
+ VERIFY(IsPowerOfTwo(StagingBufferMemReqs.alignment), "Alignment is not power of 2!");
- // VK_MEMORY_PROPERTY_HOST_COHERENT_BIT bit specifies that the host cache management commands vkFlushMappedMemoryRanges
+ // VK_MEMORY_PROPERTY_HOST_COHERENT_BIT bit specifies that the host cache management commands vkFlushMappedMemoryRanges
// and vkInvalidateMappedMemoryRanges are NOT needed to flush host writes to the device or make device writes visible
// to the host (10.2)
auto StagingMemoryAllocation = pRenderDeviceVk->AllocateMemory(StagingBufferMemReqs, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
- auto StagingBufferMemory = StagingMemoryAllocation.Page->GetVkMemory();
+ auto StagingBufferMemory = StagingMemoryAllocation.Page->GetVkMemory();
auto AlignedStagingMemOffset = Align(VkDeviceSize{StagingMemoryAllocation.UnalignedOffset}, StagingBufferMemReqs.alignment);
VERIFY_EXPR(StagingMemoryAllocation.Size >= StagingBufferMemReqs.size + (AlignedStagingMemOffset - StagingMemoryAllocation.UnalignedOffset));
@@ -224,12 +227,12 @@ BufferVkImpl :: BufferVkImpl(IReferenceCounters* pRefCounters,
CHECK_VK_ERROR_AND_THROW(err, "Failed to bind staging bufer memory");
VulkanUtilities::CommandPoolWrapper CmdPool;
- VkCommandBuffer vkCmdBuff;
+ VkCommandBuffer vkCmdBuff;
pRenderDeviceVk->AllocateTransientCmdPool(CmdPool, vkCmdBuff, "Transient command pool to copy staging data to a device buffer");
auto EnabledGraphicsShaderStages = LogicalDevice.GetEnabledGraphicsShaderStages();
VulkanUtilities::VulkanCommandBuffer::BufferMemoryBarrier(vkCmdBuff, StagingBuffer, 0, VK_ACCESS_TRANSFER_READ_BIT, EnabledGraphicsShaderStages);
- InitialState = RESOURCE_STATE_COPY_DEST;
+ InitialState = RESOURCE_STATE_COPY_DEST;
VkAccessFlags AccessFlags = ResourceStateFlagsToVkAccessFlags(InitialState);
VERIFY_EXPR(AccessFlags == VK_ACCESS_TRANSFER_WRITE_BIT);
VulkanUtilities::VulkanCommandBuffer::BufferMemoryBarrier(vkCmdBuff, m_VulkanBuffer, 0, AccessFlags, EnabledGraphicsShaderStages);
@@ -237,17 +240,17 @@ BufferVkImpl :: BufferVkImpl(IReferenceCounters* pRefCounters,
// Copy commands MUST be recorded outside of a render pass instance. This is OK here
// as copy will be the only command in the cmd buffer
VkBufferCopy BuffCopy = {};
- BuffCopy.srcOffset = 0;
- BuffCopy.dstOffset = 0;
- BuffCopy.size = VkBuffCI.size;
+ BuffCopy.srcOffset = 0;
+ BuffCopy.dstOffset = 0;
+ BuffCopy.size = VkBuffCI.size;
vkCmdCopyBuffer(vkCmdBuff, StagingBuffer, m_VulkanBuffer, 1, &BuffCopy);
Uint32 QueueIndex = 0;
- pRenderDeviceVk->ExecuteAndDisposeTransientCmdBuff(QueueIndex, vkCmdBuff, std::move(CmdPool));
+ pRenderDeviceVk->ExecuteAndDisposeTransientCmdBuff(QueueIndex, vkCmdBuff, std::move(CmdPool));
// After command buffer is submitted, safe-release staging resources. This strategy
- // is little overconservative as the resources will only be released after the
+ // is little overconservative as the resources will only be released after the
// first command buffer submitted through the immediate context is complete
// Next Cmd Buff| Next Fence | This Thread | Immediate Context
@@ -257,20 +260,20 @@ BufferVkImpl :: BufferVkImpl(IReferenceCounters* pRefCounters,
// | | ExecuteAndDisposeTransientCmdBuff(vkCmdBuff) |
// | | - SubmittedCmdBuffNumber = N |
// | | - SubmittedFenceValue = F |
- // N+1 - - | - F+1 - | |
+ // N+1 - - | - F+1 - | |
// | | Release(StagingBuffer) |
// | | - {N+1, StagingBuffer} -> Stale Objects |
// | | |
// | | |
- // | | | ExecuteCommandBuffer()
+ // | | | ExecuteCommandBuffer()
// | | | - SubmittedCmdBuffNumber = N+1
// | | | - SubmittedFenceValue = F+1
- // N+2 - - | - F+2 - | - - - - - - - - - - - - |
- // | | | - DiscardStaleVkObjects(N+1, F+1)
- // | | | - {F+1, StagingBuffer} -> Release Queue
- // | | |
+ // N+2 - - | - F+2 - | - - - - - - - - - - - - |
+ // | | | - DiscardStaleVkObjects(N+1, F+1)
+ // | | | - {F+1, StagingBuffer} -> Release Queue
+ // | | |
- pRenderDeviceVk->SafeReleaseDeviceObject(std::move(StagingBuffer), Uint64{1} << Uint64{QueueIndex});
+ pRenderDeviceVk->SafeReleaseDeviceObject(std::move(StagingBuffer), Uint64{1} << Uint64{QueueIndex});
pRenderDeviceVk->SafeReleaseDeviceObject(std::move(StagingMemoryAllocation), Uint64{1} << Uint64{QueueIndex});
}
@@ -281,59 +284,67 @@ BufferVkImpl :: BufferVkImpl(IReferenceCounters* pRefCounters,
}
-BufferVkImpl :: BufferVkImpl(IReferenceCounters* pRefCounters,
- FixedBlockMemoryAllocator& BuffViewObjMemAllocator,
- RenderDeviceVkImpl* pRenderDeviceVk,
- const BufferDesc& BuffDesc,
- RESOURCE_STATE InitialState,
- VkBuffer vkBuffer) :
- TBufferBase(pRefCounters, BuffViewObjMemAllocator, pRenderDeviceVk, BuffDesc, false),
- m_DynamicAllocations(STD_ALLOCATOR_RAW_MEM(VulkanDynamicAllocation, GetRawAllocator(), "Allocator for vector<VulkanDynamicAllocation>")),
- m_VulkanBuffer(vkBuffer)
+BufferVkImpl::BufferVkImpl(IReferenceCounters* pRefCounters,
+ FixedBlockMemoryAllocator& BuffViewObjMemAllocator,
+ RenderDeviceVkImpl* pRenderDeviceVk,
+ const BufferDesc& BuffDesc,
+ RESOURCE_STATE InitialState,
+ VkBuffer vkBuffer) :
+ // clang-format off
+ TBufferBase
+ {
+ pRefCounters,
+ BuffViewObjMemAllocator,
+ pRenderDeviceVk,
+ BuffDesc,
+ false
+ },
+ m_DynamicAllocations{STD_ALLOCATOR_RAW_MEM(VulkanDynamicAllocation, GetRawAllocator(), "Allocator for vector<VulkanDynamicAllocation>")},
+ m_VulkanBuffer{vkBuffer}
+// clang-format on
{
SetState(InitialState);
}
-BufferVkImpl :: ~BufferVkImpl()
+BufferVkImpl::~BufferVkImpl()
{
// Vk object can only be destroyed when it is no longer used by the GPU
- if(m_VulkanBuffer != VK_NULL_HANDLE)
+ if (m_VulkanBuffer != VK_NULL_HANDLE)
m_pDevice->SafeReleaseDeviceObject(std::move(m_VulkanBuffer), m_Desc.CommandQueueMask);
- if(m_MemoryAllocation.Page != nullptr)
+ if (m_MemoryAllocation.Page != nullptr)
m_pDevice->SafeReleaseDeviceObject(std::move(m_MemoryAllocation), m_Desc.CommandQueueMask);
}
-IMPLEMENT_QUERY_INTERFACE( BufferVkImpl, IID_BufferVk, TBufferBase )
+IMPLEMENT_QUERY_INTERFACE(BufferVkImpl, IID_BufferVk, TBufferBase)
-void BufferVkImpl::CreateViewInternal( const BufferViewDesc& OrigViewDesc, IBufferView** ppView, bool bIsDefaultView )
+void BufferVkImpl::CreateViewInternal(const BufferViewDesc& OrigViewDesc, IBufferView** ppView, bool bIsDefaultView)
{
- VERIFY( ppView != nullptr, "Null pointer provided" );
- if( !ppView )return;
- VERIFY( *ppView == nullptr, "Overwriting reference to existing object may cause memory leaks" );
+ VERIFY(ppView != nullptr, "Null pointer provided");
+ if (!ppView) return;
+ VERIFY(*ppView == nullptr, "Overwriting reference to existing object may cause memory leaks");
*ppView = nullptr;
try
{
auto& BuffViewAllocator = m_pDevice->GetBuffViewObjAllocator();
- VERIFY( &BuffViewAllocator == &m_dbgBuffViewAllocator, "Buff view allocator does not match allocator provided at buffer initialization" );
+ VERIFY(&BuffViewAllocator == &m_dbgBuffViewAllocator, "Buff view allocator does not match allocator provided at buffer initialization");
BufferViewDesc ViewDesc = OrigViewDesc;
- if( ViewDesc.ViewType == BUFFER_VIEW_UNORDERED_ACCESS || ViewDesc.ViewType == BUFFER_VIEW_SHADER_RESOURCE )
+ if (ViewDesc.ViewType == BUFFER_VIEW_UNORDERED_ACCESS || ViewDesc.ViewType == BUFFER_VIEW_SHADER_RESOURCE)
{
auto View = CreateView(ViewDesc);
- *ppView = NEW_RC_OBJ(BuffViewAllocator, "BufferViewVkImpl instance", BufferViewVkImpl, bIsDefaultView ? this : nullptr)
- (GetDevice(), ViewDesc, this, std::move(View), bIsDefaultView );
+ *ppView = NEW_RC_OBJ(BuffViewAllocator, "BufferViewVkImpl instance", BufferViewVkImpl, bIsDefaultView ? this : nullptr)(GetDevice(), ViewDesc, this, std::move(View), bIsDefaultView);
}
- if( !bIsDefaultView && *ppView )
+ if (!bIsDefaultView && *ppView)
(*ppView)->AddRef();
}
- catch( const std::runtime_error & )
+ catch (const std::runtime_error&)
{
- const auto *ViewTypeName = GetBufferViewTypeLiteralName(OrigViewDesc.ViewType);
- LOG_ERROR("Failed to create view \"", OrigViewDesc.Name ? OrigViewDesc.Name : "", "\" (", ViewTypeName, ") for buffer \"", m_Desc.Name, "\"" );
+ const auto* ViewTypeName = GetBufferViewTypeLiteralName(OrigViewDesc.ViewType);
+ LOG_ERROR("Failed to create view \"", OrigViewDesc.Name ? OrigViewDesc.Name : "", "\" (", ViewTypeName, ") for buffer \"", m_Desc.Name, "\"");
}
}
@@ -342,13 +353,14 @@ VulkanUtilities::BufferViewWrapper BufferVkImpl::CreateView(struct BufferViewDes
{
VulkanUtilities::BufferViewWrapper BuffView;
CorrectBufferViewDesc(ViewDesc);
- if( (ViewDesc.ViewType == BUFFER_VIEW_SHADER_RESOURCE || ViewDesc.ViewType == BUFFER_VIEW_UNORDERED_ACCESS) &&
+ if ((ViewDesc.ViewType == BUFFER_VIEW_SHADER_RESOURCE || ViewDesc.ViewType == BUFFER_VIEW_UNORDERED_ACCESS) &&
(m_Desc.Mode == BUFFER_MODE_FORMATTED || m_Desc.Mode == BUFFER_MODE_RAW))
{
VkBufferViewCreateInfo ViewCI = {};
- ViewCI.sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO;
- ViewCI.pNext = nullptr;
- ViewCI.flags = 0; // reserved for future use
+
+ ViewCI.sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO;
+ ViewCI.pNext = nullptr;
+ ViewCI.flags = 0; // reserved for future use
ViewCI.buffer = m_VulkanBuffer;
if (m_Desc.Mode == BUFFER_MODE_RAW && ViewDesc.Format.ValueType == VT_UNDEFINED)
{
@@ -360,15 +372,15 @@ VulkanUtilities::BufferViewWrapper BufferVkImpl::CreateView(struct BufferViewDes
ViewCI.format = TypeToVkFormat(ViewDesc.Format.ValueType, ViewDesc.Format.NumComponents, ViewDesc.Format.IsNormalized);
}
ViewCI.offset = ViewDesc.ByteOffset; // offset in bytes from the base address of the buffer
- ViewCI.range = ViewDesc.ByteWidth; // size in bytes of the buffer view
+ ViewCI.range = ViewDesc.ByteWidth; // size in bytes of the buffer view
const auto& LogicalDevice = m_pDevice->GetLogicalDevice();
- BuffView = LogicalDevice.CreateBufferView(ViewCI, ViewDesc.Name);
+ BuffView = LogicalDevice.CreateBufferView(ViewCI, ViewDesc.Name);
}
return BuffView;
}
-VkBuffer BufferVkImpl::GetVkBuffer()const
+VkBuffer BufferVkImpl::GetVkBuffer() const
{
if (m_VulkanBuffer != VK_NULL_HANDLE)
return m_VulkanBuffer;
@@ -384,20 +396,20 @@ void BufferVkImpl::SetAccessFlags(VkAccessFlags AccessFlags)
SetState(VkAccessFlagsToResourceStates(AccessFlags));
}
-VkAccessFlags BufferVkImpl::GetAccessFlags()const
+VkAccessFlags BufferVkImpl::GetAccessFlags() const
{
return ResourceStateFlagsToVkAccessFlags(GetState());
}
#ifdef DEVELOPMENT
-void BufferVkImpl::DvpVerifyDynamicAllocation(DeviceContextVkImpl* pCtx)const
+void BufferVkImpl::DvpVerifyDynamicAllocation(DeviceContextVkImpl* pCtx) const
{
- auto ContextId = pCtx->GetContextId();
- const auto& DynAlloc = m_DynamicAllocations[ContextId];
- auto CurrentFrame = pCtx->GetContextFrameNumber();
+ auto ContextId = pCtx->GetContextId();
+ const auto& DynAlloc = m_DynamicAllocations[ContextId];
+ auto CurrentFrame = pCtx->GetContextFrameNumber();
DEV_CHECK_ERR(DynAlloc.pDynamicMemMgr != nullptr, "Dynamic buffer '", m_Desc.Name, "' has not been mapped before its first use. Context Id: ", ContextId, ". Note: memory for dynamic buffers is allocated when a buffer is mapped.");
DEV_CHECK_ERR(DynAlloc.dvpFrameNumber == CurrentFrame, "Dynamic allocation of dynamic buffer '", m_Desc.Name, "' in frame ", CurrentFrame, " is out-of-date. Note: contents of all dynamic resources is discarded at the end of every frame. A buffer must be mapped before its first use in any frame.");
}
#endif
-}
+} // namespace Diligent
diff --git a/Graphics/GraphicsEngineVulkan/src/CommandPoolManager.cpp b/Graphics/GraphicsEngineVulkan/src/CommandPoolManager.cpp
index 30186949..fbe0caab 100644
--- a/Graphics/GraphicsEngineVulkan/src/CommandPoolManager.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/CommandPoolManager.cpp
@@ -28,15 +28,17 @@
namespace Diligent
{
-CommandPoolManager::CommandPoolManager(RenderDeviceVkImpl& DeviceVkImpl,
+CommandPoolManager::CommandPoolManager(RenderDeviceVkImpl& DeviceVkImpl,
std::string Name,
- uint32_t queueFamilyIndex,
- VkCommandPoolCreateFlags flags)noexcept:
+ uint32_t queueFamilyIndex,
+ VkCommandPoolCreateFlags flags) noexcept :
+ // clang-format off
m_DeviceVkImpl {DeviceVkImpl },
m_Name {std::move(Name) },
m_QueueFamilyIndex{queueFamilyIndex },
m_CmdPoolFlags {flags },
m_CmdPools {STD_ALLOCATOR_RAW_MEM(VulkanUtilities::CommandPoolWrapper, GetRawAllocator(), "Allocator for deque<VulkanUtilities::CommandPoolWrapper>")}
+// clang-format on
{
#ifdef DEVELOPMENT
m_AllocatedPoolCounter = 0;
@@ -45,23 +47,25 @@ CommandPoolManager::CommandPoolManager(RenderDeviceVkImpl& DeviceVkImpl,
VulkanUtilities::CommandPoolWrapper CommandPoolManager::AllocateCommandPool(const char* DebugName)
{
- std::lock_guard<std::mutex> LockGuard(m_Mutex);
+ std::lock_guard<std::mutex> LockGuard{m_Mutex};
VulkanUtilities::CommandPoolWrapper CmdPool;
- if(!m_CmdPools.empty())
+ if (!m_CmdPools.empty())
{
CmdPool = std::move(m_CmdPools.front());
m_CmdPools.pop_front();
}
auto& LogicalDevice = m_DeviceVkImpl.GetLogicalDevice();
- if(CmdPool == VK_NULL_HANDLE)
+ if (CmdPool == VK_NULL_HANDLE)
{
VkCommandPoolCreateInfo CmdPoolCI = {};
+
CmdPoolCI.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
CmdPoolCI.pNext = nullptr;
CmdPoolCI.queueFamilyIndex = m_QueueFamilyIndex;
CmdPoolCI.flags = m_CmdPoolFlags;
+
CmdPool = LogicalDevice.CreateCommandPool(CmdPoolCI);
DEV_CHECK_ERR(CmdPool != VK_NULL_HANDLE, "Failed to create Vulkan command pool");
}
@@ -80,37 +84,41 @@ void CommandPoolManager::SafeReleaseCommandPool(VulkanUtilities::CommandPoolWrap
{
public:
CommandPoolDeleter(CommandPoolManager& _CmdPoolMgr, VulkanUtilities::CommandPoolWrapper&& _Pool) :
- CmdPoolMgr(&_CmdPoolMgr),
- Pool (std::move(_Pool))
+ // clang-format off
+ CmdPoolMgr{&_CmdPoolMgr },
+ Pool {std::move(_Pool)}
+ // clang-format on
{
VERIFY_EXPR(Pool != VK_NULL_HANDLE);
}
+ // clang-format off
CommandPoolDeleter (const CommandPoolDeleter&) = delete;
CommandPoolDeleter& operator = (const CommandPoolDeleter&) = delete;
CommandPoolDeleter& operator = ( CommandPoolDeleter&&) = delete;
CommandPoolDeleter(CommandPoolDeleter&& rhs) :
- CmdPoolMgr(rhs.CmdPoolMgr),
- Pool (std::move(rhs.Pool))
+ CmdPoolMgr{rhs.CmdPoolMgr },
+ Pool {std::move(rhs.Pool)}
{
rhs.CmdPoolMgr = nullptr;
}
-
+ // clang-format on
~CommandPoolDeleter()
{
- if (CmdPoolMgr!=nullptr)
+ if (CmdPoolMgr != nullptr)
{
CmdPoolMgr->FreeCommandPool(std::move(Pool));
}
}
+
private:
CommandPoolManager* CmdPoolMgr;
VulkanUtilities::CommandPoolWrapper Pool;
};
- // Discard command pool directly to the release queue since we know exactly which queue it was submitted to
+ // Discard command pool directly to the release queue since we know exactly which queue it was submitted to
// as well as the associated FenceValue
m_DeviceVkImpl.GetReleaseQueue(CmdQueueIndex).DiscardResource(CommandPoolDeleter{*this, std::move(CmdPool)}, FenceValue);
}
@@ -128,7 +136,7 @@ void CommandPoolManager::DestroyPools()
{
std::lock_guard<std::mutex> LockGuard(m_Mutex);
DEV_CHECK_ERR(m_AllocatedPoolCounter == 0, m_AllocatedPoolCounter, " pool(s) have not been freed. This will cause a crash if the references to these pools are still in release queues when CommandPoolManager::FreeCommandPool() is called for destroyed CommandPoolManager object.");
- LOG_INFO_MESSAGE(m_Name, " allocated descriptor pool count: ", m_CmdPools.size() );
+ LOG_INFO_MESSAGE(m_Name, " allocated descriptor pool count: ", m_CmdPools.size());
m_CmdPools.clear();
}
@@ -137,4 +145,4 @@ CommandPoolManager::~CommandPoolManager()
DEV_CHECK_ERR(m_CmdPools.empty() && m_AllocatedPoolCounter == 0, "Command pools have not been destroyed");
}
-}
+} // namespace Diligent
diff --git a/Graphics/GraphicsEngineVulkan/src/CommandQueueVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/CommandQueueVkImpl.cpp
index 79c03886..cb378edd 100644
--- a/Graphics/GraphicsEngineVulkan/src/CommandQueueVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/CommandQueueVkImpl.cpp
@@ -28,25 +28,27 @@
namespace Diligent
{
-CommandQueueVkImpl::CommandQueueVkImpl(IReferenceCounters* pRefCounters,
+CommandQueueVkImpl::CommandQueueVkImpl(IReferenceCounters* pRefCounters,
std::shared_ptr<VulkanUtilities::VulkanLogicalDevice> LogicalDevice,
uint32_t QueueFamilyIndex) :
+ // clang-format off
TBase{pRefCounters},
m_LogicalDevice {LogicalDevice},
m_VkQueue {LogicalDevice->GetQueue(QueueFamilyIndex, 0)},
m_QueueFamilyIndex {QueueFamilyIndex},
m_NextFenceValue {1}
+// clang-format on
{
}
CommandQueueVkImpl::~CommandQueueVkImpl()
{
// Queues are created along with the logical device during vkCreateDevice.
- // All queues associated with the logical device are destroyed when vkDestroyDevice
+ // All queues associated with the logical device are destroyed when vkDestroyDevice
// is called on that device.
}
-IMPLEMENT_QUERY_INTERFACE( CommandQueueVkImpl, IID_CommandQueueVk, TBase )
+IMPLEMENT_QUERY_INTERFACE(CommandQueueVkImpl, IID_CommandQueueVk, TBase)
Uint64 CommandQueueVkImpl::Submit(const VkSubmitInfo& SubmitInfo)
@@ -58,13 +60,16 @@ Uint64 CommandQueueVkImpl::Submit(const VkSubmitInfo& SubmitInfo)
Atomics::AtomicIncrement(m_NextFenceValue);
auto vkFence = m_pFence->GetVkFence();
- uint32_t SubmitCount =
- (SubmitInfo.waitSemaphoreCount != 0 ||
- SubmitInfo.commandBufferCount != 0 ||
- SubmitInfo.signalSemaphoreCount != 0) ?
- 1 : 0;
+
+ uint32_t SubmitCount =
+ (SubmitInfo.waitSemaphoreCount != 0 ||
+ SubmitInfo.commandBufferCount != 0 ||
+ SubmitInfo.signalSemaphoreCount != 0) ?
+ 1 :
+ 0;
auto err = vkQueueSubmit(m_VkQueue, SubmitCount, &SubmitInfo, vkFence);
- DEV_CHECK_ERR(err == VK_SUCCESS, "Failed to submit command buffer to the command queue"); (void)err;
+ DEV_CHECK_ERR(err == VK_SUCCESS, "Failed to submit command buffer to the command queue");
+ (void)err;
// We must atomically place the (value, fence) pair into the deque
m_pFence->AddPendingFence(std::move(vkFence), FenceValue);
@@ -75,18 +80,19 @@ Uint64 CommandQueueVkImpl::Submit(const VkSubmitInfo& SubmitInfo)
Uint64 CommandQueueVkImpl::Submit(VkCommandBuffer cmdBuffer)
{
VkSubmitInfo SubmitInfo = {};
- SubmitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
+
+ SubmitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
SubmitInfo.commandBufferCount = cmdBuffer != VK_NULL_HANDLE ? 1 : 0;
- SubmitInfo.pCommandBuffers = &cmdBuffer;
- SubmitInfo.waitSemaphoreCount = 0; // the number of semaphores upon which to wait before executing the command buffers
- SubmitInfo.pWaitSemaphores = nullptr; // a pointer to an array of semaphores upon which to wait before the command
- // buffers begin execution
- SubmitInfo.pWaitDstStageMask = nullptr; // a pointer to an array of pipeline stages at which each corresponding
- // semaphore wait will occur
- SubmitInfo.signalSemaphoreCount = 0; // the number of semaphores to be signaled once the commands specified in
- // pCommandBuffers have completed execution
- SubmitInfo.pSignalSemaphores = nullptr; // a pointer to an array of semaphores which will be signaled when the
- // command buffers for this batch have completed execution
+ SubmitInfo.pCommandBuffers = &cmdBuffer;
+ SubmitInfo.waitSemaphoreCount = 0; // the number of semaphores upon which to wait before executing the command buffers
+ SubmitInfo.pWaitSemaphores = nullptr; // a pointer to an array of semaphores upon which to wait before the command
+ // buffers begin execution
+ SubmitInfo.pWaitDstStageMask = nullptr; // a pointer to an array of pipeline stages at which each corresponding
+ // semaphore wait will occur
+ SubmitInfo.signalSemaphoreCount = 0; // the number of semaphores to be signaled once the commands specified in
+ // pCommandBuffers have completed execution
+ SubmitInfo.pSignalSemaphores = nullptr; // a pointer to an array of semaphores which will be signaled when the
+ // command buffers for this batch have completed execution
return Submit(SubmitInfo);
}
@@ -115,8 +121,10 @@ Uint64 CommandQueueVkImpl::GetCompletedFenceValue()
void CommandQueueVkImpl::SignalFence(VkFence vkFence)
{
std::lock_guard<std::mutex> Lock{m_QueueMutex};
+
auto err = vkQueueSubmit(m_VkQueue, 0, nullptr, vkFence);
- DEV_CHECK_ERR(err == VK_SUCCESS, "Failed to submit command buffer to the command queue"); (void)err;
+ DEV_CHECK_ERR(err == VK_SUCCESS, "Failed to submit command buffer to the command queue");
+ (void)err;
}
VkResult CommandQueueVkImpl::Present(const VkPresentInfoKHR& PresentInfo)
@@ -125,4 +133,4 @@ VkResult CommandQueueVkImpl::Present(const VkPresentInfoKHR& PresentInfo)
return vkQueuePresentKHR(m_VkQueue, &PresentInfo);
}
-}
+} // namespace Diligent
diff --git a/Graphics/GraphicsEngineVulkan/src/DescriptorPoolManager.cpp b/Graphics/GraphicsEngineVulkan/src/DescriptorPoolManager.cpp
index c094e384..b2bf3680 100644
--- a/Graphics/GraphicsEngineVulkan/src/DescriptorPoolManager.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/DescriptorPoolManager.cpp
@@ -39,13 +39,14 @@ void DescriptorSetAllocation::Release()
}
}
-VulkanUtilities::DescriptorPoolWrapper DescriptorPoolManager::CreateDescriptorPool(const char* DebugName)const
+VulkanUtilities::DescriptorPoolWrapper DescriptorPoolManager::CreateDescriptorPool(const char* DebugName) const
{
VkDescriptorPoolCreateInfo PoolCI = {};
+
PoolCI.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
PoolCI.pNext = nullptr;
- // VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT specifies that descriptor sets can
- // return their individual allocations to the pool, i.e. all of vkAllocateDescriptorSets,
+ // VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT specifies that descriptor sets can
+ // return their individual allocations to the pool, i.e. all of vkAllocateDescriptorSets,
// vkFreeDescriptorSets, and vkResetDescriptorPool are allowed. (13.2.3)
PoolCI.flags = m_AllowFreeing ? VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT : 0;
PoolCI.maxSets = m_MaxSets;
@@ -71,7 +72,7 @@ VulkanUtilities::DescriptorPoolWrapper DescriptorPoolManager::GetPool(const char
else
{
auto& LogicalDevice = m_DeviceVkImpl.GetLogicalDevice();
- auto Pool = std::move(m_Pools.front());
+ auto Pool = std::move(m_Pools.front());
VulkanUtilities::SetDescriptorPoolName(LogicalDevice.GetVkDevice(), Pool, DebugName);
m_Pools.pop_front();
return Pool;
@@ -83,26 +84,28 @@ void DescriptorPoolManager::DisposePool(VulkanUtilities::DescriptorPoolWrapper&&
class DescriptorPoolDeleter
{
public:
+ // clang-format off
DescriptorPoolDeleter(DescriptorPoolManager& _PoolMgr,
VulkanUtilities::DescriptorPoolWrapper&& _Pool) noexcept :
- PoolMgr (&_PoolMgr),
- Pool (std::move(_Pool))
+ PoolMgr {&_PoolMgr },
+ Pool {std::move(_Pool)}
{}
- DescriptorPoolDeleter (const DescriptorPoolDeleter&) = delete;
- DescriptorPoolDeleter& operator = (const DescriptorPoolDeleter&) = delete;
- DescriptorPoolDeleter& operator = ( DescriptorPoolDeleter&&)= delete;
+ DescriptorPoolDeleter (const DescriptorPoolDeleter&) = delete;
+ DescriptorPoolDeleter& operator= (const DescriptorPoolDeleter&) = delete;
+ DescriptorPoolDeleter& operator= ( DescriptorPoolDeleter&&)= delete;
DescriptorPoolDeleter(DescriptorPoolDeleter&& rhs)noexcept :
- PoolMgr (rhs.PoolMgr),
- Pool (std::move(rhs.Pool))
+ PoolMgr {rhs.PoolMgr },
+ Pool {std::move(rhs.Pool)}
{
rhs.PoolMgr = nullptr;
}
+ // clang-format on
~DescriptorPoolDeleter()
{
- if (PoolMgr!=nullptr)
+ if (PoolMgr != nullptr)
{
PoolMgr->FreePool(std::move(Pool));
}
@@ -133,12 +136,13 @@ static VkDescriptorSet AllocateDescriptorSet(const VulkanUtilities::VulkanLogica
const char* DebugName)
{
VkDescriptorSetAllocateInfo DescrSetAllocInfo = {};
+
DescrSetAllocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
DescrSetAllocInfo.pNext = nullptr;
DescrSetAllocInfo.descriptorPool = Pool;
DescrSetAllocInfo.descriptorSetCount = 1;
DescrSetAllocInfo.pSetLayouts = &SetLayout;
- // Descriptor pools are externally synchronized, meaning that the application must not allocate
+ // Descriptor pools are externally synchronized, meaning that the application must not allocate
// and/or free descriptor sets from the same pool in multiple threads simultaneously (13.2.3)
return LogicalDevice.AllocateVkDescriptorSet(DescrSetAllocInfo, DebugName);
}
@@ -151,16 +155,16 @@ DescriptorSetAllocator::~DescriptorSetAllocator()
DescriptorSetAllocation DescriptorSetAllocator::Allocate(Uint64 CommandQueueMask, VkDescriptorSetLayout SetLayout, const char* DebugName)
{
- // Descriptor pools are externally synchronized, meaning that the application must not allocate
+ // Descriptor pools are externally synchronized, meaning that the application must not allocate
// and/or free descriptor sets from the same pool in multiple threads simultaneously (13.2.3)
std::lock_guard<std::mutex> Lock{m_Mutex};
const auto& LogicalDevice = m_DeviceVkImpl.GetLogicalDevice();
// Try all pools starting from the frontmost
- for(auto it = m_Pools.begin(); it != m_Pools.end(); ++it)
+ for (auto it = m_Pools.begin(); it != m_Pools.end(); ++it)
{
auto& Pool = *it;
- auto Set = AllocateDescriptorSet(LogicalDevice, Pool, SetLayout, DebugName);
+ auto Set = AllocateDescriptorSet(LogicalDevice, Pool, SetLayout, DebugName);
if (Set != VK_NULL_HANDLE)
{
// Move the pool to the front
@@ -181,14 +185,14 @@ DescriptorSetAllocation DescriptorSetAllocator::Allocate(Uint64 CommandQueueMask
m_Pools.emplace_front(CreateDescriptorPool("Descriptor pool"));
auto& NewPool = m_Pools.front();
- auto Set = AllocateDescriptorSet(LogicalDevice, NewPool, SetLayout, DebugName);
+ auto Set = AllocateDescriptorSet(LogicalDevice, NewPool, SetLayout, DebugName);
DEV_CHECK_ERR(Set != VK_NULL_HANDLE, "Failed to allocate descriptor set");
#ifdef DEVELOPMENT
++m_AllocatedSetCounter;
#endif
- return {Set, NewPool, CommandQueueMask, *this };
+ return {Set, NewPool, CommandQueueMask, *this};
}
void DescriptorSetAllocator::FreeDescriptorSet(VkDescriptorSet Set, VkDescriptorPool Pool, Uint64 QueueMask)
@@ -196,12 +200,13 @@ void DescriptorSetAllocator::FreeDescriptorSet(VkDescriptorSet Set, VkDescriptor
class DescriptorSetDeleter
{
public:
+ // clang-format off
DescriptorSetDeleter(DescriptorSetAllocator& _Allocator,
VkDescriptorSet _Set,
VkDescriptorPool _Pool) :
- Allocator (&_Allocator),
- Set (_Set),
- Pool (_Pool)
+ Allocator {&_Allocator},
+ Set {_Set },
+ Pool {_Pool }
{}
DescriptorSetDeleter (const DescriptorSetDeleter&) = delete;
@@ -209,18 +214,19 @@ void DescriptorSetAllocator::FreeDescriptorSet(VkDescriptorSet Set, VkDescriptor
DescriptorSetDeleter& operator = ( DescriptorSetDeleter&&)= delete;
DescriptorSetDeleter(DescriptorSetDeleter&& rhs)noexcept :
- Allocator (rhs.Allocator),
- Set (rhs.Set),
- Pool (rhs.Pool)
+ Allocator {rhs.Allocator},
+ Set {rhs.Set },
+ Pool {rhs.Pool }
{
rhs.Allocator = nullptr;
rhs.Set = nullptr;
rhs.Pool = nullptr;
}
+ // clang-format on
~DescriptorSetDeleter()
{
- if (Allocator!=nullptr)
+ if (Allocator != nullptr)
{
std::lock_guard<std::mutex> Lock{Allocator->m_Mutex};
Allocator->m_DeviceVkImpl.GetLogicalDevice().FreeDescriptorSet(Pool, Set);
@@ -241,8 +247,8 @@ void DescriptorSetAllocator::FreeDescriptorSet(VkDescriptorSet Set, VkDescriptor
VkDescriptorSet DynamicDescriptorSetAllocator::Allocate(VkDescriptorSetLayout SetLayout, const char* DebugName)
{
- VkDescriptorSet set = VK_NULL_HANDLE;
- const auto& LogicalDevice = m_GlobalPoolMgr.GetDeviceVkImpl().GetLogicalDevice();
+ VkDescriptorSet set = VK_NULL_HANDLE;
+ const auto& LogicalDevice = m_GlobalPoolMgr.GetDeviceVkImpl().GetLogicalDevice();
if (!m_AllocatedPools.empty())
{
set = AllocateDescriptorSet(LogicalDevice, m_AllocatedPools.back(), SetLayout, DebugName);
@@ -253,13 +259,13 @@ VkDescriptorSet DynamicDescriptorSetAllocator::Allocate(VkDescriptorSetLayout Se
m_AllocatedPools.emplace_back(m_GlobalPoolMgr.GetPool("Dynamic Descriptor Pool"));
set = AllocateDescriptorSet(LogicalDevice, m_AllocatedPools.back(), SetLayout, DebugName);
}
-
+
return set;
}
void DynamicDescriptorSetAllocator::ReleasePools(Uint64 QueueMask)
{
- for(auto& Pool : m_AllocatedPools)
+ for (auto& Pool : m_AllocatedPools)
{
m_GlobalPoolMgr.DisposePool(std::move(Pool), QueueMask);
}
@@ -273,4 +279,4 @@ DynamicDescriptorSetAllocator::~DynamicDescriptorSetAllocator()
LOG_INFO_MESSAGE(m_Name, " peak descriptor pool count: ", m_PeakPoolCount);
}
-}
+} // namespace Diligent
diff --git a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp
index 7231ac5e..86a4bce1 100644
--- a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp
@@ -36,2272 +36,2293 @@
namespace Diligent
{
- static std::string GetContextObjectName(const char* Object, bool bIsDeferred, Uint32 ContextId)
- {
- std::stringstream ss;
- ss << Object;
- if (bIsDeferred)
- ss << " of deferred context #" << ContextId;
- else
- ss << " of immediate context";
- return ss.str();
- }
-
- DeviceContextVkImpl::DeviceContextVkImpl(IReferenceCounters* pRefCounters,
- RenderDeviceVkImpl* pDeviceVkImpl,
- bool bIsDeferred,
- const EngineVkCreateInfo& EngineCI,
- Uint32 ContextId,
- Uint32 CommandQueueId,
- std::shared_ptr<GenerateMipsVkHelper> GenerateMipsHelper) :
- TDeviceContextBase
- {
- pRefCounters,
- pDeviceVkImpl,
- ContextId,
- CommandQueueId,
- bIsDeferred ? std::numeric_limits<decltype(m_NumCommandsToFlush)>::max() : EngineCI.NumCommandsToFlushCmdBuffer,
- bIsDeferred
- },
- m_CommandBuffer { pDeviceVkImpl->GetLogicalDevice().GetEnabledGraphicsShaderStages() },
- m_CmdListAllocator { GetRawAllocator(), sizeof(CommandListVkImpl), 64 },
- // Command pools must be thread safe because command buffers are returned into pools by release queues
- // potentially running in another thread
- m_CmdPool
- {
- pDeviceVkImpl->GetLogicalDevice().GetSharedPtr(),
- pDeviceVkImpl->GetCommandQueue(CommandQueueId).GetQueueFamilyIndex(),
- VK_COMMAND_POOL_CREATE_TRANSIENT_BIT | VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT
- },
- // Upload heap must always be thread-safe as Finish() may be called from another thread
- m_UploadHeap
- {
- *pDeviceVkImpl,
- GetContextObjectName("Upload heap", bIsDeferred, ContextId),
- EngineCI.UploadHeapPageSize
- },
- m_DynamicHeap
- {
- pDeviceVkImpl->GetDynamicMemoryManager(),
- GetContextObjectName("Dynamic heap", bIsDeferred, ContextId),
- EngineCI.DynamicHeapPageSize
- },
- m_DynamicDescrSetAllocator
- {
- pDeviceVkImpl->GetDynamicDescriptorPool(),
- GetContextObjectName("Dynamic descriptor set allocator", bIsDeferred, ContextId),
- },
- m_GenerateMipsHelper{std::move(GenerateMipsHelper)}
- {
- m_GenerateMipsHelper->CreateSRB(&m_GenerateMipsSRB);
- BufferDesc DummyVBDesc;
- DummyVBDesc.Name = "Dummy vertex buffer";
- DummyVBDesc.BindFlags = BIND_VERTEX_BUFFER;
- DummyVBDesc.Usage = USAGE_DEFAULT;
- DummyVBDesc.uiSizeInBytes = 32;
- RefCntAutoPtr<IBuffer> pDummyVB;
- m_pDevice->CreateBuffer(DummyVBDesc, nullptr, &pDummyVB);
- m_DummyVB = pDummyVB.RawPtr<BufferVkImpl>();
- }
+static std::string GetContextObjectName(const char* Object, bool bIsDeferred, Uint32 ContextId)
+{
+ std::stringstream ss;
+ ss << Object;
+ if (bIsDeferred)
+ ss << " of deferred context #" << ContextId;
+ else
+ ss << " of immediate context";
+ return ss.str();
+}
- DeviceContextVkImpl::~DeviceContextVkImpl()
+DeviceContextVkImpl::DeviceContextVkImpl(IReferenceCounters* pRefCounters,
+ RenderDeviceVkImpl* pDeviceVkImpl,
+ bool bIsDeferred,
+ const EngineVkCreateInfo& EngineCI,
+ Uint32 ContextId,
+ Uint32 CommandQueueId,
+ std::shared_ptr<GenerateMipsVkHelper> GenerateMipsHelper) :
+ // clang-format off
+ TDeviceContextBase
+ {
+ pRefCounters,
+ pDeviceVkImpl,
+ ContextId,
+ CommandQueueId,
+ bIsDeferred ? std::numeric_limits<decltype(m_NumCommandsToFlush)>::max() : EngineCI.NumCommandsToFlushCmdBuffer,
+ bIsDeferred
+ },
+ m_CommandBuffer { pDeviceVkImpl->GetLogicalDevice().GetEnabledGraphicsShaderStages() },
+ m_CmdListAllocator { GetRawAllocator(), sizeof(CommandListVkImpl), 64 },
+ // Command pools must be thread safe because command buffers are returned into pools by release queues
+ // potentially running in another thread
+ m_CmdPool
+ {
+ pDeviceVkImpl->GetLogicalDevice().GetSharedPtr(),
+ pDeviceVkImpl->GetCommandQueue(CommandQueueId).GetQueueFamilyIndex(),
+ VK_COMMAND_POOL_CREATE_TRANSIENT_BIT | VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT
+ },
+ // Upload heap must always be thread-safe as Finish() may be called from another thread
+ m_UploadHeap
+ {
+ *pDeviceVkImpl,
+ GetContextObjectName("Upload heap", bIsDeferred, ContextId),
+ EngineCI.UploadHeapPageSize
+ },
+ m_DynamicHeap
+ {
+ pDeviceVkImpl->GetDynamicMemoryManager(),
+ GetContextObjectName("Dynamic heap", bIsDeferred, ContextId),
+ EngineCI.DynamicHeapPageSize
+ },
+ m_DynamicDescrSetAllocator
+ {
+ pDeviceVkImpl->GetDynamicDescriptorPool(),
+ GetContextObjectName("Dynamic descriptor set allocator", bIsDeferred, ContextId),
+ },
+ m_GenerateMipsHelper{std::move(GenerateMipsHelper)}
+// clang-format on
+{
+ m_GenerateMipsHelper->CreateSRB(&m_GenerateMipsSRB);
+
+ BufferDesc DummyVBDesc;
+ DummyVBDesc.Name = "Dummy vertex buffer";
+ DummyVBDesc.BindFlags = BIND_VERTEX_BUFFER;
+ DummyVBDesc.Usage = USAGE_DEFAULT;
+ DummyVBDesc.uiSizeInBytes = 32;
+ RefCntAutoPtr<IBuffer> pDummyVB;
+ m_pDevice->CreateBuffer(DummyVBDesc, nullptr, &pDummyVB);
+ m_DummyVB = pDummyVB.RawPtr<BufferVkImpl>();
+}
+
+DeviceContextVkImpl::~DeviceContextVkImpl()
+{
+ if (m_State.NumCommands != 0)
{
- if (m_State.NumCommands != 0)
+ if (m_bIsDeferred)
{
- if (m_bIsDeferred)
- {
- LOG_ERROR_MESSAGE("There are outstanding commands in deferred context #", m_ContextId, " being destroyed, which indicates that FinishCommandList() has not been called."
- " This may cause synchronization issues.");
- }
- else
- {
- LOG_ERROR_MESSAGE("There are outstanding commands in the immediate context being destroyed, which indicates the context has not been Flush()'ed.",
- " This may cause synchronization issues.");
- }
+ LOG_ERROR_MESSAGE("There are outstanding commands in deferred context #", m_ContextId,
+ " being destroyed, which indicates that FinishCommandList() has not been called."
+ " This may cause synchronization issues.");
}
-
- if (!m_bIsDeferred)
+ else
{
- Flush();
+ LOG_ERROR_MESSAGE("There are outstanding commands in the immediate context being destroyed, "
+ "which indicates the context has not been Flush()'ed.",
+ " This may cause synchronization issues.");
}
+ }
- // For deferred contexts, m_SubmittedBuffersCmdQueueMask is reset to 0 after every call to FinishFrame().
- // In this case there are no resources to release, so there will be no issues.
- FinishFrame();
+ if (!m_bIsDeferred)
+ {
+ Flush();
+ }
- // There must be no stale resources
- DEV_CHECK_ERR(m_UploadHeap.GetStalePagesCount() == 0, "All allocated upload heap pages must have been released at this point");
- DEV_CHECK_ERR(m_DynamicHeap.GetAllocatedMasterBlockCount() == 0, "All allocated dynamic heap master blocks must have been released");
- DEV_CHECK_ERR(m_DynamicDescrSetAllocator.GetAllocatedPoolCount() == 0, "All allocated dynamic descriptor set pools must have been released at this point");
+ // For deferred contexts, m_SubmittedBuffersCmdQueueMask is reset to 0 after every call to FinishFrame().
+ // In this case there are no resources to release, so there will be no issues.
+ FinishFrame();
- auto VkCmdPool = m_CmdPool.Release();
- m_pDevice->SafeReleaseDeviceObject(std::move(VkCmdPool), ~Uint64{0});
-
- m_pDevice->SafeReleaseDeviceObject(std::move(m_GenerateMipsHelper), ~Uint64{0});
- m_pDevice->SafeReleaseDeviceObject(std::move(m_GenerateMipsSRB), ~Uint64{0});
- m_pDevice->SafeReleaseDeviceObject(std::move(m_DummyVB), ~Uint64{0});
+ // There must be no stale resources
+ // clang-format off
+ DEV_CHECK_ERR(m_UploadHeap.GetStalePagesCount() == 0, "All allocated upload heap pages must have been released at this point");
+ DEV_CHECK_ERR(m_DynamicHeap.GetAllocatedMasterBlockCount() == 0, "All allocated dynamic heap master blocks must have been released");
+ DEV_CHECK_ERR(m_DynamicDescrSetAllocator.GetAllocatedPoolCount() == 0, "All allocated dynamic descriptor set pools must have been released at this point");
+ // clang-format on
- // The main reason we need to idle the GPU is because we need to make sure that all command buffers are returned to the
- // pool. Upload heap, dynamic heap and dynamic descriptor manager return their resources to global managers and
- // do not really need to wait for GPU to idle.
- m_pDevice->IdleGPU();
- DEV_CHECK_ERR(m_CmdPool.DvpGetBufferCounter() == 0, "All command buffers must have been returned to the pool");
- }
+ auto VkCmdPool = m_CmdPool.Release();
+ m_pDevice->SafeReleaseDeviceObject(std::move(VkCmdPool), ~Uint64{0});
+
+ // clang-format off
+ m_pDevice->SafeReleaseDeviceObject(std::move(m_GenerateMipsHelper), ~Uint64{0});
+ m_pDevice->SafeReleaseDeviceObject(std::move(m_GenerateMipsSRB), ~Uint64{0});
+ m_pDevice->SafeReleaseDeviceObject(std::move(m_DummyVB), ~Uint64{0});
+ // clang-format on
+
+ // The main reason we need to idle the GPU is because we need to make sure that all command buffers are returned to the
+ // pool. Upload heap, dynamic heap and dynamic descriptor manager return their resources to global managers and
+ // do not really need to wait for GPU to idle.
+ m_pDevice->IdleGPU();
+ DEV_CHECK_ERR(m_CmdPool.DvpGetBufferCounter() == 0, "All command buffers must have been returned to the pool");
+}
- IMPLEMENT_QUERY_INTERFACE( DeviceContextVkImpl, IID_DeviceContextVk, TDeviceContextBase )
+IMPLEMENT_QUERY_INTERFACE(DeviceContextVkImpl, IID_DeviceContextVk, TDeviceContextBase)
- void DeviceContextVkImpl::DisposeVkCmdBuffer(Uint32 CmdQueue, VkCommandBuffer vkCmdBuff, Uint64 FenceValue)
+void DeviceContextVkImpl::DisposeVkCmdBuffer(Uint32 CmdQueue, VkCommandBuffer vkCmdBuff, Uint64 FenceValue)
+{
+ VERIFY_EXPR(vkCmdBuff != VK_NULL_HANDLE);
+ class CmdBufferDeleter
{
- VERIFY_EXPR(vkCmdBuff != VK_NULL_HANDLE);
- class CmdBufferDeleter
+ public:
+ // clang-format off
+ CmdBufferDeleter(VkCommandBuffer _vkCmdBuff,
+ VulkanUtilities::VulkanCommandBufferPool& _Pool) noexcept :
+ vkCmdBuff {_vkCmdBuff},
+ Pool {&_Pool }
{
- public:
- CmdBufferDeleter(VkCommandBuffer _vkCmdBuff,
- VulkanUtilities::VulkanCommandBufferPool& _Pool) noexcept :
- vkCmdBuff (_vkCmdBuff),
- Pool (&_Pool)
- {
- VERIFY_EXPR(vkCmdBuff != VK_NULL_HANDLE);
- }
+ VERIFY_EXPR(vkCmdBuff != VK_NULL_HANDLE);
+ }
- CmdBufferDeleter (const CmdBufferDeleter&) = delete;
- CmdBufferDeleter& operator = (const CmdBufferDeleter&) = delete;
- CmdBufferDeleter& operator = ( CmdBufferDeleter&&) = delete;
+ CmdBufferDeleter (const CmdBufferDeleter&) = delete;
+ CmdBufferDeleter& operator = (const CmdBufferDeleter&) = delete;
+ CmdBufferDeleter& operator = ( CmdBufferDeleter&&) = delete;
- CmdBufferDeleter(CmdBufferDeleter&& rhs) noexcept :
- vkCmdBuff (rhs.vkCmdBuff),
- Pool (rhs.Pool)
- {
- rhs.vkCmdBuff = VK_NULL_HANDLE;
- rhs.Pool = nullptr;
- }
+ CmdBufferDeleter(CmdBufferDeleter&& rhs) noexcept :
+ vkCmdBuff {rhs.vkCmdBuff},
+ Pool {rhs.Pool }
+ {
+ rhs.vkCmdBuff = VK_NULL_HANDLE;
+ rhs.Pool = nullptr;
+ }
+ // clang-format on
- ~CmdBufferDeleter()
+ ~CmdBufferDeleter()
+ {
+ if (Pool != nullptr)
{
- if(Pool != nullptr)
- {
- Pool->FreeCommandBuffer(std::move(vkCmdBuff));
- }
+ Pool->FreeCommandBuffer(std::move(vkCmdBuff));
}
+ }
- private:
- VkCommandBuffer vkCmdBuff;
- VulkanUtilities::VulkanCommandBufferPool* Pool;
- };
+ private:
+ VkCommandBuffer vkCmdBuff;
+ VulkanUtilities::VulkanCommandBufferPool* Pool;
+ };
- auto& ReleaseQueue = m_pDevice->GetReleaseQueue(CmdQueue);
- ReleaseQueue.DiscardResource(CmdBufferDeleter{vkCmdBuff, m_CmdPool}, FenceValue);
- }
+ auto& ReleaseQueue = m_pDevice->GetReleaseQueue(CmdQueue);
+ ReleaseQueue.DiscardResource(CmdBufferDeleter{vkCmdBuff, m_CmdPool}, FenceValue);
+}
- inline void DeviceContextVkImpl::DisposeCurrentCmdBuffer(Uint32 CmdQueue, Uint64 FenceValue)
+inline void DeviceContextVkImpl::DisposeCurrentCmdBuffer(Uint32 CmdQueue, Uint64 FenceValue)
+{
+ VERIFY(m_CommandBuffer.GetState().RenderPass == VK_NULL_HANDLE, "Disposing command buffer with unifinished render pass");
+ auto vkCmdBuff = m_CommandBuffer.GetVkCmdBuffer();
+ if (vkCmdBuff != VK_NULL_HANDLE)
{
- VERIFY(m_CommandBuffer.GetState().RenderPass == VK_NULL_HANDLE, "Disposing command buffer with unifinished render pass");
- auto vkCmdBuff = m_CommandBuffer.GetVkCmdBuffer();
- if (vkCmdBuff != VK_NULL_HANDLE)
- {
- DisposeVkCmdBuffer(CmdQueue, vkCmdBuff, FenceValue);
- m_CommandBuffer.Reset();
- }
+ DisposeVkCmdBuffer(CmdQueue, vkCmdBuff, FenceValue);
+ m_CommandBuffer.Reset();
}
+}
- void DeviceContextVkImpl::SetPipelineState(IPipelineState* pPipelineState)
+void DeviceContextVkImpl::SetPipelineState(IPipelineState* pPipelineState)
+{
+ auto* pPipelineStateVk = ValidatedCast<PipelineStateVkImpl>(pPipelineState);
+ if (PipelineStateVkImpl::IsSameObject(m_pPipelineState, pPipelineStateVk))
+ return;
+
+ // Never flush deferred context!
+ if (!m_bIsDeferred && m_State.NumCommands >= m_NumCommandsToFlush)
{
- auto* pPipelineStateVk = ValidatedCast<PipelineStateVkImpl>(pPipelineState);
- if (PipelineStateVkImpl::IsSameObject(m_pPipelineState, pPipelineStateVk))
- return;
+ Flush();
+ }
- // Never flush deferred context!
- if (!m_bIsDeferred && m_State.NumCommands >= m_NumCommandsToFlush)
- {
- Flush();
- }
+ const auto& PSODesc = pPipelineStateVk->GetDesc();
- const auto& PSODesc = pPipelineStateVk->GetDesc();
+ bool CommitStates = false;
+ bool CommitScissor = false;
+ if (!m_pPipelineState)
+ {
+ // If no pipeline state is bound, we are working with the fresh command
+ // list. We have to commit the states set in the context that are not
+ // committed by the draw command (render targets, viewports, scissor rects, etc.)
+ CommitStates = true;
+ }
+ else
+ {
+ const auto& OldPSODesc = m_pPipelineState->GetDesc();
+ // Commit all graphics states when switching from compute pipeline
+ // This is necessary because if the command list had been flushed
+ // and the first PSO set on the command list was a compute pipeline,
+ // the states would otherwise never be committed (since m_pPipelineState != nullptr)
+ CommitStates = OldPSODesc.IsComputePipeline;
+ // We also need to update scissor rect if ScissorEnable state was disabled in previous pipeline
+ CommitScissor = !OldPSODesc.GraphicsPipeline.RasterizerDesc.ScissorEnable;
+ }
- bool CommitStates = false;
- bool CommitScissor = false;
- if (!m_pPipelineState)
- {
- // If no pipeline state is bound, we are working with the fresh command
- // list. We have to commit the states set in the context that are not
- // committed by the draw command (render targets, viewports, scissor rects, etc.)
- CommitStates = true;
- }
- else
- {
- const auto& OldPSODesc = m_pPipelineState->GetDesc();
- // Commit all graphics states when switching from compute pipeline
- // This is necessary because if the command list had been flushed
- // and the first PSO set on the command list was a compute pipeline,
- // the states would otherwise never be committed (since m_pPipelineState != nullptr)
- CommitStates = OldPSODesc.IsComputePipeline;
- // We also need to update scissor rect if ScissorEnable state was disabled in previous pipeline
- CommitScissor = !OldPSODesc.GraphicsPipeline.RasterizerDesc.ScissorEnable;
- }
+ TDeviceContextBase::SetPipelineState(pPipelineStateVk, 0 /*Dummy*/);
+ EnsureVkCmdBuffer();
- TDeviceContextBase::SetPipelineState( pPipelineStateVk, 0 /*Dummy*/ );
- EnsureVkCmdBuffer();
+ if (PSODesc.IsComputePipeline)
+ {
+ auto vkPipeline = pPipelineStateVk->GetVkPipeline();
+ m_CommandBuffer.BindComputePipeline(vkPipeline);
+ }
+ else
+ {
+ auto vkPipeline = pPipelineStateVk->GetVkPipeline();
+ m_CommandBuffer.BindGraphicsPipeline(vkPipeline);
- if (PSODesc.IsComputePipeline)
+ if (CommitStates)
{
- auto vkPipeline = pPipelineStateVk->GetVkPipeline();
- m_CommandBuffer.BindComputePipeline(vkPipeline);
+ m_CommandBuffer.SetStencilReference(m_StencilRef);
+ m_CommandBuffer.SetBlendConstants(m_BlendFactors);
+ CommitRenderPassAndFramebuffer(true);
+ CommitViewports();
}
- else
- {
- auto vkPipeline = pPipelineStateVk->GetVkPipeline();
- m_CommandBuffer.BindGraphicsPipeline(vkPipeline);
- if (CommitStates)
- {
- m_CommandBuffer.SetStencilReference(m_StencilRef);
- m_CommandBuffer.SetBlendConstants(m_BlendFactors);
- CommitRenderPassAndFramebuffer(true);
- CommitViewports();
- }
-
- if (PSODesc.GraphicsPipeline.RasterizerDesc.ScissorEnable && (CommitStates || CommitScissor))
- {
- CommitScissorRects();
- }
+ if (PSODesc.GraphicsPipeline.RasterizerDesc.ScissorEnable && (CommitStates || CommitScissor))
+ {
+ CommitScissorRects();
}
-
- m_DescrSetBindInfo.Reset();
}
- void DeviceContextVkImpl::TransitionShaderResources(IPipelineState *pPipelineState, IShaderResourceBinding *pShaderResourceBinding)
- {
- VERIFY_EXPR(pPipelineState != nullptr);
+ m_DescrSetBindInfo.Reset();
+}
- auto *pPipelineStateVk = ValidatedCast<PipelineStateVkImpl>(pPipelineState);
- pPipelineStateVk->CommitAndTransitionShaderResources(pShaderResourceBinding, this, false, RESOURCE_STATE_TRANSITION_MODE_TRANSITION, nullptr);
- }
+void DeviceContextVkImpl::TransitionShaderResources(IPipelineState* pPipelineState, IShaderResourceBinding* pShaderResourceBinding)
+{
+ VERIFY_EXPR(pPipelineState != nullptr);
- void DeviceContextVkImpl::CommitShaderResources(IShaderResourceBinding *pShaderResourceBinding, RESOURCE_STATE_TRANSITION_MODE StateTransitionMode)
- {
- if (!DeviceContextBase::CommitShaderResources(pShaderResourceBinding, StateTransitionMode, 0 /*Dummy*/))
- return;
+ auto* pPipelineStateVk = ValidatedCast<PipelineStateVkImpl>(pPipelineState);
+ pPipelineStateVk->CommitAndTransitionShaderResources(pShaderResourceBinding, this, false, RESOURCE_STATE_TRANSITION_MODE_TRANSITION, nullptr);
+}
- m_pPipelineState->CommitAndTransitionShaderResources(pShaderResourceBinding, this, true, StateTransitionMode, &m_DescrSetBindInfo);
- }
+void DeviceContextVkImpl::CommitShaderResources(IShaderResourceBinding* pShaderResourceBinding, RESOURCE_STATE_TRANSITION_MODE StateTransitionMode)
+{
+ if (!DeviceContextBase::CommitShaderResources(pShaderResourceBinding, StateTransitionMode, 0 /*Dummy*/))
+ return;
- void DeviceContextVkImpl::SetStencilRef(Uint32 StencilRef)
+ m_pPipelineState->CommitAndTransitionShaderResources(pShaderResourceBinding, this, true, StateTransitionMode, &m_DescrSetBindInfo);
+}
+
+void DeviceContextVkImpl::SetStencilRef(Uint32 StencilRef)
+{
+ if (TDeviceContextBase::SetStencilRef(StencilRef, 0))
{
- if (TDeviceContextBase::SetStencilRef(StencilRef, 0))
- {
- EnsureVkCmdBuffer();
- m_CommandBuffer.SetStencilReference(m_StencilRef);
- }
+ EnsureVkCmdBuffer();
+ m_CommandBuffer.SetStencilReference(m_StencilRef);
}
+}
- void DeviceContextVkImpl::SetBlendFactors(const float* pBlendFactors)
+void DeviceContextVkImpl::SetBlendFactors(const float* pBlendFactors)
+{
+ if (TDeviceContextBase::SetBlendFactors(pBlendFactors, 0))
{
- if (TDeviceContextBase::SetBlendFactors(pBlendFactors, 0))
- {
- EnsureVkCmdBuffer();
- m_CommandBuffer.SetBlendConstants(m_BlendFactors);
- }
+ EnsureVkCmdBuffer();
+ m_CommandBuffer.SetBlendConstants(m_BlendFactors);
}
+}
- void DeviceContextVkImpl::CommitVkVertexBuffers()
- {
+void DeviceContextVkImpl::CommitVkVertexBuffers()
+{
#ifdef DEVELOPMENT
- if (m_NumVertexStreams < m_pPipelineState->GetNumBufferSlotsUsed())
- LOG_ERROR("Currently bound pipeline state '", m_pPipelineState->GetDesc().Name, "' expects ", m_pPipelineState->GetNumBufferSlotsUsed(), " input buffer slots, but only ", m_NumVertexStreams, " is bound");
+ if (m_NumVertexStreams < m_pPipelineState->GetNumBufferSlotsUsed())
+ LOG_ERROR("Currently bound pipeline state '", m_pPipelineState->GetDesc().Name, "' expects ", m_pPipelineState->GetNumBufferSlotsUsed(), " input buffer slots, but only ", m_NumVertexStreams, " is bound");
#endif
- // Do not initialize array with zeros for performance reasons
- VkBuffer vkVertexBuffers[MaxBufferSlots];// = {}
- VkDeviceSize Offsets[MaxBufferSlots];
- VERIFY( m_NumVertexStreams <= MaxBufferSlots, "Too many buffers are being set" );
- bool DynamicBufferPresent = false;
- for ( Uint32 slot = 0; slot < m_NumVertexStreams; ++slot )
+ // Do not initialize array with zeros for performance reasons
+ VkBuffer vkVertexBuffers[MaxBufferSlots]; // = {}
+ VkDeviceSize Offsets[MaxBufferSlots];
+ VERIFY(m_NumVertexStreams <= MaxBufferSlots, "Too many buffers are being set");
+ bool DynamicBufferPresent = false;
+ for (Uint32 slot = 0; slot < m_NumVertexStreams; ++slot)
+ {
+ auto& CurrStream = m_VertexStreams[slot];
+ if (auto* pBufferVk = CurrStream.pBuffer.RawPtr())
{
- auto& CurrStream = m_VertexStreams[slot];
- if (auto* pBufferVk = CurrStream.pBuffer.RawPtr())
+ if (pBufferVk->GetDesc().Usage == USAGE_DYNAMIC)
{
- if (pBufferVk->GetDesc().Usage == USAGE_DYNAMIC)
- {
- DynamicBufferPresent = true;
+ DynamicBufferPresent = true;
#ifdef DEVELOPMENT
- pBufferVk->DvpVerifyDynamicAllocation(this);
+ pBufferVk->DvpVerifyDynamicAllocation(this);
#endif
- }
+ }
- // Device context keeps strong references to all vertex buffers.
+ // Device context keeps strong references to all vertex buffers.
- vkVertexBuffers[slot] = pBufferVk->GetVkBuffer();
- Offsets[slot] = CurrStream.Offset + pBufferVk->GetDynamicOffset(m_ContextId, this);
- }
- else
- {
- // We can't bind null vertex buffer in Vulkan and have to use a dummy one
- vkVertexBuffers[slot] = m_DummyVB->GetVkBuffer();
- Offsets[slot] = 0;
- }
+ vkVertexBuffers[slot] = pBufferVk->GetVkBuffer();
+ Offsets[slot] = CurrStream.Offset + pBufferVk->GetDynamicOffset(m_ContextId, this);
}
+ else
+ {
+ // We can't bind null vertex buffer in Vulkan and have to use a dummy one
+ vkVertexBuffers[slot] = m_DummyVB->GetVkBuffer();
+ Offsets[slot] = 0;
+ }
+ }
- //GraphCtx.FlushResourceBarriers();
- if (m_NumVertexStreams > 0)
- m_CommandBuffer.BindVertexBuffers( 0, m_NumVertexStreams, vkVertexBuffers, Offsets );
+ //GraphCtx.FlushResourceBarriers();
+ if (m_NumVertexStreams > 0)
+ m_CommandBuffer.BindVertexBuffers(0, m_NumVertexStreams, vkVertexBuffers, Offsets);
- // GPU offset for a dynamic vertex buffer can change every time a draw command is invoked
- m_State.CommittedVBsUpToDate = !DynamicBufferPresent;
- }
+ // GPU offset for a dynamic vertex buffer can change every time a draw command is invoked
+ m_State.CommittedVBsUpToDate = !DynamicBufferPresent;
+}
- void DeviceContextVkImpl::DvpLogRenderPass_PSOMismatch()
- {
- std::stringstream ss;
- ss << "Active render pass is incomaptible with PSO '" << m_pPipelineState->GetDesc().Name << "'. "
- "This indicates the mismatch between the number and/or format of bound render targets and/or depth stencil buffer "
- "and the PSO. Vulkand requires exact match.\n"
- " Bound render targets (" << m_NumBoundRenderTargets << "):";
- Uint32 SampleCount = 0;
- for (Uint32 rt = 0; rt < m_NumBoundRenderTargets; ++rt)
- {
- ss << ' ';
- if (auto* pRTV = m_pBoundRenderTargets[rt].RawPtr())
- {
- VERIFY_EXPR(SampleCount == 0 || SampleCount == pRTV->GetTexture()->GetDesc().SampleCount);
- SampleCount = pRTV->GetTexture()->GetDesc().SampleCount;
- ss << GetTextureFormatAttribs(pRTV->GetDesc().Format).Name;
- }
- else
- ss << "<Not set>";
- }
- ss << "; DSV: ";
- if (m_pBoundDepthStencil)
- {
- VERIFY_EXPR(SampleCount == 0 || SampleCount == m_pBoundDepthStencil->GetTexture()->GetDesc().SampleCount);
- SampleCount = m_pBoundDepthStencil->GetTexture()->GetDesc().SampleCount;
- ss << GetTextureFormatAttribs(m_pBoundDepthStencil->GetDesc().Format).Name;
+void DeviceContextVkImpl::DvpLogRenderPass_PSOMismatch()
+{
+ std::stringstream ss;
+ ss << "Active render pass is incomaptible with PSO '" << m_pPipelineState->GetDesc().Name
+ << "'. This indicates the mismatch between the number and/or format of bound render "
+ "targets and/or depth stencil buffer and the PSO. Vulkand requires exact match.\n"
+ " Bound render targets ("
+ << m_NumBoundRenderTargets << "):";
+ Uint32 SampleCount = 0;
+ for (Uint32 rt = 0; rt < m_NumBoundRenderTargets; ++rt)
+ {
+ ss << ' ';
+ if (auto* pRTV = m_pBoundRenderTargets[rt].RawPtr())
+ {
+ VERIFY_EXPR(SampleCount == 0 || SampleCount == pRTV->GetTexture()->GetDesc().SampleCount);
+ SampleCount = pRTV->GetTexture()->GetDesc().SampleCount;
+ ss << GetTextureFormatAttribs(pRTV->GetDesc().Format).Name;
}
else
ss << "<Not set>";
- ss << "; Sample count: " << SampleCount;
+ }
+ ss << "; DSV: ";
+ if (m_pBoundDepthStencil)
+ {
+ VERIFY_EXPR(SampleCount == 0 || SampleCount == m_pBoundDepthStencil->GetTexture()->GetDesc().SampleCount);
+ SampleCount = m_pBoundDepthStencil->GetTexture()->GetDesc().SampleCount;
+ ss << GetTextureFormatAttribs(m_pBoundDepthStencil->GetDesc().Format).Name;
+ }
+ else
+ ss << "<Not set>";
+ ss << "; Sample count: " << SampleCount;
- const auto& GrPipeline = m_pPipelineState->GetDesc().GraphicsPipeline;
- ss << "\n PSO: render targets (" << Uint32{GrPipeline.NumRenderTargets} << "): ";
- for (Uint32 rt = 0; rt < GrPipeline.NumRenderTargets; ++rt)
- ss << ' ' << GetTextureFormatAttribs(GrPipeline.RTVFormats[rt]).Name;
- ss << "; DSV: " << GetTextureFormatAttribs(GrPipeline.DSVFormat).Name;
- ss << "; Sample count: " << Uint32{GrPipeline.SmplDesc.Count};
+ const auto& GrPipeline = m_pPipelineState->GetDesc().GraphicsPipeline;
+ ss << "\n PSO: render targets (" << Uint32{GrPipeline.NumRenderTargets} << "): ";
+ for (Uint32 rt = 0; rt < GrPipeline.NumRenderTargets; ++rt)
+ ss << ' ' << GetTextureFormatAttribs(GrPipeline.RTVFormats[rt]).Name;
+ ss << "; DSV: " << GetTextureFormatAttribs(GrPipeline.DSVFormat).Name;
+ ss << "; Sample count: " << Uint32{GrPipeline.SmplDesc.Count};
- LOG_ERROR_MESSAGE(ss.str());
- }
+ LOG_ERROR_MESSAGE(ss.str());
+}
- void DeviceContextVkImpl::PrepareForDraw(DRAW_FLAGS Flags)
- {
+void DeviceContextVkImpl::PrepareForDraw(DRAW_FLAGS Flags)
+{
#ifdef DEVELOPMENT
- if ((Flags & DRAW_FLAG_VERIFY_RENDER_TARGETS) != 0)
- DvpVerifyRenderTargets();
+ if ((Flags & DRAW_FLAG_VERIFY_RENDER_TARGETS) != 0)
+ DvpVerifyRenderTargets();
#endif
- EnsureVkCmdBuffer();
+ EnsureVkCmdBuffer();
- if (!m_State.CommittedVBsUpToDate && m_pPipelineState->GetNumBufferSlotsUsed() > 0)
- {
- CommitVkVertexBuffers();
- }
+ if (!m_State.CommittedVBsUpToDate && m_pPipelineState->GetNumBufferSlotsUsed() > 0)
+ {
+ CommitVkVertexBuffers();
+ }
#ifdef DEVELOPMENT
- if ((Flags & DRAW_FLAG_VERIFY_STATES) != 0)
+ if ((Flags & DRAW_FLAG_VERIFY_STATES) != 0)
+ {
+ for (Uint32 slot = 0; slot < m_NumVertexStreams; ++slot)
{
- for (Uint32 slot = 0; slot < m_NumVertexStreams; ++slot )
+ if (auto* pBufferVk = m_VertexStreams[slot].pBuffer.RawPtr())
{
- if (auto* pBufferVk = m_VertexStreams[slot].pBuffer.RawPtr())
- {
- DvpVerifyBufferState(*pBufferVk, RESOURCE_STATE_VERTEX_BUFFER, "Using vertex buffers (DeviceContextVkImpl::Draw)");
- }
+ DvpVerifyBufferState(*pBufferVk, RESOURCE_STATE_VERTEX_BUFFER, "Using vertex buffers (DeviceContextVkImpl::Draw)");
}
}
+ }
#endif
- if (m_DescrSetBindInfo.DynamicOffsetCount != 0)
+ if (m_DescrSetBindInfo.DynamicOffsetCount != 0)
+ {
+ // First time we must always bind descriptor sets with dynamic offsets.
+ // If there are no dynamic buffers bound in the resource cache, for all subsequent
+ // cals we do not need to bind the sets again.
+ if (!m_DescrSetBindInfo.DynamicDescriptorsBound ||
+ (m_DescrSetBindInfo.DynamicBuffersPresent && (Flags & DRAW_FLAG_DYNAMIC_RESOURCE_BUFFERS_INTACT) == 0))
{
- // First time we must always bind descriptor sets with dynamic offsets.
- // If there are no dynamic buffers bound in the resource cache, for all subsequent
- // cals we do not need to bind the sets again.
- if (!m_DescrSetBindInfo.DynamicDescriptorsBound ||
- (m_DescrSetBindInfo.DynamicBuffersPresent && (Flags & DRAW_FLAG_DYNAMIC_RESOURCE_BUFFERS_INTACT) == 0))
- {
- m_pPipelineState->BindDescriptorSetsWithDynamicOffsets(GetCommandBuffer(), m_ContextId, this, m_DescrSetBindInfo);
- }
+ m_pPipelineState->BindDescriptorSetsWithDynamicOffsets(GetCommandBuffer(), m_ContextId, this, m_DescrSetBindInfo);
}
+ }
#if 0
-#ifdef _DEBUG
- else
- {
- if ( m_pPipelineState->dbgContainsShaderResources() )
- LOG_ERROR_MESSAGE("Pipeline state '", m_pPipelineState->GetDesc().Name, "' contains shader resources, but IDeviceContext::CommitShaderResources() was not called" );
- }
-#endif
+# ifdef _DEBUG
+ else
+ {
+ if ( m_pPipelineState->dbgContainsShaderResources() )
+ LOG_ERROR_MESSAGE("Pipeline state '", m_pPipelineState->GetDesc().Name, "' contains shader resources, but IDeviceContext::CommitShaderResources() was not called" );
+ }
+# endif
#endif
#ifdef DEVELOPMENT
- if (m_pPipelineState->GetVkRenderPass() != m_RenderPass)
- {
- DvpLogRenderPass_PSOMismatch();
- }
+ if (m_pPipelineState->GetVkRenderPass() != m_RenderPass)
+ {
+ DvpLogRenderPass_PSOMismatch();
+ }
#endif
- CommitRenderPassAndFramebuffer((Flags & DRAW_FLAG_VERIFY_STATES) != 0);
- }
+ CommitRenderPassAndFramebuffer((Flags & DRAW_FLAG_VERIFY_STATES) != 0);
+}
- BufferVkImpl* DeviceContextVkImpl::PrepareIndirectDrawAttribsBuffer(IBuffer* pAttribsBuffer, RESOURCE_STATE_TRANSITION_MODE TransitonMode)
- {
- DEV_CHECK_ERR(pAttribsBuffer, "Indirect draw attribs buffer must not be null");
- auto* pIndirectDrawAttribsVk = ValidatedCast<BufferVkImpl>(pAttribsBuffer);
+BufferVkImpl* DeviceContextVkImpl::PrepareIndirectDrawAttribsBuffer(IBuffer* pAttribsBuffer, RESOURCE_STATE_TRANSITION_MODE TransitonMode)
+{
+ DEV_CHECK_ERR(pAttribsBuffer, "Indirect draw attribs buffer must not be null");
+ auto* pIndirectDrawAttribsVk = ValidatedCast<BufferVkImpl>(pAttribsBuffer);
#ifdef DEVELOPMENT
- if (pIndirectDrawAttribsVk->GetDesc().Usage == USAGE_DYNAMIC)
- pIndirectDrawAttribsVk->DvpVerifyDynamicAllocation(this);
+ if (pIndirectDrawAttribsVk->GetDesc().Usage == USAGE_DYNAMIC)
+ pIndirectDrawAttribsVk->DvpVerifyDynamicAllocation(this);
#endif
- // Buffer memory barries must be executed outside of render pass
- TransitionOrVerifyBufferState(*pIndirectDrawAttribsVk, TransitonMode, RESOURCE_STATE_INDIRECT_ARGUMENT,
- VK_ACCESS_INDIRECT_COMMAND_READ_BIT, "Indirect draw (DeviceContextVkImpl::Draw)");
- return pIndirectDrawAttribsVk;
- }
+ // Buffer memory barries must be executed outside of render pass
+ TransitionOrVerifyBufferState(*pIndirectDrawAttribsVk, TransitonMode, RESOURCE_STATE_INDIRECT_ARGUMENT,
+ VK_ACCESS_INDIRECT_COMMAND_READ_BIT, "Indirect draw (DeviceContextVkImpl::Draw)");
+ return pIndirectDrawAttribsVk;
+}
- void DeviceContextVkImpl::PrepareForIndexedDraw(DRAW_FLAGS Flags, VALUE_TYPE IndexType)
- {
- PrepareForDraw(Flags);
+void DeviceContextVkImpl::PrepareForIndexedDraw(DRAW_FLAGS Flags, VALUE_TYPE IndexType)
+{
+ PrepareForDraw(Flags);
#ifdef DEVELOPMENT
- if ((Flags & DRAW_FLAG_VERIFY_STATES) != 0)
- {
- DvpVerifyBufferState(*m_pIndexBuffer, RESOURCE_STATE_INDEX_BUFFER, "Indexed draw call (DeviceContextVkImpl::Draw)");
- }
-#endif
- DEV_CHECK_ERR(IndexType == VT_UINT16 || IndexType == VT_UINT32, "Unsupported index format. Only R16_UINT and R32_UINT are allowed.");
- VkIndexType vkIndexType = IndexType == VT_UINT16 ? VK_INDEX_TYPE_UINT16 : VK_INDEX_TYPE_UINT32;
- m_CommandBuffer.BindIndexBuffer(m_pIndexBuffer->GetVkBuffer(), m_IndexDataStartOffset + m_pIndexBuffer->GetDynamicOffset(m_ContextId, this), vkIndexType);
+ if ((Flags & DRAW_FLAG_VERIFY_STATES) != 0)
+ {
+ DvpVerifyBufferState(*m_pIndexBuffer, RESOURCE_STATE_INDEX_BUFFER, "Indexed draw call (DeviceContextVkImpl::Draw)");
}
+#endif
+ DEV_CHECK_ERR(IndexType == VT_UINT16 || IndexType == VT_UINT32, "Unsupported index format. Only R16_UINT and R32_UINT are allowed.");
+ VkIndexType vkIndexType = IndexType == VT_UINT16 ? VK_INDEX_TYPE_UINT16 : VK_INDEX_TYPE_UINT32;
+ m_CommandBuffer.BindIndexBuffer(m_pIndexBuffer->GetVkBuffer(), m_IndexDataStartOffset + m_pIndexBuffer->GetDynamicOffset(m_ContextId, this), vkIndexType);
+}
- void DeviceContextVkImpl::Draw(const DrawAttribs& Attribs)
- {
- if (!DvpVerifyDrawArguments(Attribs))
- return;
+void DeviceContextVkImpl::Draw(const DrawAttribs& Attribs)
+{
+ if (!DvpVerifyDrawArguments(Attribs))
+ return;
- PrepareForDraw(Attribs.Flags);
+ PrepareForDraw(Attribs.Flags);
- m_CommandBuffer.Draw(Attribs.NumVertices, Attribs.NumInstances, Attribs.StartVertexLocation, Attribs.FirstInstanceLocation );
- ++m_State.NumCommands;
- }
+ m_CommandBuffer.Draw(Attribs.NumVertices, Attribs.NumInstances, Attribs.StartVertexLocation, Attribs.FirstInstanceLocation);
+ ++m_State.NumCommands;
+}
- void DeviceContextVkImpl::DrawIndexed(const DrawIndexedAttribs& Attribs)
- {
- if (!DvpVerifyDrawIndexedArguments(Attribs))
- return;
+void DeviceContextVkImpl::DrawIndexed(const DrawIndexedAttribs& Attribs)
+{
+ if (!DvpVerifyDrawIndexedArguments(Attribs))
+ return;
- PrepareForIndexedDraw(Attribs.Flags, Attribs.IndexType);
+ PrepareForIndexedDraw(Attribs.Flags, Attribs.IndexType);
- m_CommandBuffer.DrawIndexed(Attribs.NumIndices, Attribs.NumInstances, Attribs.FirstIndexLocation, Attribs.BaseVertex, Attribs.FirstInstanceLocation);
- ++m_State.NumCommands;
- }
+ m_CommandBuffer.DrawIndexed(Attribs.NumIndices, Attribs.NumInstances, Attribs.FirstIndexLocation, Attribs.BaseVertex, Attribs.FirstInstanceLocation);
+ ++m_State.NumCommands;
+}
- void DeviceContextVkImpl::DrawIndirect(const DrawIndirectAttribs& Attribs, IBuffer* pAttribsBuffer)
- {
- if (!DvpVerifyDrawIndirectArguments(Attribs, pAttribsBuffer))
- return;
+void DeviceContextVkImpl::DrawIndirect(const DrawIndirectAttribs& Attribs, IBuffer* pAttribsBuffer)
+{
+ if (!DvpVerifyDrawIndirectArguments(Attribs, pAttribsBuffer))
+ return;
- // We must prepare indirect draw attribs buffer first because state transitions must
- // be performed outside of render pass, and PrepareForDraw commits render pass
- BufferVkImpl* pIndirectDrawAttribsVk = PrepareIndirectDrawAttribsBuffer(pAttribsBuffer, Attribs.IndirectAttribsBufferStateTransitionMode);
+ // We must prepare indirect draw attribs buffer first because state transitions must
+ // be performed outside of render pass, and PrepareForDraw commits render pass
+ BufferVkImpl* pIndirectDrawAttribsVk = PrepareIndirectDrawAttribsBuffer(pAttribsBuffer, Attribs.IndirectAttribsBufferStateTransitionMode);
- PrepareForDraw(Attribs.Flags);
+ PrepareForDraw(Attribs.Flags);
- m_CommandBuffer.DrawIndirect(pIndirectDrawAttribsVk->GetVkBuffer(), pIndirectDrawAttribsVk->GetDynamicOffset(m_ContextId, this) + Attribs.IndirectDrawArgsOffset, 1, 0);
- ++m_State.NumCommands;
- }
+ m_CommandBuffer.DrawIndirect(pIndirectDrawAttribsVk->GetVkBuffer(), pIndirectDrawAttribsVk->GetDynamicOffset(m_ContextId, this) + Attribs.IndirectDrawArgsOffset, 1, 0);
+ ++m_State.NumCommands;
+}
- void DeviceContextVkImpl::DrawIndexedIndirect(const DrawIndexedIndirectAttribs& Attribs, IBuffer* pAttribsBuffer)
- {
- if (!DvpVerifyDrawIndexedIndirectArguments(Attribs, pAttribsBuffer))
- return;
+void DeviceContextVkImpl::DrawIndexedIndirect(const DrawIndexedIndirectAttribs& Attribs, IBuffer* pAttribsBuffer)
+{
+ if (!DvpVerifyDrawIndexedIndirectArguments(Attribs, pAttribsBuffer))
+ return;
- // We must prepare indirect draw attribs buffer first because state transitions must
- // be performed outside of render pass, and PrepareForDraw commits render pass
- BufferVkImpl* pIndirectDrawAttribsVk = PrepareIndirectDrawAttribsBuffer(pAttribsBuffer, Attribs.IndirectAttribsBufferStateTransitionMode);
+ // We must prepare indirect draw attribs buffer first because state transitions must
+ // be performed outside of render pass, and PrepareForDraw commits render pass
+ BufferVkImpl* pIndirectDrawAttribsVk = PrepareIndirectDrawAttribsBuffer(pAttribsBuffer, Attribs.IndirectAttribsBufferStateTransitionMode);
- PrepareForIndexedDraw(Attribs.Flags, Attribs.IndexType);
+ PrepareForIndexedDraw(Attribs.Flags, Attribs.IndexType);
- m_CommandBuffer.DrawIndexedIndirect(pIndirectDrawAttribsVk->GetVkBuffer(), pIndirectDrawAttribsVk->GetDynamicOffset(m_ContextId, this) + Attribs.IndirectDrawArgsOffset, 1, 0);
- ++m_State.NumCommands;
- }
+ m_CommandBuffer.DrawIndexedIndirect(pIndirectDrawAttribsVk->GetVkBuffer(), pIndirectDrawAttribsVk->GetDynamicOffset(m_ContextId, this) + Attribs.IndirectDrawArgsOffset, 1, 0);
+ ++m_State.NumCommands;
+}
- void DeviceContextVkImpl::PrepareForDispatchCompute()
- {
- EnsureVkCmdBuffer();
+void DeviceContextVkImpl::PrepareForDispatchCompute()
+{
+ EnsureVkCmdBuffer();
- // Dispatch commands must be executed outside of render pass
- if (m_CommandBuffer.GetState().RenderPass != VK_NULL_HANDLE)
- m_CommandBuffer.EndRenderPass();
+ // Dispatch commands must be executed outside of render pass
+ if (m_CommandBuffer.GetState().RenderPass != VK_NULL_HANDLE)
+ m_CommandBuffer.EndRenderPass();
- if (m_DescrSetBindInfo.DynamicOffsetCount != 0)
+ if (m_DescrSetBindInfo.DynamicOffsetCount != 0)
+ {
+ if (!m_DescrSetBindInfo.DynamicDescriptorsBound || m_DescrSetBindInfo.DynamicBuffersPresent)
{
- if (!m_DescrSetBindInfo.DynamicDescriptorsBound || m_DescrSetBindInfo.DynamicBuffersPresent)
- {
- m_pPipelineState->BindDescriptorSetsWithDynamicOffsets(GetCommandBuffer(), m_ContextId, this, m_DescrSetBindInfo);
- }
+ m_pPipelineState->BindDescriptorSetsWithDynamicOffsets(GetCommandBuffer(), m_ContextId, this, m_DescrSetBindInfo);
}
+ }
#if 0
-#ifdef _DEBUG
- else
- {
- if ( m_pPipelineState->dbgContainsShaderResources() )
- LOG_ERROR_MESSAGE("Pipeline state '", m_pPipelineState->GetDesc().Name, "' contains shader resources, but IDeviceContext::CommitShaderResources() was not called" );
- }
-#endif
-#endif
+# ifdef _DEBUG
+ else
+ {
+ if ( m_pPipelineState->dbgContainsShaderResources() )
+ LOG_ERROR_MESSAGE("Pipeline state '", m_pPipelineState->GetDesc().Name, "' contains shader resources, but IDeviceContext::CommitShaderResources() was not called" );
}
+# endif
+#endif
+}
- void DeviceContextVkImpl::DispatchCompute(const DispatchComputeAttribs& Attribs)
- {
- if (!DvpVerifyDispatchArguments(Attribs))
- return;
+void DeviceContextVkImpl::DispatchCompute(const DispatchComputeAttribs& Attribs)
+{
+ if (!DvpVerifyDispatchArguments(Attribs))
+ return;
- PrepareForDispatchCompute();
- m_CommandBuffer.Dispatch(Attribs.ThreadGroupCountX, Attribs.ThreadGroupCountY, Attribs.ThreadGroupCountZ);
- ++m_State.NumCommands;
- }
+ PrepareForDispatchCompute();
+ m_CommandBuffer.Dispatch(Attribs.ThreadGroupCountX, Attribs.ThreadGroupCountY, Attribs.ThreadGroupCountZ);
+ ++m_State.NumCommands;
+}
- void DeviceContextVkImpl::DispatchComputeIndirect(const DispatchComputeIndirectAttribs& Attribs, IBuffer* pAttribsBuffer)
- {
- if (!DvpVerifyDispatchIndirectArguments(Attribs, pAttribsBuffer))
- return;
+void DeviceContextVkImpl::DispatchComputeIndirect(const DispatchComputeIndirectAttribs& Attribs, IBuffer* pAttribsBuffer)
+{
+ if (!DvpVerifyDispatchIndirectArguments(Attribs, pAttribsBuffer))
+ return;
+
+ PrepareForDispatchCompute();
- PrepareForDispatchCompute();
+ auto* pBufferVk = ValidatedCast<BufferVkImpl>(pAttribsBuffer);
- auto* pBufferVk = ValidatedCast<BufferVkImpl>(pAttribsBuffer);
-
#ifdef DEVELOPMENT
- if (pBufferVk->GetDesc().Usage == USAGE_DYNAMIC)
- pBufferVk->DvpVerifyDynamicAllocation(this);
+ if (pBufferVk->GetDesc().Usage == USAGE_DYNAMIC)
+ pBufferVk->DvpVerifyDynamicAllocation(this);
#endif
- // Buffer memory barries must be executed outside of render pass
- TransitionOrVerifyBufferState(*pBufferVk, Attribs.IndirectAttribsBufferStateTransitionMode, RESOURCE_STATE_INDIRECT_ARGUMENT,
- VK_ACCESS_INDIRECT_COMMAND_READ_BIT, "Indirect dispatch (DeviceContextVkImpl::DispatchCompute)");
+ // Buffer memory barries must be executed outside of render pass
+ TransitionOrVerifyBufferState(*pBufferVk, Attribs.IndirectAttribsBufferStateTransitionMode, RESOURCE_STATE_INDIRECT_ARGUMENT,
+ VK_ACCESS_INDIRECT_COMMAND_READ_BIT, "Indirect dispatch (DeviceContextVkImpl::DispatchCompute)");
- m_CommandBuffer.DispatchIndirect(pBufferVk->GetVkBuffer(), pBufferVk->GetDynamicOffset(m_ContextId, this) + Attribs.DispatchArgsByteOffset);
- ++m_State.NumCommands;
- }
+ m_CommandBuffer.DispatchIndirect(pBufferVk->GetVkBuffer(), pBufferVk->GetDynamicOffset(m_ContextId, this) + Attribs.DispatchArgsByteOffset);
+ ++m_State.NumCommands;
+}
- void DeviceContextVkImpl::ClearDepthStencil(ITextureView* pView,
- CLEAR_DEPTH_STENCIL_FLAGS ClearFlags,
- float fDepth,
- Uint8 Stencil,
- RESOURCE_STATE_TRANSITION_MODE StateTransitionMode)
+void DeviceContextVkImpl::ClearDepthStencil(ITextureView* pView,
+ CLEAR_DEPTH_STENCIL_FLAGS ClearFlags,
+ float fDepth,
+ Uint8 Stencil,
+ RESOURCE_STATE_TRANSITION_MODE StateTransitionMode)
+{
+ ITextureViewVk* pVkDSV = nullptr;
+ if (pView != nullptr)
{
- ITextureViewVk* pVkDSV = nullptr;
- if ( pView != nullptr )
- {
- pVkDSV = ValidatedCast<ITextureViewVk>(pView);
+ pVkDSV = ValidatedCast<ITextureViewVk>(pView);
#ifdef DEVELOPMENT
- const auto& ViewDesc = pVkDSV->GetDesc();
- if ( ViewDesc.ViewType != TEXTURE_VIEW_DEPTH_STENCIL)
+ const auto& ViewDesc = pVkDSV->GetDesc();
+ if (ViewDesc.ViewType != TEXTURE_VIEW_DEPTH_STENCIL)
+ {
+ LOG_ERROR("The type (", GetTexViewTypeLiteralName(ViewDesc.ViewType), ") of texture view '", pView->GetDesc().Name, "' is incorrect for ClearDepthStencil operation. Depth-stencil view (TEXTURE_VIEW_DEPTH_STENCIL) must be provided.");
+ return;
+ }
+#endif
+ }
+ else
+ {
+ if (m_pSwapChain)
+ {
+ pVkDSV = ValidatedCast<ITextureViewVk>(m_pSwapChain->GetDepthBufferDSV());
+ if (pVkDSV == nullptr)
{
- LOG_ERROR("The type (", GetTexViewTypeLiteralName(ViewDesc.ViewType), ") of texture view '", pView->GetDesc().Name, "' is incorrect for ClearDepthStencil operation. Depth-stencil view (TEXTURE_VIEW_DEPTH_STENCIL) must be provided." );
+ LOG_WARNING_MESSAGE("Depth buffer is not initialized in the swap chain. Clear operation will be ignored.");
return;
}
-#endif
}
else
{
- if (m_pSwapChain)
- {
- pVkDSV = ValidatedCast<ITextureViewVk>(m_pSwapChain->GetDepthBufferDSV());
- if (pVkDSV == nullptr)
- {
- LOG_WARNING_MESSAGE("Depth buffer is not initialized in the swap chain. Clear operation will be ignored.");
- return;
- }
- }
- else
- {
- LOG_ERROR("Failed to clear default depth stencil buffer: swap chain is not initialized in the device context");
- return;
- }
+ LOG_ERROR("Failed to clear default depth stencil buffer: swap chain is not initialized in the device context");
+ return;
}
+ }
- EnsureVkCmdBuffer();
+ EnsureVkCmdBuffer();
- const auto& ViewDesc = pVkDSV->GetDesc();
- VERIFY(ViewDesc.TextureDim != RESOURCE_DIM_TEX_3D, "Depth-stencil view of a 3D texture should've been created as 2D texture array view");
+ const auto& ViewDesc = pVkDSV->GetDesc();
+ VERIFY(ViewDesc.TextureDim != RESOURCE_DIM_TEX_3D, "Depth-stencil view of a 3D texture should've been created as 2D texture array view");
- if (pVkDSV == m_pBoundDepthStencil)
- {
- // Render pass may not be currently committed
- VERIFY_EXPR(m_RenderPass != VK_NULL_HANDLE && m_Framebuffer != VK_NULL_HANDLE);
- TransitionRenderTargets(StateTransitionMode);
- // No need to verify states again
- CommitRenderPassAndFramebuffer(false);
-
- VkClearAttachment ClearAttachment = {};
- ClearAttachment.aspectMask = 0;
- if (ClearFlags & CLEAR_DEPTH_FLAG) ClearAttachment.aspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT;
- if (ClearFlags & CLEAR_STENCIL_FLAG) ClearAttachment.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
- // colorAttachment is only meaningful if VK_IMAGE_ASPECT_COLOR_BIT is set in aspectMask
- ClearAttachment.colorAttachment = VK_ATTACHMENT_UNUSED;
- ClearAttachment.clearValue.depthStencil.depth = fDepth;
- ClearAttachment.clearValue.depthStencil.stencil = Stencil;
- VkClearRect ClearRect;
- // m_FramebufferWidth, m_FramebufferHeight are scaled to the proper mip level
- ClearRect.rect = { {0, 0}, {m_FramebufferWidth, m_FramebufferHeight} };
- // The layers [baseArrayLayer, baseArrayLayer + layerCount) count from the base layer of
- // the attachment image view (17.2), so baseArrayLayer is 0, not ViewDesc.FirstArraySlice
- ClearRect.baseArrayLayer = 0;
- ClearRect.layerCount = ViewDesc.NumArraySlices;
- // No memory barriers are needed between vkCmdClearAttachments and preceding or
- // subsequent draw or attachment clear commands in the same subpass (17.2)
- m_CommandBuffer.ClearAttachment(ClearAttachment, ClearRect);
- }
- else
- {
- // End render pass to clear the buffer with vkCmdClearDepthStencilImage
- if (m_CommandBuffer.GetState().RenderPass != VK_NULL_HANDLE)
- m_CommandBuffer.EndRenderPass();
+ if (pVkDSV == m_pBoundDepthStencil)
+ {
+ // Render pass may not be currently committed
+ VERIFY_EXPR(m_RenderPass != VK_NULL_HANDLE && m_Framebuffer != VK_NULL_HANDLE);
+ TransitionRenderTargets(StateTransitionMode);
+ // No need to verify states again
+ CommitRenderPassAndFramebuffer(false);
+
+ VkClearAttachment ClearAttachment = {};
+ ClearAttachment.aspectMask = 0;
+ if (ClearFlags & CLEAR_DEPTH_FLAG) ClearAttachment.aspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT;
+ if (ClearFlags & CLEAR_STENCIL_FLAG) ClearAttachment.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
+ // colorAttachment is only meaningful if VK_IMAGE_ASPECT_COLOR_BIT is set in aspectMask
+ ClearAttachment.colorAttachment = VK_ATTACHMENT_UNUSED;
+ ClearAttachment.clearValue.depthStencil.depth = fDepth;
+ ClearAttachment.clearValue.depthStencil.stencil = Stencil;
+ VkClearRect ClearRect;
+ // m_FramebufferWidth, m_FramebufferHeight are scaled to the proper mip level
+ ClearRect.rect = {{0, 0}, {m_FramebufferWidth, m_FramebufferHeight}};
+ // The layers [baseArrayLayer, baseArrayLayer + layerCount) count from the base layer of
+ // the attachment image view (17.2), so baseArrayLayer is 0, not ViewDesc.FirstArraySlice
+ ClearRect.baseArrayLayer = 0;
+ ClearRect.layerCount = ViewDesc.NumArraySlices;
+ // No memory barriers are needed between vkCmdClearAttachments and preceding or
+ // subsequent draw or attachment clear commands in the same subpass (17.2)
+ m_CommandBuffer.ClearAttachment(ClearAttachment, ClearRect);
+ }
+ else
+ {
+ // End render pass to clear the buffer with vkCmdClearDepthStencilImage
+ if (m_CommandBuffer.GetState().RenderPass != VK_NULL_HANDLE)
+ m_CommandBuffer.EndRenderPass();
- auto* pTexture = pVkDSV->GetTexture();
- auto* pTextureVk = ValidatedCast<TextureVkImpl>(pTexture);
-
- // Image layout must be VK_IMAGE_LAYOUT_GENERAL or VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL (17.1)
- TransitionOrVerifyTextureState(*pTextureVk, StateTransitionMode, RESOURCE_STATE_COPY_DEST, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
- "Clearing depth-stencil buffer outside of render pass (DeviceContextVkImpl::ClearDepthStencil)");
-
- VkClearDepthStencilValue ClearValue;
- ClearValue.depth = fDepth;
- ClearValue.stencil = Stencil;
- VkImageSubresourceRange Subresource;
- Subresource.aspectMask = 0;
- if (ClearFlags & CLEAR_DEPTH_FLAG) Subresource.aspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT;
- if (ClearFlags & CLEAR_STENCIL_FLAG) Subresource.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
- // We are clearing the image, not image view with vkCmdClearDepthStencilImage
- Subresource.baseArrayLayer = ViewDesc.FirstArraySlice;
- Subresource.layerCount = ViewDesc.NumArraySlices;
- Subresource.baseMipLevel = ViewDesc.MostDetailedMip;
- Subresource.levelCount = ViewDesc.NumMipLevels;
-
- m_CommandBuffer.ClearDepthStencilImage(pTextureVk->GetVkImage(), ClearValue, Subresource);
- }
+ auto* pTexture = pVkDSV->GetTexture();
+ auto* pTextureVk = ValidatedCast<TextureVkImpl>(pTexture);
+
+ // Image layout must be VK_IMAGE_LAYOUT_GENERAL or VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL (17.1)
+ TransitionOrVerifyTextureState(*pTextureVk, StateTransitionMode, RESOURCE_STATE_COPY_DEST, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+ "Clearing depth-stencil buffer outside of render pass (DeviceContextVkImpl::ClearDepthStencil)");
+
+ VkClearDepthStencilValue ClearValue;
+ ClearValue.depth = fDepth;
+ ClearValue.stencil = Stencil;
+ VkImageSubresourceRange Subresource;
+ Subresource.aspectMask = 0;
+ if (ClearFlags & CLEAR_DEPTH_FLAG) Subresource.aspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT;
+ if (ClearFlags & CLEAR_STENCIL_FLAG) Subresource.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
+ // We are clearing the image, not image view with vkCmdClearDepthStencilImage
+ Subresource.baseArrayLayer = ViewDesc.FirstArraySlice;
+ Subresource.layerCount = ViewDesc.NumArraySlices;
+ Subresource.baseMipLevel = ViewDesc.MostDetailedMip;
+ Subresource.levelCount = ViewDesc.NumMipLevels;
- ++m_State.NumCommands;
+ m_CommandBuffer.ClearDepthStencilImage(pTextureVk->GetVkImage(), ClearValue, Subresource);
}
- VkClearColorValue ClearValueToVkClearValue(const float *RGBA, TEXTURE_FORMAT TexFmt)
- {
- VkClearColorValue ClearValue;
- const auto& FmtAttribs = GetTextureFormatAttribs(TexFmt);
- if (FmtAttribs.ComponentType == COMPONENT_TYPE_SINT)
- {
- for (int i=0; i < 4; ++i)
- ClearValue.int32[i] = static_cast<int32_t>(RGBA[i]);
- }
- else if (FmtAttribs.ComponentType == COMPONENT_TYPE_UINT)
- {
- for (int i = 0; i < 4; ++i)
- ClearValue.uint32[i] = static_cast<uint32_t>(RGBA[i]);
- }
- else
- {
- for (int i = 0; i < 4; ++i)
- ClearValue.float32[i] = RGBA[i];
- }
+ ++m_State.NumCommands;
+}
- return ClearValue;
+VkClearColorValue ClearValueToVkClearValue(const float* RGBA, TEXTURE_FORMAT TexFmt)
+{
+ VkClearColorValue ClearValue;
+ const auto& FmtAttribs = GetTextureFormatAttribs(TexFmt);
+ if (FmtAttribs.ComponentType == COMPONENT_TYPE_SINT)
+ {
+ for (int i = 0; i < 4; ++i)
+ ClearValue.int32[i] = static_cast<int32_t>(RGBA[i]);
+ }
+ else if (FmtAttribs.ComponentType == COMPONENT_TYPE_UINT)
+ {
+ for (int i = 0; i < 4; ++i)
+ ClearValue.uint32[i] = static_cast<uint32_t>(RGBA[i]);
+ }
+ else
+ {
+ for (int i = 0; i < 4; ++i)
+ ClearValue.float32[i] = RGBA[i];
}
- void DeviceContextVkImpl::ClearRenderTarget( ITextureView *pView, const float *RGBA, RESOURCE_STATE_TRANSITION_MODE StateTransitionMode )
+ return ClearValue;
+}
+
+void DeviceContextVkImpl::ClearRenderTarget(ITextureView* pView, const float* RGBA, RESOURCE_STATE_TRANSITION_MODE StateTransitionMode)
+{
+ ITextureViewVk* pVkRTV = nullptr;
+ if (pView != nullptr)
{
- ITextureViewVk* pVkRTV = nullptr;
- if ( pView != nullptr )
- {
#ifdef DEVELOPMENT
- const auto& ViewDesc = pView->GetDesc();
- if ( ViewDesc.ViewType != TEXTURE_VIEW_RENDER_TARGET)
- {
- LOG_ERROR("The type (", GetTexViewTypeLiteralName(ViewDesc.ViewType), ") of texture view '", pView->GetDesc().Name, "' is incorrect for ClearRenderTarget operation. Render target view (TEXTURE_VIEW_RENDER_TARGET) must be provided." );
- return;
- }
+ const auto& ViewDesc = pView->GetDesc();
+ if (ViewDesc.ViewType != TEXTURE_VIEW_RENDER_TARGET)
+ {
+ LOG_ERROR("The type (", GetTexViewTypeLiteralName(ViewDesc.ViewType), ") of texture view '", pView->GetDesc().Name, "' is incorrect for ClearRenderTarget operation. Render target view (TEXTURE_VIEW_RENDER_TARGET) must be provided.");
+ return;
+ }
#endif
- pVkRTV = ValidatedCast<ITextureViewVk>(pView);
+ pVkRTV = ValidatedCast<ITextureViewVk>(pView);
+ }
+ else
+ {
+ if (m_pSwapChain)
+ {
+ pVkRTV = ValidatedCast<ITextureViewVk>(m_pSwapChain->GetCurrentBackBufferRTV());
}
else
{
- if (m_pSwapChain)
- {
- pVkRTV = ValidatedCast<ITextureViewVk>(m_pSwapChain->GetCurrentBackBufferRTV());
- }
- else
- {
- LOG_ERROR("Failed to clear default render target: swap chain is not initialized in the device context");
- return;
- }
+ LOG_ERROR("Failed to clear default render target: swap chain is not initialized in the device context");
+ return;
}
+ }
- static constexpr float Zero[4] = { 0.f, 0.f, 0.f, 0.f };
- if ( RGBA == nullptr )
- RGBA = Zero;
-
- EnsureVkCmdBuffer();
+ static constexpr float Zero[4] = {0.f, 0.f, 0.f, 0.f};
+ if (RGBA == nullptr)
+ RGBA = Zero;
- const auto& ViewDesc = pVkRTV->GetDesc();
- VERIFY(ViewDesc.TextureDim != RESOURCE_DIM_TEX_3D, "Render target view of a 3D texture should've been created as 2D texture array view");
+ EnsureVkCmdBuffer();
- // Check if the texture is one of the currently bound render targets
- static constexpr const Uint32 InvalidAttachmentIndex = static_cast<Uint32>(-1);
- Uint32 attachmentIndex = InvalidAttachmentIndex;
- for (Uint32 rt = 0; rt < m_NumBoundRenderTargets; ++rt)
- {
- if (m_pBoundRenderTargets[rt] == pVkRTV)
- {
- attachmentIndex = rt;
- break;
- }
- }
-
- if (attachmentIndex != InvalidAttachmentIndex)
+ const auto& ViewDesc = pVkRTV->GetDesc();
+ VERIFY(ViewDesc.TextureDim != RESOURCE_DIM_TEX_3D, "Render target view of a 3D texture should've been created as 2D texture array view");
+
+ // Check if the texture is one of the currently bound render targets
+ static constexpr const Uint32 InvalidAttachmentIndex = static_cast<Uint32>(-1);
+
+ Uint32 attachmentIndex = InvalidAttachmentIndex;
+ for (Uint32 rt = 0; rt < m_NumBoundRenderTargets; ++rt)
+ {
+ if (m_pBoundRenderTargets[rt] == pVkRTV)
{
- // Render pass may not be currently committed
- VERIFY_EXPR(m_RenderPass != VK_NULL_HANDLE && m_Framebuffer != VK_NULL_HANDLE);
- TransitionRenderTargets(StateTransitionMode);
- // No need to verify states again
- CommitRenderPassAndFramebuffer(false);
-
- VkClearAttachment ClearAttachment = {};
- ClearAttachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
- // colorAttachment is only meaningful if VK_IMAGE_ASPECT_COLOR_BIT is set in aspectMask,
- // in which case it is an index to the pColorAttachments array in the VkSubpassDescription
- // structure of the current subpass which selects the color attachment to clear (17.2)
- // It is NOT the render pass attachment index
- ClearAttachment.colorAttachment = attachmentIndex;
- ClearAttachment.clearValue.color = ClearValueToVkClearValue(RGBA, ViewDesc.Format);
- VkClearRect ClearRect;
- // m_FramebufferWidth, m_FramebufferHeight are scaled to the proper mip level
- ClearRect.rect = { {0, 0}, {m_FramebufferWidth, m_FramebufferHeight} };
- // The layers [baseArrayLayer, baseArrayLayer + layerCount) count from the base layer of
- // the attachment image view (17.2), so baseArrayLayer is 0, not ViewDesc.FirstArraySlice
- ClearRect.baseArrayLayer = 0;
- ClearRect.layerCount = ViewDesc.NumArraySlices;
- // No memory barriers are needed between vkCmdClearAttachments and preceding or
- // subsequent draw or attachment clear commands in the same subpass (17.2)
- m_CommandBuffer.ClearAttachment(ClearAttachment, ClearRect);
+ attachmentIndex = rt;
+ break;
}
- else
- {
- // End current render pass and clear the image with vkCmdClearColorImage
- if (m_CommandBuffer.GetState().RenderPass != VK_NULL_HANDLE)
- m_CommandBuffer.EndRenderPass();
+ }
- auto* pTexture = pVkRTV->GetTexture();
- auto* pTextureVk = ValidatedCast<TextureVkImpl>(pTexture);
+ if (attachmentIndex != InvalidAttachmentIndex)
+ {
+ // Render pass may not be currently committed
+ VERIFY_EXPR(m_RenderPass != VK_NULL_HANDLE && m_Framebuffer != VK_NULL_HANDLE);
+ TransitionRenderTargets(StateTransitionMode);
+ // No need to verify states again
+ CommitRenderPassAndFramebuffer(false);
+
+ VkClearAttachment ClearAttachment = {};
+ ClearAttachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ // colorAttachment is only meaningful if VK_IMAGE_ASPECT_COLOR_BIT is set in aspectMask,
+ // in which case it is an index to the pColorAttachments array in the VkSubpassDescription
+ // structure of the current subpass which selects the color attachment to clear (17.2)
+ // It is NOT the render pass attachment index
+ ClearAttachment.colorAttachment = attachmentIndex;
+ ClearAttachment.clearValue.color = ClearValueToVkClearValue(RGBA, ViewDesc.Format);
+ VkClearRect ClearRect;
+ // m_FramebufferWidth, m_FramebufferHeight are scaled to the proper mip level
+ ClearRect.rect = {{0, 0}, {m_FramebufferWidth, m_FramebufferHeight}};
+ // The layers [baseArrayLayer, baseArrayLayer + layerCount) count from the base layer of
+ // the attachment image view (17.2), so baseArrayLayer is 0, not ViewDesc.FirstArraySlice
+ ClearRect.baseArrayLayer = 0;
+ ClearRect.layerCount = ViewDesc.NumArraySlices;
+ // No memory barriers are needed between vkCmdClearAttachments and preceding or
+ // subsequent draw or attachment clear commands in the same subpass (17.2)
+ m_CommandBuffer.ClearAttachment(ClearAttachment, ClearRect);
+ }
+ else
+ {
+ // End current render pass and clear the image with vkCmdClearColorImage
+ if (m_CommandBuffer.GetState().RenderPass != VK_NULL_HANDLE)
+ m_CommandBuffer.EndRenderPass();
- // Image layout must be VK_IMAGE_LAYOUT_GENERAL or VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL (17.1)
- TransitionOrVerifyTextureState(*pTextureVk, StateTransitionMode, RESOURCE_STATE_COPY_DEST, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
- "Clearing render target outside of render pass (DeviceContextVkImpl::ClearRenderTarget)");
+ auto* pTexture = pVkRTV->GetTexture();
+ auto* pTextureVk = ValidatedCast<TextureVkImpl>(pTexture);
- auto ClearValue = ClearValueToVkClearValue(RGBA, ViewDesc.Format);
- VkImageSubresourceRange Subresource;
- Subresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
- // We are clearing the image, not image view with vkCmdClearColorImage
- Subresource.baseArrayLayer = ViewDesc.FirstArraySlice;
- Subresource.layerCount = ViewDesc.NumArraySlices;
- Subresource.baseMipLevel = ViewDesc.MostDetailedMip;
- Subresource.levelCount = ViewDesc.NumMipLevels;
- VERIFY(ViewDesc.NumMipLevels, "RTV must contain single mip level");
+ // Image layout must be VK_IMAGE_LAYOUT_GENERAL or VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL (17.1)
+ TransitionOrVerifyTextureState(*pTextureVk, StateTransitionMode, RESOURCE_STATE_COPY_DEST, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+ "Clearing render target outside of render pass (DeviceContextVkImpl::ClearRenderTarget)");
- m_CommandBuffer.ClearColorImage(pTextureVk->GetVkImage(), ClearValue, Subresource);
- }
+ auto ClearValue = ClearValueToVkClearValue(RGBA, ViewDesc.Format);
- ++m_State.NumCommands;
+ VkImageSubresourceRange Subresource;
+ Subresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ // We are clearing the image, not image view with vkCmdClearColorImage
+ Subresource.baseArrayLayer = ViewDesc.FirstArraySlice;
+ Subresource.layerCount = ViewDesc.NumArraySlices;
+ Subresource.baseMipLevel = ViewDesc.MostDetailedMip;
+ Subresource.levelCount = ViewDesc.NumMipLevels;
+ VERIFY(ViewDesc.NumMipLevels, "RTV must contain single mip level");
+
+ m_CommandBuffer.ClearColorImage(pTextureVk->GetVkImage(), ClearValue, Subresource);
}
- void DeviceContextVkImpl::FinishFrame()
- {
+ ++m_State.NumCommands;
+}
+
+void DeviceContextVkImpl::FinishFrame()
+{
#ifdef _DEBUG
- for(const auto& MappedBuffIt : m_DbgMappedBuffers)
+ for (const auto& MappedBuffIt : m_DbgMappedBuffers)
+ {
+ const auto& BuffDesc = MappedBuffIt.first->GetDesc();
+ if (BuffDesc.Usage == USAGE_DYNAMIC)
{
- const auto& BuffDesc = MappedBuffIt.first->GetDesc();
- if (BuffDesc.Usage == USAGE_DYNAMIC)
- {
- LOG_WARNING_MESSAGE("Dynamic buffer '", BuffDesc.Name, "' is still mapped when finishing the frame. The contents of the buffer and mapped address will become invalid");
- }
+ LOG_WARNING_MESSAGE("Dynamic buffer '", BuffDesc.Name, "' is still mapped when finishing the frame. The contents of the buffer and mapped address will become invalid");
}
+ }
#endif
- if(GetNumCommandsInCtx() != 0)
+ if (GetNumCommandsInCtx() != 0)
+ {
+ if (m_bIsDeferred)
{
- if (m_bIsDeferred)
- {
- LOG_ERROR_MESSAGE("There are outstanding commands in deferred device context #", m_ContextId,
- " when finishing the frame. This is an error and may cause unpredicted behaviour."
- " Close all deferred contexts and execute them before finishing the frame.");
-
- }
- else
- {
- LOG_ERROR_MESSAGE("There are outstanding commands in the immediate device context when finishing the frame."
- " This is an error and may cause unpredicted behaviour. Call Flush() to submit all commands"
- " for execution before finishing the frame.");
- }
+ LOG_ERROR_MESSAGE("There are outstanding commands in deferred device context #", m_ContextId,
+ " when finishing the frame. This is an error and may cause unpredicted behaviour."
+ " Close all deferred contexts and execute them before finishing the frame.");
+ }
+ else
+ {
+ LOG_ERROR_MESSAGE("There are outstanding commands in the immediate device context when finishing the frame."
+ " This is an error and may cause unpredicted behaviour. Call Flush() to submit all commands"
+ " for execution before finishing the frame.");
}
+ }
- if (!m_MappedTextures.empty())
- LOG_ERROR_MESSAGE("There are mapped textures in the device context when finishing the frame. All dynamic resources must be used in the same frame in which they are mapped.");
+ if (!m_MappedTextures.empty())
+ LOG_ERROR_MESSAGE("There are mapped textures in the device context when finishing the frame. All dynamic resources must be used in the same frame in which they are mapped.");
- VERIFY_EXPR(m_bIsDeferred || m_SubmittedBuffersCmdQueueMask == (Uint64{1}<<m_CommandQueueId));
+ VERIFY_EXPR(m_bIsDeferred || m_SubmittedBuffersCmdQueueMask == (Uint64{1} << m_CommandQueueId));
- // Release resources used by the context during this frame.
-
- // Upload heap returns all allocated pages to the global memory manager.
- // Note: as global memory manager is hosted by the render device, the upload heap can be destroyed
- // before the pages are actually returned to the manager.
- m_UploadHeap.ReleaseAllocatedPages(m_SubmittedBuffersCmdQueueMask);
-
- // Dynamic heap returns all allocated master blocks to the global dynamic memory manager.
- // Note: as global dynamic memory manager is hosted by the render device, the dynamic heap can
- // be destroyed before the blocks are actually returned to the global dynamic memory manager.
- m_DynamicHeap.ReleaseMasterBlocks(*m_pDevice, m_SubmittedBuffersCmdQueueMask);
+ // Release resources used by the context during this frame.
- // Dynamic descriptor set allocator returns all allocated pools to the global dynamic descriptor pool manager.
- // Note: as global pool manager is hosted by the render device, the allocator can
- // be destroyed before the pools are actually returned to the global pool manager.
- m_DynamicDescrSetAllocator.ReleasePools(m_SubmittedBuffersCmdQueueMask);
+ // Upload heap returns all allocated pages to the global memory manager.
+ // Note: as global memory manager is hosted by the render device, the upload heap can be destroyed
+ // before the pages are actually returned to the manager.
+ m_UploadHeap.ReleaseAllocatedPages(m_SubmittedBuffersCmdQueueMask);
- EndFrame();
- }
+ // Dynamic heap returns all allocated master blocks to the global dynamic memory manager.
+ // Note: as global dynamic memory manager is hosted by the render device, the dynamic heap can
+ // be destroyed before the blocks are actually returned to the global dynamic memory manager.
+ m_DynamicHeap.ReleaseMasterBlocks(*m_pDevice, m_SubmittedBuffersCmdQueueMask);
- void DeviceContextVkImpl::Flush()
- {
- if (m_bIsDeferred)
- {
- LOG_ERROR_MESSAGE("Flush() should only be called for immediate contexts");
- return;
- }
+ // Dynamic descriptor set allocator returns all allocated pools to the global dynamic descriptor pool manager.
+ // Note: as global pool manager is hosted by the render device, the allocator can
+ // be destroyed before the pools are actually returned to the global pool manager.
+ m_DynamicDescrSetAllocator.ReleasePools(m_SubmittedBuffersCmdQueueMask);
- VkSubmitInfo SubmitInfo = {};
- SubmitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
- SubmitInfo.pNext = nullptr;
+ EndFrame();
+}
- auto vkCmdBuff = m_CommandBuffer.GetVkCmdBuffer();
- if (vkCmdBuff != VK_NULL_HANDLE )
- {
- if (m_State.NumCommands != 0)
- {
- if (m_CommandBuffer.GetState().RenderPass != VK_NULL_HANDLE)
- {
- m_CommandBuffer.EndRenderPass();
- }
-
- m_CommandBuffer.FlushBarriers();
- m_CommandBuffer.EndCommandBuffer();
-
- SubmitInfo.commandBufferCount = 1;
- SubmitInfo.pCommandBuffers = &vkCmdBuff;
- }
- }
+void DeviceContextVkImpl::Flush()
+{
+ if (m_bIsDeferred)
+ {
+ LOG_ERROR_MESSAGE("Flush() should only be called for immediate contexts");
+ return;
+ }
- SubmitInfo.waitSemaphoreCount = static_cast<uint32_t>(m_WaitSemaphores.size());
- VERIFY_EXPR(m_WaitSemaphores.size() == m_WaitDstStageMasks.size());
- SubmitInfo.pWaitSemaphores = SubmitInfo.waitSemaphoreCount != 0 ? m_WaitSemaphores.data() : nullptr;
- SubmitInfo.pWaitDstStageMask = SubmitInfo.waitSemaphoreCount != 0 ? m_WaitDstStageMasks.data() : nullptr;
- SubmitInfo.signalSemaphoreCount = static_cast<uint32_t>(m_SignalSemaphores.size());
- SubmitInfo.pSignalSemaphores = SubmitInfo.signalSemaphoreCount != 0 ? m_SignalSemaphores.data() : nullptr;
-
- // Submit command buffer even if there are no commands to release stale resources.
- //if (SubmitInfo.commandBufferCount != 0 || SubmitInfo.waitSemaphoreCount !=0 || SubmitInfo.signalSemaphoreCount != 0)
- auto SubmittedFenceValue = m_pDevice->ExecuteCommandBuffer(m_CommandQueueId, SubmitInfo, this, &m_PendingFences);
-
- m_WaitSemaphores.clear();
- m_WaitDstStageMasks.clear();
- m_SignalSemaphores.clear();
- m_PendingFences.clear();
-
- if (vkCmdBuff != VK_NULL_HANDLE)
- {
- DisposeCurrentCmdBuffer(m_CommandQueueId, SubmittedFenceValue);
- }
+ VkSubmitInfo SubmitInfo = {};
- m_State = ContextState{};
- m_DescrSetBindInfo.Reset();
- m_CommandBuffer.Reset();
- m_pPipelineState = nullptr;
- }
+ SubmitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
+ SubmitInfo.pNext = nullptr;
- void DeviceContextVkImpl::SetVertexBuffers( Uint32 StartSlot,
- Uint32 NumBuffersSet,
- IBuffer** ppBuffers,
- Uint32* pOffsets,
- RESOURCE_STATE_TRANSITION_MODE StateTransitionMode,
- SET_VERTEX_BUFFERS_FLAGS Flags )
+ auto vkCmdBuff = m_CommandBuffer.GetVkCmdBuffer();
+ if (vkCmdBuff != VK_NULL_HANDLE)
{
- TDeviceContextBase::SetVertexBuffers( StartSlot, NumBuffersSet, ppBuffers, pOffsets, StateTransitionMode, Flags );
- for ( Uint32 Buff = 0; Buff < m_NumVertexStreams; ++Buff )
+ if (m_State.NumCommands != 0)
{
- auto& CurrStream = m_VertexStreams[Buff];
- if(auto* pBufferVk = CurrStream.pBuffer.RawPtr())
+ if (m_CommandBuffer.GetState().RenderPass != VK_NULL_HANDLE)
{
- TransitionOrVerifyBufferState(*pBufferVk, StateTransitionMode, RESOURCE_STATE_VERTEX_BUFFER, VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT,
- "Setting vertex buffers (DeviceContextVkImpl::SetVertexBuffers)");
+ m_CommandBuffer.EndRenderPass();
}
+
+ m_CommandBuffer.FlushBarriers();
+ m_CommandBuffer.EndCommandBuffer();
+
+ SubmitInfo.commandBufferCount = 1;
+ SubmitInfo.pCommandBuffers = &vkCmdBuff;
}
- m_State.CommittedVBsUpToDate = false;
}
- void DeviceContextVkImpl::InvalidateState()
+ SubmitInfo.waitSemaphoreCount = static_cast<uint32_t>(m_WaitSemaphores.size());
+ VERIFY_EXPR(m_WaitSemaphores.size() == m_WaitDstStageMasks.size());
+ SubmitInfo.pWaitSemaphores = SubmitInfo.waitSemaphoreCount != 0 ? m_WaitSemaphores.data() : nullptr;
+ SubmitInfo.pWaitDstStageMask = SubmitInfo.waitSemaphoreCount != 0 ? m_WaitDstStageMasks.data() : nullptr;
+ SubmitInfo.signalSemaphoreCount = static_cast<uint32_t>(m_SignalSemaphores.size());
+ SubmitInfo.pSignalSemaphores = SubmitInfo.signalSemaphoreCount != 0 ? m_SignalSemaphores.data() : nullptr;
+
+ // Submit command buffer even if there are no commands to release stale resources.
+ //if (SubmitInfo.commandBufferCount != 0 || SubmitInfo.waitSemaphoreCount !=0 || SubmitInfo.signalSemaphoreCount != 0)
+ auto SubmittedFenceValue = m_pDevice->ExecuteCommandBuffer(m_CommandQueueId, SubmitInfo, this, &m_PendingFences);
+
+ m_WaitSemaphores.clear();
+ m_WaitDstStageMasks.clear();
+ m_SignalSemaphores.clear();
+ m_PendingFences.clear();
+
+ if (vkCmdBuff != VK_NULL_HANDLE)
{
- if (m_State.NumCommands != 0)
- LOG_WARNING_MESSAGE("Invalidating context that has outstanding commands in it. Call Flush() to submit commands for execution");
-
- TDeviceContextBase::InvalidateState();
- m_State = ContextState{};
- m_RenderPass = VK_NULL_HANDLE;
- m_Framebuffer = VK_NULL_HANDLE;
- m_DescrSetBindInfo.Reset();
- VERIFY(m_CommandBuffer.GetState().RenderPass == VK_NULL_HANDLE, "Invalidating context with unifinished render pass");
- m_CommandBuffer.Reset();
+ DisposeCurrentCmdBuffer(m_CommandQueueId, SubmittedFenceValue);
}
- void DeviceContextVkImpl::SetIndexBuffer( IBuffer *pIndexBuffer, Uint32 ByteOffset, RESOURCE_STATE_TRANSITION_MODE StateTransitionMode )
+ m_State = ContextState{};
+ m_DescrSetBindInfo.Reset();
+ m_CommandBuffer.Reset();
+ m_pPipelineState = nullptr;
+}
+
+void DeviceContextVkImpl::SetVertexBuffers(Uint32 StartSlot,
+ Uint32 NumBuffersSet,
+ IBuffer** ppBuffers,
+ Uint32* pOffsets,
+ RESOURCE_STATE_TRANSITION_MODE StateTransitionMode,
+ SET_VERTEX_BUFFERS_FLAGS Flags)
+{
+ TDeviceContextBase::SetVertexBuffers(StartSlot, NumBuffersSet, ppBuffers, pOffsets, StateTransitionMode, Flags);
+ for (Uint32 Buff = 0; Buff < m_NumVertexStreams; ++Buff)
{
- TDeviceContextBase::SetIndexBuffer( pIndexBuffer, ByteOffset, StateTransitionMode );
- if (m_pIndexBuffer)
+ auto& CurrStream = m_VertexStreams[Buff];
+ if (auto* pBufferVk = CurrStream.pBuffer.RawPtr())
{
- TransitionOrVerifyBufferState(*m_pIndexBuffer, StateTransitionMode, RESOURCE_STATE_INDEX_BUFFER, VK_ACCESS_INDEX_READ_BIT, "Binding buffer as index buffer (DeviceContextVkImpl::SetIndexBuffer)" );
+ TransitionOrVerifyBufferState(*pBufferVk, StateTransitionMode, RESOURCE_STATE_VERTEX_BUFFER, VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT,
+ "Setting vertex buffers (DeviceContextVkImpl::SetVertexBuffers)");
}
- m_State.CommittedIBUpToDate = false;
}
+ m_State.CommittedVBsUpToDate = false;
+}
+void DeviceContextVkImpl::InvalidateState()
+{
+ if (m_State.NumCommands != 0)
+ LOG_WARNING_MESSAGE("Invalidating context that has outstanding commands in it. Call Flush() to submit commands for execution");
+
+ TDeviceContextBase::InvalidateState();
+ m_State = ContextState{};
+ m_RenderPass = VK_NULL_HANDLE;
+ m_Framebuffer = VK_NULL_HANDLE;
+ m_DescrSetBindInfo.Reset();
+ VERIFY(m_CommandBuffer.GetState().RenderPass == VK_NULL_HANDLE, "Invalidating context with unifinished render pass");
+ m_CommandBuffer.Reset();
+}
- void DeviceContextVkImpl::CommitViewports()
+void DeviceContextVkImpl::SetIndexBuffer(IBuffer* pIndexBuffer, Uint32 ByteOffset, RESOURCE_STATE_TRANSITION_MODE StateTransitionMode)
+{
+ TDeviceContextBase::SetIndexBuffer(pIndexBuffer, ByteOffset, StateTransitionMode);
+ if (m_pIndexBuffer)
{
- VkViewport VkViewports[MaxViewports]; // Do not waste time initializing array to zero
- for ( Uint32 vp = 0; vp < m_NumViewports; ++vp )
- {
- VkViewports[vp].x = m_Viewports[vp].TopLeftX;
- VkViewports[vp].y = m_Viewports[vp].TopLeftY;
- VkViewports[vp].width = m_Viewports[vp].Width;
- VkViewports[vp].height = m_Viewports[vp].Height;
- VkViewports[vp].minDepth = m_Viewports[vp].MinDepth;
- VkViewports[vp].maxDepth = m_Viewports[vp].MaxDepth;
-
- // Turn the viewport upside down to be consistent with Direct3D. Note that in both APIs,
- // the viewport covers the same texture rows. The difference is that Direct3D invertes
- // normalized device Y coordinate when transforming NDC to window coordinates. In Vulkan
- // we achieve the same effect by using negative viewport height. Therefore we need to
- // invert normalized device Y coordinate when transforming to texture V
- //
- //
- // Image Direct3D Image Vulkan
- // row row
- // 0 _ (0,0)_______________________(1,0) Tex Height _ (0,1)_______________________(1,1)
- // 1 _ | | | VP Top + Hght _ _ _ _| __________ | A
- // 2 _ | | | . | | .--> +x| | |
- // . | | | . | | | | | |
- // . | | | V Coord | | V +y | | | V Coord
- // VP Top _ _ _ _| __________ | | VP Top _ _ _ _| |__________| | |
- // . | | A +y | | | . | | |
- // . | | | | | | . | | |
- // . | | '-->+x| | | 2 _ | | |
- // . | |__________| | | 1 _ | | |
- //Tex Height _ |_______________________| V 0 _ |_______________________| |
- // (0,1) (1,1) (0,0) (1,0)
- //
- //
-
- VkViewports[vp].y = VkViewports[vp].y + VkViewports[vp].height;
- VkViewports[vp].height = -VkViewports[vp].height;
- }
- EnsureVkCmdBuffer();
- // TODO: reinterpret_cast m_Viewports to VkViewports?
- m_CommandBuffer.SetViewports(0, m_NumViewports, VkViewports);
+ TransitionOrVerifyBufferState(*m_pIndexBuffer, StateTransitionMode, RESOURCE_STATE_INDEX_BUFFER, VK_ACCESS_INDEX_READ_BIT, "Binding buffer as index buffer (DeviceContextVkImpl::SetIndexBuffer)");
}
+ m_State.CommittedIBUpToDate = false;
+}
- void DeviceContextVkImpl::SetViewports( Uint32 NumViewports, const Viewport *pViewports, Uint32 RTWidth, Uint32 RTHeight )
- {
- TDeviceContextBase::SetViewports( NumViewports, pViewports, RTWidth, RTHeight );
- VERIFY( NumViewports == m_NumViewports, "Unexpected number of viewports" );
- CommitViewports();
- }
+void DeviceContextVkImpl::CommitViewports()
+{
+ VkViewport VkViewports[MaxViewports]; // Do not waste time initializing array to zero
+ for (Uint32 vp = 0; vp < m_NumViewports; ++vp)
+ {
+ VkViewports[vp].x = m_Viewports[vp].TopLeftX;
+ VkViewports[vp].y = m_Viewports[vp].TopLeftY;
+ VkViewports[vp].width = m_Viewports[vp].Width;
+ VkViewports[vp].height = m_Viewports[vp].Height;
+ VkViewports[vp].minDepth = m_Viewports[vp].MinDepth;
+ VkViewports[vp].maxDepth = m_Viewports[vp].MaxDepth;
+
+ // Turn the viewport upside down to be consistent with Direct3D. Note that in both APIs,
+ // the viewport covers the same texture rows. The difference is that Direct3D invertes
+ // normalized device Y coordinate when transforming NDC to window coordinates. In Vulkan
+ // we achieve the same effect by using negative viewport height. Therefore we need to
+ // invert normalized device Y coordinate when transforming to texture V
+ //
+ //
+ // Image Direct3D Image Vulkan
+ // row row
+ // 0 _ (0,0)_______________________(1,0) Tex Height _ (0,1)_______________________(1,1)
+ // 1 _ | | | VP Top + Hght _ _ _ _| __________ | A
+ // 2 _ | | | . | | .--> +x| | |
+ // . | | | . | | | | | |
+ // . | | | V Coord | | V +y | | | V Coord
+ // VP Top _ _ _ _| __________ | | VP Top _ _ _ _| |__________| | |
+ // . | | A +y | | | . | | |
+ // . | | | | | | . | | |
+ // . | | '-->+x| | | 2 _ | | |
+ // . | |__________| | | 1 _ | | |
+ //Tex Height _ |_______________________| V 0 _ |_______________________| |
+ // (0,1) (1,1) (0,0) (1,0)
+ //
+ //
+
+ VkViewports[vp].y = VkViewports[vp].y + VkViewports[vp].height;
+ VkViewports[vp].height = -VkViewports[vp].height;
+ }
+ EnsureVkCmdBuffer();
+ // TODO: reinterpret_cast m_Viewports to VkViewports?
+ m_CommandBuffer.SetViewports(0, m_NumViewports, VkViewports);
+}
- void DeviceContextVkImpl::CommitScissorRects()
- {
- VERIFY(m_pPipelineState && m_pPipelineState->GetDesc().GraphicsPipeline.RasterizerDesc.ScissorEnable, "Scissor test must be enabled in the graphics pipeline");
+void DeviceContextVkImpl::SetViewports(Uint32 NumViewports, const Viewport* pViewports, Uint32 RTWidth, Uint32 RTHeight)
+{
+ TDeviceContextBase::SetViewports(NumViewports, pViewports, RTWidth, RTHeight);
+ VERIFY(NumViewports == m_NumViewports, "Unexpected number of viewports");
+
+ CommitViewports();
+}
- if (m_NumScissorRects == 0)
- return; // Scissors have not been set in the context yet
+void DeviceContextVkImpl::CommitScissorRects()
+{
+ VERIFY(m_pPipelineState && m_pPipelineState->GetDesc().GraphicsPipeline.RasterizerDesc.ScissorEnable, "Scissor test must be enabled in the graphics pipeline");
- VkRect2D VkScissorRects[MaxViewports]; // Do not waste time initializing array with zeroes
- for (Uint32 sr = 0; sr < m_NumScissorRects; ++sr)
- {
- const auto &SrcRect = m_ScissorRects[sr];
- VkScissorRects[sr].offset = {SrcRect.left, SrcRect.top};
- VkScissorRects[sr].extent = {static_cast<uint32_t>(SrcRect.right - SrcRect.left), static_cast<uint32_t>(SrcRect.bottom - SrcRect.top)};
- }
+ if (m_NumScissorRects == 0)
+ return; // Scissors have not been set in the context yet
- EnsureVkCmdBuffer();
- // TODO: reinterpret_cast m_Viewports to m_Viewports?
- m_CommandBuffer.SetScissorRects(0, m_NumScissorRects, VkScissorRects);
+ VkRect2D VkScissorRects[MaxViewports]; // Do not waste time initializing array with zeroes
+ for (Uint32 sr = 0; sr < m_NumScissorRects; ++sr)
+ {
+ const auto& SrcRect = m_ScissorRects[sr];
+ VkScissorRects[sr].offset = {SrcRect.left, SrcRect.top};
+ VkScissorRects[sr].extent = {static_cast<uint32_t>(SrcRect.right - SrcRect.left), static_cast<uint32_t>(SrcRect.bottom - SrcRect.top)};
}
+ EnsureVkCmdBuffer();
+ // TODO: reinterpret_cast m_Viewports to m_Viewports?
+ m_CommandBuffer.SetScissorRects(0, m_NumScissorRects, VkScissorRects);
+}
- void DeviceContextVkImpl::SetScissorRects( Uint32 NumRects, const Rect *pRects, Uint32 RTWidth, Uint32 RTHeight )
- {
- TDeviceContextBase::SetScissorRects(NumRects, pRects, RTWidth, RTHeight);
- // Only commit scissor rects if scissor test is enabled in the rasterizer state.
- // If scissor is currently disabled, or no PSO is bound, scissor rects will be committed by
- // the SetPipelineState() when a PSO with enabled scissor test is set.
- if ( m_pPipelineState )
+void DeviceContextVkImpl::SetScissorRects(Uint32 NumRects, const Rect* pRects, Uint32 RTWidth, Uint32 RTHeight)
+{
+ TDeviceContextBase::SetScissorRects(NumRects, pRects, RTWidth, RTHeight);
+
+ // Only commit scissor rects if scissor test is enabled in the rasterizer state.
+ // If scissor is currently disabled, or no PSO is bound, scissor rects will be committed by
+ // the SetPipelineState() when a PSO with enabled scissor test is set.
+ if (m_pPipelineState)
+ {
+ const auto& PSODesc = m_pPipelineState->GetDesc();
+ if (!PSODesc.IsComputePipeline && PSODesc.GraphicsPipeline.RasterizerDesc.ScissorEnable)
{
- const auto &PSODesc = m_pPipelineState->GetDesc();
- if (!PSODesc.IsComputePipeline && PSODesc.GraphicsPipeline.RasterizerDesc.ScissorEnable)
- {
- VERIFY(NumRects == m_NumScissorRects, "Unexpected number of scissor rects");
- CommitScissorRects();
- }
+ VERIFY(NumRects == m_NumScissorRects, "Unexpected number of scissor rects");
+ CommitScissorRects();
}
}
+}
- void DeviceContextVkImpl::TransitionRenderTargets(RESOURCE_STATE_TRANSITION_MODE StateTransitionMode)
+void DeviceContextVkImpl::TransitionRenderTargets(RESOURCE_STATE_TRANSITION_MODE StateTransitionMode)
+{
+ if (m_pBoundDepthStencil)
{
- if (m_pBoundDepthStencil)
- {
- auto* pDepthBufferVk = ValidatedCast<TextureVkImpl>(m_pBoundDepthStencil->GetTexture());
- TransitionOrVerifyTextureState(*pDepthBufferVk, StateTransitionMode, RESOURCE_STATE_DEPTH_WRITE, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
- "Binding depth-stencil buffer (DeviceContextVkImpl::TransitionRenderTargets)");
- }
+ auto* pDepthBufferVk = ValidatedCast<TextureVkImpl>(m_pBoundDepthStencil->GetTexture());
+ TransitionOrVerifyTextureState(*pDepthBufferVk, StateTransitionMode, RESOURCE_STATE_DEPTH_WRITE, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
+ "Binding depth-stencil buffer (DeviceContextVkImpl::TransitionRenderTargets)");
+ }
- for (Uint32 rt=0; rt < m_NumBoundRenderTargets; ++rt)
+ for (Uint32 rt = 0; rt < m_NumBoundRenderTargets; ++rt)
+ {
+ if (ITextureView* pRTVVk = m_pBoundRenderTargets[rt].RawPtr())
{
- if (ITextureView* pRTVVk = m_pBoundRenderTargets[rt].RawPtr())
- {
- auto* pRenderTargetVk = ValidatedCast<TextureVkImpl>(pRTVVk->GetTexture());
- TransitionOrVerifyTextureState(*pRenderTargetVk, StateTransitionMode, RESOURCE_STATE_RENDER_TARGET, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
- "Binding render targets (DeviceContextVkImpl::TransitionRenderTargets)");
- }
+ auto* pRenderTargetVk = ValidatedCast<TextureVkImpl>(pRTVVk->GetTexture());
+ TransitionOrVerifyTextureState(*pRenderTargetVk, StateTransitionMode, RESOURCE_STATE_RENDER_TARGET, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
+ "Binding render targets (DeviceContextVkImpl::TransitionRenderTargets)");
}
}
+}
- void DeviceContextVkImpl::CommitRenderPassAndFramebuffer(bool VerifyStates)
+void DeviceContextVkImpl::CommitRenderPassAndFramebuffer(bool VerifyStates)
+{
+ const auto& CmdBufferState = m_CommandBuffer.GetState();
+ if (CmdBufferState.Framebuffer != m_Framebuffer)
{
- const auto& CmdBufferState = m_CommandBuffer.GetState();
- if (CmdBufferState.Framebuffer != m_Framebuffer)
+ if (CmdBufferState.RenderPass != VK_NULL_HANDLE)
+ m_CommandBuffer.EndRenderPass();
+
+ if (m_Framebuffer != VK_NULL_HANDLE)
{
- if (CmdBufferState.RenderPass != VK_NULL_HANDLE)
- m_CommandBuffer.EndRenderPass();
-
- if (m_Framebuffer != VK_NULL_HANDLE)
- {
- VERIFY_EXPR(m_RenderPass != VK_NULL_HANDLE);
+ VERIFY_EXPR(m_RenderPass != VK_NULL_HANDLE);
#ifdef DEVELOPMENT
- if (VerifyStates)
- {
- TransitionRenderTargets(RESOURCE_STATE_TRANSITION_MODE_VERIFY);
- }
-#endif
- m_CommandBuffer.BeginRenderPass(m_RenderPass, m_Framebuffer, m_FramebufferWidth, m_FramebufferHeight);
+ if (VerifyStates)
+ {
+ TransitionRenderTargets(RESOURCE_STATE_TRANSITION_MODE_VERIFY);
}
+#endif
+ m_CommandBuffer.BeginRenderPass(m_RenderPass, m_Framebuffer, m_FramebufferWidth, m_FramebufferHeight);
}
}
+}
- void DeviceContextVkImpl::SetRenderTargets( Uint32 NumRenderTargets,
- ITextureView* ppRenderTargets[],
- ITextureView* pDepthStencil,
- RESOURCE_STATE_TRANSITION_MODE StateTransitionMode )
+void DeviceContextVkImpl::SetRenderTargets(Uint32 NumRenderTargets,
+ ITextureView* ppRenderTargets[],
+ ITextureView* pDepthStencil,
+ RESOURCE_STATE_TRANSITION_MODE StateTransitionMode)
+{
+ if (TDeviceContextBase::SetRenderTargets(NumRenderTargets, ppRenderTargets, pDepthStencil))
{
- if ( TDeviceContextBase::SetRenderTargets( NumRenderTargets, ppRenderTargets, pDepthStencil ) )
+ FramebufferCache::FramebufferCacheKey FBKey;
+ RenderPassCache::RenderPassCacheKey RenderPassKey;
+ if (m_pBoundDepthStencil)
+ {
+ auto* pDepthBuffer = m_pBoundDepthStencil->GetTexture();
+ FBKey.DSV = m_pBoundDepthStencil->GetVulkanImageView();
+ RenderPassKey.DSVFormat = m_pBoundDepthStencil->GetDesc().Format;
+ RenderPassKey.SampleCount = static_cast<Uint8>(pDepthBuffer->GetDesc().SampleCount);
+ }
+ else
+ {
+ FBKey.DSV = VK_NULL_HANDLE;
+ RenderPassKey.DSVFormat = TEX_FORMAT_UNKNOWN;
+ }
+
+ FBKey.NumRenderTargets = m_NumBoundRenderTargets;
+ RenderPassKey.NumRenderTargets = static_cast<Uint8>(m_NumBoundRenderTargets);
+
+ for (Uint32 rt = 0; rt < m_NumBoundRenderTargets; ++rt)
{
- FramebufferCache::FramebufferCacheKey FBKey;
- RenderPassCache::RenderPassCacheKey RenderPassKey;
- if (m_pBoundDepthStencil)
+ if (auto* pRTVVk = m_pBoundRenderTargets[rt].RawPtr())
{
- auto* pDepthBuffer = m_pBoundDepthStencil->GetTexture();
- FBKey.DSV = m_pBoundDepthStencil->GetVulkanImageView();
- RenderPassKey.DSVFormat = m_pBoundDepthStencil->GetDesc().Format;
- RenderPassKey.SampleCount = static_cast<Uint8>(pDepthBuffer->GetDesc().SampleCount);
+ auto* pRenderTarget = pRTVVk->GetTexture();
+ FBKey.RTVs[rt] = pRTVVk->GetVulkanImageView();
+ RenderPassKey.RTVFormats[rt] = pRenderTarget->GetDesc().Format;
+ if (RenderPassKey.SampleCount == 0)
+ RenderPassKey.SampleCount = static_cast<Uint8>(pRenderTarget->GetDesc().SampleCount);
+ else
+ VERIFY(RenderPassKey.SampleCount == pRenderTarget->GetDesc().SampleCount, "Inconsistent sample count");
}
else
{
- FBKey.DSV = VK_NULL_HANDLE;
- RenderPassKey.DSVFormat = TEX_FORMAT_UNKNOWN;
+ FBKey.RTVs[rt] = VK_NULL_HANDLE;
+ RenderPassKey.RTVFormats[rt] = TEX_FORMAT_UNKNOWN;
}
+ }
- FBKey.NumRenderTargets = m_NumBoundRenderTargets;
- RenderPassKey.NumRenderTargets = static_cast<Uint8>(m_NumBoundRenderTargets);
+ auto& FBCache = m_pDevice->GetFramebufferCache();
+ auto& RPCache = m_pDevice->GetRenderPassCache();
- for (Uint32 rt=0; rt < m_NumBoundRenderTargets; ++rt)
- {
- if (auto* pRTVVk = m_pBoundRenderTargets[rt].RawPtr())
- {
- auto* pRenderTarget = pRTVVk->GetTexture();
- FBKey.RTVs[rt] = pRTVVk->GetVulkanImageView();
- RenderPassKey.RTVFormats[rt] = pRenderTarget->GetDesc().Format;
- if (RenderPassKey.SampleCount == 0)
- RenderPassKey.SampleCount = static_cast<Uint8>(pRenderTarget->GetDesc().SampleCount);
- else
- VERIFY(RenderPassKey.SampleCount == pRenderTarget->GetDesc().SampleCount, "Inconsistent sample count");
- }
- else
- {
- FBKey.RTVs[rt] = VK_NULL_HANDLE;
- RenderPassKey.RTVFormats[rt] = TEX_FORMAT_UNKNOWN;
- }
- }
-
- auto& FBCache = m_pDevice->GetFramebufferCache();
- auto& RPCache = m_pDevice->GetRenderPassCache();
+ m_RenderPass = RPCache.GetRenderPass(RenderPassKey);
+ FBKey.Pass = m_RenderPass;
+ FBKey.CommandQueueMask = ~Uint64{0};
+ m_Framebuffer = FBCache.GetFramebuffer(FBKey, m_FramebufferWidth, m_FramebufferHeight, m_FramebufferSlices);
- m_RenderPass = RPCache.GetRenderPass(RenderPassKey);
- FBKey.Pass = m_RenderPass;
- FBKey.CommandQueueMask = ~Uint64{0};
- m_Framebuffer = FBCache.GetFramebuffer(FBKey, m_FramebufferWidth, m_FramebufferHeight, m_FramebufferSlices);
+ // Set the viewport to match the render target size
+ SetViewports(1, nullptr, 0, 0);
+ }
- // Set the viewport to match the render target size
- SetViewports(1, nullptr, 0, 0);
- }
+ // Layout transitions can only be performed outside of render pass, so defer
+ // CommitRenderPassAndFramebuffer() until draw call, otherwise we may have to
+ // to end render pass and begin it again if we need to transition any resource
+ // (for instance when CommitShaderResources() is called after SetRenderTargets())
+ TransitionRenderTargets(StateTransitionMode);
+}
- // Layout transitions can only be performed outside of render pass, so defer
- // CommitRenderPassAndFramebuffer() until draw call, otherwise we may have to
- // to end render pass and begin it again if we need to transition any resource
- // (for instance when CommitShaderResources() is called after SetRenderTargets())
- TransitionRenderTargets(StateTransitionMode);
- }
+void DeviceContextVkImpl::ResetRenderTargets()
+{
+ TDeviceContextBase::ResetRenderTargets();
+ m_RenderPass = VK_NULL_HANDLE;
+ m_Framebuffer = VK_NULL_HANDLE;
+}
- void DeviceContextVkImpl::ResetRenderTargets()
+void DeviceContextVkImpl::UpdateBufferRegion(BufferVkImpl* pBuffVk,
+ Uint64 DstOffset,
+ Uint64 NumBytes,
+ VkBuffer vkSrcBuffer,
+ Uint64 SrcOffset,
+ RESOURCE_STATE_TRANSITION_MODE TransitionMode)
+{
+#ifdef DEVELOPMENT
+ if (DstOffset + NumBytes > pBuffVk->GetDesc().uiSizeInBytes)
{
- TDeviceContextBase::ResetRenderTargets();
- m_RenderPass = VK_NULL_HANDLE;
- m_Framebuffer = VK_NULL_HANDLE;
+ LOG_ERROR("Update region is out of buffer bounds which will result in an undefined behavior");
}
-
- void DeviceContextVkImpl::UpdateBufferRegion(BufferVkImpl* pBuffVk,
- Uint64 DstOffset,
- Uint64 NumBytes,
- VkBuffer vkSrcBuffer,
- Uint64 SrcOffset,
- RESOURCE_STATE_TRANSITION_MODE TransitionMode)
- {
-#ifdef DEVELOPMENT
- if (DstOffset + NumBytes > pBuffVk->GetDesc().uiSizeInBytes)
- {
- LOG_ERROR("Update region is out of buffer bounds which will result in an undefined behavior");
- }
#endif
- EnsureVkCmdBuffer();
- TransitionOrVerifyBufferState(*pBuffVk, TransitionMode, RESOURCE_STATE_COPY_DEST, VK_ACCESS_TRANSFER_WRITE_BIT, "Updating buffer (DeviceContextVkImpl::UpdateBufferRegion)");
+ EnsureVkCmdBuffer();
+ TransitionOrVerifyBufferState(*pBuffVk, TransitionMode, RESOURCE_STATE_COPY_DEST, VK_ACCESS_TRANSFER_WRITE_BIT, "Updating buffer (DeviceContextVkImpl::UpdateBufferRegion)");
- VkBufferCopy CopyRegion;
- CopyRegion.srcOffset = SrcOffset;
- CopyRegion.dstOffset = DstOffset;
- CopyRegion.size = NumBytes;
- VERIFY(pBuffVk->m_VulkanBuffer != VK_NULL_HANDLE, "Copy destination buffer must not be suballocated");
- m_CommandBuffer.CopyBuffer(vkSrcBuffer, pBuffVk->GetVkBuffer(), 1, &CopyRegion);
- ++m_State.NumCommands;
- }
+ VkBufferCopy CopyRegion;
+ CopyRegion.srcOffset = SrcOffset;
+ CopyRegion.dstOffset = DstOffset;
+ CopyRegion.size = NumBytes;
+ VERIFY(pBuffVk->m_VulkanBuffer != VK_NULL_HANDLE, "Copy destination buffer must not be suballocated");
+ m_CommandBuffer.CopyBuffer(vkSrcBuffer, pBuffVk->GetVkBuffer(), 1, &CopyRegion);
+ ++m_State.NumCommands;
+}
- void DeviceContextVkImpl::UpdateBuffer(IBuffer* pBuffer,
- Uint32 Offset,
- Uint32 Size,
- const PVoid pData,
- RESOURCE_STATE_TRANSITION_MODE StateTransitionMode)
- {
- TDeviceContextBase::UpdateBuffer(pBuffer, Offset, Size, pData, StateTransitionMode);
+void DeviceContextVkImpl::UpdateBuffer(IBuffer* pBuffer,
+ Uint32 Offset,
+ Uint32 Size,
+ const PVoid pData,
+ RESOURCE_STATE_TRANSITION_MODE StateTransitionMode)
+{
+ TDeviceContextBase::UpdateBuffer(pBuffer, Offset, Size, pData, StateTransitionMode);
- // We must use cmd context from the device context provided, otherwise there will
- // be resource barrier issues in the cmd list in the device context
- auto* pBuffVk = ValidatedCast<BufferVkImpl>(pBuffer);
+ // We must use cmd context from the device context provided, otherwise there will
+ // be resource barrier issues in the cmd list in the device context
+ auto* pBuffVk = ValidatedCast<BufferVkImpl>(pBuffer);
#ifdef DEVELOPMENT
- if (pBuffVk->GetDesc().Usage == USAGE_DYNAMIC)
- {
- LOG_ERROR("Dynamic buffers must be updated via Map()");
- return;
- }
+ if (pBuffVk->GetDesc().Usage == USAGE_DYNAMIC)
+ {
+ LOG_ERROR("Dynamic buffers must be updated via Map()");
+ return;
+ }
#endif
- constexpr size_t Alignment = 4;
- // Source buffer offset must be multiple of 4 (18.4)
- auto TmpSpace = m_UploadHeap.Allocate(Size, Alignment);
- memcpy(TmpSpace.CPUAddress, pData, Size);
- UpdateBufferRegion(pBuffVk, Offset, Size, TmpSpace.vkBuffer, TmpSpace.AlignedOffset, StateTransitionMode);
- // The allocation will stay in the upload heap until the end of the frame at which point all upload
- // pages will be discarded
- }
+ constexpr size_t Alignment = 4;
+ // Source buffer offset must be multiple of 4 (18.4)
+ auto TmpSpace = m_UploadHeap.Allocate(Size, Alignment);
+ memcpy(TmpSpace.CPUAddress, pData, Size);
+ UpdateBufferRegion(pBuffVk, Offset, Size, TmpSpace.vkBuffer, TmpSpace.AlignedOffset, StateTransitionMode);
+ // The allocation will stay in the upload heap until the end of the frame at which point all upload
+ // pages will be discarded
+}
- void DeviceContextVkImpl::CopyBuffer(IBuffer* pSrcBuffer,
- Uint32 SrcOffset,
- RESOURCE_STATE_TRANSITION_MODE SrcBufferTransitionMode,
- IBuffer* pDstBuffer,
- Uint32 DstOffset,
- Uint32 Size,
- RESOURCE_STATE_TRANSITION_MODE DstBufferTransitionMode)
- {
- TDeviceContextBase::CopyBuffer(pSrcBuffer, SrcOffset, SrcBufferTransitionMode, pDstBuffer, DstOffset, Size, DstBufferTransitionMode);
+void DeviceContextVkImpl::CopyBuffer(IBuffer* pSrcBuffer,
+ Uint32 SrcOffset,
+ RESOURCE_STATE_TRANSITION_MODE SrcBufferTransitionMode,
+ IBuffer* pDstBuffer,
+ Uint32 DstOffset,
+ Uint32 Size,
+ RESOURCE_STATE_TRANSITION_MODE DstBufferTransitionMode)
+{
+ TDeviceContextBase::CopyBuffer(pSrcBuffer, SrcOffset, SrcBufferTransitionMode, pDstBuffer, DstOffset, Size, DstBufferTransitionMode);
- auto* pSrcBuffVk = ValidatedCast<BufferVkImpl>(pSrcBuffer);
- auto* pDstBuffVk = ValidatedCast<BufferVkImpl>(pDstBuffer);
+ auto* pSrcBuffVk = ValidatedCast<BufferVkImpl>(pSrcBuffer);
+ auto* pDstBuffVk = ValidatedCast<BufferVkImpl>(pDstBuffer);
#ifdef DEVELOPMENT
- if (pDstBuffVk->GetDesc().Usage == USAGE_DYNAMIC)
- {
- LOG_ERROR("Dynamic buffers cannot be copy destinations");
- return;
- }
+ if (pDstBuffVk->GetDesc().Usage == USAGE_DYNAMIC)
+ {
+ LOG_ERROR("Dynamic buffers cannot be copy destinations");
+ return;
+ }
#endif
- EnsureVkCmdBuffer();
- TransitionOrVerifyBufferState(*pSrcBuffVk, SrcBufferTransitionMode, RESOURCE_STATE_COPY_SOURCE, VK_ACCESS_TRANSFER_READ_BIT, "Using buffer as copy source (DeviceContextVkImpl::CopyBuffer)");
- TransitionOrVerifyBufferState(*pDstBuffVk, DstBufferTransitionMode, RESOURCE_STATE_COPY_DEST, VK_ACCESS_TRANSFER_WRITE_BIT, "Using buffer as copy destination (DeviceContextVkImpl::CopyBuffer)");
+ EnsureVkCmdBuffer();
+ TransitionOrVerifyBufferState(*pSrcBuffVk, SrcBufferTransitionMode, RESOURCE_STATE_COPY_SOURCE, VK_ACCESS_TRANSFER_READ_BIT, "Using buffer as copy source (DeviceContextVkImpl::CopyBuffer)");
+ TransitionOrVerifyBufferState(*pDstBuffVk, DstBufferTransitionMode, RESOURCE_STATE_COPY_DEST, VK_ACCESS_TRANSFER_WRITE_BIT, "Using buffer as copy destination (DeviceContextVkImpl::CopyBuffer)");
+
+ VkBufferCopy CopyRegion;
+ CopyRegion.srcOffset = SrcOffset + pSrcBuffVk->GetDynamicOffset(m_ContextId, this);
+ CopyRegion.dstOffset = DstOffset;
+ CopyRegion.size = Size;
+ VERIFY(pDstBuffVk->m_VulkanBuffer != VK_NULL_HANDLE, "Copy destination buffer must not be suballocated");
+ VERIFY_EXPR(pDstBuffVk->GetDynamicOffset(m_ContextId, this) == 0);
+ m_CommandBuffer.CopyBuffer(pSrcBuffVk->GetVkBuffer(), pDstBuffVk->GetVkBuffer(), 1, &CopyRegion);
+ ++m_State.NumCommands;
+}
- VkBufferCopy CopyRegion;
- CopyRegion.srcOffset = SrcOffset + pSrcBuffVk->GetDynamicOffset(m_ContextId, this);
- CopyRegion.dstOffset = DstOffset;
- CopyRegion.size = Size;
- VERIFY(pDstBuffVk->m_VulkanBuffer != VK_NULL_HANDLE, "Copy destination buffer must not be suballocated");
- VERIFY_EXPR(pDstBuffVk->GetDynamicOffset(m_ContextId, this) == 0);
- m_CommandBuffer.CopyBuffer(pSrcBuffVk->GetVkBuffer(), pDstBuffVk->GetVkBuffer(), 1, &CopyRegion);
- ++m_State.NumCommands;
- }
+void DeviceContextVkImpl::MapBuffer(IBuffer* pBuffer, MAP_TYPE MapType, MAP_FLAGS MapFlags, PVoid& pMappedData)
+{
+ TDeviceContextBase::MapBuffer(pBuffer, MapType, MapFlags, pMappedData);
+ auto* pBufferVk = ValidatedCast<BufferVkImpl>(pBuffer);
+ const auto& BuffDesc = pBufferVk->GetDesc();
- void DeviceContextVkImpl::MapBuffer(IBuffer* pBuffer, MAP_TYPE MapType, MAP_FLAGS MapFlags, PVoid& pMappedData)
+ if (MapType == MAP_READ)
{
- TDeviceContextBase::MapBuffer(pBuffer, MapType, MapFlags, pMappedData);
- auto* pBufferVk = ValidatedCast<BufferVkImpl>(pBuffer);
- const auto& BuffDesc = pBufferVk->GetDesc();
-
- if (MapType == MAP_READ )
+ LOG_ERROR("Mapping buffer for reading is not yet imlemented in Vulkan backend");
+ UNSUPPORTED("Mapping buffer for reading is not yet imlemented in Vulkan backend");
+ }
+ else if (MapType == MAP_WRITE)
+ {
+ if (BuffDesc.Usage == USAGE_STAGING)
{
- LOG_ERROR("Mapping buffer for reading is not yet imlemented in Vulkan backend");
- UNSUPPORTED("Mapping buffer for reading is not yet imlemented in Vulkan backend");
+ LOG_ERROR("Not implemented");
+ UNSUPPORTED("Not implemented");
}
- else if(MapType == MAP_WRITE)
+ else if (BuffDesc.Usage == USAGE_DYNAMIC)
{
- if (BuffDesc.Usage == USAGE_STAGING)
+ DEV_CHECK_ERR((MapFlags & (MAP_FLAG_DISCARD | MAP_FLAG_DO_NOT_SYNCHRONIZE)) != 0, "Failed to map buffer '",
+ BuffDesc.Name, "': Vk buffer must be mapped for writing with MAP_FLAG_DISCARD or MAP_FLAG_DO_NOT_SYNCHRONIZE flag. Context Id: ", m_ContextId);
+
+ auto& DynAllocation = pBufferVk->m_DynamicAllocations[m_ContextId];
+ if ((MapFlags & MAP_FLAG_DISCARD) != 0 || DynAllocation.pDynamicMemMgr == nullptr)
{
- LOG_ERROR("Not implemented");
- UNSUPPORTED("Not implemented");
+ DynAllocation = AllocateDynamicSpace(BuffDesc.uiSizeInBytes, pBufferVk->m_DynamicOffsetAlignment);
}
- else if (BuffDesc.Usage == USAGE_DYNAMIC)
+ else
{
- DEV_CHECK_ERR((MapFlags & (MAP_FLAG_DISCARD | MAP_FLAG_DO_NOT_SYNCHRONIZE)) != 0, "Failed to map buffer '",
- BuffDesc.Name, "': Vk buffer must be mapped for writing with MAP_FLAG_DISCARD or MAP_FLAG_DO_NOT_SYNCHRONIZE flag. Context Id: ", m_ContextId);
-
- auto& DynAllocation = pBufferVk->m_DynamicAllocations[m_ContextId];
- if ( (MapFlags & MAP_FLAG_DISCARD) != 0 || DynAllocation.pDynamicMemMgr == nullptr )
- {
- DynAllocation = AllocateDynamicSpace(BuffDesc.uiSizeInBytes, pBufferVk->m_DynamicOffsetAlignment);
- }
- else
- {
- VERIFY_EXPR(MapFlags & MAP_FLAG_DO_NOT_SYNCHRONIZE);
- // Reuse the same allocation
- }
-
- if (DynAllocation.pDynamicMemMgr != nullptr)
- {
- auto* CPUAddress = DynAllocation.pDynamicMemMgr->GetCPUAddress();
- pMappedData = CPUAddress + DynAllocation.AlignedOffset;
- }
- else
- {
- pMappedData = nullptr;
- }
+ VERIFY_EXPR(MapFlags & MAP_FLAG_DO_NOT_SYNCHRONIZE);
+ // Reuse the same allocation
+ }
+
+ if (DynAllocation.pDynamicMemMgr != nullptr)
+ {
+ auto* CPUAddress = DynAllocation.pDynamicMemMgr->GetCPUAddress();
+ pMappedData = CPUAddress + DynAllocation.AlignedOffset;
}
else
{
- LOG_ERROR("Only USAGE_DYNAMIC and USAGE_STAGING Vk buffers can be mapped for writing");
+ pMappedData = nullptr;
}
}
- else if(MapType == MAP_READ_WRITE)
- {
- LOG_ERROR("MAP_READ_WRITE is not supported on Vk");
- }
else
{
- LOG_ERROR("Only MAP_WRITE_DISCARD and MAP_READ are currently implemented in Vk");
+ LOG_ERROR("Only USAGE_DYNAMIC and USAGE_STAGING Vk buffers can be mapped for writing");
}
}
-
- void DeviceContextVkImpl::UnmapBuffer(IBuffer* pBuffer, MAP_TYPE MapType)
+ else if (MapType == MAP_READ_WRITE)
{
- TDeviceContextBase::UnmapBuffer(pBuffer, MapType);
- auto* pBufferVk = ValidatedCast<BufferVkImpl>(pBuffer);
- const auto& BuffDesc = pBufferVk->GetDesc();
-
- if (MapType == MAP_READ )
- {
- LOG_ERROR("This map type is not yet supported");
- UNSUPPORTED("This map type is not yet supported");
- }
- else if(MapType == MAP_WRITE)
- {
- if (BuffDesc.Usage == USAGE_STAGING)
- {
- LOG_ERROR("This map type is not yet supported");
- UNSUPPORTED("This map type is not yet supported");
- }
- else if (BuffDesc.Usage == USAGE_DYNAMIC)
- {
- if (pBufferVk->m_VulkanBuffer != VK_NULL_HANDLE)
- {
- auto& DynAlloc = pBufferVk->m_DynamicAllocations[m_ContextId];
- auto vkSrcBuff = DynAlloc.pDynamicMemMgr->GetVkBuffer();
- UpdateBufferRegion(pBufferVk, 0, BuffDesc.uiSizeInBytes, vkSrcBuff, DynAlloc.AlignedOffset, RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
- }
- }
- }
+ LOG_ERROR("MAP_READ_WRITE is not supported on Vk");
}
-
- void DeviceContextVkImpl::UpdateTexture(ITexture* pTexture,
- Uint32 MipLevel,
- Uint32 Slice,
- const Box& DstBox,
- const TextureSubResData& SubresData,
- RESOURCE_STATE_TRANSITION_MODE SrcBufferStateTransitionMode,
- RESOURCE_STATE_TRANSITION_MODE TextureStateTransitionModee)
+ else
{
- TDeviceContextBase::UpdateTexture( pTexture, MipLevel, Slice, DstBox, SubresData, SrcBufferStateTransitionMode, TextureStateTransitionModee );
+ LOG_ERROR("Only MAP_WRITE_DISCARD and MAP_READ are currently implemented in Vk");
+ }
+}
- auto* pTexVk = ValidatedCast<TextureVkImpl>(pTexture);
- // OpenGL backend uses UpdateData() to initialize textures, so we can't check the usage in ValidateUpdateTextureParams()
- DEV_CHECK_ERR( pTexVk->GetDesc().Usage == USAGE_DEFAULT, "Only USAGE_DEFAULT textures should be updated with UpdateData()" );
+void DeviceContextVkImpl::UnmapBuffer(IBuffer* pBuffer, MAP_TYPE MapType)
+{
+ TDeviceContextBase::UnmapBuffer(pBuffer, MapType);
+ auto* pBufferVk = ValidatedCast<BufferVkImpl>(pBuffer);
+ const auto& BuffDesc = pBufferVk->GetDesc();
- if (SubresData.pSrcBuffer != nullptr)
- {
- UNSUPPORTED("Copying buffer to texture is not implemented");
- }
- else
- {
- UpdateTextureRegion(SubresData.pData, SubresData.Stride, SubresData.DepthStride, *pTexVk,
- MipLevel, Slice, DstBox, TextureStateTransitionModee);
- }
+ if (MapType == MAP_READ)
+ {
+ LOG_ERROR("This map type is not yet supported");
+ UNSUPPORTED("This map type is not yet supported");
}
-
- void DeviceContextVkImpl::CopyTexture(const CopyTextureAttribs& CopyAttribs)
+ else if (MapType == MAP_WRITE)
{
- TDeviceContextBase::CopyTexture( CopyAttribs );
-
- auto* pSrcTexVk = ValidatedCast<TextureVkImpl>( CopyAttribs.pSrcTexture );
- auto* pDstTexVk = ValidatedCast<TextureVkImpl>( CopyAttribs.pDstTexture );
- const auto& SrcTexDesc = pSrcTexVk->GetDesc();
- const auto& DstTexDesc = pDstTexVk->GetDesc();
- auto* pSrcBox = CopyAttribs.pSrcBox;
- Box FullMipBox;
- if (pSrcBox == nullptr)
+ if (BuffDesc.Usage == USAGE_STAGING)
{
- auto MipLevelAttribs = GetMipLevelProperties(SrcTexDesc, CopyAttribs.SrcMipLevel);
- FullMipBox.MaxX = MipLevelAttribs.LogicalWidth;
- FullMipBox.MaxY = MipLevelAttribs.LogicalHeight;
- FullMipBox.MaxZ = MipLevelAttribs.Depth;
- pSrcBox = &FullMipBox;
+ LOG_ERROR("This map type is not yet supported");
+ UNSUPPORTED("This map type is not yet supported");
}
- const auto& DstFmtAttribs = GetTextureFormatAttribs(DstTexDesc.Format);
- const auto& SrcFmtAttribs = GetTextureFormatAttribs(SrcTexDesc.Format);
- if (SrcTexDesc.Usage != USAGE_STAGING && DstTexDesc.Usage != USAGE_STAGING)
+ else if (BuffDesc.Usage == USAGE_DYNAMIC)
{
- VkImageCopy CopyRegion = {};
- CopyRegion.srcOffset.x = pSrcBox->MinX;
- CopyRegion.srcOffset.y = pSrcBox->MinY;
- CopyRegion.srcOffset.z = pSrcBox->MinZ;
- CopyRegion.extent.width = pSrcBox->MaxX - pSrcBox->MinX;
- CopyRegion.extent.height = std::max(pSrcBox->MaxY - pSrcBox->MinY, 1u);
- CopyRegion.extent.depth = std::max(pSrcBox->MaxZ - pSrcBox->MinZ, 1u);
-
- VkImageAspectFlags aspectMask = 0;
- if (DstFmtAttribs.ComponentType == COMPONENT_TYPE_DEPTH)
- aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
- else if (DstFmtAttribs.ComponentType == COMPONENT_TYPE_DEPTH_STENCIL)
+ if (pBufferVk->m_VulkanBuffer != VK_NULL_HANDLE)
{
- aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
+ auto& DynAlloc = pBufferVk->m_DynamicAllocations[m_ContextId];
+ auto vkSrcBuff = DynAlloc.pDynamicMemMgr->GetVkBuffer();
+ UpdateBufferRegion(pBufferVk, 0, BuffDesc.uiSizeInBytes, vkSrcBuff, DynAlloc.AlignedOffset, RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
}
- else
- aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
-
- CopyRegion.srcSubresource.baseArrayLayer = CopyAttribs.SrcSlice;
- CopyRegion.srcSubresource.layerCount = 1;
- CopyRegion.srcSubresource.mipLevel = CopyAttribs.SrcMipLevel;
- CopyRegion.srcSubresource.aspectMask = aspectMask;
-
- CopyRegion.dstSubresource.baseArrayLayer = CopyAttribs.DstSlice;
- CopyRegion.dstSubresource.layerCount = 1;
- CopyRegion.dstSubresource.mipLevel = CopyAttribs.DstMipLevel;
- CopyRegion.dstSubresource.aspectMask = aspectMask;
-
- CopyRegion.dstOffset.x = CopyAttribs.DstX;
- CopyRegion.dstOffset.y = CopyAttribs.DstY;
- CopyRegion.dstOffset.z = CopyAttribs.DstZ;
-
- CopyTextureRegion(pSrcTexVk, CopyAttribs.SrcTextureTransitionMode, pDstTexVk, CopyAttribs.DstTextureTransitionMode, CopyRegion);
- }
- else if (SrcTexDesc.Usage == USAGE_STAGING && DstTexDesc.Usage != USAGE_STAGING)
- {
- DEV_CHECK_ERR((SrcTexDesc.CPUAccessFlags & CPU_ACCESS_WRITE), "Attempting to copy from staging texture that was not created with CPU_ACCESS_WRITE flag");
- DEV_CHECK_ERR(pSrcTexVk->GetState() == RESOURCE_STATE_COPY_SOURCE, "Source staging texture must permanently be in RESOURCE_STATE_COPY_SOURCE state");
-
- auto SrcBufferOffset = GetStagingDataOffset(SrcTexDesc, CopyAttribs.SrcSlice, CopyAttribs.SrcMipLevel);
- auto SrcMipLevelAttribs = GetMipLevelProperties(SrcTexDesc, CopyAttribs.SrcMipLevel);
- // address of (x,y,z) = region->bufferOffset + (((z * imageHeight) + y) * rowLength + x) * texelBlockSize; (18.4.1)
- SrcBufferOffset +=
- // For compressed-block formats, RowSize is the size of one compressed row.
- // For non-compressed formats, BlockHeight is 1.
- (pSrcBox->MinZ * SrcMipLevelAttribs.StorageHeight + pSrcBox->MinY) / SrcFmtAttribs.BlockHeight * SrcMipLevelAttribs.RowSize +
- // For non-compressed formats, BlockWidth is 1.
- (pSrcBox->MinX / SrcFmtAttribs.BlockWidth) * SrcFmtAttribs.GetElementSize();
-
- Box DstBox;
- DstBox.MinX = CopyAttribs.DstX;
- DstBox.MinY = CopyAttribs.DstY;
- DstBox.MinZ = CopyAttribs.DstZ;
- DstBox.MaxX = DstBox.MinX + pSrcBox->MaxX - pSrcBox->MinX;
- DstBox.MaxY = DstBox.MinY + pSrcBox->MaxY - pSrcBox->MinY;
- DstBox.MaxZ = DstBox.MinZ + pSrcBox->MaxZ - pSrcBox->MinZ;
-
- CopyBufferToTexture(
- pSrcTexVk->GetVkStagingBuffer(),
- SrcBufferOffset,
- SrcMipLevelAttribs.StorageWidth,
- *pDstTexVk,
- DstBox,
- CopyAttribs.DstMipLevel,
- CopyAttribs.DstSlice,
- CopyAttribs.DstTextureTransitionMode
- );
- }
- else if (SrcTexDesc.Usage != USAGE_STAGING && DstTexDesc.Usage == USAGE_STAGING)
- {
- DEV_CHECK_ERR((DstTexDesc.CPUAccessFlags & CPU_ACCESS_READ), "Attempting to copy to staging texture that was not created with CPU_ACCESS_READ flag");
- DEV_CHECK_ERR(pDstTexVk->GetState() == RESOURCE_STATE_COPY_DEST, "Destination staging texture must permanently be in RESOURCE_STATE_COPY_DEST state");
-
- auto DstBufferOffset = GetStagingDataOffset(DstTexDesc, CopyAttribs.DstSlice, CopyAttribs.DstMipLevel);
- auto DstMipLevelAttribs = GetMipLevelProperties(DstTexDesc, CopyAttribs.DstMipLevel);
- // address of (x,y,z) = region->bufferOffset + (((z * imageHeight) + y) * rowLength + x) * texelBlockSize; (18.4.1)
- DstBufferOffset +=
- // For compressed-block formats, RowSize is the size of one compressed row.
- // For non-compressed formats, BlockHeight is 1.
- (CopyAttribs.DstZ * DstMipLevelAttribs.StorageHeight + CopyAttribs.DstY) / DstFmtAttribs.BlockHeight * DstMipLevelAttribs.RowSize *
- // For non-compressed formats, BlockWidth is 1.
- (CopyAttribs.DstX / DstFmtAttribs.BlockWidth) * DstFmtAttribs.GetElementSize();
-
- CopyTextureToBuffer(
- *pSrcTexVk,
- *pSrcBox,
- CopyAttribs.SrcMipLevel,
- CopyAttribs.SrcSlice,
- CopyAttribs.SrcTextureTransitionMode,
- pDstTexVk->GetVkStagingBuffer(),
- DstBufferOffset,
- DstMipLevelAttribs.StorageWidth
- );
- }
- else
- {
- UNSUPPORTED("Copying data between staging textures is not supported and is likely not want you really want to do");
}
}
+}
- void DeviceContextVkImpl::CopyTextureRegion(TextureVkImpl* pSrcTexture,
- RESOURCE_STATE_TRANSITION_MODE SrcTextureTransitionMode,
- TextureVkImpl* pDstTexture,
- RESOURCE_STATE_TRANSITION_MODE DstTextureTransitionMode,
- const VkImageCopy& CopyRegion)
- {
- EnsureVkCmdBuffer();
- TransitionOrVerifyTextureState(*pSrcTexture, SrcTextureTransitionMode, RESOURCE_STATE_COPY_SOURCE, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
- "Using texture as transfer source (DeviceContextVkImpl::CopyTextureRegion)");
- TransitionOrVerifyTextureState(*pDstTexture, DstTextureTransitionMode, RESOURCE_STATE_COPY_DEST, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
- "Using texture as transfer destination (DeviceContextVkImpl::CopyTextureRegion)");
+void DeviceContextVkImpl::UpdateTexture(ITexture* pTexture,
+ Uint32 MipLevel,
+ Uint32 Slice,
+ const Box& DstBox,
+ const TextureSubResData& SubresData,
+ RESOURCE_STATE_TRANSITION_MODE SrcBufferStateTransitionMode,
+ RESOURCE_STATE_TRANSITION_MODE TextureStateTransitionModee)
+{
+ TDeviceContextBase::UpdateTexture(pTexture, MipLevel, Slice, DstBox, SubresData, SrcBufferStateTransitionMode, TextureStateTransitionModee);
- // srcImageLayout must be VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL or VK_IMAGE_LAYOUT_GENERAL
- // dstImageLayout must be VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL or VK_IMAGE_LAYOUT_GENERAL (18.3)
- m_CommandBuffer.CopyImage(pSrcTexture->GetVkImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, pDstTexture->GetVkImage(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &CopyRegion);
- ++m_State.NumCommands;
- }
+ auto* pTexVk = ValidatedCast<TextureVkImpl>(pTexture);
+ // OpenGL backend uses UpdateData() to initialize textures, so we can't check the usage in ValidateUpdateTextureParams()
+ DEV_CHECK_ERR(pTexVk->GetDesc().Usage == USAGE_DEFAULT, "Only USAGE_DEFAULT textures should be updated with UpdateData()");
- DeviceContextVkImpl::BufferToTextureCopyInfo DeviceContextVkImpl::GetBufferToTextureCopyInfo(
- const TextureDesc& TexDesc,
- Uint32 MipLevel,
- const Box& Region)const
+ if (SubresData.pSrcBuffer != nullptr)
{
- BufferToTextureCopyInfo CopyInfo;
- const auto& FmtAttribs = GetTextureFormatAttribs(TexDesc.Format);
- VERIFY_EXPR(Region.MaxX > Region.MinX && Region.MaxY > Region.MinY && Region.MaxZ > Region.MinZ);
- auto UpdateRegionWidth = Region.MaxX - Region.MinX;
- auto UpdateRegionHeight = Region.MaxY - Region.MinY;
- auto UpdateRegionDepth = Region.MaxZ - Region.MinZ;
- if(FmtAttribs.ComponentType == COMPONENT_TYPE_COMPRESSED)
- {
- // Align update region size by the block size. This is only necessary when updating
- // coarse mip levels. Otherwise UpdateRegionWidth/Height should be multiples of block size
- VERIFY_EXPR( (FmtAttribs.BlockWidth & (FmtAttribs.BlockWidth-1)) == 0 );
- VERIFY_EXPR( (FmtAttribs.BlockHeight & (FmtAttribs.BlockHeight-1)) == 0 );
- const auto BlockAlignedRegionWidth = (UpdateRegionWidth + (FmtAttribs.BlockWidth-1)) & ~(FmtAttribs.BlockWidth -1);
- const auto BlockAlignedRegionHeight = (UpdateRegionHeight + (FmtAttribs.BlockHeight-1)) & ~(FmtAttribs.BlockHeight-1);
- CopyInfo.RowSize = BlockAlignedRegionWidth / Uint32{FmtAttribs.BlockWidth} * Uint32{FmtAttribs.ComponentSize};
- CopyInfo.RowCount = BlockAlignedRegionHeight / FmtAttribs.BlockHeight;
-
- // (imageExtent.width + imageOffset.x) must be less than or equal to the image subresource width, and
- // (imageExtent.height + imageOffset.y) must be less than or equal to the image subresource height (18.4),
- // so we need to clamp UpdateRegionWidth and Height
- const Uint32 MipWidth = std::max(TexDesc.Width >> MipLevel, 1u);
- const Uint32 MipHeight = std::max(TexDesc.Height >> MipLevel, 1u);
- VERIFY_EXPR(MipWidth > Region.MinX);
- UpdateRegionWidth = std::min(UpdateRegionWidth, MipWidth - Region.MinX);
- VERIFY_EXPR(MipHeight > Region.MinY);
- UpdateRegionHeight = std::min(UpdateRegionHeight, MipHeight - Region.MinY);
- }
- else
- {
- CopyInfo.RowSize = UpdateRegionWidth * Uint32{FmtAttribs.ComponentSize} * Uint32{FmtAttribs.NumComponents};
- CopyInfo.RowCount = UpdateRegionHeight;
- }
+ UNSUPPORTED("Copying buffer to texture is not implemented");
+ }
+ else
+ {
+ UpdateTextureRegion(SubresData.pData, SubresData.Stride, SubresData.DepthStride, *pTexVk,
+ MipLevel, Slice, DstBox, TextureStateTransitionModee);
+ }
+}
- const auto& DeviceLimits = m_pDevice->GetPhysicalDevice().GetProperties().limits;
- CopyInfo.Stride = Align(CopyInfo.RowSize, static_cast<Uint32>(DeviceLimits.optimalBufferCopyRowPitchAlignment));
- if (FmtAttribs.ComponentType == COMPONENT_TYPE_COMPRESSED)
- {
- // If the calling command's VkImage parameter is a compressed image,
- // bufferRowLength must be a multiple of the compressed texel block width
- // In texels (not even in compressed blocks!)
- CopyInfo.StrideInTexels = CopyInfo.Stride / Uint32{FmtAttribs.ComponentSize} * Uint32{FmtAttribs.BlockWidth};
+void DeviceContextVkImpl::CopyTexture(const CopyTextureAttribs& CopyAttribs)
+{
+ TDeviceContextBase::CopyTexture(CopyAttribs);
+
+ auto* pSrcTexVk = ValidatedCast<TextureVkImpl>(CopyAttribs.pSrcTexture);
+ auto* pDstTexVk = ValidatedCast<TextureVkImpl>(CopyAttribs.pDstTexture);
+ const auto& SrcTexDesc = pSrcTexVk->GetDesc();
+ const auto& DstTexDesc = pDstTexVk->GetDesc();
+ auto* pSrcBox = CopyAttribs.pSrcBox;
+ Box FullMipBox;
+ if (pSrcBox == nullptr)
+ {
+ auto MipLevelAttribs = GetMipLevelProperties(SrcTexDesc, CopyAttribs.SrcMipLevel);
+ FullMipBox.MaxX = MipLevelAttribs.LogicalWidth;
+ FullMipBox.MaxY = MipLevelAttribs.LogicalHeight;
+ FullMipBox.MaxZ = MipLevelAttribs.Depth;
+ pSrcBox = &FullMipBox;
+ }
+ const auto& DstFmtAttribs = GetTextureFormatAttribs(DstTexDesc.Format);
+ const auto& SrcFmtAttribs = GetTextureFormatAttribs(SrcTexDesc.Format);
+ if (SrcTexDesc.Usage != USAGE_STAGING && DstTexDesc.Usage != USAGE_STAGING)
+ {
+ VkImageCopy CopyRegion = {};
+
+ CopyRegion.srcOffset.x = pSrcBox->MinX;
+ CopyRegion.srcOffset.y = pSrcBox->MinY;
+ CopyRegion.srcOffset.z = pSrcBox->MinZ;
+ CopyRegion.extent.width = pSrcBox->MaxX - pSrcBox->MinX;
+ CopyRegion.extent.height = std::max(pSrcBox->MaxY - pSrcBox->MinY, 1u);
+ CopyRegion.extent.depth = std::max(pSrcBox->MaxZ - pSrcBox->MinZ, 1u);
+
+ VkImageAspectFlags aspectMask = 0;
+ if (DstFmtAttribs.ComponentType == COMPONENT_TYPE_DEPTH)
+ aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
+ else if (DstFmtAttribs.ComponentType == COMPONENT_TYPE_DEPTH_STENCIL)
+ {
+ aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
}
else
- {
- CopyInfo.StrideInTexels = CopyInfo.Stride / (Uint32{FmtAttribs.ComponentSize} * Uint32{FmtAttribs.NumComponents});
- }
- CopyInfo.DepthStride = CopyInfo.RowCount * CopyInfo.Stride;
- CopyInfo.MemorySize = UpdateRegionDepth * CopyInfo.DepthStride;
- CopyInfo.Region = Region;
- return CopyInfo;
+ aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+
+ CopyRegion.srcSubresource.baseArrayLayer = CopyAttribs.SrcSlice;
+ CopyRegion.srcSubresource.layerCount = 1;
+ CopyRegion.srcSubresource.mipLevel = CopyAttribs.SrcMipLevel;
+ CopyRegion.srcSubresource.aspectMask = aspectMask;
+
+ CopyRegion.dstSubresource.baseArrayLayer = CopyAttribs.DstSlice;
+ CopyRegion.dstSubresource.layerCount = 1;
+ CopyRegion.dstSubresource.mipLevel = CopyAttribs.DstMipLevel;
+ CopyRegion.dstSubresource.aspectMask = aspectMask;
+
+ CopyRegion.dstOffset.x = CopyAttribs.DstX;
+ CopyRegion.dstOffset.y = CopyAttribs.DstY;
+ CopyRegion.dstOffset.z = CopyAttribs.DstZ;
+
+ CopyTextureRegion(pSrcTexVk, CopyAttribs.SrcTextureTransitionMode, pDstTexVk, CopyAttribs.DstTextureTransitionMode, CopyRegion);
+ }
+ else if (SrcTexDesc.Usage == USAGE_STAGING && DstTexDesc.Usage != USAGE_STAGING)
+ {
+ DEV_CHECK_ERR((SrcTexDesc.CPUAccessFlags & CPU_ACCESS_WRITE), "Attempting to copy from staging texture that was not created with CPU_ACCESS_WRITE flag");
+ DEV_CHECK_ERR(pSrcTexVk->GetState() == RESOURCE_STATE_COPY_SOURCE, "Source staging texture must permanently be in RESOURCE_STATE_COPY_SOURCE state");
+
+ auto SrcBufferOffset = GetStagingDataOffset(SrcTexDesc, CopyAttribs.SrcSlice, CopyAttribs.SrcMipLevel);
+ auto SrcMipLevelAttribs = GetMipLevelProperties(SrcTexDesc, CopyAttribs.SrcMipLevel);
+ // address of (x,y,z) = region->bufferOffset + (((z * imageHeight) + y) * rowLength + x) * texelBlockSize; (18.4.1)
+ SrcBufferOffset +=
+ // For compressed-block formats, RowSize is the size of one compressed row.
+ // For non-compressed formats, BlockHeight is 1.
+ (pSrcBox->MinZ * SrcMipLevelAttribs.StorageHeight + pSrcBox->MinY) / SrcFmtAttribs.BlockHeight * SrcMipLevelAttribs.RowSize +
+ // For non-compressed formats, BlockWidth is 1.
+ (pSrcBox->MinX / SrcFmtAttribs.BlockWidth) * SrcFmtAttribs.GetElementSize();
+
+ Box DstBox;
+ DstBox.MinX = CopyAttribs.DstX;
+ DstBox.MinY = CopyAttribs.DstY;
+ DstBox.MinZ = CopyAttribs.DstZ;
+ DstBox.MaxX = DstBox.MinX + pSrcBox->MaxX - pSrcBox->MinX;
+ DstBox.MaxY = DstBox.MinY + pSrcBox->MaxY - pSrcBox->MinY;
+ DstBox.MaxZ = DstBox.MinZ + pSrcBox->MaxZ - pSrcBox->MinZ;
+
+ CopyBufferToTexture(
+ pSrcTexVk->GetVkStagingBuffer(),
+ SrcBufferOffset,
+ SrcMipLevelAttribs.StorageWidth,
+ *pDstTexVk,
+ DstBox,
+ CopyAttribs.DstMipLevel,
+ CopyAttribs.DstSlice,
+ CopyAttribs.DstTextureTransitionMode);
+ }
+ else if (SrcTexDesc.Usage != USAGE_STAGING && DstTexDesc.Usage == USAGE_STAGING)
+ {
+ DEV_CHECK_ERR((DstTexDesc.CPUAccessFlags & CPU_ACCESS_READ), "Attempting to copy to staging texture that was not created with CPU_ACCESS_READ flag");
+ DEV_CHECK_ERR(pDstTexVk->GetState() == RESOURCE_STATE_COPY_DEST, "Destination staging texture must permanently be in RESOURCE_STATE_COPY_DEST state");
+
+ auto DstBufferOffset = GetStagingDataOffset(DstTexDesc, CopyAttribs.DstSlice, CopyAttribs.DstMipLevel);
+ auto DstMipLevelAttribs = GetMipLevelProperties(DstTexDesc, CopyAttribs.DstMipLevel);
+ // address of (x,y,z) = region->bufferOffset + (((z * imageHeight) + y) * rowLength + x) * texelBlockSize; (18.4.1)
+ DstBufferOffset +=
+ // For compressed-block formats, RowSize is the size of one compressed row.
+ // For non-compressed formats, BlockHeight is 1.
+ (CopyAttribs.DstZ * DstMipLevelAttribs.StorageHeight + CopyAttribs.DstY) / DstFmtAttribs.BlockHeight * DstMipLevelAttribs.RowSize *
+ // For non-compressed formats, BlockWidth is 1.
+ (CopyAttribs.DstX / DstFmtAttribs.BlockWidth) * DstFmtAttribs.GetElementSize();
+
+ CopyTextureToBuffer(
+ *pSrcTexVk,
+ *pSrcBox,
+ CopyAttribs.SrcMipLevel,
+ CopyAttribs.SrcSlice,
+ CopyAttribs.SrcTextureTransitionMode,
+ pDstTexVk->GetVkStagingBuffer(),
+ DstBufferOffset,
+ DstMipLevelAttribs.StorageWidth);
+ }
+ else
+ {
+ UNSUPPORTED("Copying data between staging textures is not supported and is likely not want you really want to do");
}
+}
+void DeviceContextVkImpl::CopyTextureRegion(TextureVkImpl* pSrcTexture,
+ RESOURCE_STATE_TRANSITION_MODE SrcTextureTransitionMode,
+ TextureVkImpl* pDstTexture,
+ RESOURCE_STATE_TRANSITION_MODE DstTextureTransitionMode,
+ const VkImageCopy& CopyRegion)
+{
+ EnsureVkCmdBuffer();
+ TransitionOrVerifyTextureState(*pSrcTexture, SrcTextureTransitionMode, RESOURCE_STATE_COPY_SOURCE, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+ "Using texture as transfer source (DeviceContextVkImpl::CopyTextureRegion)");
+ TransitionOrVerifyTextureState(*pDstTexture, DstTextureTransitionMode, RESOURCE_STATE_COPY_DEST, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+ "Using texture as transfer destination (DeviceContextVkImpl::CopyTextureRegion)");
+
+ // srcImageLayout must be VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL or VK_IMAGE_LAYOUT_GENERAL
+ // dstImageLayout must be VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL or VK_IMAGE_LAYOUT_GENERAL (18.3)
+ m_CommandBuffer.CopyImage(pSrcTexture->GetVkImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, pDstTexture->GetVkImage(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &CopyRegion);
+ ++m_State.NumCommands;
+}
- void DeviceContextVkImpl::UpdateTextureRegion(const void* pSrcData,
- Uint32 SrcStride,
- Uint32 SrcDepthStride,
- TextureVkImpl& TextureVk,
- Uint32 MipLevel,
- Uint32 Slice,
- const Box& DstBox,
- RESOURCE_STATE_TRANSITION_MODE TextureTransitionMode)
- {
- const auto& TexDesc = TextureVk.GetDesc();
- VERIFY(TexDesc.SampleCount == 1, "Only single-sample textures can be updated with vkCmdCopyBufferToImage()");
- auto CopyInfo = GetBufferToTextureCopyInfo(TexDesc, MipLevel, DstBox);
- const auto UpdateRegionDepth = CopyInfo.Region.MaxZ - CopyInfo.Region.MinZ;
+DeviceContextVkImpl::BufferToTextureCopyInfo DeviceContextVkImpl::GetBufferToTextureCopyInfo(
+ const TextureDesc& TexDesc,
+ Uint32 MipLevel,
+ const Box& Region) const
+{
+ BufferToTextureCopyInfo CopyInfo;
+ const auto& FmtAttribs = GetTextureFormatAttribs(TexDesc.Format);
+ VERIFY_EXPR(Region.MaxX > Region.MinX && Region.MaxY > Region.MinY && Region.MaxZ > Region.MinZ);
+ auto UpdateRegionWidth = Region.MaxX - Region.MinX;
+ auto UpdateRegionHeight = Region.MaxY - Region.MinY;
+ auto UpdateRegionDepth = Region.MaxZ - Region.MinZ;
+ if (FmtAttribs.ComponentType == COMPONENT_TYPE_COMPRESSED)
+ {
+ // Align update region size by the block size. This is only necessary when updating
+ // coarse mip levels. Otherwise UpdateRegionWidth/Height should be multiples of block size
+ VERIFY_EXPR((FmtAttribs.BlockWidth & (FmtAttribs.BlockWidth - 1)) == 0);
+ VERIFY_EXPR((FmtAttribs.BlockHeight & (FmtAttribs.BlockHeight - 1)) == 0);
+ const auto BlockAlignedRegionWidth = (UpdateRegionWidth + (FmtAttribs.BlockWidth - 1)) & ~(FmtAttribs.BlockWidth - 1);
+ const auto BlockAlignedRegionHeight = (UpdateRegionHeight + (FmtAttribs.BlockHeight - 1)) & ~(FmtAttribs.BlockHeight - 1);
+ CopyInfo.RowSize = BlockAlignedRegionWidth / Uint32{FmtAttribs.BlockWidth} * Uint32{FmtAttribs.ComponentSize};
+ CopyInfo.RowCount = BlockAlignedRegionHeight / FmtAttribs.BlockHeight;
+
+ // (imageExtent.width + imageOffset.x) must be less than or equal to the image subresource width, and
+ // (imageExtent.height + imageOffset.y) must be less than or equal to the image subresource height (18.4),
+ // so we need to clamp UpdateRegionWidth and Height
+ const Uint32 MipWidth = std::max(TexDesc.Width >> MipLevel, 1u);
+ const Uint32 MipHeight = std::max(TexDesc.Height >> MipLevel, 1u);
+ VERIFY_EXPR(MipWidth > Region.MinX);
+ UpdateRegionWidth = std::min(UpdateRegionWidth, MipWidth - Region.MinX);
+ VERIFY_EXPR(MipHeight > Region.MinY);
+ UpdateRegionHeight = std::min(UpdateRegionHeight, MipHeight - Region.MinY);
+ }
+ else
+ {
+ CopyInfo.RowSize = UpdateRegionWidth * Uint32{FmtAttribs.ComponentSize} * Uint32{FmtAttribs.NumComponents};
+ CopyInfo.RowCount = UpdateRegionHeight;
+ }
+
+ const auto& DeviceLimits = m_pDevice->GetPhysicalDevice().GetProperties().limits;
+ CopyInfo.Stride = Align(CopyInfo.RowSize, static_cast<Uint32>(DeviceLimits.optimalBufferCopyRowPitchAlignment));
+ if (FmtAttribs.ComponentType == COMPONENT_TYPE_COMPRESSED)
+ {
+ // If the calling command's VkImage parameter is a compressed image,
+ // bufferRowLength must be a multiple of the compressed texel block width
+ // In texels (not even in compressed blocks!)
+ CopyInfo.StrideInTexels = CopyInfo.Stride / Uint32{FmtAttribs.ComponentSize} * Uint32{FmtAttribs.BlockWidth};
+ }
+ else
+ {
+ CopyInfo.StrideInTexels = CopyInfo.Stride / (Uint32{FmtAttribs.ComponentSize} * Uint32{FmtAttribs.NumComponents});
+ }
+ CopyInfo.DepthStride = CopyInfo.RowCount * CopyInfo.Stride;
+ CopyInfo.MemorySize = UpdateRegionDepth * CopyInfo.DepthStride;
+ CopyInfo.Region = Region;
+ return CopyInfo;
+}
- // For UpdateTextureRegion(), use UploadHeap, not dynamic heap
- const auto& DeviceLimits = m_pDevice->GetPhysicalDevice().GetProperties().limits;
- // Source buffer offset must be multiple of 4 (18.4)
- auto BufferOffsetAlignment = std::max(DeviceLimits.optimalBufferCopyOffsetAlignment, VkDeviceSize{4});
- // If the calling command's VkImage parameter is a compressed image, bufferOffset must be a multiple of
- // the compressed texel block size in bytes (18.4)
- const auto& FmtAttribs = GetTextureFormatAttribs(TexDesc.Format);
- if (FmtAttribs.ComponentType == COMPONENT_TYPE_COMPRESSED)
- {
- BufferOffsetAlignment = std::max(BufferOffsetAlignment, VkDeviceSize{FmtAttribs.ComponentSize});
- }
- auto Allocation = m_UploadHeap.Allocate(CopyInfo.MemorySize, BufferOffsetAlignment);
- // The allocation will stay in the upload heap until the end of the frame at which point all upload
- // pages will be discarded
- VERIFY( (Allocation.AlignedOffset % BufferOffsetAlignment) == 0, "Allocation offset must be at least 32-bit algined");
-#ifdef _DEBUG
- {
- VERIFY(SrcStride >= CopyInfo.RowSize, "Source data stride (", SrcStride, ") is below the image row size (", CopyInfo.RowSize, ")");
- const Uint32 PlaneSize = SrcStride * CopyInfo.RowCount;
- VERIFY(UpdateRegionDepth == 1 || SrcDepthStride >= PlaneSize, "Source data depth stride (", SrcDepthStride, ") is below the image plane size (", PlaneSize, ")");
- }
-#endif
- for(Uint32 DepthSlice = 0; DepthSlice < UpdateRegionDepth; ++DepthSlice)
- {
- for(Uint32 row = 0; row < CopyInfo.RowCount; ++row)
- {
- const auto* pSrcPtr =
- reinterpret_cast<const Uint8*>(pSrcData)
- + row * SrcStride
- + DepthSlice * SrcDepthStride;
- auto* pDstPtr =
- reinterpret_cast<Uint8*>(Allocation.CPUAddress)
- + row * CopyInfo.Stride
- + DepthSlice * CopyInfo.DepthStride;
-
- memcpy(pDstPtr, pSrcPtr, CopyInfo.RowSize);
- }
- }
- CopyBufferToTexture(Allocation.vkBuffer,
- static_cast<Uint32>(Allocation.AlignedOffset),
- CopyInfo.StrideInTexels,
- TextureVk,
- CopyInfo.Region,
- MipLevel,
- Slice,
- TextureTransitionMode);
- }
+void DeviceContextVkImpl::UpdateTextureRegion(const void* pSrcData,
+ Uint32 SrcStride,
+ Uint32 SrcDepthStride,
+ TextureVkImpl& TextureVk,
+ Uint32 MipLevel,
+ Uint32 Slice,
+ const Box& DstBox,
+ RESOURCE_STATE_TRANSITION_MODE TextureTransitionMode)
+{
+ const auto& TexDesc = TextureVk.GetDesc();
+ VERIFY(TexDesc.SampleCount == 1, "Only single-sample textures can be updated with vkCmdCopyBufferToImage()");
+ auto CopyInfo = GetBufferToTextureCopyInfo(TexDesc, MipLevel, DstBox);
+ const auto UpdateRegionDepth = CopyInfo.Region.MaxZ - CopyInfo.Region.MinZ;
+
+ // For UpdateTextureRegion(), use UploadHeap, not dynamic heap
+ const auto& DeviceLimits = m_pDevice->GetPhysicalDevice().GetProperties().limits;
+ // Source buffer offset must be multiple of 4 (18.4)
+ auto BufferOffsetAlignment = std::max(DeviceLimits.optimalBufferCopyOffsetAlignment, VkDeviceSize{4});
+ // If the calling command's VkImage parameter is a compressed image, bufferOffset must be a multiple of
+ // the compressed texel block size in bytes (18.4)
+ const auto& FmtAttribs = GetTextureFormatAttribs(TexDesc.Format);
+ if (FmtAttribs.ComponentType == COMPONENT_TYPE_COMPRESSED)
+ {
+ BufferOffsetAlignment = std::max(BufferOffsetAlignment, VkDeviceSize{FmtAttribs.ComponentSize});
+ }
+ auto Allocation = m_UploadHeap.Allocate(CopyInfo.MemorySize, BufferOffsetAlignment);
+ // The allocation will stay in the upload heap until the end of the frame at which point all upload
+ // pages will be discarded
+ VERIFY((Allocation.AlignedOffset % BufferOffsetAlignment) == 0, "Allocation offset must be at least 32-bit algined");
- void DeviceContextVkImpl::GenerateMips(ITextureView* pTexView)
+#ifdef _DEBUG
{
- TDeviceContextBase::GenerateMips(pTexView);
- m_GenerateMipsHelper->GenerateMips(*ValidatedCast<TextureViewVkImpl>(pTexView), *this, *m_GenerateMipsSRB);
+ VERIFY(SrcStride >= CopyInfo.RowSize, "Source data stride (", SrcStride, ") is below the image row size (", CopyInfo.RowSize, ")");
+ const Uint32 PlaneSize = SrcStride * CopyInfo.RowCount;
+ VERIFY(UpdateRegionDepth == 1 || SrcDepthStride >= PlaneSize, "Source data depth stride (", SrcDepthStride, ") is below the image plane size (", PlaneSize, ")");
}
+#endif
+ for (Uint32 DepthSlice = 0; DepthSlice < UpdateRegionDepth; ++DepthSlice)
+ {
+ for (Uint32 row = 0; row < CopyInfo.RowCount; ++row)
+ {
+ // clang-format off
+ const auto* pSrcPtr =
+ reinterpret_cast<const Uint8*>(pSrcData)
+ + row * SrcStride
+ + DepthSlice * SrcDepthStride;
+ auto* pDstPtr =
+ reinterpret_cast<Uint8*>(Allocation.CPUAddress)
+ + row * CopyInfo.Stride
+ + DepthSlice * CopyInfo.DepthStride;
+ // clang-format on
+
+ memcpy(pDstPtr, pSrcPtr, CopyInfo.RowSize);
+ }
+ }
+ CopyBufferToTexture(Allocation.vkBuffer,
+ static_cast<Uint32>(Allocation.AlignedOffset),
+ CopyInfo.StrideInTexels,
+ TextureVk,
+ CopyInfo.Region,
+ MipLevel,
+ Slice,
+ TextureTransitionMode);
+}
- static VkBufferImageCopy GetBufferImageCopyInfo(Uint32 BufferOffset,
- Uint32 BufferRowStrideInTexels,
- const TextureDesc& TexDesc,
- const Box& Region,
- Uint32 MipLevel,
- Uint32 ArraySlice)
- {
- VkBufferImageCopy CopyRegion = {};
- VERIFY( (BufferOffset % 4) == 0, "Source buffer offset must be multiple of 4 (18.4)");
- CopyRegion.bufferOffset = BufferOffset; // must be a multiple of 4 (18.4)
+void DeviceContextVkImpl::GenerateMips(ITextureView* pTexView)
+{
+ TDeviceContextBase::GenerateMips(pTexView);
+ m_GenerateMipsHelper->GenerateMips(*ValidatedCast<TextureViewVkImpl>(pTexView), *this, *m_GenerateMipsSRB);
+}
- // bufferRowLength and bufferImageHeight specify the data in buffer memory as a subregion of a larger two- or
- // three-dimensional image, and control the addressing calculations of data in buffer memory. If either of these
- // values is zero, that aspect of the buffer memory is considered to be tightly packed according to the imageExtent (18.4).
- CopyRegion.bufferRowLength = BufferRowStrideInTexels;
- CopyRegion.bufferImageHeight = 0;
+static VkBufferImageCopy GetBufferImageCopyInfo(Uint32 BufferOffset,
+ Uint32 BufferRowStrideInTexels,
+ const TextureDesc& TexDesc,
+ const Box& Region,
+ Uint32 MipLevel,
+ Uint32 ArraySlice)
+{
+ VkBufferImageCopy CopyRegion = {};
+ VERIFY((BufferOffset % 4) == 0, "Source buffer offset must be multiple of 4 (18.4)");
+ CopyRegion.bufferOffset = BufferOffset; // must be a multiple of 4 (18.4)
+
+ // bufferRowLength and bufferImageHeight specify the data in buffer memory as a subregion of a larger two- or
+ // three-dimensional image, and control the addressing calculations of data in buffer memory. If either of these
+ // values is zero, that aspect of the buffer memory is considered to be tightly packed according to the imageExtent (18.4).
+ CopyRegion.bufferRowLength = BufferRowStrideInTexels;
+ CopyRegion.bufferImageHeight = 0;
+
+ const auto& FmtAttribs = GetTextureFormatAttribs(TexDesc.Format);
+ // The aspectMask member of imageSubresource must only have a single bit set (18.4)
+ if (FmtAttribs.ComponentType == COMPONENT_TYPE_DEPTH)
+ CopyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
+ else if (FmtAttribs.ComponentType == COMPONENT_TYPE_DEPTH_STENCIL)
+ {
+ UNSUPPORTED("Updating depth-stencil texture is not currently supported");
+ // When copying to or from a depth or stencil aspect, the data in buffer memory uses a layout
+ // that is a (mostly) tightly packed representation of the depth or stencil data.
+ // To copy both the depth and stencil aspects of a depth/stencil format, two entries in
+ // pRegions can be used, where one specifies the depth aspect in imageSubresource, and the
+ // other specifies the stencil aspect (18.4)
+ }
+ else
+ CopyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+
+ CopyRegion.imageSubresource.baseArrayLayer = ArraySlice;
+ CopyRegion.imageSubresource.layerCount = 1;
+ CopyRegion.imageSubresource.mipLevel = MipLevel;
+ // - imageOffset.x and (imageExtent.width + imageOffset.x) must both be greater than or equal to 0 and
+ // less than or equal to the image subresource width (18.4)
+ // - imageOffset.y and (imageExtent.height + imageOffset.y) must both be greater than or equal to 0 and
+ // less than or equal to the image subresource height (18.4)
+ CopyRegion.imageOffset =
+ VkOffset3D //
+ {
+ static_cast<int32_t>(Region.MinX),
+ static_cast<int32_t>(Region.MinY),
+ static_cast<int32_t>(Region.MinZ) //
+ };
+ VERIFY(Region.MaxX > Region.MinX && Region.MaxY - Region.MinY && Region.MaxZ > Region.MinZ,
+ "[", Region.MinX, " .. ", Region.MaxX, ") x [", Region.MinY, " .. ", Region.MaxY, ") x [", Region.MinZ, " .. ", Region.MaxZ, ") is not a vaild region");
+ CopyRegion.imageExtent =
+ VkExtent3D //
+ {
+ static_cast<uint32_t>(Region.MaxX - Region.MinX),
+ static_cast<uint32_t>(Region.MaxY - Region.MinY),
+ static_cast<uint32_t>(Region.MaxZ - Region.MinZ) //
+ };
- const auto& FmtAttribs = GetTextureFormatAttribs(TexDesc.Format);
- // The aspectMask member of imageSubresource must only have a single bit set (18.4)
- if (FmtAttribs.ComponentType == COMPONENT_TYPE_DEPTH)
- CopyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
- else if (FmtAttribs.ComponentType == COMPONENT_TYPE_DEPTH_STENCIL)
- {
- UNSUPPORTED("Updating depth-stencil texture is not currently supported");
- // When copying to or from a depth or stencil aspect, the data in buffer memory uses a layout
- // that is a (mostly) tightly packed representation of the depth or stencil data.
- // To copy both the depth and stencil aspects of a depth/stencil format, two entries in
- // pRegions can be used, where one specifies the depth aspect in imageSubresource, and the
- // other specifies the stencil aspect (18.4)
- }
- else
- CopyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
-
- CopyRegion.imageSubresource.baseArrayLayer = ArraySlice;
- CopyRegion.imageSubresource.layerCount = 1;
- CopyRegion.imageSubresource.mipLevel = MipLevel;
- // - imageOffset.x and (imageExtent.width + imageOffset.x) must both be greater than or equal to 0 and
- // less than or equal to the image subresource width (18.4)
- // - imageOffset.y and (imageExtent.height + imageOffset.y) must both be greater than or equal to 0 and
- // less than or equal to the image subresource height (18.4)
- CopyRegion.imageOffset =
- VkOffset3D
- {
- static_cast<int32_t>(Region.MinX),
- static_cast<int32_t>(Region.MinY),
- static_cast<int32_t>(Region.MinZ)
- };
- VERIFY(Region.MaxX > Region.MinX && Region.MaxY - Region.MinY && Region.MaxZ > Region.MinZ,
- "[", Region.MinX, " .. ", Region.MaxX, ") x [", Region.MinY, " .. ", Region.MaxY, ") x [", Region.MinZ, " .. ", Region.MaxZ, ") is not a vaild region");
- CopyRegion.imageExtent =
- VkExtent3D
- {
- static_cast<uint32_t>(Region.MaxX - Region.MinX),
- static_cast<uint32_t>(Region.MaxY - Region.MinY),
- static_cast<uint32_t>(Region.MaxZ - Region.MinZ)
- };
+ return CopyRegion;
+}
- return CopyRegion;
- }
+void DeviceContextVkImpl::CopyBufferToTexture(VkBuffer vkSrcBuffer,
+ Uint32 SrcBufferOffset,
+ Uint32 SrcBufferRowStrideInTexels,
+ TextureVkImpl& DstTextureVk,
+ const Box& DstRegion,
+ Uint32 DstMipLevel,
+ Uint32 DstArraySlice,
+ RESOURCE_STATE_TRANSITION_MODE DstTextureTransitionMode)
+{
+ EnsureVkCmdBuffer();
+ TransitionOrVerifyTextureState(DstTextureVk, DstTextureTransitionMode, RESOURCE_STATE_COPY_DEST, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+ "Using texture as copy destination (DeviceContextVkImpl::CopyBufferToTexture)");
+
+ const auto& TexDesc = DstTextureVk.GetDesc();
+ VkBufferImageCopy BuffImgCopy = GetBufferImageCopyInfo(SrcBufferOffset, SrcBufferRowStrideInTexels, TexDesc, DstRegion, DstMipLevel, DstArraySlice);
+
+ m_CommandBuffer.CopyBufferToImage(
+ vkSrcBuffer,
+ DstTextureVk.GetVkImage(),
+ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // must be VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL or VK_IMAGE_LAYOUT_GENERAL (18.4)
+ 1,
+ &BuffImgCopy);
+}
- void DeviceContextVkImpl::CopyBufferToTexture(VkBuffer vkSrcBuffer,
- Uint32 SrcBufferOffset,
- Uint32 SrcBufferRowStrideInTexels,
- TextureVkImpl& DstTextureVk,
- const Box& DstRegion,
- Uint32 DstMipLevel,
- Uint32 DstArraySlice,
- RESOURCE_STATE_TRANSITION_MODE DstTextureTransitionMode)
- {
- EnsureVkCmdBuffer();
- TransitionOrVerifyTextureState(DstTextureVk, DstTextureTransitionMode, RESOURCE_STATE_COPY_DEST, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
- "Using texture as copy destination (DeviceContextVkImpl::CopyBufferToTexture)");
+void DeviceContextVkImpl::CopyTextureToBuffer(TextureVkImpl& SrcTextureVk,
+ const Box& SrcRegion,
+ Uint32 SrcMipLevel,
+ Uint32 SrcArraySlice,
+ RESOURCE_STATE_TRANSITION_MODE SrcTextureTransitionMode,
+ VkBuffer vkDstBuffer,
+ Uint32 DstBufferOffset,
+ Uint32 DstBufferRowStrideInTexels)
+{
+ EnsureVkCmdBuffer();
+ TransitionOrVerifyTextureState(SrcTextureVk, SrcTextureTransitionMode, RESOURCE_STATE_COPY_SOURCE, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+ "Using texture as source destination (DeviceContextVkImpl::CopyTextureToBuffer)");
+
+ const auto& TexDesc = SrcTextureVk.GetDesc();
+ VkBufferImageCopy BuffImgCopy = GetBufferImageCopyInfo(DstBufferOffset, DstBufferRowStrideInTexels, TexDesc, SrcRegion, SrcMipLevel, SrcArraySlice);
+
+ m_CommandBuffer.CopyImageToBuffer(
+ SrcTextureVk.GetVkImage(),
+ VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // must be VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL or VK_IMAGE_LAYOUT_GENERAL (18.4)
+ vkDstBuffer,
+ 1,
+ &BuffImgCopy);
+}
- const auto& TexDesc = DstTextureVk.GetDesc();
- VkBufferImageCopy BuffImgCopy = GetBufferImageCopyInfo(SrcBufferOffset, SrcBufferRowStrideInTexels, TexDesc, DstRegion, DstMipLevel, DstArraySlice);
- m_CommandBuffer.CopyBufferToImage(
- vkSrcBuffer,
- DstTextureVk.GetVkImage(),
- VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // must be VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL or VK_IMAGE_LAYOUT_GENERAL (18.4)
- 1,
- &BuffImgCopy);
- }
+void DeviceContextVkImpl::MapTextureSubresource(ITexture* pTexture,
+ Uint32 MipLevel,
+ Uint32 ArraySlice,
+ MAP_TYPE MapType,
+ MAP_FLAGS MapFlags,
+ const Box* pMapRegion,
+ MappedTextureSubresource& MappedData)
+{
+ TDeviceContextBase::MapTextureSubresource(pTexture, MipLevel, ArraySlice, MapType, MapFlags, pMapRegion, MappedData);
- void DeviceContextVkImpl::CopyTextureToBuffer(TextureVkImpl& SrcTextureVk,
- const Box& SrcRegion,
- Uint32 SrcMipLevel,
- Uint32 SrcArraySlice,
- RESOURCE_STATE_TRANSITION_MODE SrcTextureTransitionMode,
- VkBuffer vkDstBuffer,
- Uint32 DstBufferOffset,
- Uint32 DstBufferRowStrideInTexels)
- {
- EnsureVkCmdBuffer();
- TransitionOrVerifyTextureState(SrcTextureVk, SrcTextureTransitionMode, RESOURCE_STATE_COPY_SOURCE, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
- "Using texture as source destination (DeviceContextVkImpl::CopyTextureToBuffer)");
+ TextureVkImpl& TextureVk = *ValidatedCast<TextureVkImpl>(pTexture);
+ const auto& TexDesc = TextureVk.GetDesc();
+ const auto& FmtAttribs = GetTextureFormatAttribs(TexDesc.Format);
- const auto& TexDesc = SrcTextureVk.GetDesc();
- VkBufferImageCopy BuffImgCopy = GetBufferImageCopyInfo(DstBufferOffset, DstBufferRowStrideInTexels, TexDesc, SrcRegion, SrcMipLevel, SrcArraySlice);
-
- m_CommandBuffer.CopyImageToBuffer(
- SrcTextureVk.GetVkImage(),
- VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // must be VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL or VK_IMAGE_LAYOUT_GENERAL (18.4)
- vkDstBuffer,
- 1,
- &BuffImgCopy);
+ Box FullExtentBox;
+ if (pMapRegion == nullptr)
+ {
+ auto MipLevelAttribs = GetMipLevelProperties(TexDesc, MipLevel);
+ FullExtentBox.MaxX = MipLevelAttribs.LogicalWidth;
+ FullExtentBox.MaxY = MipLevelAttribs.LogicalHeight;
+ FullExtentBox.MaxZ = MipLevelAttribs.Depth;
+ pMapRegion = &FullExtentBox;
}
-
- void DeviceContextVkImpl::MapTextureSubresource( ITexture* pTexture,
- Uint32 MipLevel,
- Uint32 ArraySlice,
- MAP_TYPE MapType,
- MAP_FLAGS MapFlags,
- const Box* pMapRegion,
- MappedTextureSubresource& MappedData )
+ if (TexDesc.Usage == USAGE_DYNAMIC)
{
- TDeviceContextBase::MapTextureSubresource(pTexture, MipLevel, ArraySlice, MapType, MapFlags, pMapRegion, MappedData);
+ if (MapType != MAP_WRITE)
+ {
+ LOG_ERROR("Textures can currently only be mapped for writing in Vulkan backend");
+ MappedData = MappedTextureSubresource{};
+ return;
+ }
- TextureVkImpl& TextureVk = *ValidatedCast<TextureVkImpl>(pTexture);
- const auto& TexDesc = TextureVk.GetDesc();
- const auto& FmtAttribs = GetTextureFormatAttribs(TexDesc.Format);
+ if ((MapFlags & (MAP_FLAG_DISCARD | MAP_FLAG_DO_NOT_SYNCHRONIZE)) != 0)
+ LOG_INFO_MESSAGE_ONCE("Mapping textures with flags MAP_FLAG_DISCARD or MAP_FLAG_DO_NOT_SYNCHRONIZE has no effect in Vulkan backend");
- Box FullExtentBox;
- if (pMapRegion == nullptr)
+ auto CopyInfo = GetBufferToTextureCopyInfo(TexDesc, MipLevel, *pMapRegion);
+ const auto& DeviceLimits = m_pDevice->GetPhysicalDevice().GetProperties().limits;
+ // Source buffer offset must be multiple of 4 (18.4)
+ auto Alignment = std::max(DeviceLimits.optimalBufferCopyOffsetAlignment, VkDeviceSize{4});
+ // If the calling command's VkImage parameter is a compressed image, bufferOffset must be a multiple of
+ // the compressed texel block size in bytes (18.4)
+ if (FmtAttribs.ComponentType == COMPONENT_TYPE_COMPRESSED)
{
- auto MipLevelAttribs = GetMipLevelProperties(TexDesc, MipLevel);
- FullExtentBox.MaxX = MipLevelAttribs.LogicalWidth;
- FullExtentBox.MaxY = MipLevelAttribs.LogicalHeight;
- FullExtentBox.MaxZ = MipLevelAttribs.Depth;
- pMapRegion = &FullExtentBox;
+ Alignment = std::max(Alignment, VkDeviceSize{FmtAttribs.ComponentSize});
}
+ auto Allocation = AllocateDynamicSpace(CopyInfo.MemorySize, static_cast<Uint32>(Alignment));
+
+ MappedData.pData = reinterpret_cast<Uint8*>(Allocation.pDynamicMemMgr->GetCPUAddress()) + Allocation.AlignedOffset;
+ MappedData.Stride = CopyInfo.Stride;
+ MappedData.DepthStride = CopyInfo.DepthStride;
- if (TexDesc.Usage == USAGE_DYNAMIC)
+ auto it = m_MappedTextures.emplace(MappedTextureKey{&TextureVk, MipLevel, ArraySlice}, MappedTexture{CopyInfo, std::move(Allocation)});
+ if (!it.second)
+ LOG_ERROR_MESSAGE("Mip level ", MipLevel, ", slice ", ArraySlice, " of texture '", TexDesc.Name, "' has already been mapped");
+ }
+ else if (TexDesc.Usage == USAGE_STAGING)
+ {
+ if ((MapFlags & MAP_FLAG_DO_NOT_SYNCHRONIZE) == 0)
{
- if (MapType != MAP_WRITE)
- {
- LOG_ERROR("Textures can currently only be mapped for writing in Vulkan backend");
- MappedData = MappedTextureSubresource{};
- return;
- }
+ LOG_WARNING_MESSAGE_ONCE("Mapping staging textures is never synchronized in Vulkan backend. "
+ "Application must use fences or other synchronization methods to explicitly synchronize "
+ "access and map texture with MAP_FLAG_DO_NOT_SYNCHRONIZE flag.");
+ }
- if ((MapFlags & (MAP_FLAG_DISCARD | MAP_FLAG_DO_NOT_SYNCHRONIZE)) != 0)
- LOG_INFO_MESSAGE_ONCE("Mapping textures with flags MAP_FLAG_DISCARD or MAP_FLAG_DO_NOT_SYNCHRONIZE has no effect in Vulkan backend");
-
- auto CopyInfo = GetBufferToTextureCopyInfo(TexDesc, MipLevel, *pMapRegion);
- const auto& DeviceLimits = m_pDevice->GetPhysicalDevice().GetProperties().limits;
- // Source buffer offset must be multiple of 4 (18.4)
- auto Alignment = std::max(DeviceLimits.optimalBufferCopyOffsetAlignment, VkDeviceSize{4});
- // If the calling command's VkImage parameter is a compressed image, bufferOffset must be a multiple of
- // the compressed texel block size in bytes (18.4)
- if (FmtAttribs.ComponentType == COMPONENT_TYPE_COMPRESSED)
- {
- Alignment = std::max(Alignment, VkDeviceSize{FmtAttribs.ComponentSize});
- }
- auto Allocation = AllocateDynamicSpace(CopyInfo.MemorySize, static_cast<Uint32>(Alignment));
+ auto SubresourceOffset = GetStagingDataOffset(TexDesc, ArraySlice, MipLevel);
+ auto MipLevelAttribs = GetMipLevelProperties(TexDesc, MipLevel);
+ // address of (x,y,z) = region->bufferOffset + (((z * imageHeight) + y) * rowLength + x) * texelBlockSize; (18.4.1)
+ auto MapStartOffset = SubresourceOffset +
+ // For compressed-block formats, RowSize is the size of one compressed row.
+ // For non-compressed formats, BlockHeight is 1.
+ (pMapRegion->MinZ * MipLevelAttribs.StorageHeight + pMapRegion->MinY) / FmtAttribs.BlockHeight * MipLevelAttribs.RowSize +
+ // For non-compressed formats, BlockWidth is 1.
+ pMapRegion->MinX / FmtAttribs.BlockWidth * FmtAttribs.GetElementSize();
- MappedData.pData = reinterpret_cast<Uint8*>(Allocation.pDynamicMemMgr->GetCPUAddress()) + Allocation.AlignedOffset;
- MappedData.Stride = CopyInfo.Stride;
- MappedData.DepthStride = CopyInfo.DepthStride;
+ MappedData.pData = TextureVk.GetStagingDataCPUAddress() + MapStartOffset;
+ MappedData.Stride = MipLevelAttribs.RowSize;
+ MappedData.DepthStride = MipLevelAttribs.DepthSliceSize;
- auto it = m_MappedTextures.emplace(MappedTextureKey{&TextureVk, MipLevel, ArraySlice}, MappedTexture{CopyInfo, std::move(Allocation)});
- if(!it.second)
- LOG_ERROR_MESSAGE("Mip level ", MipLevel, ", slice ", ArraySlice, " of texture '", TexDesc.Name, "' has already been mapped");
- }
- else if (TexDesc.Usage == USAGE_STAGING)
+ if (MapType == MAP_READ)
{
- if( (MapFlags & MAP_FLAG_DO_NOT_SYNCHRONIZE) == 0 )
- {
- LOG_WARNING_MESSAGE_ONCE("Mapping staging textures is never synchronized in Vulkan backend. "
- "Application must use fences or other synchronization methods to explicitly synchronize "
- "access and map texture with MAP_FLAG_DO_NOT_SYNCHRONIZE flag.");
- }
-
- auto SubresourceOffset = GetStagingDataOffset(TexDesc, ArraySlice, MipLevel);
- auto MipLevelAttribs = GetMipLevelProperties(TexDesc, MipLevel);
- // address of (x,y,z) = region->bufferOffset + (((z * imageHeight) + y) * rowLength + x) * texelBlockSize; (18.4.1)
- auto MapStartOffset = SubresourceOffset +
- // For compressed-block formats, RowSize is the size of one compressed row.
- // For non-compressed formats, BlockHeight is 1.
- (pMapRegion->MinZ * MipLevelAttribs.StorageHeight + pMapRegion->MinY) / FmtAttribs.BlockHeight * MipLevelAttribs.RowSize +
- // For non-compressed formats, BlockWidth is 1.
- pMapRegion->MinX / FmtAttribs.BlockWidth * FmtAttribs.GetElementSize();
-
- MappedData.pData = TextureVk.GetStagingDataCPUAddress() + MapStartOffset;
- MappedData.Stride = MipLevelAttribs.RowSize;
- MappedData.DepthStride = MipLevelAttribs.DepthSliceSize;
-
- if (MapType == MAP_READ)
- {
- DEV_CHECK_ERR((TexDesc.CPUAccessFlags & CPU_ACCESS_READ), "Texture '", TexDesc.Name, "' was not created with CPU_ACCESS_READ flag and can't be mapped for reading");
- // Reaback memory is not created with HOST_COHERENT flag, so we have to explicitly invalidate the mapped range
- // to make device writes visible to CPU reads
- VERIFY_EXPR(pMapRegion->MaxZ >= 1 && pMapRegion->MaxY >= 1);
- auto BlockAlignedMaxX = Align(pMapRegion->MaxX, Uint32{FmtAttribs.BlockWidth});
- auto BlockAlignedMaxY = Align(pMapRegion->MaxY, Uint32{FmtAttribs.BlockHeight});
- auto MapEndOffset = SubresourceOffset +
- ((pMapRegion->MaxZ-1) * MipLevelAttribs.StorageHeight + (BlockAlignedMaxY - FmtAttribs.BlockHeight)) / FmtAttribs.BlockHeight * MipLevelAttribs.RowSize +
- (BlockAlignedMaxX / FmtAttribs.BlockWidth) * FmtAttribs.GetElementSize();
- TextureVk.InvalidateStagingRange(MapStartOffset, MapEndOffset - MapStartOffset);
- }
- else if (MapType == MAP_WRITE)
- {
- DEV_CHECK_ERR((TexDesc.CPUAccessFlags & CPU_ACCESS_WRITE), "Texture '", TexDesc.Name, "' was not created with CPU_ACCESS_WRITE flag and can't be mapped for writing");
- // Nothing needs to be done when mapping texture for writing
- }
+ DEV_CHECK_ERR((TexDesc.CPUAccessFlags & CPU_ACCESS_READ), "Texture '", TexDesc.Name, "' was not created with CPU_ACCESS_READ flag and can't be mapped for reading");
+ // Reaback memory is not created with HOST_COHERENT flag, so we have to explicitly invalidate the mapped range
+ // to make device writes visible to CPU reads
+ VERIFY_EXPR(pMapRegion->MaxZ >= 1 && pMapRegion->MaxY >= 1);
+ auto BlockAlignedMaxX = Align(pMapRegion->MaxX, Uint32{FmtAttribs.BlockWidth});
+ auto BlockAlignedMaxY = Align(pMapRegion->MaxY, Uint32{FmtAttribs.BlockHeight});
+ auto MapEndOffset = SubresourceOffset +
+ ((pMapRegion->MaxZ - 1) * MipLevelAttribs.StorageHeight + (BlockAlignedMaxY - FmtAttribs.BlockHeight)) / FmtAttribs.BlockHeight * MipLevelAttribs.RowSize +
+ (BlockAlignedMaxX / FmtAttribs.BlockWidth) * FmtAttribs.GetElementSize();
+ TextureVk.InvalidateStagingRange(MapStartOffset, MapEndOffset - MapStartOffset);
}
- else
+ else if (MapType == MAP_WRITE)
{
- UNSUPPORTED(GetUsageString(TexDesc.Usage), " textures cannot currently be mapped in Vulkan back-end");
+ DEV_CHECK_ERR((TexDesc.CPUAccessFlags & CPU_ACCESS_WRITE), "Texture '", TexDesc.Name, "' was not created with CPU_ACCESS_WRITE flag and can't be mapped for writing");
+ // Nothing needs to be done when mapping texture for writing
}
}
-
- void DeviceContextVkImpl::UnmapTextureSubresource(ITexture* pTexture,
- Uint32 MipLevel,
- Uint32 ArraySlice)
+ else
{
- TDeviceContextBase::UnmapTextureSubresource( pTexture, MipLevel, ArraySlice);
+ UNSUPPORTED(GetUsageString(TexDesc.Usage), " textures cannot currently be mapped in Vulkan back-end");
+ }
+}
- TextureVkImpl& TextureVk = *ValidatedCast<TextureVkImpl>(pTexture);
- const auto& TexDesc = TextureVk.GetDesc();
+void DeviceContextVkImpl::UnmapTextureSubresource(ITexture* pTexture,
+ Uint32 MipLevel,
+ Uint32 ArraySlice)
+{
+ TDeviceContextBase::UnmapTextureSubresource(pTexture, MipLevel, ArraySlice);
- if (TexDesc.Usage == USAGE_DYNAMIC)
- {
- auto UploadSpaceIt = m_MappedTextures.find(MappedTextureKey{&TextureVk, MipLevel, ArraySlice});
- if(UploadSpaceIt != m_MappedTextures.end())
- {
- auto& MappedTex = UploadSpaceIt->second;
- CopyBufferToTexture(MappedTex.Allocation.pDynamicMemMgr->GetVkBuffer(),
- static_cast<Uint32>(MappedTex.Allocation.AlignedOffset),
- MappedTex.CopyInfo.StrideInTexels,
- TextureVk,
- MappedTex.CopyInfo.Region,
- MipLevel,
- ArraySlice,
- RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
- m_MappedTextures.erase(UploadSpaceIt);
- }
- else
- {
- LOG_ERROR_MESSAGE("Failed to unmap mip level ", MipLevel, ", slice ", ArraySlice, " of texture '", TexDesc.Name, "'. The texture has either been unmapped already or has not been mapped");
- }
- }
- else if (TexDesc.Usage == USAGE_STAGING)
+ TextureVkImpl& TextureVk = *ValidatedCast<TextureVkImpl>(pTexture);
+ const auto& TexDesc = TextureVk.GetDesc();
+
+ if (TexDesc.Usage == USAGE_DYNAMIC)
+ {
+ auto UploadSpaceIt = m_MappedTextures.find(MappedTextureKey{&TextureVk, MipLevel, ArraySlice});
+ if (UploadSpaceIt != m_MappedTextures.end())
{
- if (TexDesc.CPUAccessFlags & CPU_ACCESS_READ)
- {
- // Nothing needs to be done
- }
- else if (TexDesc.CPUAccessFlags & CPU_ACCESS_WRITE)
- {
- // Upload textures are currently created with VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, so
- // there is no need to explicitly flush the mapped range.
- }
+ auto& MappedTex = UploadSpaceIt->second;
+ CopyBufferToTexture(MappedTex.Allocation.pDynamicMemMgr->GetVkBuffer(),
+ static_cast<Uint32>(MappedTex.Allocation.AlignedOffset),
+ MappedTex.CopyInfo.StrideInTexels,
+ TextureVk,
+ MappedTex.CopyInfo.Region,
+ MipLevel,
+ ArraySlice,
+ RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
+ m_MappedTextures.erase(UploadSpaceIt);
}
else
{
- UNSUPPORTED(GetUsageString(TexDesc.Usage), " textures cannot currently be mapped in Vulkan back-end");
+ LOG_ERROR_MESSAGE("Failed to unmap mip level ", MipLevel, ", slice ", ArraySlice, " of texture '", TexDesc.Name, "'. The texture has either been unmapped already or has not been mapped");
}
}
-
- void DeviceContextVkImpl::FinishCommandList(class ICommandList **ppCommandList)
+ else if (TexDesc.Usage == USAGE_STAGING)
{
- if (m_CommandBuffer.GetState().RenderPass != VK_NULL_HANDLE)
+ if (TexDesc.CPUAccessFlags & CPU_ACCESS_READ)
{
- m_CommandBuffer.EndRenderPass();
+ // Nothing needs to be done
+ }
+ else if (TexDesc.CPUAccessFlags & CPU_ACCESS_WRITE)
+ {
+ // Upload textures are currently created with VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, so
+ // there is no need to explicitly flush the mapped range.
}
+ }
+ else
+ {
+ UNSUPPORTED(GetUsageString(TexDesc.Usage), " textures cannot currently be mapped in Vulkan back-end");
+ }
+}
- auto vkCmdBuff = m_CommandBuffer.GetVkCmdBuffer();
- auto err = vkEndCommandBuffer(vkCmdBuff);
- DEV_CHECK_ERR(err == VK_SUCCESS, "Failed to end command buffer"); (void)err;
+void DeviceContextVkImpl::FinishCommandList(class ICommandList** ppCommandList)
+{
+ if (m_CommandBuffer.GetState().RenderPass != VK_NULL_HANDLE)
+ {
+ m_CommandBuffer.EndRenderPass();
+ }
- CommandListVkImpl *pCmdListVk( NEW_RC_OBJ(m_CmdListAllocator, "CommandListVkImpl instance", CommandListVkImpl)
- (m_pDevice, this, vkCmdBuff) );
- pCmdListVk->QueryInterface( IID_CommandList, reinterpret_cast<IObject**>(ppCommandList) );
+ auto vkCmdBuff = m_CommandBuffer.GetVkCmdBuffer();
+ auto err = vkEndCommandBuffer(vkCmdBuff);
+ DEV_CHECK_ERR(err == VK_SUCCESS, "Failed to end command buffer");
+ (void)err;
- m_CommandBuffer.Reset();
- m_State = ContextState{};
- m_DescrSetBindInfo.Reset();
- m_pPipelineState = nullptr;
+ CommandListVkImpl* pCmdListVk(NEW_RC_OBJ(m_CmdListAllocator, "CommandListVkImpl instance", CommandListVkImpl)(m_pDevice, this, vkCmdBuff));
+ pCmdListVk->QueryInterface(IID_CommandList, reinterpret_cast<IObject**>(ppCommandList));
- InvalidateState();
- }
+ m_CommandBuffer.Reset();
+ m_State = ContextState{};
+ m_DescrSetBindInfo.Reset();
+ m_pPipelineState = nullptr;
+
+ InvalidateState();
+}
- void DeviceContextVkImpl::ExecuteCommandList(class ICommandList *pCommandList)
+void DeviceContextVkImpl::ExecuteCommandList(class ICommandList* pCommandList)
+{
+ if (m_bIsDeferred)
{
- if (m_bIsDeferred)
- {
- LOG_ERROR_MESSAGE("Only immediate context can execute command list");
- return;
- }
+ LOG_ERROR_MESSAGE("Only immediate context can execute command list");
+ return;
+ }
- Flush();
+ Flush();
- InvalidateState();
+ InvalidateState();
- CommandListVkImpl* pCmdListVk = ValidatedCast<CommandListVkImpl>(pCommandList);
- VkCommandBuffer vkCmdBuff = VK_NULL_HANDLE;
- RefCntAutoPtr<IDeviceContext> pDeferredCtx;
- pCmdListVk->Close(vkCmdBuff, pDeferredCtx);
- VERIFY(vkCmdBuff != VK_NULL_HANDLE, "Trying to execute empty command buffer");
- VERIFY_EXPR(pDeferredCtx);
- VkSubmitInfo SubmitInfo = {};
- SubmitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
- SubmitInfo.pNext = nullptr;
- SubmitInfo.commandBufferCount = 1;
- SubmitInfo.pCommandBuffers = &vkCmdBuff;
- VERIFY_EXPR(m_PendingFences.empty());
- auto pDeferredCtxVkImpl = pDeferredCtx.RawPtr<DeviceContextVkImpl>();
- auto SubmittedFenceValue = m_pDevice->ExecuteCommandBuffer(m_CommandQueueId, SubmitInfo, this, nullptr);
- // Set the bit in the deferred context cmd queue mask corresponding to cmd queue of this context
- pDeferredCtxVkImpl->m_SubmittedBuffersCmdQueueMask |= Uint64{1} << m_CommandQueueId;
- // It is OK to dispose command buffer from another thread. We are not going to
- // record any commands and only need to add the buffer to the queue
- pDeferredCtxVkImpl->DisposeVkCmdBuffer(m_CommandQueueId, vkCmdBuff, SubmittedFenceValue);
- }
+ CommandListVkImpl* pCmdListVk = ValidatedCast<CommandListVkImpl>(pCommandList);
+ VkCommandBuffer vkCmdBuff = VK_NULL_HANDLE;
- void DeviceContextVkImpl::SignalFence(IFence* pFence, Uint64 Value)
- {
- VERIFY(!m_bIsDeferred, "Fence can only be signaled from immediate context");
- m_PendingFences.emplace_back( std::make_pair(Value, pFence) );
- }
+ RefCntAutoPtr<IDeviceContext> pDeferredCtx;
+ pCmdListVk->Close(vkCmdBuff, pDeferredCtx);
+ VERIFY(vkCmdBuff != VK_NULL_HANDLE, "Trying to execute empty command buffer");
+ VERIFY_EXPR(pDeferredCtx);
+ VkSubmitInfo SubmitInfo = {};
+
+ SubmitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
+ SubmitInfo.pNext = nullptr;
+ SubmitInfo.commandBufferCount = 1;
+ SubmitInfo.pCommandBuffers = &vkCmdBuff;
+ VERIFY_EXPR(m_PendingFences.empty());
+ auto pDeferredCtxVkImpl = pDeferredCtx.RawPtr<DeviceContextVkImpl>();
+ auto SubmittedFenceValue = m_pDevice->ExecuteCommandBuffer(m_CommandQueueId, SubmitInfo, this, nullptr);
+ // Set the bit in the deferred context cmd queue mask corresponding to cmd queue of this context
+ pDeferredCtxVkImpl->m_SubmittedBuffersCmdQueueMask |= Uint64{1} << m_CommandQueueId;
+ // It is OK to dispose command buffer from another thread. We are not going to
+ // record any commands and only need to add the buffer to the queue
+ pDeferredCtxVkImpl->DisposeVkCmdBuffer(m_CommandQueueId, vkCmdBuff, SubmittedFenceValue);
+}
+
+void DeviceContextVkImpl::SignalFence(IFence* pFence, Uint64 Value)
+{
+ VERIFY(!m_bIsDeferred, "Fence can only be signaled from immediate context");
+ m_PendingFences.emplace_back(std::make_pair(Value, pFence));
+}
+
+void DeviceContextVkImpl::WaitForFence(IFence* pFence, Uint64 Value, bool FlushContext)
+{
+ VERIFY(!m_bIsDeferred, "Fence can only be waited from immediate context");
+ if (FlushContext)
+ Flush();
+ auto* pFenceVk = ValidatedCast<FenceVkImpl>(pFence);
+ pFenceVk->Wait(Value);
+}
+
+void DeviceContextVkImpl::WaitForIdle()
+{
+ VERIFY(!m_bIsDeferred, "Only immediate contexts can be idled");
+ Flush();
+ m_pDevice->IdleCommandQueue(m_CommandQueueId, true);
+}
- void DeviceContextVkImpl::WaitForFence(IFence* pFence, Uint64 Value, bool FlushContext)
+void DeviceContextVkImpl::TransitionImageLayout(ITexture* pTexture, VkImageLayout NewLayout)
+{
+ VERIFY_EXPR(pTexture != nullptr);
+ auto pTextureVk = ValidatedCast<TextureVkImpl>(pTexture);
+ if (!pTextureVk->IsInKnownState())
{
- VERIFY(!m_bIsDeferred, "Fence can only be waited from immediate context");
- if (FlushContext)
- Flush();
- auto* pFenceVk = ValidatedCast<FenceVkImpl>(pFence);
- pFenceVk->Wait(Value);
+ LOG_ERROR_MESSAGE("Failed to transition layout for texture '", pTextureVk->GetDesc().Name, "' because the texture state is unknown");
+ return;
}
-
- void DeviceContextVkImpl::WaitForIdle()
+ auto NewState = VkImageLayoutToResourceState(NewLayout);
+ if (!pTextureVk->CheckState(NewState))
{
- VERIFY(!m_bIsDeferred, "Only immediate contexts can be idled");
- Flush();
- m_pDevice->IdleCommandQueue(m_CommandQueueId, true);
+ TransitionTextureState(*pTextureVk, RESOURCE_STATE_UNKNOWN, NewState, true);
}
+}
- void DeviceContextVkImpl::TransitionImageLayout(ITexture* pTexture, VkImageLayout NewLayout)
+void DeviceContextVkImpl::TransitionTextureState(TextureVkImpl& TextureVk,
+ RESOURCE_STATE OldState,
+ RESOURCE_STATE NewState,
+ bool UpdateTextureState,
+ VkImageSubresourceRange* pSubresRange /* = nullptr*/)
+{
+ if (OldState == RESOURCE_STATE_UNKNOWN)
{
- VERIFY_EXPR(pTexture != nullptr);
- auto pTextureVk = ValidatedCast<TextureVkImpl>(pTexture);
- if (!pTextureVk->IsInKnownState())
+ if (TextureVk.IsInKnownState())
{
- LOG_ERROR_MESSAGE("Failed to transition layout for texture '", pTextureVk->GetDesc().Name, "' because the texture state is unknown");
- return;
+ OldState = TextureVk.GetState();
}
- auto NewState = VkImageLayoutToResourceState(NewLayout);
- if (!pTextureVk->CheckState(NewState))
+ else
{
- TransitionTextureState(*pTextureVk, RESOURCE_STATE_UNKNOWN, NewState, true);
+ LOG_ERROR_MESSAGE("Failed to transition the state of texture '", TextureVk.GetDesc().Name, "' because the state is unknown and is not explicitly specified.");
+ return;
}
}
-
- void DeviceContextVkImpl::TransitionTextureState(TextureVkImpl& TextureVk,
- RESOURCE_STATE OldState,
- RESOURCE_STATE NewState,
- bool UpdateTextureState,
- VkImageSubresourceRange* pSubresRange/* = nullptr*/)
+ else
{
- if (OldState == RESOURCE_STATE_UNKNOWN)
- {
- if (TextureVk.IsInKnownState())
- {
- OldState = TextureVk.GetState();
- }
- else
- {
- LOG_ERROR_MESSAGE("Failed to transition the state of texture '", TextureVk.GetDesc().Name, "' because the state is unknown and is not explicitly specified.");
- return;
- }
- }
- else
+ if (TextureVk.IsInKnownState() && TextureVk.GetState() != OldState)
{
- if (TextureVk.IsInKnownState() && TextureVk.GetState() != OldState)
- {
- LOG_ERROR_MESSAGE("The state ", GetResourceStateString(TextureVk.GetState()), " of texture '",
- TextureVk.GetDesc().Name, "' does not match the old state ", GetResourceStateString(OldState),
- " specified by the barrier");
- }
+ LOG_ERROR_MESSAGE("The state ", GetResourceStateString(TextureVk.GetState()), " of texture '",
+ TextureVk.GetDesc().Name, "' does not match the old state ", GetResourceStateString(OldState),
+ " specified by the barrier");
}
+ }
- EnsureVkCmdBuffer();
+ EnsureVkCmdBuffer();
- auto vkImg = TextureVk.GetVkImage();
- VkImageSubresourceRange FullSubresRange;
- if (pSubresRange == nullptr)
- {
- pSubresRange = &FullSubresRange;
- FullSubresRange.aspectMask = 0;
- FullSubresRange.baseArrayLayer = 0;
- FullSubresRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
- FullSubresRange.baseMipLevel = 0;
- FullSubresRange.levelCount = VK_REMAINING_MIP_LEVELS;
- }
+ auto vkImg = TextureVk.GetVkImage();
- if (pSubresRange->aspectMask == 0)
- {
- const auto& TexDesc = TextureVk.GetDesc();
- const auto& FmtAttribs = GetTextureFormatAttribs(TexDesc.Format);
- if (FmtAttribs.ComponentType == COMPONENT_TYPE_DEPTH)
- pSubresRange->aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
- else if (FmtAttribs.ComponentType == COMPONENT_TYPE_DEPTH_STENCIL)
- {
- // If image has a depth / stencil format with both depth and stencil components, then the
- // aspectMask member of subresourceRange must include both VK_IMAGE_ASPECT_DEPTH_BIT and
- // VK_IMAGE_ASPECT_STENCIL_BIT (6.7.3)
- pSubresRange->aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
- }
- else
- pSubresRange->aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
- }
+ VkImageSubresourceRange FullSubresRange;
+ if (pSubresRange == nullptr)
+ {
+ pSubresRange = &FullSubresRange;
+
+ FullSubresRange.aspectMask = 0;
+ FullSubresRange.baseArrayLayer = 0;
+ FullSubresRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
+ FullSubresRange.baseMipLevel = 0;
+ FullSubresRange.levelCount = VK_REMAINING_MIP_LEVELS;
+ }
- // Note that when both old and new states are RESOURCE_STATE_UNORDERED_ACCESS, we need to execute UAV barrier
- // to make sure that all UAV writes are complete and visible.
- auto OldLayout = ResourceStateToVkImageLayout(OldState);
- auto NewLayout = ResourceStateToVkImageLayout(NewState);
- m_CommandBuffer.TransitionImageLayout(vkImg, OldLayout, NewLayout, *pSubresRange);
- if(UpdateTextureState)
+ if (pSubresRange->aspectMask == 0)
+ {
+ const auto& TexDesc = TextureVk.GetDesc();
+ const auto& FmtAttribs = GetTextureFormatAttribs(TexDesc.Format);
+ if (FmtAttribs.ComponentType == COMPONENT_TYPE_DEPTH)
+ pSubresRange->aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
+ else if (FmtAttribs.ComponentType == COMPONENT_TYPE_DEPTH_STENCIL)
{
- TextureVk.SetState(NewState);
- VERIFY_EXPR(TextureVk.GetLayout() == NewLayout);
+ // If image has a depth / stencil format with both depth and stencil components, then the
+ // aspectMask member of subresourceRange must include both VK_IMAGE_ASPECT_DEPTH_BIT and
+ // VK_IMAGE_ASPECT_STENCIL_BIT (6.7.3)
+ pSubresRange->aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
}
+ else
+ pSubresRange->aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
}
- void DeviceContextVkImpl::TransitionOrVerifyTextureState(TextureVkImpl& Texture,
- RESOURCE_STATE_TRANSITION_MODE TransitionMode,
- RESOURCE_STATE RequiredState,
- VkImageLayout ExpectedLayout,
- const char* OperationName)
+ // Note that when both old and new states are RESOURCE_STATE_UNORDERED_ACCESS, we need to execute UAV barrier
+ // to make sure that all UAV writes are complete and visible.
+ auto OldLayout = ResourceStateToVkImageLayout(OldState);
+ auto NewLayout = ResourceStateToVkImageLayout(NewState);
+ m_CommandBuffer.TransitionImageLayout(vkImg, OldLayout, NewLayout, *pSubresRange);
+ if (UpdateTextureState)
{
- if (TransitionMode == RESOURCE_STATE_TRANSITION_MODE_TRANSITION)
+ TextureVk.SetState(NewState);
+ VERIFY_EXPR(TextureVk.GetLayout() == NewLayout);
+ }
+}
+
+void DeviceContextVkImpl::TransitionOrVerifyTextureState(TextureVkImpl& Texture,
+ RESOURCE_STATE_TRANSITION_MODE TransitionMode,
+ RESOURCE_STATE RequiredState,
+ VkImageLayout ExpectedLayout,
+ const char* OperationName)
+{
+ if (TransitionMode == RESOURCE_STATE_TRANSITION_MODE_TRANSITION)
+ {
+ if (Texture.IsInKnownState())
{
- if (Texture.IsInKnownState())
+ if (!Texture.CheckState(RequiredState))
{
- if (!Texture.CheckState(RequiredState))
- {
- TransitionTextureState(Texture, RESOURCE_STATE_UNKNOWN, RequiredState, true);
- }
- VERIFY_EXPR(Texture.GetLayout() == ExpectedLayout);
+ TransitionTextureState(Texture, RESOURCE_STATE_UNKNOWN, RequiredState, true);
}
+ VERIFY_EXPR(Texture.GetLayout() == ExpectedLayout);
}
+ }
#ifdef DEVELOPMENT
- else if (TransitionMode == RESOURCE_STATE_TRANSITION_MODE_VERIFY)
- {
- DvpVerifyTextureState(Texture, RequiredState, OperationName);
- }
-#endif
+ else if (TransitionMode == RESOURCE_STATE_TRANSITION_MODE_VERIFY)
+ {
+ DvpVerifyTextureState(Texture, RequiredState, OperationName);
}
+#endif
+}
- void DeviceContextVkImpl::TransitionImageLayout(TextureVkImpl& TextureVk, VkImageLayout OldLayout, VkImageLayout NewLayout, const VkImageSubresourceRange& SubresRange)
- {
- // Note that the method may be used to transition texture subresources when global texture state is not altered,
- // so the debug check below can't be used
- // VERIFY(!TextureVk.IsInKnownState() || TextureVk.GetLayout() != NewLayout, "The texture is already transitioned to correct layout");
+void DeviceContextVkImpl::TransitionImageLayout(TextureVkImpl& TextureVk, VkImageLayout OldLayout, VkImageLayout NewLayout, const VkImageSubresourceRange& SubresRange)
+{
+ // Note that the method may be used to transition texture subresources when global texture state is not altered,
+ // so the debug check below can't be used
+ // VERIFY(!TextureVk.IsInKnownState() || TextureVk.GetLayout() != NewLayout, "The texture is already transitioned to correct layout");
+
+ VERIFY(OldLayout != NewLayout, "Old and new layouts are the same");
+ EnsureVkCmdBuffer();
+ auto vkImg = TextureVk.GetVkImage();
+ m_CommandBuffer.TransitionImageLayout(vkImg, OldLayout, NewLayout, SubresRange);
+}
- VERIFY(OldLayout != NewLayout, "Old and new layouts are the same");
- EnsureVkCmdBuffer();
- auto vkImg = TextureVk.GetVkImage();
- m_CommandBuffer.TransitionImageLayout(vkImg, OldLayout, NewLayout, SubresRange);
+void DeviceContextVkImpl::BufferMemoryBarrier(IBuffer* pBuffer, VkAccessFlags NewAccessFlags)
+{
+ VERIFY_EXPR(pBuffer != nullptr);
+ auto pBuffVk = ValidatedCast<BufferVkImpl>(pBuffer);
+ if (!pBuffVk->IsInKnownState())
+ {
+ LOG_ERROR_MESSAGE("Failed to execute buffer memory barrier for buffer '", pBuffVk->GetDesc().Name, "' because the buffer state is unknown");
+ return;
+ }
+ auto NewState = VkAccessFlagsToResourceStates(NewAccessFlags);
+ if ((pBuffVk->GetState() & NewState) != NewState)
+ {
+ TransitionBufferState(*pBuffVk, RESOURCE_STATE_UNKNOWN, NewState, true);
}
+}
- void DeviceContextVkImpl::BufferMemoryBarrier(IBuffer* pBuffer, VkAccessFlags NewAccessFlags)
+void DeviceContextVkImpl::TransitionBufferState(BufferVkImpl& BufferVk, RESOURCE_STATE OldState, RESOURCE_STATE NewState, bool UpdateBufferState)
+{
+ if (OldState == RESOURCE_STATE_UNKNOWN)
{
- VERIFY_EXPR(pBuffer != nullptr);
- auto pBuffVk = ValidatedCast<BufferVkImpl>(pBuffer);
- if (!pBuffVk->IsInKnownState())
+ if (BufferVk.IsInKnownState())
{
- LOG_ERROR_MESSAGE("Failed to execute buffer memory barrier for buffer '", pBuffVk->GetDesc().Name, "' because the buffer state is unknown");
- return;
+ OldState = BufferVk.GetState();
}
- auto NewState = VkAccessFlagsToResourceStates(NewAccessFlags);
- if ((pBuffVk->GetState() & NewState) != NewState)
+ else
{
- TransitionBufferState(*pBuffVk, RESOURCE_STATE_UNKNOWN, NewState, true);
+ LOG_ERROR_MESSAGE("Failed to transition the state of buffer '", BufferVk.GetDesc().Name, "' because the buffer state is unknown and is not explicitly specified");
+ return;
}
}
-
- void DeviceContextVkImpl::TransitionBufferState(BufferVkImpl& BufferVk, RESOURCE_STATE OldState, RESOURCE_STATE NewState, bool UpdateBufferState)
+ else
{
- if (OldState == RESOURCE_STATE_UNKNOWN)
- {
- if (BufferVk.IsInKnownState())
- {
- OldState = BufferVk.GetState();
- }
- else
- {
- LOG_ERROR_MESSAGE("Failed to transition the state of buffer '", BufferVk.GetDesc().Name, "' because the buffer state is unknown and is not explicitly specified");
- return;
- }
- }
- else
+ if (BufferVk.IsInKnownState() && BufferVk.GetState() != OldState)
{
- if (BufferVk.IsInKnownState() && BufferVk.GetState() != OldState)
- {
- LOG_ERROR_MESSAGE("The state ", GetResourceStateString(BufferVk.GetState()), " of buffer '",
- BufferVk.GetDesc().Name, "' does not match the old state ", GetResourceStateString(OldState),
- " specified by the barrier");
- }
+ LOG_ERROR_MESSAGE("The state ", GetResourceStateString(BufferVk.GetState()), " of buffer '",
+ BufferVk.GetDesc().Name, "' does not match the old state ", GetResourceStateString(OldState),
+ " specified by the barrier");
}
+ }
+
+ // When both old and new states are RESOURCE_STATE_UNORDERED_ACCESS, we need to execute UAV barrier
+ // to make sure that all UAV writes are complete and visible.
+ if (((OldState & NewState) != NewState) || NewState == RESOURCE_STATE_UNORDERED_ACCESS)
+ {
+ DEV_CHECK_ERR(BufferVk.m_VulkanBuffer != VK_NULL_HANDLE, "Cannot transition suballocated buffer");
+ VERIFY_EXPR(BufferVk.GetDynamicOffset(m_ContextId, this) == 0);
- // When both old and new states are RESOURCE_STATE_UNORDERED_ACCESS, we need to execute UAV barrier
- // to make sure that all UAV writes are complete and visible.
- if (((OldState & NewState) != NewState) || NewState == RESOURCE_STATE_UNORDERED_ACCESS)
+ EnsureVkCmdBuffer();
+ auto vkBuff = BufferVk.GetVkBuffer();
+ auto OldAccessFlags = ResourceStateFlagsToVkAccessFlags(OldState);
+ auto NewAccessFlags = ResourceStateFlagsToVkAccessFlags(NewState);
+ m_CommandBuffer.BufferMemoryBarrier(vkBuff, OldAccessFlags, NewAccessFlags);
+ if (UpdateBufferState)
{
- DEV_CHECK_ERR(BufferVk.m_VulkanBuffer != VK_NULL_HANDLE, "Cannot transition suballocated buffer");
- VERIFY_EXPR(BufferVk.GetDynamicOffset(m_ContextId, this) == 0);
-
- EnsureVkCmdBuffer();
- auto vkBuff = BufferVk.GetVkBuffer();
- auto OldAccessFlags = ResourceStateFlagsToVkAccessFlags(OldState);
- auto NewAccessFlags = ResourceStateFlagsToVkAccessFlags(NewState);
- m_CommandBuffer.BufferMemoryBarrier(vkBuff, OldAccessFlags, NewAccessFlags);
- if (UpdateBufferState)
- {
- BufferVk.SetState(NewState);
- }
+ BufferVk.SetState(NewState);
}
}
+}
- void DeviceContextVkImpl::TransitionOrVerifyBufferState(BufferVkImpl& Buffer,
- RESOURCE_STATE_TRANSITION_MODE TransitionMode,
- RESOURCE_STATE RequiredState,
- VkAccessFlagBits ExpectedAccessFlags,
- const char* OperationName)
+void DeviceContextVkImpl::TransitionOrVerifyBufferState(BufferVkImpl& Buffer,
+ RESOURCE_STATE_TRANSITION_MODE TransitionMode,
+ RESOURCE_STATE RequiredState,
+ VkAccessFlagBits ExpectedAccessFlags,
+ const char* OperationName)
+{
+ if (TransitionMode == RESOURCE_STATE_TRANSITION_MODE_TRANSITION)
{
- if (TransitionMode == RESOURCE_STATE_TRANSITION_MODE_TRANSITION)
+ if (Buffer.IsInKnownState())
{
- if (Buffer.IsInKnownState())
+ if (!Buffer.CheckState(RequiredState))
{
- if (!Buffer.CheckState(RequiredState))
- {
- TransitionBufferState(Buffer, RESOURCE_STATE_UNKNOWN, RequiredState, true);
- }
- VERIFY_EXPR(Buffer.CheckAccessFlags(ExpectedAccessFlags));
+ TransitionBufferState(Buffer, RESOURCE_STATE_UNKNOWN, RequiredState, true);
}
+ VERIFY_EXPR(Buffer.CheckAccessFlags(ExpectedAccessFlags));
}
+ }
#ifdef DEVELOPMENT
- else if (TransitionMode == RESOURCE_STATE_TRANSITION_MODE_VERIFY)
- {
- DvpVerifyBufferState(Buffer, RequiredState, OperationName);
- }
-#endif
+ else if (TransitionMode == RESOURCE_STATE_TRANSITION_MODE_VERIFY)
+ {
+ DvpVerifyBufferState(Buffer, RequiredState, OperationName);
}
+#endif
+}
- VulkanDynamicAllocation DeviceContextVkImpl::AllocateDynamicSpace(Uint32 SizeInBytes, Uint32 Alignment)
- {
- auto DynAlloc = m_DynamicHeap.Allocate(SizeInBytes, Alignment);
+VulkanDynamicAllocation DeviceContextVkImpl::AllocateDynamicSpace(Uint32 SizeInBytes, Uint32 Alignment)
+{
+ auto DynAlloc = m_DynamicHeap.Allocate(SizeInBytes, Alignment);
#ifdef DEVELOPMENT
- DynAlloc.dvpFrameNumber = m_ContextFrameNumber;
+ DynAlloc.dvpFrameNumber = m_ContextFrameNumber;
#endif
- return DynAlloc;
- }
+ return DynAlloc;
+}
- void DeviceContextVkImpl::TransitionResourceStates(Uint32 BarrierCount, StateTransitionDesc* pResourceBarriers)
- {
- if (BarrierCount == 0)
- return;
+void DeviceContextVkImpl::TransitionResourceStates(Uint32 BarrierCount, StateTransitionDesc* pResourceBarriers)
+{
+ if (BarrierCount == 0)
+ return;
- EnsureVkCmdBuffer();
+ EnsureVkCmdBuffer();
- for(Uint32 i=0; i < BarrierCount; ++i)
- {
- const auto& Barrier = pResourceBarriers[i];
+ for (Uint32 i = 0; i < BarrierCount; ++i)
+ {
+ const auto& Barrier = pResourceBarriers[i];
#ifdef DEVELOPMENT
- DvpVerifyStateTransitionDesc(Barrier);
+ DvpVerifyStateTransitionDesc(Barrier);
#endif
- if (Barrier.TransitionType == STATE_TRANSITION_TYPE_BEGIN)
- {
- // Skip begin-split barriers
- VERIFY(!Barrier.UpdateResourceState, "Resource state can't be updated in begin-split barrier");
- continue;
- }
- VERIFY(Barrier.TransitionType == STATE_TRANSITION_TYPE_IMMEDIATE || Barrier.TransitionType == STATE_TRANSITION_TYPE_END, "Unexpected barrier type");
-
- if (Barrier.pTexture)
- {
- auto* pTextureVkImpl = ValidatedCast<TextureVkImpl>(Barrier.pTexture);
- VkImageSubresourceRange SubResRange;
- SubResRange.aspectMask = 0;
- SubResRange.baseMipLevel = Barrier.FirstMipLevel;
- SubResRange.levelCount = (Barrier.MipLevelsCount == StateTransitionDesc::RemainingMipLevels) ? VK_REMAINING_MIP_LEVELS : Barrier.MipLevelsCount;
- SubResRange.baseArrayLayer = Barrier.FirstArraySlice;
- SubResRange.layerCount = (Barrier.ArraySliceCount == StateTransitionDesc::RemainingArraySlices) ? VK_REMAINING_ARRAY_LAYERS : Barrier.ArraySliceCount;
- TransitionTextureState(*pTextureVkImpl, Barrier.OldState, Barrier.NewState, Barrier.UpdateResourceState, &SubResRange);
- }
- else
- {
- VERIFY_EXPR(Barrier.pBuffer != nullptr);
- auto* pBufferVkImpl = ValidatedCast<BufferVkImpl>(Barrier.pBuffer);
- TransitionBufferState(*pBufferVkImpl, Barrier.OldState, Barrier.NewState, Barrier.UpdateResourceState);
- }
+ if (Barrier.TransitionType == STATE_TRANSITION_TYPE_BEGIN)
+ {
+ // Skip begin-split barriers
+ VERIFY(!Barrier.UpdateResourceState, "Resource state can't be updated in begin-split barrier");
+ continue;
}
- }
-
- void DeviceContextVkImpl::ResolveTextureSubresource(ITexture* pSrcTexture,
- ITexture* pDstTexture,
- const ResolveTextureSubresourceAttribs& ResolveAttribs)
- {
- TDeviceContextBase::ResolveTextureSubresource(pSrcTexture, pDstTexture, ResolveAttribs);
+ VERIFY(Barrier.TransitionType == STATE_TRANSITION_TYPE_IMMEDIATE || Barrier.TransitionType == STATE_TRANSITION_TYPE_END, "Unexpected barrier type");
- auto* pSrcTexVk = ValidatedCast<TextureVkImpl>(pSrcTexture);
- auto* pDstTexVk = ValidatedCast<TextureVkImpl>(pDstTexture);
- const auto& SrcTexDesc = pSrcTexVk->GetDesc();
- const auto& DstTexDesc = pDstTexVk->GetDesc();
-
- DEV_CHECK_ERR(SrcTexDesc.Format == DstTexDesc.Format, "Vulkan requires that source and destination textures of a resolve operation "
- "have the same format (18.6)");(void)DstTexDesc;
-
- EnsureVkCmdBuffer();
- // srcImageLayout must be VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL or VK_IMAGE_LAYOUT_GENERAL (18.6)
- TransitionOrVerifyTextureState(*pSrcTexVk, ResolveAttribs.SrcTextureTransitionMode, RESOURCE_STATE_RESOLVE_SOURCE, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
- "Resolving multi-sampled texture (DeviceContextVkImpl::ResolveTextureSubresource)");
-
- // dstImageLayout must be VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL or VK_IMAGE_LAYOUT_GENERAL (18.6)
- TransitionOrVerifyTextureState(*pDstTexVk, ResolveAttribs.DstTextureTransitionMode, RESOURCE_STATE_RESOLVE_DEST, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
- "Resolving multi-sampled texture (DeviceContextVkImpl::ResolveTextureSubresource)");
-
- const auto& ResolveFmtAttribs = GetTextureFormatAttribs(SrcTexDesc.Format);
- DEV_CHECK_ERR(ResolveFmtAttribs.ComponentType != COMPONENT_TYPE_DEPTH && ResolveFmtAttribs.ComponentType != COMPONENT_TYPE_DEPTH_STENCIL,
- "Vulkan only allows resolve operation for color formats");(void)ResolveFmtAttribs;
- // The aspectMask member of srcSubresource and dstSubresource must only contain VK_IMAGE_ASPECT_COLOR_BIT (18.6)
- VkImageAspectFlags aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
-
- VkImageResolve ResolveRegion;
- ResolveRegion.srcSubresource.baseArrayLayer = ResolveAttribs.SrcSlice;
- ResolveRegion.srcSubresource.layerCount = 1;
- ResolveRegion.srcSubresource.mipLevel = ResolveAttribs.SrcMipLevel;
- ResolveRegion.srcSubresource.aspectMask = aspectMask;
-
- ResolveRegion.dstSubresource.baseArrayLayer = ResolveAttribs.DstSlice;
- ResolveRegion.dstSubresource.layerCount = 1;
- ResolveRegion.dstSubresource.mipLevel = ResolveAttribs.DstMipLevel;
- ResolveRegion.dstSubresource.aspectMask = aspectMask;
-
- ResolveRegion.srcOffset = VkOffset3D{};
- ResolveRegion.dstOffset = VkOffset3D{};
- const auto& MipAttribs = GetMipLevelProperties(SrcTexDesc, ResolveAttribs.SrcMipLevel);
- ResolveRegion.extent = VkExtent3D
- {
- static_cast<uint32_t>(MipAttribs.LogicalWidth),
- static_cast<uint32_t>(MipAttribs.LogicalHeight),
- static_cast<uint32_t>(MipAttribs.Depth)
- };
+ if (Barrier.pTexture)
+ {
+ auto* pTextureVkImpl = ValidatedCast<TextureVkImpl>(Barrier.pTexture);
- m_CommandBuffer.ResolveImage(pSrcTexVk->GetVkImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
- pDstTexVk->GetVkImage(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
- 1, &ResolveRegion);
+ VkImageSubresourceRange SubResRange;
+ SubResRange.aspectMask = 0;
+ SubResRange.baseMipLevel = Barrier.FirstMipLevel;
+ SubResRange.levelCount = (Barrier.MipLevelsCount == StateTransitionDesc::RemainingMipLevels) ? VK_REMAINING_MIP_LEVELS : Barrier.MipLevelsCount;
+ SubResRange.baseArrayLayer = Barrier.FirstArraySlice;
+ SubResRange.layerCount = (Barrier.ArraySliceCount == StateTransitionDesc::RemainingArraySlices) ? VK_REMAINING_ARRAY_LAYERS : Barrier.ArraySliceCount;
+ TransitionTextureState(*pTextureVkImpl, Barrier.OldState, Barrier.NewState, Barrier.UpdateResourceState, &SubResRange);
+ }
+ else
+ {
+ VERIFY_EXPR(Barrier.pBuffer != nullptr);
+ auto* pBufferVkImpl = ValidatedCast<BufferVkImpl>(Barrier.pBuffer);
+ TransitionBufferState(*pBufferVkImpl, Barrier.OldState, Barrier.NewState, Barrier.UpdateResourceState);
+ }
}
}
+
+void DeviceContextVkImpl::ResolveTextureSubresource(ITexture* pSrcTexture,
+ ITexture* pDstTexture,
+ const ResolveTextureSubresourceAttribs& ResolveAttribs)
+{
+ TDeviceContextBase::ResolveTextureSubresource(pSrcTexture, pDstTexture, ResolveAttribs);
+
+ auto* pSrcTexVk = ValidatedCast<TextureVkImpl>(pSrcTexture);
+ auto* pDstTexVk = ValidatedCast<TextureVkImpl>(pDstTexture);
+ const auto& SrcTexDesc = pSrcTexVk->GetDesc();
+ const auto& DstTexDesc = pDstTexVk->GetDesc();
+
+ DEV_CHECK_ERR(SrcTexDesc.Format == DstTexDesc.Format, "Vulkan requires that source and destination textures of a resolve operation "
+ "have the same format (18.6)");
+ (void)DstTexDesc;
+
+ EnsureVkCmdBuffer();
+ // srcImageLayout must be VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL or VK_IMAGE_LAYOUT_GENERAL (18.6)
+ TransitionOrVerifyTextureState(*pSrcTexVk, ResolveAttribs.SrcTextureTransitionMode, RESOURCE_STATE_RESOLVE_SOURCE, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+ "Resolving multi-sampled texture (DeviceContextVkImpl::ResolveTextureSubresource)");
+
+ // dstImageLayout must be VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL or VK_IMAGE_LAYOUT_GENERAL (18.6)
+ TransitionOrVerifyTextureState(*pDstTexVk, ResolveAttribs.DstTextureTransitionMode, RESOURCE_STATE_RESOLVE_DEST, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+ "Resolving multi-sampled texture (DeviceContextVkImpl::ResolveTextureSubresource)");
+
+ const auto& ResolveFmtAttribs = GetTextureFormatAttribs(SrcTexDesc.Format);
+ DEV_CHECK_ERR(ResolveFmtAttribs.ComponentType != COMPONENT_TYPE_DEPTH && ResolveFmtAttribs.ComponentType != COMPONENT_TYPE_DEPTH_STENCIL,
+ "Vulkan only allows resolve operation for color formats");
+ (void)ResolveFmtAttribs;
+ // The aspectMask member of srcSubresource and dstSubresource must only contain VK_IMAGE_ASPECT_COLOR_BIT (18.6)
+ VkImageAspectFlags aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+
+ VkImageResolve ResolveRegion;
+ ResolveRegion.srcSubresource.baseArrayLayer = ResolveAttribs.SrcSlice;
+ ResolveRegion.srcSubresource.layerCount = 1;
+ ResolveRegion.srcSubresource.mipLevel = ResolveAttribs.SrcMipLevel;
+ ResolveRegion.srcSubresource.aspectMask = aspectMask;
+
+ ResolveRegion.dstSubresource.baseArrayLayer = ResolveAttribs.DstSlice;
+ ResolveRegion.dstSubresource.layerCount = 1;
+ ResolveRegion.dstSubresource.mipLevel = ResolveAttribs.DstMipLevel;
+ ResolveRegion.dstSubresource.aspectMask = aspectMask;
+
+ ResolveRegion.srcOffset = VkOffset3D{};
+ ResolveRegion.dstOffset = VkOffset3D{};
+ const auto& MipAttribs = GetMipLevelProperties(SrcTexDesc, ResolveAttribs.SrcMipLevel);
+ ResolveRegion.extent = VkExtent3D{
+ static_cast<uint32_t>(MipAttribs.LogicalWidth),
+ static_cast<uint32_t>(MipAttribs.LogicalHeight),
+ static_cast<uint32_t>(MipAttribs.Depth)};
+
+ m_CommandBuffer.ResolveImage(pSrcTexVk->GetVkImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+ pDstTexVk->GetVkImage(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+ 1, &ResolveRegion);
+}
+
+} // namespace Diligent
diff --git a/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp b/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp
index 496eb67f..0debf7eb 100644
--- a/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp
@@ -54,44 +54,44 @@ public:
TBase{IID_EngineFactoryVk}
{}
- void CreateDeviceAndContextsVk(const EngineVkCreateInfo& EngineCI,
- IRenderDevice** ppDevice,
- IDeviceContext** ppContexts)override final;
+ void CreateDeviceAndContextsVk(const EngineVkCreateInfo& EngineCI,
+ IRenderDevice** ppDevice,
+ IDeviceContext** ppContexts) override final;
void AttachToVulkanDevice(std::shared_ptr<VulkanUtilities::VulkanInstance> Instance,
std::unique_ptr<VulkanUtilities::VulkanPhysicalDevice> PhysicalDevice,
std::shared_ptr<VulkanUtilities::VulkanLogicalDevice> LogicalDevice,
- size_t CommandQueueCount,
- ICommandQueueVk** ppCommandQueues,
- const EngineVkCreateInfo& EngineCI,
- IRenderDevice** ppDevice,
- IDeviceContext** ppContexts);//override final;
-
- void CreateSwapChainVk(IRenderDevice* pDevice,
- IDeviceContext* pImmediateContext,
- const SwapChainDesc& SwapChainDesc,
- void* pNativeWndHandle,
- ISwapChain** ppSwapChain)override final;
+ size_t CommandQueueCount,
+ ICommandQueueVk** ppCommandQueues,
+ const EngineVkCreateInfo& EngineCI,
+ IRenderDevice** ppDevice,
+ IDeviceContext** ppContexts); //override final;
+
+ void CreateSwapChainVk(IRenderDevice* pDevice,
+ IDeviceContext* pImmediateContext,
+ const SwapChainDesc& SwapChainDesc,
+ void* pNativeWndHandle,
+ ISwapChain** ppSwapChain) override final;
};
/// Creates render device and device contexts for Vulkan backend
/// \param [in] EngineCI - Engine creation attributes.
-/// \param [out] ppDevice - Address of the memory location where pointer to
+/// \param [out] ppDevice - Address of the memory location where pointer to
/// the created device will be written
-/// \param [out] ppContexts - Address of the memory location where pointers to
+/// \param [out] ppContexts - Address of the memory location where pointers to
/// the contexts will be written. Immediate context goes at
/// position 0. If EngineCI.NumDeferredContexts > 0,
/// pointers to the deferred contexts are written afterwards.
void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _EngineCI,
- IRenderDevice** ppDevice,
+ IRenderDevice** ppDevice,
IDeviceContext** ppContexts)
{
if (_EngineCI.APIVersion != DILIGENT_API_VERSION)
LOG_ERROR_AND_THROW("Diligent Engine runtime (", _EngineCI.APIVersion, ") is not compatible with the client API version (", DILIGENT_API_VERSION, ")");
- VERIFY( ppDevice && ppContexts, "Null pointer provided" );
- if( !ppDevice || !ppContexts )
+ VERIFY(ppDevice && ppContexts, "Null pointer provided");
+ if (!ppDevice || !ppContexts)
return;
EngineVkCreateInfo EngineCI = _EngineCI;
@@ -123,52 +123,52 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E
try
{
auto Instance = VulkanUtilities::VulkanInstance::Create(
- EngineCI.EnableValidation,
- EngineCI.GlobalExtensionCount,
+ EngineCI.EnableValidation,
+ EngineCI.GlobalExtensionCount,
EngineCI.ppGlobalExtensionNames,
reinterpret_cast<VkAllocationCallbacks*>(EngineCI.pVkAllocator));
- auto vkDevice = Instance->SelectPhysicalDevice();
- auto PhysicalDevice = VulkanUtilities::VulkanPhysicalDevice::Create(vkDevice);
+ auto vkDevice = Instance->SelectPhysicalDevice();
+ auto PhysicalDevice = VulkanUtilities::VulkanPhysicalDevice::Create(vkDevice);
const auto& PhysicalDeviceFeatures = PhysicalDevice->GetFeatures();
- // If an implementation exposes any queue family that supports graphics operations,
- // at least one queue family of at least one physical device exposed by the implementation
+ // If an implementation exposes any queue family that supports graphics operations,
+ // at least one queue family of at least one physical device exposed by the implementation
// must support both graphics and compute operations.
VkDeviceQueueCreateInfo QueueInfo{};
QueueInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
QueueInfo.flags = 0; // reserved for future use
- // All commands that are allowed on a queue that supports transfer operations are also allowed on a
- // queue that supports either graphics or compute operations.Thus, if the capabilities of a queue family
- // include VK_QUEUE_GRAPHICS_BIT or VK_QUEUE_COMPUTE_BIT, then reporting the VK_QUEUE_TRANSFER_BIT
+ // All commands that are allowed on a queue that supports transfer operations are also allowed on a
+ // queue that supports either graphics or compute operations.Thus, if the capabilities of a queue family
+ // include VK_QUEUE_GRAPHICS_BIT or VK_QUEUE_COMPUTE_BIT, then reporting the VK_QUEUE_TRANSFER_BIT
// capability separately for that queue family is optional (4.1).
- QueueInfo.queueFamilyIndex = PhysicalDevice->FindQueueFamily(VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT);
- QueueInfo.queueCount = 1;
+ QueueInfo.queueFamilyIndex = PhysicalDevice->FindQueueFamily(VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT);
+ QueueInfo.queueCount = 1;
const float defaultQueuePriority = 1.0f; // Ask for highest priority for our queue. (range [0,1])
- QueueInfo.pQueuePriorities = &defaultQueuePriority;
+ QueueInfo.pQueuePriorities = &defaultQueuePriority;
VkDeviceCreateInfo DeviceCreateInfo = {};
- DeviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
- DeviceCreateInfo.flags = 0; // Reserved for future use
+ DeviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
+ DeviceCreateInfo.flags = 0; // Reserved for future use
// https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#extended-functionality-device-layer-deprecation
- DeviceCreateInfo.enabledLayerCount = 0; // Deprecated and ignored.
- DeviceCreateInfo.ppEnabledLayerNames = nullptr; // Deprecated and ignored
- DeviceCreateInfo.queueCreateInfoCount = 1;
- DeviceCreateInfo.pQueueCreateInfos = &QueueInfo;
+ DeviceCreateInfo.enabledLayerCount = 0; // Deprecated and ignored.
+ DeviceCreateInfo.ppEnabledLayerNames = nullptr; // Deprecated and ignored
+ DeviceCreateInfo.queueCreateInfoCount = 1;
+ DeviceCreateInfo.pQueueCreateInfos = &QueueInfo;
VkPhysicalDeviceFeatures DeviceFeatures = {};
-#define ENABLE_FEATURE(Feature)\
- if (EngineCI.EnabledFeatures.Feature)\
- { \
- if (PhysicalDeviceFeatures.Feature) \
- DeviceFeatures.Feature = VK_TRUE; \
- else \
- { \
- LOG_WARNING_MESSAGE("Requested device feature " #Feature " is not supported by the physical device and will be disabled");\
- EngineCI.EnabledFeatures.Feature = false; \
- } \
- }
+#define ENABLE_FEATURE(Feature) \
+ if (EngineCI.EnabledFeatures.Feature) \
+ { \
+ if (PhysicalDeviceFeatures.Feature) \
+ DeviceFeatures.Feature = VK_TRUE; \
+ else \
+ { \
+ LOG_WARNING_MESSAGE("Requested device feature " #Feature " is not supported by the physical device and will be disabled"); \
+ EngineCI.EnabledFeatures.Feature = false; \
+ } \
+ }
ENABLE_FEATURE(depthBiasClamp)
ENABLE_FEATURE(fillModeNonSolid)
@@ -186,24 +186,24 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E
ENABLE_FEATURE(shaderStorageImageExtendedFormats)
#undef ENABLE_FEATURE
- DeviceCreateInfo.pEnabledFeatures = &DeviceFeatures; // NULL or a pointer to a VkPhysicalDeviceFeatures structure that contains
+ DeviceCreateInfo.pEnabledFeatures = &DeviceFeatures; // NULL or a pointer to a VkPhysicalDeviceFeatures structure that contains
// boolean indicators of all the features to be enabled.
- std::vector<const char*> DeviceExtensions =
- {
- VK_KHR_SWAPCHAIN_EXTENSION_NAME,
- VK_KHR_MAINTENANCE1_EXTENSION_NAME // To allow negative viewport height
- };
+ std::vector<const char*> DeviceExtensions =
+ {
+ VK_KHR_SWAPCHAIN_EXTENSION_NAME,
+ VK_KHR_MAINTENANCE1_EXTENSION_NAME // To allow negative viewport height
+ };
DeviceCreateInfo.ppEnabledExtensionNames = DeviceExtensions.empty() ? nullptr : DeviceExtensions.data();
- DeviceCreateInfo.enabledExtensionCount = static_cast<uint32_t>(DeviceExtensions.size());
+ DeviceCreateInfo.enabledExtensionCount = static_cast<uint32_t>(DeviceExtensions.size());
- auto vkAllocator = Instance->GetVkAllocator();
+ auto vkAllocator = Instance->GetVkAllocator();
auto vkPhysicalDevice = PhysicalDevice->GetVkDeviceHandle();
- auto LogicalDevice = VulkanUtilities::VulkanLogicalDevice::Create(vkPhysicalDevice, DeviceCreateInfo, vkAllocator);
+ auto LogicalDevice = VulkanUtilities::VulkanLogicalDevice::Create(vkPhysicalDevice, DeviceCreateInfo, vkAllocator);
RefCntAutoPtr<CommandQueueVkImpl> pCmdQueueVk;
- auto &RawMemAllocator = GetRawAllocator();
- pCmdQueueVk = NEW_RC_OBJ(RawMemAllocator, "CommandQueueVk instance", CommandQueueVkImpl)(LogicalDevice, QueueInfo.queueFamilyIndex);
+ auto& RawMemAllocator = GetRawAllocator();
+ pCmdQueueVk = NEW_RC_OBJ(RawMemAllocator, "CommandQueueVk instance", CommandQueueVkImpl)(LogicalDevice, QueueInfo.queueFamilyIndex);
std::array<ICommandQueueVk*, 1> CommandQueues = {{pCmdQueueVk}};
AttachToVulkanDevice(Instance, std::move(PhysicalDevice), LogicalDevice, CommandQueues.size(), CommandQueues.data(), EngineCI, ppDevice, ppContexts);
@@ -211,12 +211,13 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E
FenceDesc Desc;
Desc.Name = "Command queue fence";
// Render device owns command queue that in turn owns the fence, so it is an internal device object
- bool IsDeviceInternal = true;
- auto* pRenderDeviceVk = ValidatedCast<RenderDeviceVkImpl>(*ppDevice);
- RefCntAutoPtr<FenceVkImpl> pFenceVk( NEW_RC_OBJ(RawMemAllocator, "FenceVkImpl instance", FenceVkImpl)(pRenderDeviceVk, Desc, IsDeviceInternal) );
+ bool IsDeviceInternal = true;
+ auto* pRenderDeviceVk = ValidatedCast<RenderDeviceVkImpl>(*ppDevice);
+
+ RefCntAutoPtr<FenceVkImpl> pFenceVk(NEW_RC_OBJ(RawMemAllocator, "FenceVkImpl instance", FenceVkImpl)(pRenderDeviceVk, Desc, IsDeviceInternal));
pCmdQueueVk->SetFence(std::move(pFenceVk));
}
- catch(std::runtime_error& )
+ catch (std::runtime_error&)
{
return;
}
@@ -229,26 +230,26 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E
/// \param [in] LogicalDevice - shared pointer to a VulkanUtilities::VulkanLogicalDevice object
/// \param [in] pCommandQueue - pointer to the implementation of command queue
/// \param [in] EngineCI - Engine creation attributes.
-/// \param [out] ppDevice - Address of the memory location where pointer to
+/// \param [out] ppDevice - Address of the memory location where pointer to
/// the created device will be written
-/// \param [out] ppContexts - Address of the memory location where pointers to
+/// \param [out] ppContexts - Address of the memory location where pointers to
/// the contexts will be written. Immediate context goes at
/// position 0. If EngineCI.NumDeferredContexts > 0,
/// pointers to the deferred contexts are written afterwards.
void EngineFactoryVkImpl::AttachToVulkanDevice(std::shared_ptr<VulkanUtilities::VulkanInstance> Instance,
std::unique_ptr<VulkanUtilities::VulkanPhysicalDevice> PhysicalDevice,
std::shared_ptr<VulkanUtilities::VulkanLogicalDevice> LogicalDevice,
- size_t CommandQueueCount,
- ICommandQueueVk** ppCommandQueues,
- const EngineVkCreateInfo& EngineCI,
- IRenderDevice** ppDevice,
- IDeviceContext** ppContexts)
+ size_t CommandQueueCount,
+ ICommandQueueVk** ppCommandQueues,
+ const EngineVkCreateInfo& EngineCI,
+ IRenderDevice** ppDevice,
+ IDeviceContext** ppContexts)
{
if (EngineCI.APIVersion != DILIGENT_API_VERSION)
LOG_ERROR_AND_THROW("Diligent Engine runtime (", EngineCI.APIVersion, ") is not compatible with the client API version (", DILIGENT_API_VERSION, ")");
- VERIFY( ppCommandQueues && ppDevice && ppContexts, "Null pointer provided" );
- if(!LogicalDevice || !ppCommandQueues || !ppDevice || !ppContexts )
+ VERIFY(ppCommandQueues && ppDevice && ppContexts, "Null pointer provided");
+ if (!LogicalDevice || !ppCommandQueues || !ppDevice || !ppContexts)
return;
*ppDevice = nullptr;
@@ -256,44 +257,45 @@ void EngineFactoryVkImpl::AttachToVulkanDevice(std::shared_ptr<VulkanUtilities::
try
{
- auto &RawMemAllocator = GetRawAllocator();
- RenderDeviceVkImpl *pRenderDeviceVk( NEW_RC_OBJ(RawMemAllocator, "RenderDeviceVkImpl instance", RenderDeviceVkImpl)(RawMemAllocator, this, EngineCI, CommandQueueCount, ppCommandQueues, Instance, std::move(PhysicalDevice), LogicalDevice) );
- pRenderDeviceVk->QueryInterface(IID_RenderDevice, reinterpret_cast<IObject**>(ppDevice) );
+ auto& RawMemAllocator = GetRawAllocator();
+
+ RenderDeviceVkImpl* pRenderDeviceVk(NEW_RC_OBJ(RawMemAllocator, "RenderDeviceVkImpl instance", RenderDeviceVkImpl)(RawMemAllocator, this, EngineCI, CommandQueueCount, ppCommandQueues, Instance, std::move(PhysicalDevice), LogicalDevice));
+ pRenderDeviceVk->QueryInterface(IID_RenderDevice, reinterpret_cast<IObject**>(ppDevice));
std::shared_ptr<GenerateMipsVkHelper> GenerateMipsHelper(new GenerateMipsVkHelper(*pRenderDeviceVk));
- RefCntAutoPtr<DeviceContextVkImpl> pImmediateCtxVk( NEW_RC_OBJ(RawMemAllocator, "DeviceContextVkImpl instance", DeviceContextVkImpl)(pRenderDeviceVk, false, EngineCI, 0, 0, GenerateMipsHelper) );
+ RefCntAutoPtr<DeviceContextVkImpl> pImmediateCtxVk(NEW_RC_OBJ(RawMemAllocator, "DeviceContextVkImpl instance", DeviceContextVkImpl)(pRenderDeviceVk, false, EngineCI, 0, 0, GenerateMipsHelper));
// We must call AddRef() (implicitly through QueryInterface()) because pRenderDeviceVk will
// keep a weak reference to the context
- pImmediateCtxVk->QueryInterface(IID_DeviceContext, reinterpret_cast<IObject**>(ppContexts) );
+ pImmediateCtxVk->QueryInterface(IID_DeviceContext, reinterpret_cast<IObject**>(ppContexts));
pRenderDeviceVk->SetImmediateContext(pImmediateCtxVk);
for (Uint32 DeferredCtx = 0; DeferredCtx < EngineCI.NumDeferredContexts; ++DeferredCtx)
{
- RefCntAutoPtr<DeviceContextVkImpl> pDeferredCtxVk( NEW_RC_OBJ(RawMemAllocator, "DeviceContextVkImpl instance", DeviceContextVkImpl)(pRenderDeviceVk, true, EngineCI, 1+DeferredCtx, 0, GenerateMipsHelper) );
+ RefCntAutoPtr<DeviceContextVkImpl> pDeferredCtxVk(NEW_RC_OBJ(RawMemAllocator, "DeviceContextVkImpl instance", DeviceContextVkImpl)(pRenderDeviceVk, true, EngineCI, 1 + DeferredCtx, 0, GenerateMipsHelper));
// We must call AddRef() (implicitly through QueryInterface()) because pRenderDeviceVk will
// keep a weak reference to the context
- pDeferredCtxVk->QueryInterface(IID_DeviceContext, reinterpret_cast<IObject**>(ppContexts + 1 + DeferredCtx) );
+ pDeferredCtxVk->QueryInterface(IID_DeviceContext, reinterpret_cast<IObject**>(ppContexts + 1 + DeferredCtx));
pRenderDeviceVk->SetDeferredContext(DeferredCtx, pDeferredCtxVk);
}
}
- catch( const std::runtime_error & )
+ catch (const std::runtime_error&)
{
- if( *ppDevice )
+ if (*ppDevice)
{
(*ppDevice)->Release();
*ppDevice = nullptr;
}
- for(Uint32 ctx=0; ctx < 1 + EngineCI.NumDeferredContexts; ++ctx)
+ for (Uint32 ctx = 0; ctx < 1 + EngineCI.NumDeferredContexts; ++ctx)
{
- if( ppContexts[ctx] != nullptr )
+ if (ppContexts[ctx] != nullptr)
{
ppContexts[ctx]->Release();
ppContexts[ctx] = nullptr;
}
}
- LOG_ERROR( "Failed to create device and contexts" );
+ LOG_ERROR("Failed to create device and contexts");
}
}
@@ -303,31 +305,31 @@ void EngineFactoryVkImpl::AttachToVulkanDevice(std::shared_ptr<VulkanUtilities::
/// \param [in] pDevice - Pointer to the render device
/// \param [in] pImmediateContext - Pointer to the immediate device context
/// \param [in] SCDesc - Swap chain description
-/// \param [in] pNativeWndHandle - Platform-specific native handle of the window
+/// \param [in] pNativeWndHandle - Platform-specific native handle of the window
/// the swap chain will be associated with:
/// * On Win32 platform, this should be window handle (HWND)
-/// * On Universal Windows Platform, this should be reference to the
+/// * On Universal Windows Platform, this should be reference to the
/// core window (Windows::UI::Core::CoreWindow)
-///
-/// \param [out] ppSwapChain - Address of the memory location where pointer to the new
+///
+/// \param [out] ppSwapChain - Address of the memory location where pointer to the new
/// swap chain will be written
-void EngineFactoryVkImpl::CreateSwapChainVk(IRenderDevice* pDevice,
- IDeviceContext* pImmediateContext,
- const SwapChainDesc& SCDesc,
- void* pNativeWndHandle,
+void EngineFactoryVkImpl::CreateSwapChainVk(IRenderDevice* pDevice,
+ IDeviceContext* pImmediateContext,
+ const SwapChainDesc& SCDesc,
+ void* pNativeWndHandle,
ISwapChain** ppSwapChain)
{
- VERIFY( ppSwapChain, "Null pointer provided" );
- if( !ppSwapChain )
+ VERIFY(ppSwapChain, "Null pointer provided");
+ if (!ppSwapChain)
return;
*ppSwapChain = nullptr;
try
{
- auto* pDeviceVk = ValidatedCast<RenderDeviceVkImpl>( pDevice );
+ auto* pDeviceVk = ValidatedCast<RenderDeviceVkImpl>(pDevice);
auto* pDeviceContextVk = ValidatedCast<DeviceContextVkImpl>(pImmediateContext);
- auto& RawMemAllocator = GetRawAllocator();
+ auto& RawMemAllocator = GetRawAllocator();
if (pDeviceContextVk->GetSwapChain() != nullptr && SCDesc.IsPrimary)
{
@@ -337,40 +339,40 @@ void EngineFactoryVkImpl::CreateSwapChainVk(IRenderDevice* pDevice,
auto* pSwapChainVk = NEW_RC_OBJ(RawMemAllocator, "SwapChainVkImpl instance", SwapChainVkImpl)(SCDesc, pDeviceVk, pDeviceContextVk, pNativeWndHandle);
- pSwapChainVk->QueryInterface( IID_SwapChain, reinterpret_cast<IObject**>(ppSwapChain) );
+ pSwapChainVk->QueryInterface(IID_SwapChain, reinterpret_cast<IObject**>(ppSwapChain));
if (SCDesc.IsPrimary)
{
pDeviceContextVk->SetSwapChain(pSwapChainVk);
// Bind default render target
- pDeviceContextVk->SetRenderTargets( 0, nullptr, nullptr, RESOURCE_STATE_TRANSITION_MODE_TRANSITION );
+ pDeviceContextVk->SetRenderTargets(0, nullptr, nullptr, RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
// Set default viewport
- pDeviceContextVk->SetViewports( 1, nullptr, 0, 0 );
-
+ pDeviceContextVk->SetViewports(1, nullptr, 0, 0);
+
auto NumDeferredCtx = pDeviceVk->GetNumDeferredContexts();
for (size_t ctx = 0; ctx < NumDeferredCtx; ++ctx)
{
if (auto pDeferredCtx = pDeviceVk->GetDeferredContext(ctx))
{
- auto *pDeferredCtxVk = pDeferredCtx.RawPtr<DeviceContextVkImpl>();
+ auto* pDeferredCtxVk = pDeferredCtx.RawPtr<DeviceContextVkImpl>();
pDeferredCtxVk->SetSwapChain(pSwapChainVk);
// We cannot bind default render target here because
// there is no guarantee that deferred context will be used
- // in this frame. It is an error to bind
+ // in this frame. It is an error to bind
// RTV of an inactive buffer in the swap chain
}
}
}
}
- catch( const std::runtime_error & )
+ catch (const std::runtime_error&)
{
- if( *ppSwapChain )
+ if (*ppSwapChain)
{
(*ppSwapChain)->Release();
*ppSwapChain = nullptr;
}
- LOG_ERROR( "Failed to create the swap chain" );
+ LOG_ERROR("Failed to create the swap chain");
}
}
@@ -385,10 +387,10 @@ void EngineFactoryVkImpl::CreateSwapChainVk(IRenderDevice* pDevice,
/// x86 | GraphicsEngineVk_32d.dll | GraphicsEngineVk_32r.dll
/// x64 | GraphicsEngineVk_64d.dll | GraphicsEngineVk_64r.dll
///
-void LoadGraphicsEngineVk(GetEngineFactoryVkType &GetFactoryFunc)
+void LoadGraphicsEngineVk(GetEngineFactoryVkType& GetFactoryFunc)
{
- // This function is only required because DoxyGen refuses to generate documentation for a static function when SHOW_FILES==NO
- #error This function must never be compiled;
+// This function is only required because DoxyGen refuses to generate documentation for a static function when SHOW_FILES==NO
+# error This function must never be compiled;
}
#endif
@@ -398,4 +400,4 @@ IEngineFactoryVk* GetEngineFactoryVk()
return EngineFactoryVkImpl::GetInstance();
}
-}
+} // namespace Diligent
diff --git a/Graphics/GraphicsEngineVulkan/src/FenceVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/FenceVkImpl.cpp
index cb1be2b8..7f6f99a3 100644
--- a/Graphics/GraphicsEngineVulkan/src/FenceVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/FenceVkImpl.cpp
@@ -29,11 +29,12 @@
namespace Diligent
{
-
-FenceVkImpl :: FenceVkImpl(IReferenceCounters* pRefCounters,
- RenderDeviceVkImpl* pRendeDeviceVkImpl,
- const FenceDesc& Desc,
- bool IsDeviceInternal) :
+
+FenceVkImpl ::FenceVkImpl(IReferenceCounters* pRefCounters,
+ RenderDeviceVkImpl* pRendeDeviceVkImpl,
+ const FenceDesc& Desc,
+ bool IsDeviceInternal) :
+ // clang-format off
TFenceBase
{
pRefCounters,
@@ -42,30 +43,32 @@ FenceVkImpl :: FenceVkImpl(IReferenceCounters* pRefCounters,
IsDeviceInternal
},
m_FencePool{pRendeDeviceVkImpl->GetLogicalDevice().GetSharedPtr()}
+// clang-format on
{
}
-FenceVkImpl :: ~FenceVkImpl()
+FenceVkImpl ::~FenceVkImpl()
{
if (!m_PendingFences.empty())
{
LOG_INFO_MESSAGE("FenceVkImpl::~FenceVkImpl(): waiting for ", m_PendingFences.size(), " pending Vulkan ",
(m_PendingFences.size() > 1 ? "fences." : "fence."));
- // Vulkan spec states that all queue submission commands that refer to
+ // Vulkan spec states that all queue submission commands that refer to
// a fence must have completed execution before the fence is destroyed.
// (https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-vkDestroyFence-fence-01120)
Wait(UINT64_MAX);
}
}
-Uint64 FenceVkImpl :: GetCompletedValue()
+Uint64 FenceVkImpl ::GetCompletedValue()
{
const auto& LogicalDevice = m_pDevice->GetLogicalDevice();
while (!m_PendingFences.empty())
{
auto& Value_Fence = m_PendingFences.front();
+
auto status = LogicalDevice.GetFenceStatus(Value_Fence.second);
- if(status == VK_SUCCESS)
+ if (status == VK_SUCCESS)
{
if (Value_Fence.first > m_LastCompletedFenceValue)
m_LastCompletedFenceValue = Value_Fence.first;
@@ -81,7 +84,7 @@ Uint64 FenceVkImpl :: GetCompletedValue()
return m_LastCompletedFenceValue;
}
-void FenceVkImpl :: Reset(Uint64 Value)
+void FenceVkImpl ::Reset(Uint64 Value)
{
DEV_CHECK_ERR(Value >= m_LastCompletedFenceValue, "Resetting fence '", m_Desc.Name, "' to the value (", Value, ") that is smaller than the last completed value (", m_LastCompletedFenceValue, ")");
if (Value > m_LastCompletedFenceValue)
@@ -89,7 +92,7 @@ void FenceVkImpl :: Reset(Uint64 Value)
}
-void FenceVkImpl :: Wait(Uint64 Value)
+void FenceVkImpl ::Wait(Uint64 Value)
{
const auto& LogicalDevice = m_pDevice->GetLogicalDevice();
while (!m_PendingFences.empty())
@@ -102,10 +105,12 @@ void FenceVkImpl :: Wait(Uint64 Value)
if (status == VK_NOT_READY)
{
VkFence FenceToWait = val_fence.second;
+
status = LogicalDevice.WaitForFences(1, &FenceToWait, VK_TRUE, UINT64_MAX);
}
- DEV_CHECK_ERR(status == VK_SUCCESS, "All pending fences must now be complete!"); (void)status;
+ DEV_CHECK_ERR(status == VK_SUCCESS, "All pending fences must now be complete!");
+ (void)status;
if (val_fence.first > m_LastCompletedFenceValue)
m_LastCompletedFenceValue = val_fence.first;
m_FencePool.DisposeFence(std::move(val_fence.second));
@@ -114,4 +119,4 @@ void FenceVkImpl :: Wait(Uint64 Value)
}
}
-}
+} // namespace Diligent
diff --git a/Graphics/GraphicsEngineVulkan/src/FramebufferCache.cpp b/Graphics/GraphicsEngineVulkan/src/FramebufferCache.cpp
index 050fb1aa..70b66475 100644
--- a/Graphics/GraphicsEngineVulkan/src/FramebufferCache.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/FramebufferCache.cpp
@@ -29,9 +29,10 @@
namespace Diligent
{
-
-bool FramebufferCache::FramebufferCacheKey::operator == (const FramebufferCacheKey &rhs)const
+
+bool FramebufferCache::FramebufferCacheKey::operator==(const FramebufferCacheKey& rhs) const
{
+ // clang-format off
if (GetHash() != rhs.GetHash() ||
Pass != rhs.Pass ||
NumRenderTargets != rhs.NumRenderTargets ||
@@ -40,6 +41,7 @@ bool FramebufferCache::FramebufferCacheKey::operator == (const FramebufferCacheK
{
return false;
}
+ // clang-format on
for (Uint32 rt = 0; rt < NumRenderTargets; ++rt)
if (RTVs[rt] != rhs.RTVs[rt])
@@ -48,12 +50,12 @@ bool FramebufferCache::FramebufferCacheKey::operator == (const FramebufferCacheK
return true;
}
-size_t FramebufferCache::FramebufferCacheKey::GetHash()const
+size_t FramebufferCache::FramebufferCacheKey::GetHash() const
{
if (Hash == 0)
{
Hash = ComputeHash(Pass, NumRenderTargets, DSV, CommandQueueMask);
- for(Uint32 rt = 0; rt < NumRenderTargets; ++rt)
+ for (Uint32 rt = 0; rt < NumRenderTargets; ++rt)
HashCombine(Hash, RTVs[rt]);
}
return Hash;
@@ -62,7 +64,7 @@ size_t FramebufferCache::FramebufferCacheKey::GetHash()const
VkFramebuffer FramebufferCache::GetFramebuffer(const FramebufferCacheKey& Key, uint32_t width, uint32_t height, uint32_t layers)
{
std::lock_guard<std::mutex> Lock{m_Mutex};
- auto it = m_Cache.find(Key);
+ auto it = m_Cache.find(Key);
if (it != m_Cache.end())
{
return it->second;
@@ -70,32 +72,34 @@ VkFramebuffer FramebufferCache::GetFramebuffer(const FramebufferCacheKey& Key, u
else
{
VkFramebufferCreateInfo FramebufferCI = {};
- FramebufferCI.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
- FramebufferCI.pNext = nullptr;
- FramebufferCI.flags = 0; // reserved for future use
- FramebufferCI.renderPass = Key.Pass;
+
+ FramebufferCI.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
+ FramebufferCI.pNext = nullptr;
+ FramebufferCI.flags = 0; // reserved for future use
+ FramebufferCI.renderPass = Key.Pass;
FramebufferCI.attachmentCount = (Key.DSV != VK_NULL_HANDLE ? 1 : 0) + Key.NumRenderTargets;
VkImageView Attachments[1 + MaxRenderTargets];
- uint32_t attachment = 0;
+ uint32_t attachment = 0;
if (Key.DSV != VK_NULL_HANDLE)
Attachments[attachment++] = Key.DSV;
- for (Uint32 rt=0; rt < Key.NumRenderTargets; ++rt)
+ for (Uint32 rt = 0; rt < Key.NumRenderTargets; ++rt)
Attachments[attachment++] = Key.RTVs[rt];
VERIFY_EXPR(attachment == FramebufferCI.attachmentCount);
FramebufferCI.pAttachments = Attachments;
- FramebufferCI.width = width;
- FramebufferCI.height = height;
- FramebufferCI.layers = layers;
- auto Framebuffer = m_DeviceVk.GetLogicalDevice().CreateFramebuffer(FramebufferCI);
- VkFramebuffer fb = Framebuffer;
+ FramebufferCI.width = width;
+ FramebufferCI.height = height;
+ FramebufferCI.layers = layers;
+ auto Framebuffer = m_DeviceVk.GetLogicalDevice().CreateFramebuffer(FramebufferCI);
+ VkFramebuffer fb = Framebuffer;
auto new_it = m_Cache.insert(std::make_pair(Key, std::move(Framebuffer)));
- VERIFY(new_it.second, "New framebuffer must be inserted into the map"); (void)new_it;
+ VERIFY(new_it.second, "New framebuffer must be inserted into the map");
+ (void)new_it;
m_RenderPassToKeyMap.emplace(Key.Pass, Key);
if (Key.DSV != VK_NULL_HANDLE)
m_ViewToKeyMap.emplace(Key.DSV, Key);
- for (Uint32 rt=0; rt < Key.NumRenderTargets; ++rt)
+ for (Uint32 rt = 0; rt < Key.NumRenderTargets; ++rt)
if (Key.RTVs[rt] != VK_NULL_HANDLE)
m_ViewToKeyMap.emplace(Key.RTVs[rt], Key);
@@ -112,11 +116,12 @@ FramebufferCache::~FramebufferCache()
void FramebufferCache::OnDestroyImageView(VkImageView ImgView)
{
- // TODO: when a render pass is released, we need to also destroy
+ // TODO: when a render pass is released, we need to also destroy
// all entries in the m_ViewToKeyMap that refer to all keys with
// that render pass
std::lock_guard<std::mutex> Lock{m_Mutex};
+
auto equal_range = m_ViewToKeyMap.equal_range(ImgView);
for (auto it = equal_range.first; it != equal_range.second; ++it)
{
@@ -134,10 +139,11 @@ void FramebufferCache::OnDestroyImageView(VkImageView ImgView)
void FramebufferCache::OnDestroyRenderPass(VkRenderPass Pass)
{
- // TODO: when an image view is released, we need to also destroy
+ // TODO: when an image view is released, we need to also destroy
// all entries in the m_RenderPassToKeyMap that refer to the keys
// with the same image view
std::lock_guard<std::mutex> Lock{m_Mutex};
+
auto equal_range = m_RenderPassToKeyMap.equal_range(Pass);
for (auto it = equal_range.first; it != equal_range.second; ++it)
{
@@ -153,4 +159,4 @@ void FramebufferCache::OnDestroyRenderPass(VkRenderPass Pass)
m_RenderPassToKeyMap.erase(equal_range.first, equal_range.second);
}
-}
+} // namespace Diligent
diff --git a/Graphics/GraphicsEngineVulkan/src/GenerateMipsVkHelper.cpp b/Graphics/GraphicsEngineVulkan/src/GenerateMipsVkHelper.cpp
index 112c0bf3..cfa8ff75 100644
--- a/Graphics/GraphicsEngineVulkan/src/GenerateMipsVkHelper.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/GenerateMipsVkHelper.cpp
@@ -35,419 +35,434 @@
#include "../../GraphicsTools/include/CommonlyUsedStates.h"
-static const char* g_GenerateMipsCSSource =
+// clang-format off
+static const char* g_GenerateMipsCSSource =
{
#include "../shaders/GenerateMipsCS_inc.h"
};
+// clang-format on
namespace Diligent
{
- void GenerateMipsVkHelper::GetGlImageFormat(const TextureFormatAttribs& FmtAttribs, std::array<char, 16>& GlFmt)
- {
- size_t pos = 0;
- GlFmt[pos++] = 'r';
- if(FmtAttribs.NumComponents >= 2)
- GlFmt[pos++] = 'g';
- if(FmtAttribs.NumComponents >= 3)
- GlFmt[pos++] = 'b';
- if(FmtAttribs.NumComponents >= 4)
- GlFmt[pos++] = 'a';
- VERIFY_EXPR(FmtAttribs.NumComponents <= 4);
- auto ComponentSize = Uint32{FmtAttribs.ComponentSize} * 8;
- int pow10 = 1;
- while(ComponentSize / (10*pow10) != 0)
- pow10 *= 10;
- VERIFY_EXPR(ComponentSize !=0);
- while(ComponentSize != 0)
- {
- char digit = static_cast<char>(ComponentSize/pow10);
- GlFmt[pos++] = '0' + digit;
- ComponentSize -= digit * pow10;
- pow10 /= 10;
- }
-
- switch(FmtAttribs.ComponentType)
- {
- case COMPONENT_TYPE_FLOAT:
- GlFmt[pos++] = 'f';
- break;
-
- case COMPONENT_TYPE_UNORM:
- case COMPONENT_TYPE_UNORM_SRGB:
- // No suffix
- break;
-
- case COMPONENT_TYPE_SNORM:
- GlFmt[pos++] = '_';
- GlFmt[pos++] = 's';
- GlFmt[pos++] = 'n';
- GlFmt[pos++] = 'o';
- GlFmt[pos++] = 'r';
- GlFmt[pos++] = 'm';
- break;
-
- case COMPONENT_TYPE_SINT:
- GlFmt[pos++] = 'i';
- break;
-
- case COMPONENT_TYPE_UINT:
- GlFmt[pos++] = 'u';
- GlFmt[pos++] = 'i';
- break;
-
- default:
- UNSUPPORTED("Unsupported component type");
- }
- GlFmt[pos] = 0;
+void GenerateMipsVkHelper::GetGlImageFormat(const TextureFormatAttribs& FmtAttribs, std::array<char, 16>& GlFmt)
+{
+ size_t pos = 0;
+ GlFmt[pos++] = 'r';
+ if (FmtAttribs.NumComponents >= 2)
+ GlFmt[pos++] = 'g';
+ if (FmtAttribs.NumComponents >= 3)
+ GlFmt[pos++] = 'b';
+ if (FmtAttribs.NumComponents >= 4)
+ GlFmt[pos++] = 'a';
+ VERIFY_EXPR(FmtAttribs.NumComponents <= 4);
+ auto ComponentSize = Uint32{FmtAttribs.ComponentSize} * 8;
+
+ int pow10 = 1;
+ while (ComponentSize / (10 * pow10) != 0)
+ pow10 *= 10;
+ VERIFY_EXPR(ComponentSize != 0);
+ while (ComponentSize != 0)
+ {
+ char digit = static_cast<char>(ComponentSize / pow10);
+ GlFmt[pos++] = '0' + digit;
+ ComponentSize -= digit * pow10;
+ pow10 /= 10;
}
- std::array<RefCntAutoPtr<IPipelineState>, 4> GenerateMipsVkHelper::CreatePSOs(TEXTURE_FORMAT Fmt)
+ switch (FmtAttribs.ComponentType)
{
- ShaderCreateInfo CSCreateInfo;
- std::array<RefCntAutoPtr<IPipelineState>, 4> PSOs;
-
- CSCreateInfo.Source = g_GenerateMipsCSSource;
- CSCreateInfo.EntryPoint = "main";
- CSCreateInfo.SourceLanguage = SHADER_SOURCE_LANGUAGE_GLSL;
- CSCreateInfo.Desc.ShaderType = SHADER_TYPE_COMPUTE;
-
- const auto& FmtAttribs = GetTextureFormatAttribs(Fmt);
- bool IsGamma = FmtAttribs.ComponentType == COMPONENT_TYPE_UNORM_SRGB;
- std::array<char, 16> GlFmt;
- GetGlImageFormat(FmtAttribs, GlFmt);
-
- for (Int32 NonPowOfTwo=0; NonPowOfTwo < 4; ++NonPowOfTwo)
- {
- ShaderMacroHelper Macros;
- Macros.AddShaderMacro("NON_POWER_OF_TWO", NonPowOfTwo);
- Macros.AddShaderMacro("CONVERT_TO_SRGB", IsGamma);
- Macros.AddShaderMacro("IMG_FORMAT", GlFmt.data());
+ case COMPONENT_TYPE_FLOAT:
+ GlFmt[pos++] = 'f';
+ break;
+
+ case COMPONENT_TYPE_UNORM:
+ case COMPONENT_TYPE_UNORM_SRGB:
+ // No suffix
+ break;
+
+ case COMPONENT_TYPE_SNORM:
+ GlFmt[pos++] = '_';
+ GlFmt[pos++] = 's';
+ GlFmt[pos++] = 'n';
+ GlFmt[pos++] = 'o';
+ GlFmt[pos++] = 'r';
+ GlFmt[pos++] = 'm';
+ break;
+
+ case COMPONENT_TYPE_SINT:
+ GlFmt[pos++] = 'i';
+ break;
+
+ case COMPONENT_TYPE_UINT:
+ GlFmt[pos++] = 'u';
+ GlFmt[pos++] = 'i';
+ break;
+
+ default:
+ UNSUPPORTED("Unsupported component type");
+ }
+
+ GlFmt[pos] = 0;
+}
- Macros.Finalize();
- CSCreateInfo.Macros = Macros;
+std::array<RefCntAutoPtr<IPipelineState>, 4> GenerateMipsVkHelper::CreatePSOs(TEXTURE_FORMAT Fmt)
+{
+ ShaderCreateInfo CSCreateInfo;
- std::stringstream name_ss;
- name_ss << "Generate mips " << GlFmt.data();
- switch(NonPowOfTwo)
- {
- case 0: name_ss << " even"; break;
- case 1: name_ss << " odd X"; break;
- case 2: name_ss << " odd Y"; break;
- case 3: name_ss << " odd XY"; break;
- default: UNEXPECTED("Unexpected value");
- }
- auto name = name_ss.str();
- CSCreateInfo.Desc.Name = name.c_str();
- RefCntAutoPtr<IShader> pCS;
-
- m_DeviceVkImpl.CreateShader(CSCreateInfo, &pCS);
- PipelineStateDesc PSODesc;
- PSODesc.IsComputePipeline = true;
- PSODesc.Name = name.c_str();
- PSODesc.ComputePipeline.pCS = pCS;
-
- PSODesc.ResourceLayout.DefaultVariableType = SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC;
- ShaderResourceVariableDesc VarDesc{SHADER_TYPE_COMPUTE, "CB", SHADER_RESOURCE_VARIABLE_TYPE_STATIC};
- PSODesc.ResourceLayout.Variables = &VarDesc;
- PSODesc.ResourceLayout.NumVariables = 1;
-
- const StaticSamplerDesc StaticSampler(SHADER_TYPE_COMPUTE, "SrcMip", Sam_LinearClamp);
- PSODesc.ResourceLayout.StaticSamplers = &StaticSampler;
- PSODesc.ResourceLayout.NumStaticSamplers = 1;
-
- m_DeviceVkImpl.CreatePipelineState(PSODesc, &PSOs[NonPowOfTwo]);
- PSOs[NonPowOfTwo]->GetStaticVariableByName(SHADER_TYPE_COMPUTE, "CB")->Set(m_ConstantsCB);
- }
+ std::array<RefCntAutoPtr<IPipelineState>, 4> PSOs;
- return PSOs;
- }
+ CSCreateInfo.Source = g_GenerateMipsCSSource;
+ CSCreateInfo.EntryPoint = "main";
+ CSCreateInfo.SourceLanguage = SHADER_SOURCE_LANGUAGE_GLSL;
+ CSCreateInfo.Desc.ShaderType = SHADER_TYPE_COMPUTE;
+
+ const auto& FmtAttribs = GetTextureFormatAttribs(Fmt);
+ bool IsGamma = FmtAttribs.ComponentType == COMPONENT_TYPE_UNORM_SRGB;
- GenerateMipsVkHelper::GenerateMipsVkHelper(RenderDeviceVkImpl& DeviceVkImpl) :
- m_DeviceVkImpl(DeviceVkImpl)
+ std::array<char, 16> GlFmt;
+ GetGlImageFormat(FmtAttribs, GlFmt);
+
+ for (Int32 NonPowOfTwo = 0; NonPowOfTwo < 4; ++NonPowOfTwo)
{
- BufferDesc ConstantsCBDesc;
- ConstantsCBDesc.Name = "Constants CB buffer";
- ConstantsCBDesc.BindFlags = BIND_UNIFORM_BUFFER;
- ConstantsCBDesc.Usage = USAGE_DYNAMIC;
- ConstantsCBDesc.CPUAccessFlags = CPU_ACCESS_WRITE;
- ConstantsCBDesc.uiSizeInBytes = 32;
- DeviceVkImpl.CreateBuffer(ConstantsCBDesc, nullptr, &m_ConstantsCB);
-
- FindPSOs(TEX_FORMAT_RGBA8_UNORM);
- FindPSOs(TEX_FORMAT_BGRA8_UNORM);
+ ShaderMacroHelper Macros;
+ Macros.AddShaderMacro("NON_POWER_OF_TWO", NonPowOfTwo);
+ Macros.AddShaderMacro("CONVERT_TO_SRGB", IsGamma);
+ Macros.AddShaderMacro("IMG_FORMAT", GlFmt.data());
+
+ Macros.Finalize();
+ CSCreateInfo.Macros = Macros;
+
+ std::stringstream name_ss;
+ name_ss << "Generate mips " << GlFmt.data();
+ switch (NonPowOfTwo)
+ {
+ case 0: name_ss << " even"; break;
+ case 1: name_ss << " odd X"; break;
+ case 2: name_ss << " odd Y"; break;
+ case 3: name_ss << " odd XY"; break;
+ default: UNEXPECTED("Unexpected value");
+ }
+ auto name = name_ss.str();
+ CSCreateInfo.Desc.Name = name.c_str();
+ RefCntAutoPtr<IShader> pCS;
+
+ m_DeviceVkImpl.CreateShader(CSCreateInfo, &pCS);
+ PipelineStateDesc PSODesc;
+ PSODesc.IsComputePipeline = true;
+ PSODesc.Name = name.c_str();
+ PSODesc.ComputePipeline.pCS = pCS;
+
+ PSODesc.ResourceLayout.DefaultVariableType = SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC;
+ ShaderResourceVariableDesc VarDesc{SHADER_TYPE_COMPUTE, "CB", SHADER_RESOURCE_VARIABLE_TYPE_STATIC};
+ PSODesc.ResourceLayout.Variables = &VarDesc;
+ PSODesc.ResourceLayout.NumVariables = 1;
+
+ const StaticSamplerDesc StaticSampler(SHADER_TYPE_COMPUTE, "SrcMip", Sam_LinearClamp);
+ PSODesc.ResourceLayout.StaticSamplers = &StaticSampler;
+ PSODesc.ResourceLayout.NumStaticSamplers = 1;
+
+ m_DeviceVkImpl.CreatePipelineState(PSODesc, &PSOs[NonPowOfTwo]);
+ PSOs[NonPowOfTwo]->GetStaticVariableByName(SHADER_TYPE_COMPUTE, "CB")->Set(m_ConstantsCB);
}
- void GenerateMipsVkHelper::CreateSRB(IShaderResourceBinding** ppSRB)
+ return PSOs;
+}
+
+GenerateMipsVkHelper::GenerateMipsVkHelper(RenderDeviceVkImpl& DeviceVkImpl) :
+ m_DeviceVkImpl(DeviceVkImpl)
+{
+ BufferDesc ConstantsCBDesc;
+ ConstantsCBDesc.Name = "Constants CB buffer";
+ ConstantsCBDesc.BindFlags = BIND_UNIFORM_BUFFER;
+ ConstantsCBDesc.Usage = USAGE_DYNAMIC;
+ ConstantsCBDesc.CPUAccessFlags = CPU_ACCESS_WRITE;
+ ConstantsCBDesc.uiSizeInBytes = 32;
+ DeviceVkImpl.CreateBuffer(ConstantsCBDesc, nullptr, &m_ConstantsCB);
+
+ FindPSOs(TEX_FORMAT_RGBA8_UNORM);
+ FindPSOs(TEX_FORMAT_BGRA8_UNORM);
+}
+
+void GenerateMipsVkHelper::CreateSRB(IShaderResourceBinding** ppSRB)
+{
+ // All PSOs are compatible
+ auto& PSO = FindPSOs(TEX_FORMAT_RGBA8_UNORM);
+ PSO[0]->CreateShaderResourceBinding(ppSRB, true);
+}
+
+std::array<RefCntAutoPtr<IPipelineState>, 4>& GenerateMipsVkHelper::FindPSOs(TEXTURE_FORMAT Fmt)
+{
+ std::lock_guard<std::mutex> Lock{m_PSOMutex};
+
+ auto it = m_PSOHash.find(Fmt);
+ if (it == m_PSOHash.end())
+ it = m_PSOHash.emplace(Fmt, CreatePSOs(Fmt)).first;
+ return it->second;
+}
+
+void GenerateMipsVkHelper::WarmUpCache(TEXTURE_FORMAT Fmt)
+{
+ FindPSOs(Fmt);
+}
+
+void GenerateMipsVkHelper::GenerateMips(TextureViewVkImpl& TexView, DeviceContextVkImpl& Ctx, IShaderResourceBinding& SRB)
+{
+ auto* pTexVk = TexView.GetTexture<TextureVkImpl>();
+ if (!pTexVk->IsInKnownState())
{
- // All PSOs are compatible
- auto& PSO = FindPSOs(TEX_FORMAT_RGBA8_UNORM);
- PSO[0]->CreateShaderResourceBinding(ppSRB, true);
+ LOG_ERROR_MESSAGE("Unable to generate mips for texture '", pTexVk->GetDesc().Name, "' because the texture state is unknown");
+ return;
}
- std::array<RefCntAutoPtr<IPipelineState>, 4>& GenerateMipsVkHelper::FindPSOs(TEXTURE_FORMAT Fmt)
+ const auto OriginalState = pTexVk->GetState();
+ const auto OriginalLayout = pTexVk->GetLayout();
+ const auto& TexDesc = pTexVk->GetDesc();
+ const auto& ViewDesc = TexView.GetDesc();
+
+ DEV_CHECK_ERR(ViewDesc.NumMipLevels > 1, "Number of mip levels in the view must be greater than 1");
+ DEV_CHECK_ERR(OriginalState != RESOURCE_STATE_UNDEFINED,
+ "Attempting to generate mipmaps for texture '", TexDesc.Name,
+ "' which is in RESOURCE_STATE_UNDEFINED state ."
+ "This is not expected in Vulkan backend as textures are transition to a defined state when created.");
+ (void)OriginalState;
+
+ const auto& FmtAttribs = GetTextureFormatAttribs(ViewDesc.Format);
+
+ VkImageSubresourceRange SubresRange = {};
+ if (FmtAttribs.ComponentType == COMPONENT_TYPE_DEPTH)
+ SubresRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
+ else if (FmtAttribs.ComponentType == COMPONENT_TYPE_DEPTH_STENCIL)
{
- std::lock_guard<std::mutex> Lock{m_PSOMutex};
- auto it = m_PSOHash.find(Fmt);
- if(it == m_PSOHash.end())
- it = m_PSOHash.emplace(Fmt, CreatePSOs(Fmt)).first;
- return it->second;
+ // If image has a depth / stencil format with both depth and stencil components, then the
+ // aspectMask member of subresourceRange must include both VK_IMAGE_ASPECT_DEPTH_BIT and
+ // VK_IMAGE_ASPECT_STENCIL_BIT (6.7.3)
+ SubresRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
}
-
- void GenerateMipsVkHelper::WarmUpCache(TEXTURE_FORMAT Fmt)
+ else
+ SubresRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ SubresRange.baseArrayLayer = ViewDesc.FirstArraySlice;
+ SubresRange.layerCount = ViewDesc.NumArraySlices;
+ SubresRange.baseMipLevel = ViewDesc.MostDetailedMip;
+ SubresRange.levelCount = 1;
+
+ VkImageLayout AffectedMipLevelLayout;
+ if (TexView.HasMipLevelViews())
{
- FindPSOs(Fmt);
+ AffectedMipLevelLayout = GenerateMipsCS(TexView, Ctx, SRB, SubresRange);
}
-
- void GenerateMipsVkHelper::GenerateMips(TextureViewVkImpl& TexView, DeviceContextVkImpl& Ctx, IShaderResourceBinding& SRB)
+ else
{
- auto* pTexVk = TexView.GetTexture<TextureVkImpl>();
- if (!pTexVk->IsInKnownState())
- {
- LOG_ERROR_MESSAGE("Unable to generate mips for texture '", pTexVk->GetDesc().Name, "' because the texture state is unknown");
- return;
- }
+ AffectedMipLevelLayout = GenerateMipsBlit(TexView, Ctx, SRB, SubresRange);
+ }
- const auto OriginalState = pTexVk->GetState();
- const auto OriginalLayout = pTexVk->GetLayout();
- const auto& TexDesc = pTexVk->GetDesc();
- const auto& ViewDesc = TexView.GetDesc();
-
- DEV_CHECK_ERR(ViewDesc.NumMipLevels > 1, "Number of mip levels in the view must be greater than 1");
- DEV_CHECK_ERR(OriginalState != RESOURCE_STATE_UNDEFINED,
- "Attempting to generate mipmaps for texture '", TexDesc.Name, "' which is in RESOURCE_STATE_UNDEFINED state ."
- "This is not expected in Vulkan backend as textures are transition to a defined state when created."); (void)OriginalState;
-
- const auto& FmtAttribs = GetTextureFormatAttribs(ViewDesc.Format);
- VkImageSubresourceRange SubresRange = {};
- if (FmtAttribs.ComponentType == COMPONENT_TYPE_DEPTH)
- SubresRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
- else if (FmtAttribs.ComponentType == COMPONENT_TYPE_DEPTH_STENCIL)
- {
- // If image has a depth / stencil format with both depth and stencil components, then the
- // aspectMask member of subresourceRange must include both VK_IMAGE_ASPECT_DEPTH_BIT and
- // VK_IMAGE_ASPECT_STENCIL_BIT (6.7.3)
- SubresRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
- }
- else
- SubresRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
- SubresRange.baseArrayLayer = ViewDesc.FirstArraySlice;
- SubresRange.layerCount = ViewDesc.NumArraySlices;
- SubresRange.baseMipLevel = ViewDesc.MostDetailedMip;
- SubresRange.levelCount = 1;
-
- VkImageLayout AffectedMipLevelLayout;
- if (TexView.HasMipLevelViews())
+ // All affected mip levels are now in VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL state
+ if (AffectedMipLevelLayout != OriginalLayout)
+ {
+ bool IsAllSlices = (TexDesc.Type != RESOURCE_DIM_TEX_1D_ARRAY &&
+ TexDesc.Type != RESOURCE_DIM_TEX_2D_ARRAY &&
+ TexDesc.Type != RESOURCE_DIM_TEX_CUBE_ARRAY) ||
+ TexDesc.ArraySize == ViewDesc.NumArraySlices;
+ bool IsAllMips = ViewDesc.NumMipLevels == TexDesc.MipLevels;
+ if (IsAllSlices && IsAllMips)
{
- AffectedMipLevelLayout = GenerateMipsCS(TexView, Ctx, SRB, SubresRange);
+ pTexVk->SetLayout(AffectedMipLevelLayout);
}
else
{
- AffectedMipLevelLayout = GenerateMipsBlit(TexView, Ctx, SRB, SubresRange);
- }
-
- // All affected mip levels are now in VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL state
- if (AffectedMipLevelLayout != OriginalLayout)
- {
- bool IsAllSlices = (TexDesc.Type != RESOURCE_DIM_TEX_1D_ARRAY &&
- TexDesc.Type != RESOURCE_DIM_TEX_2D_ARRAY &&
- TexDesc.Type != RESOURCE_DIM_TEX_CUBE_ARRAY) ||
- TexDesc.ArraySize == ViewDesc.NumArraySlices;
- bool IsAllMips = ViewDesc.NumMipLevels == TexDesc.MipLevels;
- if (IsAllSlices && IsAllMips)
- {
- pTexVk->SetLayout(AffectedMipLevelLayout);
- }
- else
- {
- VERIFY(OriginalLayout != VK_IMAGE_LAYOUT_UNDEFINED, "Original layout must not be undefined");
- SubresRange.baseMipLevel = ViewDesc.MostDetailedMip;
- SubresRange.levelCount = ViewDesc.NumMipLevels;
- // Transition all affected subresources back to original layout
- Ctx.TransitionImageLayout(*pTexVk, AffectedMipLevelLayout, OriginalLayout, SubresRange);
- VERIFY_EXPR(pTexVk->GetLayout() == OriginalLayout);
- }
+ VERIFY(OriginalLayout != VK_IMAGE_LAYOUT_UNDEFINED, "Original layout must not be undefined");
+ SubresRange.baseMipLevel = ViewDesc.MostDetailedMip;
+ SubresRange.levelCount = ViewDesc.NumMipLevels;
+ // Transition all affected subresources back to original layout
+ Ctx.TransitionImageLayout(*pTexVk, AffectedMipLevelLayout, OriginalLayout, SubresRange);
+ VERIFY_EXPR(pTexVk->GetLayout() == OriginalLayout);
}
}
+}
- VkImageLayout GenerateMipsVkHelper::GenerateMipsCS(TextureViewVkImpl& TexView, DeviceContextVkImpl& Ctx, IShaderResourceBinding& SRB, VkImageSubresourceRange& SubresRange)
- {
- auto* pTexVk = TexView.GetTexture<TextureVkImpl>();
- const auto& TexDesc = pTexVk->GetDesc();
-
- VERIFY(TexDesc.Type == RESOURCE_DIM_TEX_2D || TexDesc.Type == RESOURCE_DIM_TEX_2D_ARRAY,
- "CS-based mipmap generation is only supported for 2D textures and texture arrays");
-
- const auto& ViewDesc = TexView.GetDesc();
- auto* pSrcMipVar = SRB.GetVariableByName(SHADER_TYPE_COMPUTE, "SrcMip");
- IShaderResourceVariable* pOutMipVar[4] =
+VkImageLayout GenerateMipsVkHelper::GenerateMipsCS(TextureViewVkImpl& TexView, DeviceContextVkImpl& Ctx, IShaderResourceBinding& SRB, VkImageSubresourceRange& SubresRange)
+{
+ auto* pTexVk = TexView.GetTexture<TextureVkImpl>();
+ const auto& TexDesc = pTexVk->GetDesc();
+
+ VERIFY(TexDesc.Type == RESOURCE_DIM_TEX_2D || TexDesc.Type == RESOURCE_DIM_TEX_2D_ARRAY,
+ "CS-based mipmap generation is only supported for 2D textures and texture arrays");
+
+ const auto& ViewDesc = TexView.GetDesc();
+ auto* pSrcMipVar = SRB.GetVariableByName(SHADER_TYPE_COMPUTE, "SrcMip");
+
+ IShaderResourceVariable* pOutMipVar[4] =
{
SRB.GetVariableByName(SHADER_TYPE_COMPUTE, "OutMip0"),
SRB.GetVariableByName(SHADER_TYPE_COMPUTE, "OutMip1"),
SRB.GetVariableByName(SHADER_TYPE_COMPUTE, "OutMip2"),
- SRB.GetVariableByName(SHADER_TYPE_COMPUTE, "OutMip3")
+ SRB.GetVariableByName(SHADER_TYPE_COMPUTE, "OutMip3") //
};
- auto& PSOs = FindPSOs(ViewDesc.Format);
-
- const auto OriginalState = pTexVk->GetState();
- const auto OriginalLayout = pTexVk->GetLayout();
-
- // Transition the lowest mip level to VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
- SubresRange.baseMipLevel = ViewDesc.MostDetailedMip;
- SubresRange.levelCount = 1;
- if (OriginalState != RESOURCE_STATE_SHADER_RESOURCE)
- Ctx.TransitionTextureState(*pTexVk, OriginalState, RESOURCE_STATE_SHADER_RESOURCE, false /*UpdateTextureState*/, &SubresRange);
- VERIFY_EXPR(ResourceStateToVkImageLayout(RESOURCE_STATE_SHADER_RESOURCE) == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
-
- // Note that mip levels are relative to the view's most detailed mip
- auto BottomMip = ViewDesc.NumMipLevels - 1;
- for (uint32_t TopMip = 0; TopMip < BottomMip; )
- {
- // In Vulkan, all subresources of a view must be transitioned to the same layout, so
- // we can't bind the entire texture and have to bind single mip level at a time
- auto SrcMipLevelSRV = TexView.GetMipLevelSRV(TopMip);
- VERIFY_EXPR(SrcMipLevelSRV != nullptr);
- pSrcMipVar->Set(SrcMipLevelSRV);
-
- uint32_t SrcWidth = std::max(TexDesc.Width >> (TopMip + ViewDesc.MostDetailedMip), 1u);
- uint32_t SrcHeight = std::max(TexDesc.Height >> (TopMip + ViewDesc.MostDetailedMip), 1u);
- uint32_t DstWidth = std::max(SrcWidth >> 1, 1u);
- uint32_t DstHeight = std::max(SrcHeight >> 1, 1u);
-
- // Determine if the first downsample is more than 2:1. This happens whenever
- // the source width or height is odd.
- uint32_t NonPowerOfTwo = (SrcWidth & 1) | (SrcHeight & 1) << 1;
- Ctx.SetPipelineState(PSOs[NonPowerOfTwo]);
-
- // We can downsample up to four times, but if the ratio between levels is not
- // exactly 2:1, we have to shift our blend weights, which gets complicated or
- // expensive. Maybe we can update the code later to compute sample weights for
- // each successive downsample. We use _BitScanForward to count number of zeros
- // in the low bits. Zeros indicate we can divide by two without truncating.
- uint32_t AdditionalMips = PlatformMisc::GetLSB(DstWidth | DstHeight);
- uint32_t NumMips = 1 + (AdditionalMips > 3 ? 3 : AdditionalMips);
- if (TopMip + NumMips > BottomMip)
- NumMips = BottomMip - TopMip;
-
- // These are clamped to 1 after computing additional mips because clamped
- // dimensions should not limit us from downsampling multiple times. (E.g.
- // 16x1 -> 8x1 -> 4x1 -> 2x1 -> 1x1.)
- if (DstWidth == 0)
- DstWidth = 1;
- if (DstHeight == 0)
- DstHeight = 1;
+ auto& PSOs = FindPSOs(ViewDesc.Format);
+
+ const auto OriginalState = pTexVk->GetState();
+ const auto OriginalLayout = pTexVk->GetLayout();
+
+ // Transition the lowest mip level to VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
+ SubresRange.baseMipLevel = ViewDesc.MostDetailedMip;
+ SubresRange.levelCount = 1;
+ if (OriginalState != RESOURCE_STATE_SHADER_RESOURCE)
+ Ctx.TransitionTextureState(*pTexVk, OriginalState, RESOURCE_STATE_SHADER_RESOURCE, false /*UpdateTextureState*/, &SubresRange);
+ VERIFY_EXPR(ResourceStateToVkImageLayout(RESOURCE_STATE_SHADER_RESOURCE) == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
+
+ // Note that mip levels are relative to the view's most detailed mip
+ auto BottomMip = ViewDesc.NumMipLevels - 1;
+ for (uint32_t TopMip = 0; TopMip < BottomMip;)
+ {
+ // In Vulkan, all subresources of a view must be transitioned to the same layout, so
+ // we can't bind the entire texture and have to bind single mip level at a time
+ auto SrcMipLevelSRV = TexView.GetMipLevelSRV(TopMip);
+ VERIFY_EXPR(SrcMipLevelSRV != nullptr);
+ pSrcMipVar->Set(SrcMipLevelSRV);
+
+ uint32_t SrcWidth = std::max(TexDesc.Width >> (TopMip + ViewDesc.MostDetailedMip), 1u);
+ uint32_t SrcHeight = std::max(TexDesc.Height >> (TopMip + ViewDesc.MostDetailedMip), 1u);
+ uint32_t DstWidth = std::max(SrcWidth >> 1, 1u);
+ uint32_t DstHeight = std::max(SrcHeight >> 1, 1u);
+
+ // Determine if the first downsample is more than 2:1. This happens whenever
+ // the source width or height is odd.
+ uint32_t NonPowerOfTwo = (SrcWidth & 1) | (SrcHeight & 1) << 1;
+ Ctx.SetPipelineState(PSOs[NonPowerOfTwo]);
+
+ // We can downsample up to four times, but if the ratio between levels is not
+ // exactly 2:1, we have to shift our blend weights, which gets complicated or
+ // expensive. Maybe we can update the code later to compute sample weights for
+ // each successive downsample. We use _BitScanForward to count number of zeros
+ // in the low bits. Zeros indicate we can divide by two without truncating.
+ uint32_t AdditionalMips = PlatformMisc::GetLSB(DstWidth | DstHeight);
+ uint32_t NumMips = 1 + (AdditionalMips > 3 ? 3 : AdditionalMips);
+ if (TopMip + NumMips > BottomMip)
+ NumMips = BottomMip - TopMip;
+
+ // These are clamped to 1 after computing additional mips because clamped
+ // dimensions should not limit us from downsampling multiple times. (E.g.
+ // 16x1 -> 8x1 -> 4x1 -> 2x1 -> 1x1.)
+ if (DstWidth == 0)
+ DstWidth = 1;
+ if (DstHeight == 0)
+ DstHeight = 1;
+ {
+ struct CBData
{
- struct CBData
- {
- Int32 SrcMipLevel; // Texture level of source mip
- Int32 NumMipLevels; // Number of OutMips to write: [1, 4]
- Int32 ArraySlice;
- Int32 Dummy;
- float TexelSize[2]; // 1.0 / OutMip1.Dimensions
- };
- MapHelper<CBData> MappedData(&Ctx, m_ConstantsCB, MAP_WRITE, MAP_FLAG_DISCARD);
-
- *MappedData =
+ Int32 SrcMipLevel; // Texture level of source mip
+ Int32 NumMipLevels; // Number of OutMips to write: [1, 4]
+ Int32 ArraySlice;
+ Int32 Dummy;
+ float TexelSize[2]; // 1.0 / OutMip1.Dimensions
+ };
+ MapHelper<CBData> MappedData(&Ctx, m_ConstantsCB, MAP_WRITE, MAP_FLAG_DISCARD);
+
+ *MappedData =
{
static_cast<Int32>(TopMip), // Mip levels are relateive to the view's most detailed mip
static_cast<Int32>(NumMips),
0, // Array slices are relative to the view's first array slice
0, // Unused
- {1.0f / static_cast<float>(DstWidth), 1.0f / static_cast<float>(DstHeight)}
+ {
+ 1.0f / static_cast<float>(DstWidth), 1.0f / static_cast<float>(DstHeight) //
+ } //
};
- }
-
- constexpr const Uint32 MaxMipsHandledByCS = 4; // Max number of mip levels processed by one CS shader invocation
- for (Uint32 u = 0; u < MaxMipsHandledByCS; ++u)
- {
- auto* MipLevelUAV = TexView.GetMipLevelUAV(TopMip + std::min(u + 1, NumMips));
- pOutMipVar[u]->Set(MipLevelUAV);
- }
+ }
- SubresRange.baseMipLevel = ViewDesc.MostDetailedMip + TopMip + 1;
- SubresRange.levelCount = NumMips;
- if (OriginalLayout != VK_IMAGE_LAYOUT_GENERAL)
- Ctx.TransitionImageLayout(*pTexVk, OriginalLayout, VK_IMAGE_LAYOUT_GENERAL, SubresRange);
+ constexpr const Uint32 MaxMipsHandledByCS = 4; // Max number of mip levels processed by one CS shader invocation
+ for (Uint32 u = 0; u < MaxMipsHandledByCS; ++u)
+ {
+ auto* MipLevelUAV = TexView.GetMipLevelUAV(TopMip + std::min(u + 1, NumMips));
+ pOutMipVar[u]->Set(MipLevelUAV);
+ }
- Ctx.CommitShaderResources(&SRB, RESOURCE_STATE_TRANSITION_MODE_NONE);
- DispatchComputeAttribs DispatchAttrs((DstWidth + 7) / 8, (DstHeight + 7) / 8, ViewDesc.NumArraySlices);
- Ctx.DispatchCompute(DispatchAttrs);
+ SubresRange.baseMipLevel = ViewDesc.MostDetailedMip + TopMip + 1;
+ SubresRange.levelCount = NumMips;
+ if (OriginalLayout != VK_IMAGE_LAYOUT_GENERAL)
+ Ctx.TransitionImageLayout(*pTexVk, OriginalLayout, VK_IMAGE_LAYOUT_GENERAL, SubresRange);
- Ctx.TransitionImageLayout(*pTexVk, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, SubresRange);
+ Ctx.CommitShaderResources(&SRB, RESOURCE_STATE_TRANSITION_MODE_NONE);
+ DispatchComputeAttribs DispatchAttrs((DstWidth + 7) / 8, (DstHeight + 7) / 8, ViewDesc.NumArraySlices);
+ Ctx.DispatchCompute(DispatchAttrs);
- TopMip += NumMips;
- }
+ Ctx.TransitionImageLayout(*pTexVk, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, SubresRange);
- return VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+ TopMip += NumMips;
}
- VkImageLayout GenerateMipsVkHelper::GenerateMipsBlit(TextureViewVkImpl& TexView, DeviceContextVkImpl& Ctx, IShaderResourceBinding& SRB, VkImageSubresourceRange& SubresRange)const
+ return VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+}
+
+VkImageLayout GenerateMipsVkHelper::GenerateMipsBlit(TextureViewVkImpl& TexView, DeviceContextVkImpl& Ctx, IShaderResourceBinding& SRB, VkImageSubresourceRange& SubresRange) const
+{
+ auto* pTexVk = TexView.GetTexture<TextureVkImpl>();
+ const auto& TexDesc = pTexVk->GetDesc();
+ const auto& ViewDesc = TexView.GetDesc();
+ auto vkImage = pTexVk->GetVkImage();
+
+ const auto OriginalState = pTexVk->GetState();
+ const auto OriginalLayout = ResourceStateToVkImageLayout(OriginalState);
+
+ VkImageBlit BlitRegion = {};
+
+ BlitRegion.srcSubresource.baseArrayLayer = ViewDesc.FirstArraySlice;
+ BlitRegion.srcSubresource.layerCount = ViewDesc.NumArraySlices;
+ BlitRegion.srcSubresource.aspectMask = SubresRange.aspectMask;
+ BlitRegion.dstSubresource.baseArrayLayer = BlitRegion.srcSubresource.baseArrayLayer;
+ BlitRegion.dstSubresource.layerCount = BlitRegion.srcSubresource.layerCount;
+ BlitRegion.dstSubresource.aspectMask = BlitRegion.srcSubresource.aspectMask;
+ BlitRegion.srcOffsets[0] = VkOffset3D{0, 0, 0};
+ BlitRegion.dstOffsets[0] = VkOffset3D{0, 0, 0};
+
+ SubresRange.baseMipLevel = ViewDesc.MostDetailedMip;
+ SubresRange.levelCount = 1;
+ if (OriginalState != RESOURCE_STATE_COPY_SOURCE)
+ Ctx.TransitionTextureState(*pTexVk, OriginalState, RESOURCE_STATE_COPY_SOURCE, false /*UpdateTextureState*/, &SubresRange);
+
+ auto& CmdBuffer = Ctx.GetCommandBuffer();
+ for (uint32_t mip = ViewDesc.MostDetailedMip + 1; mip < ViewDesc.MostDetailedMip + ViewDesc.NumMipLevels; ++mip)
{
- auto* pTexVk = TexView.GetTexture<TextureVkImpl>();
- const auto& TexDesc = pTexVk->GetDesc();
- const auto& ViewDesc = TexView.GetDesc();
- auto vkImage = pTexVk->GetVkImage();
-
- const auto OriginalState = pTexVk->GetState();
- const auto OriginalLayout = ResourceStateToVkImageLayout(OriginalState);
-
- VkImageBlit BlitRegion = {};
- BlitRegion.srcSubresource.baseArrayLayer = ViewDesc.FirstArraySlice;
- BlitRegion.srcSubresource.layerCount = ViewDesc.NumArraySlices;
- BlitRegion.srcSubresource.aspectMask = SubresRange.aspectMask;
- BlitRegion.dstSubresource.baseArrayLayer = BlitRegion.srcSubresource.baseArrayLayer;
- BlitRegion.dstSubresource.layerCount = BlitRegion.srcSubresource.layerCount;
- BlitRegion.dstSubresource.aspectMask = BlitRegion.srcSubresource.aspectMask;
- BlitRegion.srcOffsets[0] = VkOffset3D{0, 0, 0};
- BlitRegion.dstOffsets[0] = VkOffset3D{0, 0, 0};
-
- SubresRange.baseMipLevel = ViewDesc.MostDetailedMip;
- SubresRange.levelCount = 1;
- if (OriginalState != RESOURCE_STATE_COPY_SOURCE)
- Ctx.TransitionTextureState(*pTexVk, OriginalState, RESOURCE_STATE_COPY_SOURCE, false /*UpdateTextureState*/, &SubresRange);
-
- auto& CmdBuffer = Ctx.GetCommandBuffer();
- for (uint32_t mip = ViewDesc.MostDetailedMip + 1; mip < ViewDesc.MostDetailedMip + ViewDesc.NumMipLevels; ++mip)
- {
- BlitRegion.srcSubresource.mipLevel = mip-1;
- BlitRegion.dstSubresource.mipLevel = mip;
-
- BlitRegion.srcOffsets[1] =
- VkOffset3D
- {
- static_cast<int32_t>(std::max(TexDesc.Width >> (mip-1), 1u)),
- static_cast<int32_t>(std::max(TexDesc.Height >> (mip-1), 1u)),
- 1
- };
- BlitRegion.dstOffsets[1] =
- VkOffset3D
- {
- static_cast<int32_t>(std::max(TexDesc.Width >> mip, 1u)),
- static_cast<int32_t>(std::max(TexDesc.Height >> mip, 1u)),
- 1
- };
- if (TexDesc.Type == RESOURCE_DIM_TEX_3D)
+ BlitRegion.srcSubresource.mipLevel = mip - 1;
+ BlitRegion.dstSubresource.mipLevel = mip;
+
+ BlitRegion.srcOffsets[1] =
+ VkOffset3D //
+ {
+ static_cast<int32_t>(std::max(TexDesc.Width >> (mip - 1), 1u)),
+ static_cast<int32_t>(std::max(TexDesc.Height >> (mip - 1), 1u)),
+ 1 //
+ };
+ BlitRegion.dstOffsets[1] =
+ VkOffset3D //
{
- BlitRegion.srcOffsets[1].z = std::max(TexDesc.Depth >> (mip-1), 1u);
- BlitRegion.dstOffsets[1].z = std::max(TexDesc.Depth >> mip, 1u);
- }
-
- SubresRange.baseMipLevel = mip;
- if (OriginalLayout != VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL)
- Ctx.TransitionImageLayout(*pTexVk, OriginalLayout, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, SubresRange);
-
- CmdBuffer.BlitImage(vkImage,
- VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // must be VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL or VK_IMAGE_LAYOUT_GENERAL
- vkImage,
- VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // must be VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL or VK_IMAGE_LAYOUT_GENERAL
- 1,
- &BlitRegion,
- VK_FILTER_LINEAR);
- Ctx.TransitionImageLayout(*pTexVk, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, SubresRange);
+ static_cast<int32_t>(std::max(TexDesc.Width >> mip, 1u)),
+ static_cast<int32_t>(std::max(TexDesc.Height >> mip, 1u)),
+ 1 //
+ };
+ if (TexDesc.Type == RESOURCE_DIM_TEX_3D)
+ {
+ BlitRegion.srcOffsets[1].z = std::max(TexDesc.Depth >> (mip - 1), 1u);
+ BlitRegion.dstOffsets[1].z = std::max(TexDesc.Depth >> mip, 1u);
}
- return VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
+ SubresRange.baseMipLevel = mip;
+ if (OriginalLayout != VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL)
+ Ctx.TransitionImageLayout(*pTexVk, OriginalLayout, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, SubresRange);
+
+ CmdBuffer.BlitImage(vkImage,
+ VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // must be VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL or VK_IMAGE_LAYOUT_GENERAL
+ vkImage,
+ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // must be VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL or VK_IMAGE_LAYOUT_GENERAL
+ 1,
+ &BlitRegion,
+ VK_FILTER_LINEAR);
+ Ctx.TransitionImageLayout(*pTexVk, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, SubresRange);
}
+
+ return VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
}
+
+} // namespace Diligent
diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp
index 5179f38f..cda19a9a 100644
--- a/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp
@@ -39,16 +39,17 @@ namespace Diligent
static VkShaderStageFlagBits ShaderTypeToVkShaderStageFlagBit(SHADER_TYPE ShaderType)
{
- switch(ShaderType)
+ switch (ShaderType)
{
+ // clang-format off
case SHADER_TYPE_VERTEX: return VK_SHADER_STAGE_VERTEX_BIT;
case SHADER_TYPE_HULL: return VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
case SHADER_TYPE_DOMAIN: return VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
case SHADER_TYPE_GEOMETRY: return VK_SHADER_STAGE_GEOMETRY_BIT;
case SHADER_TYPE_PIXEL: return VK_SHADER_STAGE_FRAGMENT_BIT;
case SHADER_TYPE_COMPUTE: return VK_SHADER_STAGE_COMPUTE_BIT;
-
- default:
+ // clang-format on
+ default:
UNEXPECTED("Unknown shader type");
return VK_SHADER_STAGE_VERTEX_BIT;
}
@@ -72,7 +73,7 @@ public:
m_Map[SPIRVShaderResourceAttribs::ResourceType::SeparateSampler] = VK_DESCRIPTOR_TYPE_SAMPLER;
}
- VkDescriptorType operator[](SPIRVShaderResourceAttribs::ResourceType ResType)const
+ VkDescriptorType operator[](SPIRVShaderResourceAttribs::ResourceType ResType) const
{
return m_Map[static_cast<int>(ResType)];
}
@@ -81,26 +82,26 @@ private:
std::array<VkDescriptorType, SPIRVShaderResourceAttribs::ResourceType::NumResourceTypes> m_Map = {};
};
-VkDescriptorType PipelineLayout::GetVkDescriptorType(const SPIRVShaderResourceAttribs &Res)
+VkDescriptorType PipelineLayout::GetVkDescriptorType(const SPIRVShaderResourceAttribs& Res)
{
static const ResourceTypeToVkDescriptorType ResTypeToVkDescrType;
return ResTypeToVkDescrType[Res.Type];
}
-PipelineLayout::DescriptorSetLayoutManager::DescriptorSetLayoutManager(IMemoryAllocator &MemAllocator):
- m_MemAllocator {MemAllocator},
+PipelineLayout::DescriptorSetLayoutManager::DescriptorSetLayoutManager(IMemoryAllocator& MemAllocator) :
+ m_MemAllocator{MemAllocator},
m_LayoutBindings{STD_ALLOCATOR_RAW_MEM(VkDescriptorSetLayoutBinding, MemAllocator, "Allocator for Layout Bindings")}
{}
-void PipelineLayout::DescriptorSetLayoutManager::DescriptorSetLayout::AddBinding(const VkDescriptorSetLayoutBinding &Binding, IMemoryAllocator &MemAllocator)
+void PipelineLayout::DescriptorSetLayoutManager::DescriptorSetLayout::AddBinding(const VkDescriptorSetLayoutBinding& Binding, IMemoryAllocator& MemAllocator)
{
VERIFY(VkLayout == VK_NULL_HANDLE, "Descriptor set must not be finalized");
ReserveMemory(NumLayoutBindings + 1, MemAllocator);
pBindings[NumLayoutBindings++] = Binding;
TotalDescriptors += Binding.descriptorCount;
- if (Binding.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC ||
- Binding.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC)
+ if (Binding.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC ||
+ Binding.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC)
{
VERIFY(NumDynamicDescriptors + Binding.descriptorCount <= std::numeric_limits<decltype(NumDynamicDescriptors)>::max(), "Number of dynamic descriptors exceeds max representable value");
NumDynamicDescriptors += static_cast<decltype(NumDynamicDescriptors)>(Binding.descriptorCount);
@@ -121,25 +122,25 @@ size_t PipelineLayout::DescriptorSetLayoutManager::DescriptorSetLayout::GetMemor
// NumBindings = 2^n
// n n-1 2 1 0
// 2^n = 1 0 ... 0 0 0
- //
+ //
// n n-1 2 1 0
// 2^n-1 = 0 1 ... 1 1 1
- // msb = n-1
+ // msb = n-1
// MemSize = 2^n
// NumBindings = 2^n + [1 .. 2^n-1]
- // n n-1
- // 2^n = 1 0 ... 1 ...
- //
- // n n-1
- // 2^n-1 = 1 0 ...
- // msb = n
+ // n n-1
+ // 2^n = 1 0 ... 1 ...
+ //
+ // n n-1
+ // 2^n-1 = 1 0 ...
+ // msb = n
// MemSize = 2^(n+1)
- MemSize = Uint32{2U << PlatformMisc::GetMSB(NumBindings-1)};
+ MemSize = Uint32{2U << PlatformMisc::GetMSB(NumBindings - 1)};
}
- VERIFY_EXPR( ((NumBindings & (NumBindings-1)) == 0) && NumBindings == MemSize || NumBindings < MemSize);
+ VERIFY_EXPR(((NumBindings & (NumBindings - 1)) == 0) && NumBindings == MemSize || NumBindings < MemSize);
#ifdef _DEBUG
static constexpr size_t MinMemSize = 1;
@@ -150,7 +151,7 @@ size_t PipelineLayout::DescriptorSetLayoutManager::DescriptorSetLayout::GetMemor
return MemSize * sizeof(VkDescriptorSetLayoutBinding);
}
-void PipelineLayout::DescriptorSetLayoutManager::DescriptorSetLayout::ReserveMemory(Uint32 NumBindings, IMemoryAllocator &MemAllocator)
+void PipelineLayout::DescriptorSetLayoutManager::DescriptorSetLayout::ReserveMemory(Uint32 NumBindings, IMemoryAllocator& MemAllocator)
{
size_t ReservedMemory = GetMemorySize(NumLayoutBindings);
size_t RequiredMemory = GetMemorySize(NumBindings);
@@ -166,33 +167,34 @@ void PipelineLayout::DescriptorSetLayoutManager::DescriptorSetLayout::ReserveMem
}
}
-void PipelineLayout::DescriptorSetLayoutManager::DescriptorSetLayout::Finalize(const VulkanUtilities::VulkanLogicalDevice &LogicalDevice,
- IMemoryAllocator &MemAllocator,
- VkDescriptorSetLayoutBinding* pNewBindings)
+void PipelineLayout::DescriptorSetLayoutManager::DescriptorSetLayout::Finalize(const VulkanUtilities::VulkanLogicalDevice& LogicalDevice,
+ IMemoryAllocator& MemAllocator,
+ VkDescriptorSetLayoutBinding* pNewBindings)
{
- VERIFY_EXPR( memcmp(pBindings, pNewBindings, sizeof(VkDescriptorSetLayoutBinding)*NumLayoutBindings) == 0 );
+ VERIFY_EXPR(memcmp(pBindings, pNewBindings, sizeof(VkDescriptorSetLayoutBinding) * NumLayoutBindings) == 0);
VkDescriptorSetLayoutCreateInfo SetLayoutCI = {};
- SetLayoutCI.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
- SetLayoutCI.pNext = nullptr;
- SetLayoutCI.flags = 0;
+
+ SetLayoutCI.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
+ SetLayoutCI.pNext = nullptr;
+ SetLayoutCI.flags = 0;
SetLayoutCI.bindingCount = NumLayoutBindings;
- SetLayoutCI.pBindings = pBindings;
- VkLayout = LogicalDevice.CreateDescriptorSetLayout(SetLayoutCI);
+ SetLayoutCI.pBindings = pBindings;
+ VkLayout = LogicalDevice.CreateDescriptorSetLayout(SetLayoutCI);
MemAllocator.Free(pBindings);
pBindings = pNewBindings;
}
-void PipelineLayout::DescriptorSetLayoutManager::DescriptorSetLayout::Release(RenderDeviceVkImpl *pRenderDeviceVk, IMemoryAllocator &MemAllocator, Uint64 CommandQueueMask)
+void PipelineLayout::DescriptorSetLayoutManager::DescriptorSetLayout::Release(RenderDeviceVkImpl* pRenderDeviceVk, IMemoryAllocator& MemAllocator, Uint64 CommandQueueMask)
{
pRenderDeviceVk->SafeReleaseDeviceObject(std::move(VkLayout), CommandQueueMask);
- for (uint32_t b=0; b < NumLayoutBindings; ++b)
+ for (uint32_t b = 0; b < NumLayoutBindings; ++b)
{
if (pBindings[b].pImmutableSamplers != nullptr)
MemAllocator.Free(const_cast<VkSampler*>(pBindings[b].pImmutableSamplers));
}
- pBindings = nullptr;
+ pBindings = nullptr;
NumLayoutBindings = 0;
}
@@ -201,55 +203,60 @@ PipelineLayout::DescriptorSetLayoutManager::DescriptorSetLayout::~DescriptorSetL
VERIFY(VkLayout == VK_NULL_HANDLE, "Vulkan descriptor set layout has not been released. Did you forget to call Release()?");
}
-bool PipelineLayout::DescriptorSetLayoutManager::DescriptorSetLayout::operator == (const DescriptorSetLayout& rhs)const
+bool PipelineLayout::DescriptorSetLayoutManager::DescriptorSetLayout::operator==(const DescriptorSetLayout& rhs) const
{
+ // clang-format off
if (TotalDescriptors != rhs.TotalDescriptors ||
SetIndex != rhs.SetIndex ||
NumDynamicDescriptors != rhs.NumDynamicDescriptors ||
NumLayoutBindings != rhs.NumLayoutBindings)
return false;
+ // clang-format on
- for(uint32_t b=0; b < NumLayoutBindings; ++b)
+ for (uint32_t b = 0; b < NumLayoutBindings; ++b)
{
- const auto &B0 = pBindings[b];
- const auto &B1 = rhs.pBindings[b];
+ const auto& B0 = pBindings[b];
+ const auto& B1 = rhs.pBindings[b];
+ // clang-format off
if (B0.binding != B1.binding ||
B0.descriptorType != B1.descriptorType ||
B0.descriptorCount != B1.descriptorCount ||
B0.stageFlags != B1.stageFlags)
return false;
- if ( (B0.pImmutableSamplers != nullptr && B1.pImmutableSamplers == nullptr) ||
- (B0.pImmutableSamplers == nullptr && B1.pImmutableSamplers != nullptr) )
+ if ((B0.pImmutableSamplers != nullptr && B1.pImmutableSamplers == nullptr) ||
+ (B0.pImmutableSamplers == nullptr && B1.pImmutableSamplers != nullptr))
return false;
// Static samplers themselves should not affect compatibility
+ // clang-format on
}
return true;
}
-size_t PipelineLayout::DescriptorSetLayoutManager::DescriptorSetLayout::GetHash()const
+size_t PipelineLayout::DescriptorSetLayoutManager::DescriptorSetLayout::GetHash() const
{
size_t Hash = ComputeHash(SetIndex, NumLayoutBindings, TotalDescriptors, NumDynamicDescriptors);
for (uint32_t b = 0; b < NumLayoutBindings; ++b)
{
- const auto &B = pBindings[b];
+ const auto& B = pBindings[b];
HashCombine(Hash, B.binding, static_cast<size_t>(B.descriptorType), B.descriptorCount, static_cast<size_t>(B.stageFlags), B.pImmutableSamplers != nullptr);
}
return Hash;
}
-void PipelineLayout::DescriptorSetLayoutManager::Finalize(const VulkanUtilities::VulkanLogicalDevice &LogicalDevice)
+void PipelineLayout::DescriptorSetLayoutManager::Finalize(const VulkanUtilities::VulkanLogicalDevice& LogicalDevice)
{
size_t TotalBindings = 0;
- for (const auto &Layout : m_DescriptorSetLayouts)
+ for (const auto& Layout : m_DescriptorSetLayouts)
{
TotalBindings += Layout.NumLayoutBindings;
}
m_LayoutBindings.resize(TotalBindings);
size_t BindingOffset = 0;
+
std::array<VkDescriptorSetLayout, 2> ActiveDescrSetLayouts = {};
- for (auto &Layout : m_DescriptorSetLayouts)
+ for (auto& Layout : m_DescriptorSetLayouts)
{
if (Layout.SetIndex >= 0)
{
@@ -260,26 +267,29 @@ void PipelineLayout::DescriptorSetLayoutManager::Finalize(const VulkanUtilities:
}
}
VERIFY_EXPR(BindingOffset == TotalBindings);
+ // clang-format off
VERIFY_EXPR(m_ActiveSets == 0 && ActiveDescrSetLayouts[0] == VK_NULL_HANDLE && ActiveDescrSetLayouts[1] == VK_NULL_HANDLE ||
m_ActiveSets == 1 && ActiveDescrSetLayouts[0] != VK_NULL_HANDLE && ActiveDescrSetLayouts[1] == VK_NULL_HANDLE ||
m_ActiveSets == 2 && ActiveDescrSetLayouts[0] != VK_NULL_HANDLE && ActiveDescrSetLayouts[1] != VK_NULL_HANDLE);
+ // clang-format on
VkPipelineLayoutCreateInfo PipelineLayoutCI = {};
- PipelineLayoutCI.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
- PipelineLayoutCI.pNext = nullptr;
- PipelineLayoutCI.flags = 0; // reserved for future use
- PipelineLayoutCI.setLayoutCount = m_ActiveSets;
- PipelineLayoutCI.pSetLayouts = PipelineLayoutCI.setLayoutCount != 0 ? ActiveDescrSetLayouts.data() : nullptr;
+
+ PipelineLayoutCI.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
+ PipelineLayoutCI.pNext = nullptr;
+ PipelineLayoutCI.flags = 0; // reserved for future use
+ PipelineLayoutCI.setLayoutCount = m_ActiveSets;
+ PipelineLayoutCI.pSetLayouts = PipelineLayoutCI.setLayoutCount != 0 ? ActiveDescrSetLayouts.data() : nullptr;
PipelineLayoutCI.pushConstantRangeCount = 0;
- PipelineLayoutCI.pPushConstantRanges = nullptr;
- m_VkPipelineLayout = LogicalDevice.CreatePipelineLayout(PipelineLayoutCI);
+ PipelineLayoutCI.pPushConstantRanges = nullptr;
+ m_VkPipelineLayout = LogicalDevice.CreatePipelineLayout(PipelineLayoutCI);
VERIFY_EXPR(BindingOffset == TotalBindings);
}
-void PipelineLayout::DescriptorSetLayoutManager::Release(RenderDeviceVkImpl *pRenderDeviceVk, Uint64 CommandQueueMask)
+void PipelineLayout::DescriptorSetLayoutManager::Release(RenderDeviceVkImpl* pRenderDeviceVk, Uint64 CommandQueueMask)
{
- for (auto &Layout : m_DescriptorSetLayouts)
+ for (auto& Layout : m_DescriptorSetLayouts)
Layout.Release(pRenderDeviceVk, m_MemAllocator, CommandQueueMask);
pRenderDeviceVk->SafeReleaseDeviceObject(std::move(m_VkPipelineLayout), CommandQueueMask);
@@ -290,26 +300,26 @@ PipelineLayout::DescriptorSetLayoutManager::~DescriptorSetLayoutManager()
VERIFY(m_VkPipelineLayout == VK_NULL_HANDLE, "Vulkan pipeline layout has not been released. Did you forget to call Release()?");
}
-bool PipelineLayout::DescriptorSetLayoutManager::operator == (const DescriptorSetLayoutManager& rhs)const
+bool PipelineLayout::DescriptorSetLayoutManager::operator==(const DescriptorSetLayoutManager& rhs) const
{
- // Two pipeline layouts are defined to be “compatible for set N” if they were created with identically
- // defined descriptor set layouts for sets zero through N, and if they were created with identical push
+ // Two pipeline layouts are defined to be "compatible for set N" if they were created with identically
+ // defined descriptor set layouts for sets zero through N, and if they were created with identical push
// constant ranges (13.2.2)
if (m_ActiveSets != rhs.m_ActiveSets)
return false;
- for (size_t i=0; i < m_DescriptorSetLayouts.size(); ++i)
+ for (size_t i = 0; i < m_DescriptorSetLayouts.size(); ++i)
if (m_DescriptorSetLayouts[i] != rhs.m_DescriptorSetLayouts[i])
return false;
return true;
}
-size_t PipelineLayout::DescriptorSetLayoutManager::GetHash()const
+size_t PipelineLayout::DescriptorSetLayoutManager::GetHash() const
{
size_t Hash = 0;
- for (const auto &SetLayout : m_DescriptorSetLayouts)
+ for (const auto& SetLayout : m_DescriptorSetLayouts)
HashCombine(Hash, SetLayout.GetHash());
return Hash;
@@ -331,19 +341,21 @@ void PipelineLayout::DescriptorSetLayoutManager::AllocateResourceSlot(const SPIR
DescriptorSet = DescrSet.SetIndex;
VkDescriptorSetLayoutBinding VkBinding = {};
+
Binding = DescrSet.NumLayoutBindings;
- VkBinding.binding = Binding;
- VkBinding.descriptorType = GetVkDescriptorType(ResAttribs);
+
+ VkBinding.binding = Binding;
+ VkBinding.descriptorType = GetVkDescriptorType(ResAttribs);
VkBinding.descriptorCount = ResAttribs.ArraySize;
// There are no limitations on what combinations of stages can use a descriptor binding (13.2.1)
VkBinding.stageFlags = ShaderTypeToVkShaderStageFlagBit(ShaderType);
if (vkImmutableSampler != VK_NULL_HANDLE)
{
- // If descriptorType is VK_DESCRIPTOR_TYPE_SAMPLER or VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, and
- // descriptorCount is not 0 and pImmutableSamplers is not NULL, pImmutableSamplers must be a valid pointer
+ // If descriptorType is VK_DESCRIPTOR_TYPE_SAMPLER or VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, and
+ // descriptorCount is not 0 and pImmutableSamplers is not NULL, pImmutableSamplers must be a valid pointer
// to an array of descriptorCount valid VkSampler handles (13.2.1)
auto* pImmutableSamplers = ALLOCATE(m_MemAllocator, "Memory buffer for immutable samplers", VkSampler, VkBinding.descriptorCount);
- for (uint32_t s=0; s < VkBinding.descriptorCount; ++s)
+ for (uint32_t s = 0; s < VkBinding.descriptorCount; ++s)
pImmutableSamplers[s] = vkImmutableSampler;
VkBinding.pImmutableSamplers = pImmutableSamplers;
}
@@ -354,13 +366,13 @@ void PipelineLayout::DescriptorSetLayoutManager::AllocateResourceSlot(const SPIR
DescrSet.AddBinding(VkBinding, m_MemAllocator);
}
-PipelineLayout::PipelineLayout() :
- m_MemAllocator(GetRawAllocator()),
- m_LayoutMgr(m_MemAllocator)
+PipelineLayout::PipelineLayout() :
+ m_MemAllocator{GetRawAllocator()},
+ m_LayoutMgr{m_MemAllocator}
{
}
-void PipelineLayout::Release(RenderDeviceVkImpl *pDeviceVkImpl, Uint64 CommandQueueMask)
+void PipelineLayout::Release(RenderDeviceVkImpl* pDeviceVkImpl, Uint64 CommandQueueMask)
{
m_LayoutMgr.Release(pDeviceVkImpl, CommandQueueMask);
}
@@ -370,15 +382,16 @@ void PipelineLayout::AllocateResourceSlot(const SPIRVShaderResourceAttribs& ResA
VkSampler vkImmutableSampler,
SHADER_TYPE ShaderType,
Uint32& DescriptorSet, // Output parameter
- Uint32& Binding, // Output parameter
+ Uint32& Binding, // Output parameter
Uint32& OffsetInCache,
std::vector<uint32_t>& SPIRV)
{
- VERIFY( (ResAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage ||
- ResAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler) || vkImmutableSampler == VK_NULL_HANDLE,
- "Immutable sampler should only be specified for combined image samplers or separate samplers");
- m_LayoutMgr.AllocateResourceSlot(ResAttribs, VariableType ,vkImmutableSampler, ShaderType, DescriptorSet, Binding, OffsetInCache);
- SPIRV[ResAttribs.BindingDecorationOffset] = Binding;
+ VERIFY((ResAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage ||
+ ResAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler) ||
+ vkImmutableSampler == VK_NULL_HANDLE,
+ "Immutable sampler should only be specified for combined image samplers or separate samplers");
+ m_LayoutMgr.AllocateResourceSlot(ResAttribs, VariableType, vkImmutableSampler, ShaderType, DescriptorSet, Binding, OffsetInCache);
+ SPIRV[ResAttribs.BindingDecorationOffset] = Binding;
SPIRV[ResAttribs.DescriptorSetDecorationOffset] = DescriptorSet;
}
@@ -387,22 +400,22 @@ void PipelineLayout::Finalize(const VulkanUtilities::VulkanLogicalDevice& Logica
m_LayoutMgr.Finalize(LogicalDevice);
}
-std::array<Uint32, 2> PipelineLayout::GetDescriptorSetSizes(Uint32& NumSets)const
+std::array<Uint32, 2> PipelineLayout::GetDescriptorSetSizes(Uint32& NumSets) const
{
- NumSets = 0;
+ NumSets = 0;
std::array<Uint32, 2> SetSizes = {};
- const auto &StaticAndMutSet = m_LayoutMgr.GetDescriptorSet(SHADER_RESOURCE_VARIABLE_TYPE_STATIC);
+ const auto& StaticAndMutSet = m_LayoutMgr.GetDescriptorSet(SHADER_RESOURCE_VARIABLE_TYPE_STATIC);
if (StaticAndMutSet.SetIndex >= 0)
{
- NumSets = std::max(NumSets, static_cast<Uint32>(StaticAndMutSet.SetIndex + 1));
+ NumSets = std::max(NumSets, static_cast<Uint32>(StaticAndMutSet.SetIndex + 1));
SetSizes[StaticAndMutSet.SetIndex] = StaticAndMutSet.TotalDescriptors;
}
- const auto &DynamicSet = m_LayoutMgr.GetDescriptorSet(SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC);
+ const auto& DynamicSet = m_LayoutMgr.GetDescriptorSet(SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC);
if (DynamicSet.SetIndex >= 0)
{
- NumSets = std::max(NumSets, static_cast<Uint32>(DynamicSet.SetIndex + 1));
+ NumSets = std::max(NumSets, static_cast<Uint32>(DynamicSet.SetIndex + 1));
SetSizes[DynamicSet.SetIndex] = DynamicSet.TotalDescriptors;
}
@@ -412,11 +425,11 @@ std::array<Uint32, 2> PipelineLayout::GetDescriptorSetSizes(Uint32& NumSets)cons
void PipelineLayout::InitResourceCache(RenderDeviceVkImpl* pDeviceVkImpl,
ShaderResourceCacheVk& ResourceCache,
IMemoryAllocator& CacheMemAllocator,
- const char* DbgPipelineName)const
+ const char* DbgPipelineName) const
{
- Uint32 NumSets = 0;
- auto SetSizes = GetDescriptorSetSizes(NumSets);
-
+ Uint32 NumSets = 0;
+ auto SetSizes = GetDescriptorSetSizes(NumSets);
+
// This call only initializes descriptor sets (ShaderResourceCacheVk::DescriptorSet) in the resource cache
// Resources are initialized by source layout when shader resource binding objects are created
ResourceCache.InitializeSets(CacheMemAllocator, NumSets, SetSizes.data());
@@ -435,24 +448,25 @@ void PipelineLayout::InitResourceCache(RenderDeviceVkImpl* pDeviceVkImpl,
}
}
-void PipelineLayout::PrepareDescriptorSets(DeviceContextVkImpl* pCtxVkImpl,
- bool IsCompute,
- const ShaderResourceCacheVk& ResourceCache,
- DescriptorSetBindInfo& BindInfo,
- VkDescriptorSet VkDynamicDescrSet)const
+void PipelineLayout::PrepareDescriptorSets(DeviceContextVkImpl* pCtxVkImpl,
+ bool IsCompute,
+ const ShaderResourceCacheVk& ResourceCache,
+ DescriptorSetBindInfo& BindInfo,
+ VkDescriptorSet VkDynamicDescrSet) const
{
#ifdef _DEBUG
BindInfo.vkSets.clear();
#endif
- // Do not use vector::resize for BindInfo.vkSets and BindInfo.DynamicOffsets as this
+ // Do not use vector::resize for BindInfo.vkSets and BindInfo.DynamicOffsets as this
// causes unnecessary work to zero-initialize new elements
- VERIFY(m_LayoutMgr.GetDescriptorSet(SHADER_RESOURCE_VARIABLE_TYPE_STATIC).SetIndex == m_LayoutMgr.GetDescriptorSet(SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE).SetIndex,
+ VERIFY(m_LayoutMgr.GetDescriptorSet(SHADER_RESOURCE_VARIABLE_TYPE_STATIC).SetIndex == m_LayoutMgr.GetDescriptorSet(SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE).SetIndex,
"Static and mutable variables are expected to share the same descriptor set");
Uint32 TotalDynamicDescriptors = 0;
+
BindInfo.SetCout = 0;
- for(SHADER_RESOURCE_VARIABLE_TYPE VarType = SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE; VarType <= SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC; VarType = static_cast<SHADER_RESOURCE_VARIABLE_TYPE>(VarType+1))
+ for (SHADER_RESOURCE_VARIABLE_TYPE VarType = SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE; VarType <= SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC; VarType = static_cast<SHADER_RESOURCE_VARIABLE_TYPE>(VarType + 1))
{
const auto& Set = m_LayoutMgr.GetDescriptorSet(VarType);
if (Set.SetIndex >= 0)
@@ -481,7 +495,7 @@ void PipelineLayout::PrepareDescriptorSets(DeviceContextVkImpl* pCtxVkI
BindInfo.DynamicOffsetCount = TotalDynamicDescriptors;
if (TotalDynamicDescriptors > BindInfo.DynamicOffsets.size())
BindInfo.DynamicOffsets.resize(TotalDynamicDescriptors);
- BindInfo.BindPoint = IsCompute ? VK_PIPELINE_BIND_POINT_COMPUTE : VK_PIPELINE_BIND_POINT_GRAPHICS;
+ BindInfo.BindPoint = IsCompute ? VK_PIPELINE_BIND_POINT_COMPUTE : VK_PIPELINE_BIND_POINT_GRAPHICS;
BindInfo.pResourceCache = &ResourceCache;
#ifdef _DEBUG
BindInfo.pDbgPipelineLayout = this;
@@ -493,15 +507,15 @@ void PipelineLayout::PrepareDescriptorSets(DeviceContextVkImpl* pCtxVkI
// There are no dynamic descriptors, so we can bind descriptor sets right now
auto& CmdBuffer = pCtxVkImpl->GetCommandBuffer();
CmdBuffer.BindDescriptorSets(BindInfo.BindPoint,
- m_LayoutMgr.GetVkPipelineLayout(),
+ m_LayoutMgr.GetVkPipelineLayout(),
0, // First set
BindInfo.SetCout,
BindInfo.vkSets.data(), // BindInfo.vkSets is never empty
- 0,
+ 0,
nullptr);
}
BindInfo.DynamicDescriptorsBound = false;
}
-}
+} // namespace Diligent
diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp
index 1c4cd26c..3eb7851d 100644
--- a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp
@@ -37,25 +37,26 @@ namespace Diligent
{
VkRenderPassCreateInfo PipelineStateVkImpl::GetRenderPassCreateInfo(
- Uint32 NumRenderTargets,
- const TEXTURE_FORMAT RTVFormats[],
- TEXTURE_FORMAT DSVFormat,
- Uint32 SampleCount,
- std::array<VkAttachmentDescription, MaxRenderTargets+1>& Attachments,
- std::array<VkAttachmentReference, MaxRenderTargets+1>& AttachmentReferences,
- VkSubpassDescription& SubpassDesc)
+ Uint32 NumRenderTargets,
+ const TEXTURE_FORMAT RTVFormats[],
+ TEXTURE_FORMAT DSVFormat,
+ Uint32 SampleCount,
+ std::array<VkAttachmentDescription, MaxRenderTargets + 1>& Attachments,
+ std::array<VkAttachmentReference, MaxRenderTargets + 1>& AttachmentReferences,
+ VkSubpassDescription& SubpassDesc)
{
VERIFY_EXPR(NumRenderTargets <= MaxRenderTargets);
// Prepare render pass create info (7.1)
VkRenderPassCreateInfo RenderPassCI = {};
+
RenderPassCI.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
RenderPassCI.pNext = nullptr;
RenderPassCI.flags = 0; // reserved for future use
RenderPassCI.attachmentCount = (DSVFormat != TEX_FORMAT_UNKNOWN ? 1 : 0) + NumRenderTargets;
- uint32_t AttachmentInd = 0;
- VkSampleCountFlagBits SampleCountFlags = static_cast<VkSampleCountFlagBits>(SampleCount);
+ uint32_t AttachmentInd = 0;
+ VkSampleCountFlagBits SampleCountFlags = static_cast<VkSampleCountFlagBits>(SampleCount);
VkAttachmentReference* pDepthAttachmentReference = nullptr;
if (DSVFormat != TEX_FORMAT_UNKNOWN)
{
@@ -64,20 +65,20 @@ VkRenderPassCreateInfo PipelineStateVkImpl::GetRenderPassCreateInfo(
DepthAttachment.flags = 0; // Allowed value VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT
DepthAttachment.format = TexFormatToVkFormat(DSVFormat);
DepthAttachment.samples = SampleCountFlags;
- DepthAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; // previous contents of the image within the render area
- // will be preserved. For attachments with a depth/stencil format,
- // this uses the access type VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT.
- DepthAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; // the contents generated during the render pass and within the render
+ DepthAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; // previous contents of the image within the render area
+ // will be preserved. For attachments with a depth/stencil format,
+ // this uses the access type VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT.
+ DepthAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; // the contents generated during the render pass and within the render
// area are written to memory. For attachments with a depth/stencil format,
- // this uses the access type VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT.
+ // this uses the access type VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT.
DepthAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
DepthAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
DepthAttachment.initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
DepthAttachment.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
- pDepthAttachmentReference = &AttachmentReferences[AttachmentInd];
+ pDepthAttachmentReference = &AttachmentReferences[AttachmentInd];
pDepthAttachmentReference->attachment = AttachmentInd;
- pDepthAttachmentReference->layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+ pDepthAttachmentReference->layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
++AttachmentInd;
}
@@ -90,18 +91,18 @@ VkRenderPassCreateInfo PipelineStateVkImpl::GetRenderPassCreateInfo(
ColorAttachment.flags = 0; // Allowed value VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT
ColorAttachment.format = TexFormatToVkFormat(RTVFormats[rt]);
ColorAttachment.samples = SampleCountFlags;
- ColorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; // previous contents of the image within the render area
- // will be preserved. For attachments with a depth/stencil format,
- // this uses the access type VK_ACCESS_COLOR_ATTACHMENT_READ_BIT.
+ ColorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; // previous contents of the image within the render area
+ // will be preserved. For attachments with a depth/stencil format,
+ // this uses the access type VK_ACCESS_COLOR_ATTACHMENT_READ_BIT.
ColorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; // the contents generated during the render pass and within the render
// area are written to memory. For attachments with a color format,
- // this uses the access type VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT.
+ // this uses the access type VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT.
ColorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
ColorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
ColorAttachment.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
ColorAttachment.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
- auto& ColorAttachmentRef = AttachmentReferences[AttachmentInd];
+ auto& ColorAttachmentRef = AttachmentReferences[AttachmentInd];
ColorAttachmentRef.attachment = AttachmentInd;
ColorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
}
@@ -109,12 +110,12 @@ VkRenderPassCreateInfo PipelineStateVkImpl::GetRenderPassCreateInfo(
RenderPassCI.pAttachments = Attachments.data();
RenderPassCI.subpassCount = 1;
RenderPassCI.pSubpasses = &SubpassDesc;
- RenderPassCI.dependencyCount = 0; // the number of dependencies between pairs of subpasses, or zero indicating no dependencies.
- RenderPassCI.pDependencies = nullptr; // an array of dependencyCount number of VkSubpassDependency structures describing
- // dependencies between pairs of subpasses, or NULL if dependencyCount is zero.
+ RenderPassCI.dependencyCount = 0; // the number of dependencies between pairs of subpasses, or zero indicating no dependencies.
+ RenderPassCI.pDependencies = nullptr; // an array of dependencyCount number of VkSubpassDependency structures describing
+ // dependencies between pairs of subpasses, or NULL if dependencyCount is zero.
- SubpassDesc.flags = 0; // All bits for this type are defined by extensions
+ SubpassDesc.flags = 0; // All bits for this type are defined by extensions
SubpassDesc.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; // Currently, only graphics subpasses are supported.
SubpassDesc.inputAttachmentCount = 0;
SubpassDesc.pInputAttachments = nullptr;
@@ -131,7 +132,7 @@ VkRenderPassCreateInfo PipelineStateVkImpl::GetRenderPassCreateInfo(
static std::vector<uint32_t> StripReflection(const std::vector<uint32_t>& OriginalSPIRV)
{
std::vector<uint32_t> StrippedSPIRV;
- spvtools::Optimizer SpirvOptimizer(SPV_ENV_VULKAN_1_0);
+ spvtools::Optimizer SpirvOptimizer(SPV_ENV_VULKAN_1_0);
// Decorations defined in SPV_GOOGLE_hlsl_functionality1 are the only instructions
// removed by strip-reflect-info pass. SPIRV offsets become INVALID after this operation.
SpirvOptimizer.RegisterPass(spvtools::CreateStripReflectInfoPass());
@@ -144,30 +145,32 @@ static std::vector<uint32_t> StripReflection(const std::vector<uint32_t>& Origin
return StrippedSPIRV;
}
-PipelineStateVkImpl :: PipelineStateVkImpl(IReferenceCounters* pRefCounters,
- RenderDeviceVkImpl* pDeviceVk,
- const PipelineStateDesc& PipelineDesc) :
+PipelineStateVkImpl ::PipelineStateVkImpl(IReferenceCounters* pRefCounters,
+ RenderDeviceVkImpl* pDeviceVk,
+ const PipelineStateDesc& PipelineDesc) :
TPipelineStateBase{pRefCounters, pDeviceVk, PipelineDesc},
- m_SRBMemAllocator {GetRawAllocator()}
+ m_SRBMemAllocator{GetRawAllocator()}
{
const auto& LogicalDevice = pDeviceVk->GetLogicalDevice();
// Initialize shader resource layouts
auto& ShaderResLayoutAllocator = GetRawAllocator();
+
std::array<std::shared_ptr<const SPIRVShaderResources>, MaxShadersInPipeline> ShaderResources;
- std::array<std::vector<uint32_t>, MaxShadersInPipeline> ShaderSPIRVs;
- m_ShaderResourceLayouts = ALLOCATE(ShaderResLayoutAllocator, "Raw memory for ShaderResourceLayoutVk", ShaderResourceLayoutVk, m_NumShaders * 2);
- m_StaticResCaches = ALLOCATE(GetRawAllocator(), "Raw memory for ShaderResourceCacheVk", ShaderResourceCacheVk, m_NumShaders);
- m_StaticVarsMgrs = ALLOCATE(GetRawAllocator(), "Raw memory for ShaderVariableManagerVk", ShaderVariableManagerVk, m_NumShaders);
- for (Uint32 s=0; s < m_NumShaders; ++s)
+ std::array<std::vector<uint32_t>, MaxShadersInPipeline> ShaderSPIRVs;
+
+ m_ShaderResourceLayouts = ALLOCATE(ShaderResLayoutAllocator, "Raw memory for ShaderResourceLayoutVk", ShaderResourceLayoutVk, m_NumShaders * 2);
+ m_StaticResCaches = ALLOCATE(GetRawAllocator(), "Raw memory for ShaderResourceCacheVk", ShaderResourceCacheVk, m_NumShaders);
+ m_StaticVarsMgrs = ALLOCATE(GetRawAllocator(), "Raw memory for ShaderVariableManagerVk", ShaderVariableManagerVk, m_NumShaders);
+ for (Uint32 s = 0; s < m_NumShaders; ++s)
{
new (m_ShaderResourceLayouts + s) ShaderResourceLayoutVk(LogicalDevice);
- auto* pShaderVk = GetShader<const ShaderVkImpl>(s);
+ auto* pShaderVk = GetShader<const ShaderVkImpl>(s);
ShaderResources[s] = pShaderVk->GetShaderResources();
ShaderSPIRVs[s] = pShaderVk->GetSPIRV();
- const auto ShaderType = pShaderVk->GetDesc().ShaderType;
- const auto ShaderTypeInd = GetShaderTypeIndex(ShaderType);
+ const auto ShaderType = pShaderVk->GetDesc().ShaderType;
+ const auto ShaderTypeInd = GetShaderTypeIndex(ShaderType);
m_ResourceLayoutIndex[ShaderTypeInd] = static_cast<Int8>(s);
auto* pStaticResLayout = new (m_ShaderResourceLayouts + m_NumShaders + s) ShaderResourceLayoutVk(LogicalDevice);
@@ -186,13 +189,14 @@ PipelineStateVkImpl :: PipelineStateVkImpl(IReferenceCounters* pRefCounters
for (Uint32 s = 0; s < m_NumShaders; ++s)
{
const SHADER_RESOURCE_VARIABLE_TYPE AllowedVarTypes[] = {SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE, SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC};
- Uint32 UnusedNumVars = 0;
+
+ Uint32 UnusedNumVars = 0;
ShaderVariableDataSizes[s] = ShaderVariableManagerVk::GetRequiredMemorySize(m_ShaderResourceLayouts[s], AllowedVarTypes, _countof(AllowedVarTypes), UnusedNumVars);
}
- Uint32 NumSets = 0;
- auto DescriptorSetSizes = m_PipelineLayout.GetDescriptorSetSizes(NumSets);
- auto CacheMemorySize = ShaderResourceCacheVk::GetRequiredMemorySize(NumSets, DescriptorSetSizes.data());
+ Uint32 NumSets = 0;
+ auto DescriptorSetSizes = m_PipelineLayout.GetDescriptorSetSizes(NumSets);
+ auto CacheMemorySize = ShaderResourceCacheVk::GetRequiredMemorySize(NumSets, DescriptorSetSizes.data());
m_SRBMemAllocator.Initialize(PipelineDesc.SRBAllocationGranularity, m_NumShaders, ShaderVariableDataSizes.data(), 1, &CacheMemorySize);
}
@@ -201,8 +205,8 @@ PipelineStateVkImpl :: PipelineStateVkImpl(IReferenceCounters* pRefCounters
std::array<VkPipelineShaderStageCreateInfo, MaxShadersInPipeline> ShaderStages = {};
for (Uint32 s = 0; s < m_NumShaders; ++s)
{
- auto* pShaderVk = GetShader<const ShaderVkImpl>(s);
- auto ShaderType = pShaderVk->GetDesc().ShaderType;
+ auto* pShaderVk = GetShader<const ShaderVkImpl>(s);
+ auto ShaderType = pShaderVk->GetDesc().ShaderType;
auto& StageCI = ShaderStages[s];
StageCI.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
@@ -210,6 +214,7 @@ PipelineStateVkImpl :: PipelineStateVkImpl(IReferenceCounters* pRefCounters
StageCI.flags = 0; // reserved for future use
switch (ShaderType)
{
+ // clang-format off
case SHADER_TYPE_VERTEX: StageCI.stage = VK_SHADER_STAGE_VERTEX_BIT; break;
case SHADER_TYPE_HULL: StageCI.stage = VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT; break;
case SHADER_TYPE_DOMAIN: StageCI.stage = VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT; break;
@@ -217,16 +222,18 @@ PipelineStateVkImpl :: PipelineStateVkImpl(IReferenceCounters* pRefCounters
case SHADER_TYPE_PIXEL: StageCI.stage = VK_SHADER_STAGE_FRAGMENT_BIT; break;
case SHADER_TYPE_COMPUTE: StageCI.stage = VK_SHADER_STAGE_COMPUTE_BIT; break;
default: UNEXPECTED("Unknown shader type");
+ // clang-format on
}
VkShaderModuleCreateInfo ShaderModuleCI = {};
+
ShaderModuleCI.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
ShaderModuleCI.pNext = nullptr;
ShaderModuleCI.flags = 0;
- const auto& SPIRV = ShaderSPIRVs[s];
+ const auto& SPIRV = ShaderSPIRVs[s];
// We have to strip reflection instructions to fix the follownig validation error:
- // SPIR-V module not valid: DecorateStringGOOGLE requires one of the following extensions: SPV_GOOGLE_decorate_string
+ // SPIR-V module not valid: DecorateStringGOOGLE requires one of the following extensions: SPV_GOOGLE_decorate_string
// Optimizer also performs validation and may catch problems with the byte code.
auto StrippedSPIRV = StripReflection(SPIRV);
if (!StrippedSPIRV.empty())
@@ -243,8 +250,8 @@ PipelineStateVkImpl :: PipelineStateVkImpl(IReferenceCounters* pRefCounters
m_ShaderModules[s] = LogicalDevice.CreateShaderModule(ShaderModuleCI, pShaderVk->GetDesc().Name);
- StageCI.module = m_ShaderModules[s];
- StageCI.pName = pShaderVk->GetEntryPoint();
+ StageCI.module = m_ShaderModules[s];
+ StageCI.pName = pShaderVk->GetEntryPoint();
StageCI.pSpecializationInfo = nullptr;
}
@@ -253,79 +260,85 @@ PipelineStateVkImpl :: PipelineStateVkImpl(IReferenceCounters* pRefCounters
{
auto& ComputePipeline = m_Desc.ComputePipeline;
- if ( ComputePipeline.pCS == nullptr )
+ if (ComputePipeline.pCS == nullptr)
LOG_ERROR_AND_THROW("Compute shader is not set in the pipeline desc");
VkComputePipelineCreateInfo PipelineCI = {};
+
PipelineCI.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
PipelineCI.pNext = nullptr;
#ifdef _DEBUG
PipelineCI.flags = VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT;
-#endif
+#endif
PipelineCI.basePipelineHandle = VK_NULL_HANDLE; // a pipeline to derive from
- PipelineCI.basePipelineIndex = 0; // an index into the pCreateInfos parameter to use as a pipeline to derive from
+ PipelineCI.basePipelineIndex = 0; // an index into the pCreateInfos parameter to use as a pipeline to derive from
PipelineCI.stage = ShaderStages[0];
PipelineCI.layout = m_PipelineLayout.GetVkPipelineLayout();
-
+
m_Pipeline = LogicalDevice.CreateComputePipeline(PipelineCI, VK_NULL_HANDLE, m_Desc.Name);
}
else
{
- const auto& PhysicalDevice = pDeviceVk->GetPhysicalDevice();
-
- auto& GraphicsPipeline = m_Desc.GraphicsPipeline;
+ const auto& PhysicalDevice = pDeviceVk->GetPhysicalDevice();
+ auto& GraphicsPipeline = m_Desc.GraphicsPipeline;
+ auto& RPCache = pDeviceVk->GetRenderPassCache();
- auto& RPCache = pDeviceVk->GetRenderPassCache();
- RenderPassCache::RenderPassCacheKey Key(
+ RenderPassCache::RenderPassCacheKey Key{
GraphicsPipeline.NumRenderTargets,
GraphicsPipeline.SmplDesc.Count,
GraphicsPipeline.RTVFormats,
- GraphicsPipeline.DSVFormat);
+ GraphicsPipeline.DSVFormat};
m_RenderPass = RPCache.GetRenderPass(Key);
VkGraphicsPipelineCreateInfo PipelineCI = {};
+
PipelineCI.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
PipelineCI.pNext = nullptr;
#ifdef _DEBUG
PipelineCI.flags = VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT;
-#endif
+#endif
PipelineCI.stageCount = m_NumShaders;
PipelineCI.pStages = ShaderStages.data();
PipelineCI.layout = m_PipelineLayout.GetVkPipelineLayout();
-
+
VkPipelineVertexInputStateCreateInfo VertexInputStateCI = {};
- std::array<VkVertexInputBindingDescription, iMaxLayoutElements> BindingDescriptions;
+
+ std::array<VkVertexInputBindingDescription, iMaxLayoutElements> BindingDescriptions;
std::array<VkVertexInputAttributeDescription, iMaxLayoutElements> AttributeDescription;
InputLayoutDesc_To_VkVertexInputStateCI(GraphicsPipeline.InputLayout, VertexInputStateCI, BindingDescriptions, AttributeDescription);
PipelineCI.pVertexInputState = &VertexInputStateCI;
VkPipelineInputAssemblyStateCreateInfo InputAssemblyCI = {};
- InputAssemblyCI.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
- InputAssemblyCI.pNext = nullptr;
- InputAssemblyCI.flags = 0; // reserved for future use
+
+ InputAssemblyCI.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
+ InputAssemblyCI.pNext = nullptr;
+ InputAssemblyCI.flags = 0; // reserved for future use
InputAssemblyCI.primitiveRestartEnable = VK_FALSE;
- PipelineCI.pInputAssemblyState = &InputAssemblyCI;
+ PipelineCI.pInputAssemblyState = &InputAssemblyCI;
+
VkPipelineTessellationStateCreateInfo TessStateCI = {};
- TessStateCI.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO;
- TessStateCI.pNext = nullptr;
- TessStateCI.flags = 0; // reserved for future use
+
+ TessStateCI.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO;
+ TessStateCI.pNext = nullptr;
+ TessStateCI.flags = 0; // reserved for future use
PipelineCI.pTessellationState = &TessStateCI;
PrimitiveTopology_To_VkPrimitiveTopologyAndPatchCPCount(GraphicsPipeline.PrimitiveTopology, InputAssemblyCI.topology, TessStateCI.patchControlPoints);
-
+
VkPipelineViewportStateCreateInfo ViewPortStateCI = {};
+
ViewPortStateCI.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
ViewPortStateCI.pNext = nullptr;
ViewPortStateCI.flags = 0; // reserved for future use
- ViewPortStateCI.viewportCount =
- GraphicsPipeline.NumViewports; // Even though we use dynamic viewports, the number of viewports used
- // by the pipeline is still specified by the viewportCount member (23.5)
- ViewPortStateCI.pViewports = nullptr; // We will be using dynamic viewport & scissor states
+ ViewPortStateCI.viewportCount =
+ GraphicsPipeline.NumViewports; // Even though we use dynamic viewports, the number of viewports used
+ // by the pipeline is still specified by the viewportCount member (23.5)
+ ViewPortStateCI.pViewports = nullptr; // We will be using dynamic viewport & scissor states
ViewPortStateCI.scissorCount = ViewPortStateCI.viewportCount; // the number of scissors must match the number of viewports (23.5)
// (why the hell it is in the struct then?)
VkRect2D ScissorRect = {};
@@ -343,86 +356,90 @@ PipelineStateVkImpl :: PipelineStateVkImpl(IReferenceCounters* pRefCounters
ScissorRect.extent.height = Props.limits.maxViewportDimensions[1];
ViewPortStateCI.pScissors = &ScissorRect;
}
- PipelineCI.pViewportState = &ViewPortStateCI;
-
- VkPipelineRasterizationStateCreateInfo RasterizerStateCI =
+ PipelineCI.pViewportState = &ViewPortStateCI;
+
+ VkPipelineRasterizationStateCreateInfo RasterizerStateCI =
RasterizerStateDesc_To_VkRasterizationStateCI(GraphicsPipeline.RasterizerDesc);
PipelineCI.pRasterizationState = &RasterizerStateCI;
-
+
// Multisample state (24)
VkPipelineMultisampleStateCreateInfo MSStateCI = {};
+
MSStateCI.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
MSStateCI.pNext = nullptr;
MSStateCI.flags = 0; // reserved for future use
- // If subpass uses color and/or depth/stencil attachments, then the rasterizationSamples member of
+ // If subpass uses color and/or depth/stencil attachments, then the rasterizationSamples member of
// pMultisampleState must be the same as the sample count for those subpass attachments
MSStateCI.rasterizationSamples = static_cast<VkSampleCountFlagBits>(GraphicsPipeline.SmplDesc.Count);
- MSStateCI.sampleShadingEnable = VK_FALSE;
- MSStateCI.minSampleShading = 0; // a minimum fraction of sample shading if sampleShadingEnable is set to VK_TRUE.
- uint32_t SampleMask[] = {GraphicsPipeline.SampleMask, 0}; // Vulkan spec allows up to 64 samples
- MSStateCI.pSampleMask = SampleMask; // an array of static coverage information that is ANDed with
- // the coverage information generated during rasterization (25.3)
- MSStateCI.alphaToCoverageEnable = VK_FALSE; // whether a temporary coverage value is generated based on
- // the alpha component of the fragment's first color output
- MSStateCI.alphaToOneEnable = VK_FALSE; // whether the alpha component of the fragment's first color output is replaced with one
+ MSStateCI.sampleShadingEnable = VK_FALSE;
+ MSStateCI.minSampleShading = 0; // a minimum fraction of sample shading if sampleShadingEnable is set to VK_TRUE.
+ uint32_t SampleMask[] = {GraphicsPipeline.SampleMask, 0}; // Vulkan spec allows up to 64 samples
+ MSStateCI.pSampleMask = SampleMask; // an array of static coverage information that is ANDed with
+ // the coverage information generated during rasterization (25.3)
+ MSStateCI.alphaToCoverageEnable = VK_FALSE; // whether a temporary coverage value is generated based on
+ // the alpha component of the fragment's first color output
+ MSStateCI.alphaToOneEnable = VK_FALSE; // whether the alpha component of the fragment's first color output is replaced with one
PipelineCI.pMultisampleState = &MSStateCI;
- VkPipelineDepthStencilStateCreateInfo DepthStencilStateCI =
+ VkPipelineDepthStencilStateCreateInfo DepthStencilStateCI =
DepthStencilStateDesc_To_VkDepthStencilStateCI(GraphicsPipeline.DepthStencilDesc);
PipelineCI.pDepthStencilState = &DepthStencilStateCI;
std::vector<VkPipelineColorBlendAttachmentState> ColorBlendAttachmentStates(m_Desc.GraphicsPipeline.NumRenderTargets);
+
VkPipelineColorBlendStateCreateInfo BlendStateCI = {};
- BlendStateCI.pAttachments = !ColorBlendAttachmentStates.empty() ? ColorBlendAttachmentStates.data() : nullptr;
- BlendStateCI.attachmentCount = m_Desc.GraphicsPipeline.NumRenderTargets; // must equal the colorAttachmentCount for the subpass
+
+ BlendStateCI.pAttachments = !ColorBlendAttachmentStates.empty() ? ColorBlendAttachmentStates.data() : nullptr;
+ BlendStateCI.attachmentCount = m_Desc.GraphicsPipeline.NumRenderTargets; // must equal the colorAttachmentCount for the subpass
// in which this pipeline is used.
BlendStateDesc_To_VkBlendStateCI(GraphicsPipeline.BlendDesc, BlendStateCI, ColorBlendAttachmentStates);
PipelineCI.pColorBlendState = &BlendStateCI;
VkPipelineDynamicStateCreateInfo DynamicStateCI = {};
+
DynamicStateCI.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
DynamicStateCI.pNext = nullptr;
DynamicStateCI.flags = 0; // reserved for future use
- std::vector<VkDynamicState> DynamicStates =
- {
- VK_DYNAMIC_STATE_VIEWPORT,// pViewports state in VkPipelineViewportStateCreateInfo will be ignored and must be
- // set dynamically with vkCmdSetViewport before any draw commands. The number of viewports
- // used by a pipeline is still specified by the viewportCount member of
- // VkPipelineViewportStateCreateInfo.
+ std::vector<VkDynamicState> DynamicStates =
+ {
+ VK_DYNAMIC_STATE_VIEWPORT, // pViewports state in VkPipelineViewportStateCreateInfo will be ignored and must be
+ // set dynamically with vkCmdSetViewport before any draw commands. The number of viewports
+ // used by a pipeline is still specified by the viewportCount member of
+ // VkPipelineViewportStateCreateInfo.
- VK_DYNAMIC_STATE_BLEND_CONSTANTS, // blendConstants state in VkPipelineColorBlendStateCreateInfo will be ignored
- // and must be set dynamically with vkCmdSetBlendConstants
+ VK_DYNAMIC_STATE_BLEND_CONSTANTS, // blendConstants state in VkPipelineColorBlendStateCreateInfo will be ignored
+ // and must be set dynamically with vkCmdSetBlendConstants
- VK_DYNAMIC_STATE_STENCIL_REFERENCE // pecifies that the reference state in VkPipelineDepthStencilStateCreateInfo
- // for both front and back will be ignored and must be set dynamically
- // with vkCmdSetStencilReference
- };
+ VK_DYNAMIC_STATE_STENCIL_REFERENCE // pecifies that the reference state in VkPipelineDepthStencilStateCreateInfo
+ // for both front and back will be ignored and must be set dynamically
+ // with vkCmdSetStencilReference
+ };
if (GraphicsPipeline.RasterizerDesc.ScissorEnable)
{
- // pScissors state in VkPipelineViewportStateCreateInfo will be ignored and must be set
- // dynamically with vkCmdSetScissor before any draw commands. The number of scissor rectangles
- // used by a pipeline is still specified by the scissorCount member of
+ // pScissors state in VkPipelineViewportStateCreateInfo will be ignored and must be set
+ // dynamically with vkCmdSetScissor before any draw commands. The number of scissor rectangles
+ // used by a pipeline is still specified by the scissorCount member of
// VkPipelineViewportStateCreateInfo.
DynamicStates.push_back(VK_DYNAMIC_STATE_SCISSOR);
}
DynamicStateCI.dynamicStateCount = static_cast<uint32_t>(DynamicStates.size());
- DynamicStateCI.pDynamicStates = DynamicStates.data();
- PipelineCI.pDynamicState = &DynamicStateCI;
+ DynamicStateCI.pDynamicStates = DynamicStates.data();
+ PipelineCI.pDynamicState = &DynamicStateCI;
+
-
- PipelineCI.renderPass = m_RenderPass;
- PipelineCI.subpass = 0;
+ PipelineCI.renderPass = m_RenderPass;
+ PipelineCI.subpass = 0;
PipelineCI.basePipelineHandle = VK_NULL_HANDLE; // a pipeline to derive from
- PipelineCI.basePipelineIndex = 0; // an index into the pCreateInfos parameter to use as a pipeline to derive from
+ PipelineCI.basePipelineIndex = 0; // an index into the pCreateInfos parameter to use as a pipeline to derive from
m_Pipeline = LogicalDevice.CreateGraphicsPipeline(PipelineCI, VK_NULL_HANDLE, m_Desc.Name);
}
- m_HasStaticResources = false;
+ m_HasStaticResources = false;
m_HasNonStaticResources = false;
- for (Uint32 s=0; s < m_NumShaders; ++s)
+ for (Uint32 s = 0; s < m_NumShaders; ++s)
{
const auto& Layout = m_ShaderResourceLayouts[s];
if (Layout.GetResourceCount(SHADER_RESOURCE_VARIABLE_TYPE_STATIC) != 0)
@@ -450,12 +467,12 @@ PipelineStateVkImpl::~PipelineStateVkImpl()
}
auto& RawAllocator = GetRawAllocator();
- for (Uint32 s=0; s < m_NumShaders*2; ++s)
+ for (Uint32 s = 0; s < m_NumShaders * 2; ++s)
{
m_ShaderResourceLayouts[s].~ShaderResourceLayoutVk();
}
- for (Uint32 s=0; s < m_NumShaders; ++s)
+ for (Uint32 s = 0; s < m_NumShaders; ++s)
{
m_StaticResCaches[s].~ShaderResourceCacheVk();
m_StaticVarsMgrs[s].DestroyVariables(GetRawAllocator());
@@ -466,19 +483,19 @@ PipelineStateVkImpl::~PipelineStateVkImpl()
RawAllocator.Free(m_StaticVarsMgrs);
}
-IMPLEMENT_QUERY_INTERFACE( PipelineStateVkImpl, IID_PipelineStateVk, TPipelineStateBase )
+IMPLEMENT_QUERY_INTERFACE(PipelineStateVkImpl, IID_PipelineStateVk, TPipelineStateBase)
-void PipelineStateVkImpl::CreateShaderResourceBinding(IShaderResourceBinding **ppShaderResourceBinding, bool InitStaticResources)
+void PipelineStateVkImpl::CreateShaderResourceBinding(IShaderResourceBinding** ppShaderResourceBinding, bool InitStaticResources)
{
- auto& SRBAllocator = m_pDevice->GetSRBAllocator();
- auto pResBindingVk = NEW_RC_OBJ(SRBAllocator, "ShaderResourceBindingVkImpl instance", ShaderResourceBindingVkImpl)(this, false);
+ auto& SRBAllocator = m_pDevice->GetSRBAllocator();
+ auto pResBindingVk = NEW_RC_OBJ(SRBAllocator, "ShaderResourceBindingVkImpl instance", ShaderResourceBindingVkImpl)(this, false);
if (InitStaticResources)
pResBindingVk->InitializeStaticResources(nullptr);
pResBindingVk->QueryInterface(IID_ShaderResourceBinding, reinterpret_cast<IObject**>(ppShaderResourceBinding));
}
-bool PipelineStateVkImpl::IsCompatibleWith(const IPipelineState *pPSO)const
+bool PipelineStateVkImpl::IsCompatibleWith(const IPipelineState* pPSO) const
{
VERIFY_EXPR(pPSO != nullptr);
@@ -527,11 +544,11 @@ bool PipelineStateVkImpl::IsCompatibleWith(const IPipelineState *pPSO)const
}
-void PipelineStateVkImpl::CommitAndTransitionShaderResources(IShaderResourceBinding* pShaderResourceBinding,
+void PipelineStateVkImpl::CommitAndTransitionShaderResources(IShaderResourceBinding* pShaderResourceBinding,
DeviceContextVkImpl* pCtxVkImpl,
bool CommitResources,
RESOURCE_STATE_TRANSITION_MODE StateTransitionMode,
- PipelineLayout::DescriptorSetBindInfo* pDescrSetBindInfo)const
+ PipelineLayout::DescriptorSetBindInfo* pDescrSetBindInfo) const
{
VERIFY(CommitResources || StateTransitionMode == RESOURCE_STATE_TRANSITION_MODE_TRANSITION, "Resources should be transitioned or committed or both");
@@ -548,7 +565,7 @@ void PipelineStateVkImpl::CommitAndTransitionShaderResources(IShaderResourceBind
#endif
auto* pResBindingVkImpl = ValidatedCast<ShaderResourceBindingVkImpl>(pShaderResourceBinding);
-
+
#ifdef DEVELOPMENT
{
auto* pRefPSO = pResBindingVkImpl->GetPipelineState();
@@ -561,7 +578,7 @@ void PipelineStateVkImpl::CommitAndTransitionShaderResources(IShaderResourceBind
if (m_HasStaticResources && !pResBindingVkImpl->StaticResourcesInitialized())
{
- LOG_ERROR_MESSAGE("Static resources have not been initialized in the shader resource binding object being committed for PSO '", m_Desc.Name,"'. Please call IShaderResourceBinding::InitializeStaticResources().");
+ LOG_ERROR_MESSAGE("Static resources have not been initialized in the shader resource binding object being committed for PSO '", m_Desc.Name, "'. Please call IShaderResourceBinding::InitializeStaticResources().");
}
#endif
@@ -590,8 +607,8 @@ void PipelineStateVkImpl::CommitAndTransitionShaderResources(IShaderResourceBind
if (CommitResources)
{
- VkDescriptorSet DynamicDescrSet = VK_NULL_HANDLE;
- auto DynamicDescriptorSetVkLayout = m_PipelineLayout.GetDynamicDescriptorSetVkLayout();
+ VkDescriptorSet DynamicDescrSet = VK_NULL_HANDLE;
+ auto DynamicDescriptorSetVkLayout = m_PipelineLayout.GetDynamicDescriptorSetVkLayout();
if (DynamicDescriptorSetVkLayout != VK_NULL_HANDLE)
{
const char* DynamicDescrSetName = "Dynamic Descriptor Set";
@@ -603,7 +620,7 @@ void PipelineStateVkImpl::CommitAndTransitionShaderResources(IShaderResourceBind
// Allocate vulkan descriptor set for dynamic resources
DynamicDescrSet = pCtxVkImpl->AllocateDynamicDescriptorSet(DynamicDescriptorSetVkLayout, DynamicDescrSetName);
// Commit all dynamic resource descriptors
- for (Uint32 s=0; s < m_NumShaders; ++s)
+ for (Uint32 s = 0; s < m_NumShaders; ++s)
{
const auto& Layout = m_ShaderResourceLayouts[s];
if (Layout.GetResourceCount(SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC) != 0)
@@ -613,14 +630,14 @@ void PipelineStateVkImpl::CommitAndTransitionShaderResources(IShaderResourceBind
// Prepare descriptor sets, and also bind them if there are no dynamic descriptors
VERIFY_EXPR(pDescrSetBindInfo != nullptr);
m_PipelineLayout.PrepareDescriptorSets(pCtxVkImpl, m_Desc.IsComputePipeline, ResourceCache, *pDescrSetBindInfo, DynamicDescrSet);
- // Dynamic descriptor sets are not released individually. Instead, all dynamic descriptor pools
+ // Dynamic descriptor sets are not released individually. Instead, all dynamic descriptor pools
// are released at the end of the frame by DeviceContextVkImpl::FinishFrame().
}
}
void PipelineStateVkImpl::BindStaticResources(Uint32 ShaderFlags, IResourceMapping* pResourceMapping, Uint32 Flags)
{
- for (Uint32 s=0; s < m_NumShaders; ++s)
+ for (Uint32 s = 0; s < m_NumShaders; ++s)
{
auto ShaderType = GetStaticShaderResLayout(s).GetShaderType();
if ((ShaderType & ShaderFlags) != 0)
@@ -662,19 +679,20 @@ IShaderResourceVariable* PipelineStateVkImpl::GetStaticVariableByIndex(SHADER_TY
}
-void PipelineStateVkImpl::InitializeStaticSRBResources(ShaderResourceCacheVk& ResourceCache)const
+void PipelineStateVkImpl::InitializeStaticSRBResources(ShaderResourceCacheVk& ResourceCache) const
{
for (Uint32 s = 0; s < m_NumShaders; ++s)
{
const auto& StaticResLayout = GetStaticShaderResLayout(s);
- const auto& StaticResCache = GetStaticResCache(s);
+ const auto& StaticResCache = GetStaticResCache(s);
#ifdef DEVELOPMENT
if (!StaticResLayout.dvpVerifyBindings(StaticResCache))
{
const auto* pShaderVk = GetShader<const ShaderVkImpl>(s);
- LOG_ERROR_MESSAGE("Static resources in SRB of PSO '", GetDesc().Name, "' will not be successfully initialized "
- "because not all static resource bindings in shader '", pShaderVk->GetDesc().Name, "' are valid. "
- "Please make sure you bind all static resources to PSO before calling InitializeStaticResources() "
+ LOG_ERROR_MESSAGE("Static resources in SRB of PSO '", GetDesc().Name,
+ "' will not be successfully initialized because not all static resource bindings in shader '",
+ pShaderVk->GetDesc().Name,
+ "' are valid. Please make sure you bind all static resources to PSO before calling InitializeStaticResources() "
"directly or indirectly by passing InitStaticResources=true to CreateShaderResourceBinding() method.");
}
#endif
@@ -686,4 +704,4 @@ void PipelineStateVkImpl::InitializeStaticSRBResources(ShaderResourceCacheVk& Re
#endif
}
-}
+} // namespace Diligent
diff --git a/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp
index c2086c95..665fa5d8 100644
--- a/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp
@@ -37,15 +37,16 @@
namespace Diligent
{
-RenderDeviceVkImpl :: RenderDeviceVkImpl(IReferenceCounters* pRefCounters,
- IMemoryAllocator& RawMemAllocator,
- IEngineFactory* pEngineFactory,
- const EngineVkCreateInfo& EngineCI,
- size_t CommandQueueCount,
- ICommandQueueVk** CmdQueues,
- std::shared_ptr<VulkanUtilities::VulkanInstance> Instance,
- std::unique_ptr<VulkanUtilities::VulkanPhysicalDevice> PhysicalDevice,
- std::shared_ptr<VulkanUtilities::VulkanLogicalDevice> LogicalDevice) :
+RenderDeviceVkImpl::RenderDeviceVkImpl(IReferenceCounters* pRefCounters,
+ IMemoryAllocator& RawMemAllocator,
+ IEngineFactory* pEngineFactory,
+ const EngineVkCreateInfo& EngineCI,
+ size_t CommandQueueCount,
+ ICommandQueueVk** CmdQueues,
+ std::shared_ptr<VulkanUtilities::VulkanInstance> Instance,
+ std::unique_ptr<VulkanUtilities::VulkanPhysicalDevice> PhysicalDevice,
+ std::shared_ptr<VulkanUtilities::VulkanLogicalDevice> LogicalDevice) :
+ // clang-format off
TRenderDeviceBase
{
pRefCounters,
@@ -138,13 +139,14 @@ RenderDeviceVkImpl :: RenderDeviceVkImpl(IReferenceCounters*
EngineCI.DynamicHeapSize,
~Uint64{0}
}
+// clang-format on
{
- m_DeviceCaps.DevType = DeviceType::Vulkan;
- m_DeviceCaps.MajorVersion = 1;
- m_DeviceCaps.MinorVersion = 0;
- m_DeviceCaps.bSeparableProgramSupported = True;
+ m_DeviceCaps.DevType = DeviceType::Vulkan;
+ m_DeviceCaps.MajorVersion = 1;
+ m_DeviceCaps.MinorVersion = 0;
+ m_DeviceCaps.bSeparableProgramSupported = True;
m_DeviceCaps.bMultithreadedResourceCreationSupported = True;
- for(int fmt = 1; fmt < m_TextureFormatsInfo.size(); ++fmt)
+ for (int fmt = 1; fmt < m_TextureFormatsInfo.size(); ++fmt)
m_TextureFormatsInfo[fmt].Supported = true; // We will test every format on a specific hardware device
m_DeviceCaps.bGeometryShadersSupported = EngineCI.EnabledFeatures.geometryShader;
@@ -154,13 +156,13 @@ RenderDeviceVkImpl :: RenderDeviceVkImpl(IReferenceCounters*
RenderDeviceVkImpl::~RenderDeviceVkImpl()
{
- // Explicitly destroy dynamic heap. This will move resources owned by
+ // Explicitly destroy dynamic heap. This will move resources owned by
// the heap into release queues
m_DynamicMemoryManager.Destroy();
// Wait for the GPU to complete all its operations
IdleGPU();
-
+
ReleaseStaleResources(true);
DEV_CHECK_ERR(m_DescriptorSetAllocator.GetAllocatedDescriptorSetCounter() == 0, "All allocated descriptor sets must have been released now.");
@@ -183,29 +185,35 @@ RenderDeviceVkImpl::~RenderDeviceVkImpl()
}
-void RenderDeviceVkImpl::AllocateTransientCmdPool(VulkanUtilities::CommandPoolWrapper& CmdPool, VkCommandBuffer& vkCmdBuff, const Char *DebugPoolName)
+void RenderDeviceVkImpl::AllocateTransientCmdPool(VulkanUtilities::CommandPoolWrapper& CmdPool, VkCommandBuffer& vkCmdBuff, const Char* DebugPoolName)
{
CmdPool = m_TransientCmdPoolMgr.AllocateCommandPool(DebugPoolName);
// Allocate command buffer from the cmd pool
VkCommandBufferAllocateInfo BuffAllocInfo = {};
+
BuffAllocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
BuffAllocInfo.pNext = nullptr;
BuffAllocInfo.commandPool = CmdPool;
BuffAllocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
BuffAllocInfo.commandBufferCount = 1;
+
vkCmdBuff = m_LogicalVkDevice->AllocateVkCommandBuffer(BuffAllocInfo);
DEV_CHECK_ERR(vkCmdBuff != VK_NULL_HANDLE, "Failed to allocate Vulkan command buffer");
-
+
+
VkCommandBufferBeginInfo CmdBuffBeginInfo = {};
+
CmdBuffBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
CmdBuffBeginInfo.pNext = nullptr;
- CmdBuffBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; // Each recording of the command buffer will only be
- // submitted once, and the command buffer will be reset
+ CmdBuffBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; // Each recording of the command buffer will only be
+ // submitted once, and the command buffer will be reset
// and recorded again between each submission.
- CmdBuffBeginInfo.pInheritanceInfo = nullptr; // Ignored for a primary command buffer
+ CmdBuffBeginInfo.pInheritanceInfo = nullptr; // Ignored for a primary command buffer
+
auto err = vkBeginCommandBuffer(vkCmdBuff, &CmdBuffBeginInfo);
- DEV_CHECK_ERR(err == VK_SUCCESS, "vkBeginCommandBuffer() failed"); (void)err;
+ DEV_CHECK_ERR(err == VK_SUCCESS, "vkBeginCommandBuffer() failed");
+ (void)err;
}
@@ -214,17 +222,19 @@ void RenderDeviceVkImpl::ExecuteAndDisposeTransientCmdBuff(Uint32 QueueIndex, Vk
VERIFY_EXPR(vkCmdBuff != VK_NULL_HANDLE);
auto err = vkEndCommandBuffer(vkCmdBuff);
- DEV_CHECK_ERR(err == VK_SUCCESS, "Failed to end command buffer"); (void)err;
+ DEV_CHECK_ERR(err == VK_SUCCESS, "Failed to end command buffer");
+ (void)err;
VkSubmitInfo SubmitInfo = {};
+
SubmitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
SubmitInfo.commandBufferCount = 1;
SubmitInfo.pCommandBuffers = &vkCmdBuff;
// We MUST NOT discard stale objects when executing transient command buffer,
// otherwise a resource can be destroyed while still being used by the GPU:
- //
- //
+ //
+ //
// Next Cmd Buff| Next Fence | Immediate Context | This thread |
// | | | |
// N | F | | |
@@ -247,24 +257,24 @@ void RenderDeviceVkImpl::ExecuteAndDisposeTransientCmdBuff(Uint32 QueueIndex, Vk
// Since transient command buffers do not count as real command buffers, submit them directly to the queue
// to avoid interference with the command buffer counter
Uint64 FenceValue = 0;
- LockCmdQueueAndRun(QueueIndex,
- [&](ICommandQueueVk* pCmdQueueVk)
- {
- FenceValue = pCmdQueueVk->Submit(SubmitInfo);
- }
+ LockCmdQueueAndRun(QueueIndex,
+ [&](ICommandQueueVk* pCmdQueueVk) //
+ {
+ FenceValue = pCmdQueueVk->Submit(SubmitInfo);
+ } //
);
m_TransientCmdPoolMgr.SafeReleaseCommandPool(std::move(CmdPool), QueueIndex, FenceValue);
}
-void RenderDeviceVkImpl::SubmitCommandBuffer(Uint32 QueueIndex,
- const VkSubmitInfo& SubmitInfo,
- Uint64& SubmittedCmdBuffNumber, // Number of the submitted command buffer
- Uint64& SubmittedFenceValue, // Fence value associated with the submitted command buffer
- std::vector<std::pair<Uint64, RefCntAutoPtr<IFence> > >* pFences // List of fences to signal
- )
+void RenderDeviceVkImpl::SubmitCommandBuffer(Uint32 QueueIndex,
+ const VkSubmitInfo& SubmitInfo,
+ Uint64& SubmittedCmdBuffNumber, // Number of the submitted command buffer
+ Uint64& SubmittedFenceValue, // Fence value associated with the submitted command buffer
+ std::vector<std::pair<Uint64, RefCntAutoPtr<IFence>>>* pFences // List of fences to signal
+)
{
- // Submit the command list to the queue
- auto CmbBuffInfo = TRenderDeviceBase::SubmitCommandBuffer(QueueIndex, SubmitInfo, true);
+ // Submit the command list to the queue
+ auto CmbBuffInfo = TRenderDeviceBase::SubmitCommandBuffer(QueueIndex, SubmitInfo, true);
SubmittedFenceValue = CmbBuffInfo.FenceValue;
SubmittedCmdBuffNumber = CmbBuffInfo.CmdBufferNumber;
if (pFences != nullptr)
@@ -272,20 +282,20 @@ void RenderDeviceVkImpl::SubmitCommandBuffer(Uint32 QueueIndex,
for (auto& val_fence : *pFences)
{
auto* pFenceVkImpl = val_fence.second.RawPtr<FenceVkImpl>();
- auto vkFence = pFenceVkImpl->GetVkFence();
+ auto vkFence = pFenceVkImpl->GetVkFence();
m_CommandQueues[QueueIndex].CmdQueue->SignalFence(vkFence);
pFenceVkImpl->AddPendingFence(std::move(vkFence), val_fence.first);
}
}
}
-Uint64 RenderDeviceVkImpl::ExecuteCommandBuffer(Uint32 QueueIndex, const VkSubmitInfo& SubmitInfo, DeviceContextVkImpl* pImmediateCtx, std::vector<std::pair<Uint64, RefCntAutoPtr<IFence> > >* pSignalFences)
+Uint64 RenderDeviceVkImpl::ExecuteCommandBuffer(Uint32 QueueIndex, const VkSubmitInfo& SubmitInfo, DeviceContextVkImpl* pImmediateCtx, std::vector<std::pair<Uint64, RefCntAutoPtr<IFence>>>* pSignalFences)
{
// pImmediateCtx parameter is only used to make sure the command buffer is submitted from the immediate context
// Stale objects MUST only be discarded when submitting cmd list from the immediate context
VERIFY(!pImmediateCtx->IsDeferred(), "Command buffers must be submitted from immediate context only");
- Uint64 SubmittedFenceValue = 0;
+ Uint64 SubmittedFenceValue = 0;
Uint64 SubmittedCmdBuffNumber = 0;
SubmitCommandBuffer(QueueIndex, SubmitInfo, SubmittedCmdBuffNumber, SubmittedFenceValue, pSignalFences);
@@ -296,8 +306,8 @@ Uint64 RenderDeviceVkImpl::ExecuteCommandBuffer(Uint32 QueueIndex, const VkSubmi
}
-void RenderDeviceVkImpl::IdleGPU()
-{
+void RenderDeviceVkImpl::IdleGPU()
+{
IdleAllCommandQueues(true);
m_LogicalVkDevice->WaitIdle();
ReleaseStaleResources();
@@ -305,7 +315,7 @@ void RenderDeviceVkImpl::IdleGPU()
void RenderDeviceVkImpl::FlushStaleResources(Uint32 CmdQueueIndex)
{
- // Submit empty command buffer to the queue. This will effectively signal the fence and
+ // Submit empty command buffer to the queue. This will effectively signal the fence and
// discard all resources
VkSubmitInfo DummySumbitInfo = {};
TRenderDeviceBase::SubmitCommandBuffer(0, DummySumbitInfo, true);
@@ -318,67 +328,71 @@ void RenderDeviceVkImpl::ReleaseStaleResources(bool ForceRelease)
}
-void RenderDeviceVkImpl::TestTextureFormat( TEXTURE_FORMAT TexFormat )
+void RenderDeviceVkImpl::TestTextureFormat(TEXTURE_FORMAT TexFormat)
{
- auto &TexFormatInfo = m_TextureFormatsInfo[TexFormat];
- VERIFY( TexFormatInfo.Supported, "Texture format is not supported" );
+ auto& TexFormatInfo = m_TextureFormatsInfo[TexFormat];
+ VERIFY(TexFormatInfo.Supported, "Texture format is not supported");
auto vkPhysicalDevice = m_PhysicalDevice->GetVkDeviceHandle();
auto SRVFormat = GetDefaultTextureViewFormat(TexFormat, TEXTURE_VIEW_SHADER_RESOURCE, BIND_SHADER_RESOURCE);
auto RTVFormat = GetDefaultTextureViewFormat(TexFormat, TEXTURE_VIEW_RENDER_TARGET, BIND_RENDER_TARGET);
auto DSVFormat = GetDefaultTextureViewFormat(TexFormat, TEXTURE_VIEW_DEPTH_STENCIL, BIND_DEPTH_STENCIL);
-
- if(SRVFormat != TEX_FORMAT_UNKNOWN)
+
+ if (SRVFormat != TEX_FORMAT_UNKNOWN)
{
- VkFormat vkSrvFormat = TexFormatToVkFormat(SRVFormat);
+ VkFormat vkSrvFormat = TexFormatToVkFormat(SRVFormat);
VkFormatProperties vkSrvFmtProps = {};
vkGetPhysicalDeviceFormatProperties(vkPhysicalDevice, vkSrvFormat, &vkSrvFmtProps);
- if(vkSrvFmtProps.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT)
+ if (vkSrvFmtProps.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT)
{
TexFormatInfo.Filterable = true;
{
VkImageFormatProperties ImgFmtProps = {};
- auto err = vkGetPhysicalDeviceImageFormatProperties(vkPhysicalDevice, vkSrvFormat, VK_IMAGE_TYPE_1D, VK_IMAGE_TILING_OPTIMAL,
+
+ auto err = vkGetPhysicalDeviceImageFormatProperties(vkPhysicalDevice, vkSrvFormat, VK_IMAGE_TYPE_1D, VK_IMAGE_TILING_OPTIMAL,
VK_IMAGE_USAGE_SAMPLED_BIT, 0, &ImgFmtProps);
TexFormatInfo.Tex1DFmt = err == VK_SUCCESS;
}
{
VkImageFormatProperties ImgFmtProps = {};
- auto err = vkGetPhysicalDeviceImageFormatProperties(vkPhysicalDevice, vkSrvFormat, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
+
+ auto err = vkGetPhysicalDeviceImageFormatProperties(vkPhysicalDevice, vkSrvFormat, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
VK_IMAGE_USAGE_SAMPLED_BIT, 0, &ImgFmtProps);
TexFormatInfo.Tex2DFmt = err == VK_SUCCESS;
}
{
VkImageFormatProperties ImgFmtProps = {};
- auto err = vkGetPhysicalDeviceImageFormatProperties(vkPhysicalDevice, vkSrvFormat, VK_IMAGE_TYPE_3D, VK_IMAGE_TILING_OPTIMAL,
+
+ auto err = vkGetPhysicalDeviceImageFormatProperties(vkPhysicalDevice, vkSrvFormat, VK_IMAGE_TYPE_3D, VK_IMAGE_TILING_OPTIMAL,
VK_IMAGE_USAGE_SAMPLED_BIT, 0, &ImgFmtProps);
TexFormatInfo.Tex3DFmt = err == VK_SUCCESS;
}
{
VkImageFormatProperties ImgFmtProps = {};
- auto err = vkGetPhysicalDeviceImageFormatProperties(vkPhysicalDevice, vkSrvFormat, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
+
+ auto err = vkGetPhysicalDeviceImageFormatProperties(vkPhysicalDevice, vkSrvFormat, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT, &ImgFmtProps);
TexFormatInfo.TexCubeFmt = err == VK_SUCCESS;
}
-
}
}
if (RTVFormat != TEX_FORMAT_UNKNOWN)
{
- VkFormat vkRtvFormat = TexFormatToVkFormat(RTVFormat);
+ VkFormat vkRtvFormat = TexFormatToVkFormat(RTVFormat);
VkFormatProperties vkRtvFmtProps = {};
vkGetPhysicalDeviceFormatProperties(vkPhysicalDevice, vkRtvFormat, &vkRtvFmtProps);
if (vkRtvFmtProps.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT)
{
VkImageFormatProperties ImgFmtProps = {};
- auto err = vkGetPhysicalDeviceImageFormatProperties(vkPhysicalDevice, vkRtvFormat, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
+
+ auto err = vkGetPhysicalDeviceImageFormatProperties(vkPhysicalDevice, vkRtvFormat, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, 0, &ImgFmtProps);
TexFormatInfo.ColorRenderable = err == VK_SUCCESS;
if (TexFormatInfo.ColorRenderable)
@@ -390,15 +404,15 @@ void RenderDeviceVkImpl::TestTextureFormat( TEXTURE_FORMAT TexFormat )
if (DSVFormat != TEX_FORMAT_UNKNOWN)
{
- VkFormat vkDsvFormat = TexFormatToVkFormat(DSVFormat);
+ VkFormat vkDsvFormat = TexFormatToVkFormat(DSVFormat);
VkFormatProperties vkDsvFmtProps = {};
vkGetPhysicalDeviceFormatProperties(vkPhysicalDevice, vkDsvFormat, &vkDsvFmtProps);
if (vkDsvFmtProps.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)
{
VkImageFormatProperties ImgFmtProps = {};
- auto err = vkGetPhysicalDeviceImageFormatProperties(vkPhysicalDevice, vkDsvFormat, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
+ auto err = vkGetPhysicalDeviceImageFormatProperties(vkPhysicalDevice, vkDsvFormat, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, 0, &ImgFmtProps);
- TexFormatInfo.DepthRenderable = err == VK_SUCCESS;
+ TexFormatInfo.DepthRenderable = err == VK_SUCCESS;
if (TexFormatInfo.DepthRenderable)
{
TexFormatInfo.SampleCounts = ImgFmtProps.sampleCounts;
@@ -408,132 +422,140 @@ void RenderDeviceVkImpl::TestTextureFormat( TEXTURE_FORMAT TexFormat )
}
-IMPLEMENT_QUERY_INTERFACE( RenderDeviceVkImpl, IID_RenderDeviceVk, TRenderDeviceBase )
+IMPLEMENT_QUERY_INTERFACE(RenderDeviceVkImpl, IID_RenderDeviceVk, TRenderDeviceBase)
-void RenderDeviceVkImpl::CreatePipelineState(const PipelineStateDesc &PipelineDesc, IPipelineState **ppPipelineState)
+void RenderDeviceVkImpl::CreatePipelineState(const PipelineStateDesc& PipelineDesc, IPipelineState** ppPipelineState)
{
- CreateDeviceObject("Pipeline State", PipelineDesc, ppPipelineState,
- [&]()
+ CreateDeviceObject(
+ "Pipeline State", PipelineDesc, ppPipelineState,
+ [&]() //
{
- PipelineStateVkImpl *pPipelineStateVk( NEW_RC_OBJ(m_PSOAllocator, "PipelineStateVkImpl instance", PipelineStateVkImpl)(this, PipelineDesc ) );
- pPipelineStateVk->QueryInterface( IID_PipelineState, reinterpret_cast<IObject**>(ppPipelineState) );
- OnCreateDeviceObject( pPipelineStateVk );
- }
+ PipelineStateVkImpl* pPipelineStateVk(NEW_RC_OBJ(m_PSOAllocator, "PipelineStateVkImpl instance", PipelineStateVkImpl)(this, PipelineDesc));
+ pPipelineStateVk->QueryInterface(IID_PipelineState, reinterpret_cast<IObject**>(ppPipelineState));
+ OnCreateDeviceObject(pPipelineStateVk);
+ } //
);
}
-void RenderDeviceVkImpl :: CreateBufferFromVulkanResource(VkBuffer vkBuffer, const BufferDesc& BuffDesc, RESOURCE_STATE InitialState, IBuffer** ppBuffer)
+void RenderDeviceVkImpl::CreateBufferFromVulkanResource(VkBuffer vkBuffer, const BufferDesc& BuffDesc, RESOURCE_STATE InitialState, IBuffer** ppBuffer)
{
- CreateDeviceObject("buffer", BuffDesc, ppBuffer,
- [&]()
+ CreateDeviceObject(
+ "buffer", BuffDesc, ppBuffer,
+ [&]() //
{
- BufferVkImpl* pBufferVk( NEW_RC_OBJ(m_BufObjAllocator, "BufferVkImpl instance", BufferVkImpl)(m_BuffViewObjAllocator, this, BuffDesc, InitialState, vkBuffer ) );
- pBufferVk->QueryInterface( IID_Buffer, reinterpret_cast<IObject**>(ppBuffer) );
+ BufferVkImpl* pBufferVk(NEW_RC_OBJ(m_BufObjAllocator, "BufferVkImpl instance", BufferVkImpl)(m_BuffViewObjAllocator, this, BuffDesc, InitialState, vkBuffer));
+ pBufferVk->QueryInterface(IID_Buffer, reinterpret_cast<IObject**>(ppBuffer));
pBufferVk->CreateDefaultViews();
- OnCreateDeviceObject( pBufferVk );
- }
+ OnCreateDeviceObject(pBufferVk);
+ } //
);
}
-void RenderDeviceVkImpl :: CreateBuffer(const BufferDesc& BuffDesc, const BufferData* pBuffData, IBuffer **ppBuffer)
+void RenderDeviceVkImpl::CreateBuffer(const BufferDesc& BuffDesc, const BufferData* pBuffData, IBuffer** ppBuffer)
{
- CreateDeviceObject("buffer", BuffDesc, ppBuffer,
- [&]()
+ CreateDeviceObject(
+ "buffer", BuffDesc, ppBuffer,
+ [&]() //
{
- BufferVkImpl* pBufferVk( NEW_RC_OBJ(m_BufObjAllocator, "BufferVkImpl instance", BufferVkImpl)(m_BuffViewObjAllocator, this, BuffDesc, pBuffData ) );
- pBufferVk->QueryInterface( IID_Buffer, reinterpret_cast<IObject**>(ppBuffer) );
+ BufferVkImpl* pBufferVk(NEW_RC_OBJ(m_BufObjAllocator, "BufferVkImpl instance", BufferVkImpl)(m_BuffViewObjAllocator, this, BuffDesc, pBuffData));
+ pBufferVk->QueryInterface(IID_Buffer, reinterpret_cast<IObject**>(ppBuffer));
pBufferVk->CreateDefaultViews();
- OnCreateDeviceObject( pBufferVk );
- }
+ OnCreateDeviceObject(pBufferVk);
+ } //
);
}
-void RenderDeviceVkImpl :: CreateShader(const ShaderCreateInfo& ShaderCI, IShader **ppShader)
+void RenderDeviceVkImpl::CreateShader(const ShaderCreateInfo& ShaderCI, IShader** ppShader)
{
- CreateDeviceObject( "shader", ShaderCI.Desc, ppShader,
- [&]()
+ CreateDeviceObject(
+ "shader", ShaderCI.Desc, ppShader,
+ [&]() //
{
- ShaderVkImpl *pShaderVk( NEW_RC_OBJ(m_ShaderObjAllocator, "ShaderVkImpl instance", ShaderVkImpl)(this, ShaderCI) );
- pShaderVk->QueryInterface( IID_Shader, reinterpret_cast<IObject**>(ppShader) );
+ ShaderVkImpl* pShaderVk(NEW_RC_OBJ(m_ShaderObjAllocator, "ShaderVkImpl instance", ShaderVkImpl)(this, ShaderCI));
+ pShaderVk->QueryInterface(IID_Shader, reinterpret_cast<IObject**>(ppShader));
- OnCreateDeviceObject( pShaderVk );
- }
+ OnCreateDeviceObject(pShaderVk);
+ } //
);
}
void RenderDeviceVkImpl::CreateTextureFromVulkanImage(VkImage vkImage, const TextureDesc& TexDesc, RESOURCE_STATE InitialState, ITexture** ppTexture)
{
- CreateDeviceObject( "texture", TexDesc, ppTexture,
- [&]()
+ CreateDeviceObject(
+ "texture", TexDesc, ppTexture,
+ [&]() //
{
- TextureVkImpl* pTextureVk = NEW_RC_OBJ(m_TexObjAllocator, "TextureVkImpl instance", TextureVkImpl)(m_TexViewObjAllocator, this, TexDesc, InitialState, vkImage );
+ TextureVkImpl* pTextureVk = NEW_RC_OBJ(m_TexObjAllocator, "TextureVkImpl instance", TextureVkImpl)(m_TexViewObjAllocator, this, TexDesc, InitialState, vkImage);
- pTextureVk->QueryInterface( IID_Texture, reinterpret_cast<IObject**>(ppTexture) );
+ pTextureVk->QueryInterface(IID_Texture, reinterpret_cast<IObject**>(ppTexture));
pTextureVk->CreateDefaultViews();
- OnCreateDeviceObject( pTextureVk );
- }
+ OnCreateDeviceObject(pTextureVk);
+ } //
);
}
-void RenderDeviceVkImpl::CreateTexture(const TextureDesc& TexDesc, VkImage vkImgHandle, RESOURCE_STATE InitialState, class TextureVkImpl **ppTexture)
+void RenderDeviceVkImpl::CreateTexture(const TextureDesc& TexDesc, VkImage vkImgHandle, RESOURCE_STATE InitialState, class TextureVkImpl** ppTexture)
{
- CreateDeviceObject( "texture", TexDesc, ppTexture,
- [&]()
+ CreateDeviceObject(
+ "texture", TexDesc, ppTexture,
+ [&]() //
{
TextureVkImpl* pTextureVk = NEW_RC_OBJ(m_TexObjAllocator, "TextureVkImpl instance", TextureVkImpl)(m_TexViewObjAllocator, this, TexDesc, InitialState, std::move(vkImgHandle));
- pTextureVk->QueryInterface( IID_TextureVk, reinterpret_cast<IObject**>(ppTexture) );
- }
+ pTextureVk->QueryInterface(IID_TextureVk, reinterpret_cast<IObject**>(ppTexture));
+ } //
);
}
-void RenderDeviceVkImpl :: CreateTexture(const TextureDesc& TexDesc, const TextureData* pData, ITexture **ppTexture)
+void RenderDeviceVkImpl::CreateTexture(const TextureDesc& TexDesc, const TextureData* pData, ITexture** ppTexture)
{
- CreateDeviceObject( "texture", TexDesc, ppTexture,
- [&]()
+ CreateDeviceObject(
+ "texture", TexDesc, ppTexture,
+ [&]() //
{
- TextureVkImpl* pTextureVk = NEW_RC_OBJ(m_TexObjAllocator, "TextureVkImpl instance", TextureVkImpl)(m_TexViewObjAllocator, this, TexDesc, pData );
+ TextureVkImpl* pTextureVk = NEW_RC_OBJ(m_TexObjAllocator, "TextureVkImpl instance", TextureVkImpl)(m_TexViewObjAllocator, this, TexDesc, pData);
- pTextureVk->QueryInterface( IID_Texture, reinterpret_cast<IObject**>(ppTexture) );
+ pTextureVk->QueryInterface(IID_Texture, reinterpret_cast<IObject**>(ppTexture));
pTextureVk->CreateDefaultViews();
- OnCreateDeviceObject( pTextureVk );
- }
+ OnCreateDeviceObject(pTextureVk);
+ } //
);
}
-void RenderDeviceVkImpl :: CreateSampler(const SamplerDesc& SamplerDesc, ISampler **ppSampler)
+void RenderDeviceVkImpl::CreateSampler(const SamplerDesc& SamplerDesc, ISampler** ppSampler)
{
- CreateDeviceObject( "sampler", SamplerDesc, ppSampler,
- [&]()
+ CreateDeviceObject(
+ "sampler", SamplerDesc, ppSampler,
+ [&]() //
{
- m_SamplersRegistry.Find( SamplerDesc, reinterpret_cast<IDeviceObject**>(ppSampler) );
- if( *ppSampler == nullptr )
+ m_SamplersRegistry.Find(SamplerDesc, reinterpret_cast<IDeviceObject**>(ppSampler));
+ if (*ppSampler == nullptr)
{
- SamplerVkImpl* pSamplerVk( NEW_RC_OBJ(m_SamplerObjAllocator, "SamplerVkImpl instance", SamplerVkImpl)(this, SamplerDesc ) );
- pSamplerVk->QueryInterface( IID_Sampler, reinterpret_cast<IObject**>(ppSampler) );
- OnCreateDeviceObject( pSamplerVk );
- m_SamplersRegistry.Add( SamplerDesc, *ppSampler );
+ SamplerVkImpl* pSamplerVk(NEW_RC_OBJ(m_SamplerObjAllocator, "SamplerVkImpl instance", SamplerVkImpl)(this, SamplerDesc));
+ pSamplerVk->QueryInterface(IID_Sampler, reinterpret_cast<IObject**>(ppSampler));
+ OnCreateDeviceObject(pSamplerVk);
+ m_SamplersRegistry.Add(SamplerDesc, *ppSampler);
}
- }
+ } //
);
}
void RenderDeviceVkImpl::CreateFence(const FenceDesc& Desc, IFence** ppFence)
{
- CreateDeviceObject( "Fence", Desc, ppFence,
- [&]()
+ CreateDeviceObject(
+ "Fence", Desc, ppFence,
+ [&]() //
{
- FenceVkImpl* pFenceVk( NEW_RC_OBJ(m_FenceAllocator, "FenceVkImpl instance", FenceVkImpl)
- (this, Desc) );
- pFenceVk->QueryInterface( IID_Fence, reinterpret_cast<IObject**>(ppFence) );
- OnCreateDeviceObject( pFenceVk );
- }
+ FenceVkImpl* pFenceVk(NEW_RC_OBJ(m_FenceAllocator, "FenceVkImpl instance", FenceVkImpl)(this, Desc));
+ pFenceVk->QueryInterface(IID_Fence, reinterpret_cast<IObject**>(ppFence));
+ OnCreateDeviceObject(pFenceVk);
+ } //
);
}
-}
+} // namespace Diligent
diff --git a/Graphics/GraphicsEngineVulkan/src/RenderPassCache.cpp b/Graphics/GraphicsEngineVulkan/src/RenderPassCache.cpp
index 7bc212c0..fbe574dc 100644
--- a/Graphics/GraphicsEngineVulkan/src/RenderPassCache.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/RenderPassCache.cpp
@@ -33,7 +33,7 @@ namespace Diligent
RenderPassCache::~RenderPassCache()
{
auto& FBCache = m_DeviceVkImpl.GetFramebufferCache();
- for(auto it = m_Cache.begin(); it != m_Cache.end(); ++it)
+ for (auto it = m_Cache.begin(); it != m_Cache.end(); ++it)
{
FBCache.OnDestroyRenderPass(it->second);
}
@@ -42,19 +42,22 @@ RenderPassCache::~RenderPassCache()
VkRenderPass RenderPassCache::GetRenderPass(const RenderPassCacheKey& Key)
{
std::lock_guard<std::mutex> Lock{m_Mutex};
- auto it = m_Cache.find(Key);
- if(it == m_Cache.end())
+ auto it = m_Cache.find(Key);
+ if (it == m_Cache.end())
{
// Do not zero-intitialize arrays
- std::array<VkAttachmentDescription, MaxRenderTargets+1> Attachments;
- std::array<VkAttachmentReference, MaxRenderTargets+1> AttachmentReferences;
- VkSubpassDescription Subpass;
- auto RenderPassCI = PipelineStateVkImpl::GetRenderPassCreateInfo(Key.NumRenderTargets, Key.RTVFormats, Key.DSVFormat,
- Key.SampleCount, Attachments, AttachmentReferences, Subpass);
+ std::array<VkAttachmentDescription, MaxRenderTargets + 1> Attachments;
+ std::array<VkAttachmentReference, MaxRenderTargets + 1> AttachmentReferences;
+
+ VkSubpassDescription Subpass;
+
+ auto RenderPassCI =
+ PipelineStateVkImpl::GetRenderPassCreateInfo(Key.NumRenderTargets, Key.RTVFormats, Key.DSVFormat,
+ Key.SampleCount, Attachments, AttachmentReferences, Subpass);
std::stringstream PassNameSS;
- PassNameSS << "Render pass: rt count: " << Key.NumRenderTargets << "; sample count: "<< Key.SampleCount
+ PassNameSS << "Render pass: rt count: " << Key.NumRenderTargets << "; sample count: " << Key.SampleCount
<< "; DSV Format: " << GetTextureFormatAttribs(Key.DSVFormat).Name << "; RTV Formats: ";
- for(Uint32 rt = 0; rt < Key.NumRenderTargets; ++rt)
+ for (Uint32 rt = 0; rt < Key.NumRenderTargets; ++rt)
PassNameSS << (rt > 0 ? ", " : "") << GetTextureFormatAttribs(Key.RTVFormats[rt]).Name;
auto RenderPass = m_DeviceVkImpl.GetLogicalDevice().CreateRenderPass(RenderPassCI, PassNameSS.str().c_str());
VERIFY_EXPR(RenderPass != VK_NULL_HANDLE);
@@ -64,4 +67,4 @@ VkRenderPass RenderPassCache::GetRenderPass(const RenderPassCacheKey& Key)
return it->second;
}
-}
+} // namespace Diligent
diff --git a/Graphics/GraphicsEngineVulkan/src/SamplerVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/SamplerVkImpl.cpp
index 534f01ba..97896641 100644
--- a/Graphics/GraphicsEngineVulkan/src/SamplerVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/SamplerVkImpl.cpp
@@ -30,30 +30,34 @@
namespace Diligent
{
-SamplerVkImpl::SamplerVkImpl(IReferenceCounters* pRefCounters, RenderDeviceVkImpl* pRenderDeviceVk, const SamplerDesc& SamplerDesc) :
+SamplerVkImpl::SamplerVkImpl(IReferenceCounters* pRefCounters, RenderDeviceVkImpl* pRenderDeviceVk, const SamplerDesc& SamplerDesc) :
+ // clang-format off
TSamplerBase
{
pRefCounters,
pRenderDeviceVk,
SamplerDesc
}
+// clang-format on
{
- const auto &LogicalDevice = pRenderDeviceVk->GetLogicalDevice();
+ const auto& LogicalDevice = pRenderDeviceVk->GetLogicalDevice();
+
VkSamplerCreateInfo SamplerCI = {};
- SamplerCI.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
- SamplerCI.pNext = nullptr;
- SamplerCI.flags = 0; // reserved for future use
- SamplerCI.magFilter = FilterTypeToVkFilter(m_Desc.MagFilter);
- SamplerCI.minFilter = FilterTypeToVkFilter(m_Desc.MinFilter);
- SamplerCI.mipmapMode = FilterTypeToVkMipmapMode(m_Desc.MipFilter);
- SamplerCI.addressModeU = AddressModeToVkAddressMode(m_Desc.AddressU);
- SamplerCI.addressModeV = AddressModeToVkAddressMode(m_Desc.AddressV);
- SamplerCI.addressModeW = AddressModeToVkAddressMode(m_Desc.AddressW);
- SamplerCI.mipLodBias = m_Desc.MipLODBias;
+
+ SamplerCI.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
+ SamplerCI.pNext = nullptr;
+ SamplerCI.flags = 0; // reserved for future use
+ SamplerCI.magFilter = FilterTypeToVkFilter(m_Desc.MagFilter);
+ SamplerCI.minFilter = FilterTypeToVkFilter(m_Desc.MinFilter);
+ SamplerCI.mipmapMode = FilterTypeToVkMipmapMode(m_Desc.MipFilter);
+ SamplerCI.addressModeU = AddressModeToVkAddressMode(m_Desc.AddressU);
+ SamplerCI.addressModeV = AddressModeToVkAddressMode(m_Desc.AddressV);
+ SamplerCI.addressModeW = AddressModeToVkAddressMode(m_Desc.AddressW);
+ SamplerCI.mipLodBias = m_Desc.MipLODBias;
SamplerCI.anisotropyEnable = IsAnisotropicFilter(m_Desc.MinFilter);
#ifdef DEVELOPMENT
- if( !( (SamplerCI.anisotropyEnable && IsAnisotropicFilter(m_Desc.MagFilter)) ||
- (!SamplerCI.anisotropyEnable && !IsAnisotropicFilter(m_Desc.MagFilter)) ) )
+ if (!((SamplerCI.anisotropyEnable && IsAnisotropicFilter(m_Desc.MagFilter)) ||
+ (!SamplerCI.anisotropyEnable && !IsAnisotropicFilter(m_Desc.MagFilter))))
{
LOG_ERROR("Min and mag fiters must both be either anisotropic filters or non-anisotropic ones");
}
@@ -62,17 +66,17 @@ SamplerVkImpl::SamplerVkImpl(IReferenceCounters* pRefCounters, RenderDeviceVkImp
SamplerCI.maxAnisotropy = static_cast<float>(m_Desc.MaxAnisotropy);
SamplerCI.compareEnable = IsComparisonFilter(m_Desc.MinFilter);
#ifdef DEVELOPMENT
- if( !( (SamplerCI.compareEnable && IsComparisonFilter(m_Desc.MagFilter)) ||
- (!SamplerCI.compareEnable && !IsComparisonFilter(m_Desc.MagFilter)) ) )
+ if (!((SamplerCI.compareEnable && IsComparisonFilter(m_Desc.MagFilter)) ||
+ (!SamplerCI.compareEnable && !IsComparisonFilter(m_Desc.MagFilter))))
{
LOG_ERROR("Min and mag fiters must both be either comparison filters or non-comparison ones");
}
#endif
- SamplerCI.compareOp = ComparisonFuncToVkCompareOp(m_Desc.ComparisonFunc);
- SamplerCI.minLod = m_Desc.MinLOD;
- SamplerCI.maxLod = m_Desc.MaxLOD;
- SamplerCI.borderColor = BorderColorToVkBorderColor(m_Desc.BorderColor);
+ SamplerCI.compareOp = ComparisonFuncToVkCompareOp(m_Desc.ComparisonFunc);
+ SamplerCI.minLod = m_Desc.MinLOD;
+ SamplerCI.maxLod = m_Desc.MaxLOD;
+ SamplerCI.borderColor = BorderColorToVkBorderColor(m_Desc.BorderColor);
SamplerCI.unnormalizedCoordinates = VK_FALSE;
m_VkSampler = LogicalDevice.CreateSampler(SamplerCI);
@@ -83,6 +87,6 @@ SamplerVkImpl::~SamplerVkImpl()
m_pDevice->SafeReleaseDeviceObject(std::move(m_VkSampler), m_CommandQueueMask);
}
-IMPLEMENT_QUERY_INTERFACE( SamplerVkImpl, IID_SamplerVk, TSamplerBase )
+IMPLEMENT_QUERY_INTERFACE(SamplerVkImpl, IID_SamplerVk, TSamplerBase)
-}
+} // namespace Diligent
diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderResourceBindingVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceBindingVkImpl.cpp
index 1d47c00b..e6f1fff2 100644
--- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceBindingVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceBindingVkImpl.cpp
@@ -30,7 +30,10 @@
namespace Diligent
{
-ShaderResourceBindingVkImpl::ShaderResourceBindingVkImpl(IReferenceCounters* pRefCounters, PipelineStateVkImpl* pPSO, bool IsPSOInternal) :
+ShaderResourceBindingVkImpl::ShaderResourceBindingVkImpl(IReferenceCounters* pRefCounters,
+ PipelineStateVkImpl* pPSO,
+ bool IsPSOInternal) :
+ // clang-format off
TBase
{
pRefCounters,
@@ -38,23 +41,25 @@ ShaderResourceBindingVkImpl::ShaderResourceBindingVkImpl(IReferenceCounters* pRe
IsPSOInternal
},
m_ShaderResourceCache{ShaderResourceCacheVk::DbgCacheContentType::SRBResources}
+// clang-format on
{
auto* ppShaders = pPSO->GetShaders();
- m_NumShaders = static_cast<decltype(m_NumShaders)>(pPSO->GetNumShaders());
+ m_NumShaders = static_cast<decltype(m_NumShaders)>(pPSO->GetNumShaders());
auto* pRenderDeviceVkImpl = pPSO->GetDevice();
// This will only allocate memory and initialize descriptor sets in the resource cache
// Resources will be initialized by InitializeResourceMemoryInCache()
auto& ResourceCacheDataAllocator = pPSO->GetSRBMemoryAllocator().GetResourceCacheDataAllocator(0);
pPSO->GetPipelineLayout().InitResourceCache(pRenderDeviceVkImpl, m_ShaderResourceCache, ResourceCacheDataAllocator, pPSO->GetDesc().Name);
-
+
m_pShaderVarMgrs = ALLOCATE(GetRawAllocator(), "Raw memory for ShaderVariableManagerVk", ShaderVariableManagerVk, m_NumShaders);
for (Uint32 s = 0; s < m_NumShaders; ++s)
{
- auto* pShader = ppShaders[s];
- auto ShaderType = pShader->GetDesc().ShaderType;
- auto ShaderInd = GetShaderTypeIndex(ShaderType);
+ auto* pShader = ppShaders[s];
+ auto ShaderType = pShader->GetDesc().ShaderType;
+ auto ShaderInd = GetShaderTypeIndex(ShaderType);
+
m_ResourceLayoutIndex[ShaderInd] = static_cast<Int8>(s);
auto& VarDataAllocator = pPSO->GetSRBMemoryAllocator().GetShaderVariableDataAllocator(s);
@@ -72,13 +77,12 @@ ShaderResourceBindingVkImpl::ShaderResourceBindingVkImpl(IReferenceCounters* pRe
#ifdef _DEBUG
m_ShaderResourceCache.DbgVerifyResourceInitialization();
#endif
-
}
ShaderResourceBindingVkImpl::~ShaderResourceBindingVkImpl()
{
PipelineStateVkImpl* pPSO = ValidatedCast<PipelineStateVkImpl>(m_pPSO);
- for(Uint32 s = 0; s < m_NumShaders; ++s)
+ for (Uint32 s = 0; s < m_NumShaders; ++s)
{
auto& VarDataAllocator = pPSO->GetSRBMemoryAllocator().GetShaderVariableDataAllocator(s);
m_pShaderVarMgrs[s].DestroyVariables(VarDataAllocator);
@@ -88,16 +92,16 @@ ShaderResourceBindingVkImpl::~ShaderResourceBindingVkImpl()
GetRawAllocator().Free(m_pShaderVarMgrs);
}
-IMPLEMENT_QUERY_INTERFACE( ShaderResourceBindingVkImpl, IID_ShaderResourceBindingVk, TBase )
+IMPLEMENT_QUERY_INTERFACE(ShaderResourceBindingVkImpl, IID_ShaderResourceBindingVk, TBase)
-void ShaderResourceBindingVkImpl::BindResources(Uint32 ShaderFlags, IResourceMapping *pResMapping, Uint32 Flags)
+void ShaderResourceBindingVkImpl::BindResources(Uint32 ShaderFlags, IResourceMapping* pResMapping, Uint32 Flags)
{
- for (auto ShaderInd = 0; ShaderInd <= CSInd; ++ShaderInd )
+ for (auto ShaderInd = 0; ShaderInd <= CSInd; ++ShaderInd)
{
if (ShaderFlags & GetShaderTypeFromIndex(ShaderInd))
{
auto ResLayoutInd = m_ResourceLayoutIndex[ShaderInd];
- if(ResLayoutInd >= 0)
+ if (ResLayoutInd >= 0)
{
m_pShaderVarMgrs[ResLayoutInd].BindResources(pResMapping, Flags);
}
@@ -107,7 +111,7 @@ void ShaderResourceBindingVkImpl::BindResources(Uint32 ShaderFlags, IResourceMap
IShaderResourceVariable* ShaderResourceBindingVkImpl::GetVariableByName(SHADER_TYPE ShaderType, const char* Name)
{
- auto ShaderInd = GetShaderTypeIndex(ShaderType);
+ auto ShaderInd = GetShaderTypeIndex(ShaderType);
auto ResLayoutInd = m_ResourceLayoutIndex[ShaderInd];
if (ResLayoutInd < 0)
{
@@ -120,7 +124,7 @@ IShaderResourceVariable* ShaderResourceBindingVkImpl::GetVariableByName(SHADER_T
Uint32 ShaderResourceBindingVkImpl::GetVariableCount(SHADER_TYPE ShaderType) const
{
- auto ShaderInd = GetShaderTypeIndex(ShaderType);
+ auto ShaderInd = GetShaderTypeIndex(ShaderType);
auto ResLayoutInd = m_ResourceLayoutIndex[ShaderInd];
if (ResLayoutInd < 0)
{
@@ -133,7 +137,7 @@ Uint32 ShaderResourceBindingVkImpl::GetVariableCount(SHADER_TYPE ShaderType) con
IShaderResourceVariable* ShaderResourceBindingVkImpl::GetVariableByIndex(SHADER_TYPE ShaderType, Uint32 Index)
{
- auto ShaderInd = GetShaderTypeIndex(ShaderType);
+ auto ShaderInd = GetShaderTypeIndex(ShaderType);
auto ResLayoutInd = m_ResourceLayoutIndex[ShaderInd];
if (ResLayoutInd < 0)
{
@@ -158,9 +162,9 @@ void ShaderResourceBindingVkImpl::InitializeStaticResources(const IPipelineState
}
else
{
- DEV_CHECK_ERR(pPipelineState->IsCompatibleWith(GetPipelineState()), "The pipeline state '", pPipelineState->GetDesc().Name, "' "
- "is not compatible with the pipeline state '", m_pPSO->GetDesc().Name, "' this SRB was created from and cannot be "
- "used to initialize static resources.");
+ DEV_CHECK_ERR(pPipelineState->IsCompatibleWith(GetPipelineState()), "The pipeline state '", pPipelineState->GetDesc().Name,
+ "' is not compatible with the pipeline state '", m_pPSO->GetDesc().Name,
+ "' this SRB was created from and cannot be used to initialize static resources.");
}
auto* pPSOVK = ValidatedCast<const PipelineStateVkImpl>(pPipelineState);
@@ -168,4 +172,4 @@ void ShaderResourceBindingVkImpl::InitializeStaticResources(const IPipelineState
m_bStaticResourcesInitialized = true;
}
-}
+} // namespace Diligent
diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp
index c899d706..8caafad6 100644
--- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp
@@ -37,7 +37,7 @@ namespace Diligent
size_t ShaderResourceCacheVk::GetRequiredMemorySize(Uint32 NumSets, Uint32 SetSizes[])
{
Uint32 TotalResources = 0;
- for (Uint32 t=0; t < NumSets; ++t)
+ for (Uint32 t = 0; t < NumSets; ++t)
TotalResources += SetSizes[t];
auto MemorySize = NumSets * sizeof(DescriptorSet) + TotalResources * sizeof(Resource);
return MemorySize;
@@ -56,11 +56,11 @@ void ShaderResourceCacheVk::InitializeSets(IMemoryAllocator& MemAllocator, Uint3
// Ns = m_NumSets
VERIFY(m_pAllocator == nullptr && m_pMemory == nullptr, "Cache already initialized");
- m_pAllocator = &MemAllocator;
+ m_pAllocator = &MemAllocator;
VERIFY(NumSets < std::numeric_limits<decltype(m_NumSets)>::max(), "NumSets (", NumSets, ") exceed maximum representable value");
m_NumSets = static_cast<Uint16>(NumSets);
m_TotalResources = 0;
- for (Uint32 t=0; t < NumSets; ++t)
+ for (Uint32 t = 0; t < NumSets; ++t)
m_TotalResources += SetSizes[t];
auto MemorySize = NumSets * sizeof(DescriptorSet) + m_TotalResources * sizeof(Resource);
VERIFY_EXPR(MemorySize == GetRequiredMemorySize(NumSets, SetSizes));
@@ -69,12 +69,12 @@ void ShaderResourceCacheVk::InitializeSets(IMemoryAllocator& MemAllocator, Uint3
#endif
if (MemorySize > 0)
{
- m_pMemory = ALLOCATE_RAW( *m_pAllocator, "Memory for shader resource cache data", MemorySize);
- auto* pSets = reinterpret_cast<DescriptorSet*>(m_pMemory);
+ m_pMemory = ALLOCATE_RAW(*m_pAllocator, "Memory for shader resource cache data", MemorySize);
+ auto* pSets = reinterpret_cast<DescriptorSet*>(m_pMemory);
auto* pCurrResPtr = reinterpret_cast<Resource*>(pSets + m_NumSets);
for (Uint32 t = 0; t < NumSets; ++t)
{
- new(&GetDescriptorSet(t)) DescriptorSet(SetSizes[t], SetSizes[t] > 0 ? pCurrResPtr : nullptr);
+ new (&GetDescriptorSet(t)) DescriptorSet(SetSizes[t], SetSizes[t] > 0 ? pCurrResPtr : nullptr);
pCurrResPtr += SetSizes[t];
#ifdef _DEBUG
m_DbgInitializedResources[t].resize(SetSizes[t]);
@@ -89,7 +89,7 @@ void ShaderResourceCacheVk::InitializeResources(Uint32 Set, Uint32 Offset, Uint3
auto& DescrSet = GetDescriptorSet(Set);
for (Uint32 res = 0; res < ArraySize; ++res)
{
- new(&DescrSet.GetResource(Offset + res)) Resource{Type};
+ new (&DescrSet.GetResource(Offset + res)) Resource{Type};
#ifdef _DEBUG
m_DbgInitializedResources[Set][Offset + res] = true;
#endif
@@ -97,7 +97,7 @@ void ShaderResourceCacheVk::InitializeResources(Uint32 Set, Uint32 Offset, Uint3
}
#ifdef _DEBUG
-void ShaderResourceCacheVk::DbgVerifyResourceInitialization()const
+void ShaderResourceCacheVk::DbgVerifyResourceInitialization() const
{
for (const auto& SetFlags : m_DbgInitializedResources)
{
@@ -105,11 +105,11 @@ void ShaderResourceCacheVk::DbgVerifyResourceInitialization()const
VERIFY(ResInitialized, "Not all resources in the cache have been initialized. This is a bug.");
}
}
-void ShaderResourceCacheVk::DbgVerifyDynamicBuffersCounter()const
+void ShaderResourceCacheVk::DbgVerifyDynamicBuffersCounter() const
{
- const auto* pResources = GetFirstResourcePtr();
- Uint32 NumDynamicBuffers = 0;
- for (Uint32 res=0; res < m_TotalResources; ++res)
+ const auto* pResources = GetFirstResourcePtr();
+ Uint32 NumDynamicBuffers = 0;
+ for (Uint32 res = 0; res < m_TotalResources; ++res)
{
const auto& Res = pResources[res];
if (Res.Type == SPIRVShaderResourceAttribs::ResourceType::UniformBuffer)
@@ -117,8 +117,8 @@ void ShaderResourceCacheVk::DbgVerifyDynamicBuffersCounter()const
if (Res.pObject && Res.pObject.RawPtr<const BufferVkImpl>()->GetDesc().Usage == USAGE_DYNAMIC)
++NumDynamicBuffers;
}
- else if (Res.Type == SPIRVShaderResourceAttribs::ResourceType::ROStorageBuffer ||
- Res.Type == SPIRVShaderResourceAttribs::ResourceType::RWStorageBuffer ||
+ else if (Res.Type == SPIRVShaderResourceAttribs::ResourceType::ROStorageBuffer ||
+ Res.Type == SPIRVShaderResourceAttribs::ResourceType::RWStorageBuffer ||
Res.Type == SPIRVShaderResourceAttribs::ResourceType::UniformTexelBuffer ||
Res.Type == SPIRVShaderResourceAttribs::ResourceType::StorageTexelBuffer)
{
@@ -135,7 +135,7 @@ ShaderResourceCacheVk::~ShaderResourceCacheVk()
if (m_pMemory)
{
auto* pResources = GetFirstResourcePtr();
- for (Uint32 res=0; res < m_TotalResources; ++res)
+ for (Uint32 res = 0; res < m_TotalResources; ++res)
pResources[res].~Resource();
for (Uint32 t = 0; t < m_NumSets; ++t)
GetDescriptorSet(t).~DescriptorSet();
@@ -144,7 +144,7 @@ ShaderResourceCacheVk::~ShaderResourceCacheVk()
}
}
-template<bool VerifyOnly>
+template <bool VerifyOnly>
void ShaderResourceCacheVk::TransitionResources(DeviceContextVkImpl* pCtxVkImpl)
{
auto* pResources = GetFirstResourcePtr();
@@ -166,11 +166,11 @@ void ShaderResourceCacheVk::TransitionResources(DeviceContextVkImpl* pCtxVkImpl)
if (!IsInRequiredState)
{
LOG_ERROR_MESSAGE("State of buffer '", pBufferVk->GetDesc().Name, "' is incorrect. Required state: ",
- GetResourceStateString(RequiredState), ". Actual state: ",
- GetResourceStateString(pBufferVk->GetState()),
- ". Call IDeviceContext::TransitionShaderResources(), use RESOURCE_STATE_TRANSITION_MODE_TRANSITION "
- "when calling IDeviceContext::CommitShaderResources() or explicitly transition the buffer state "
- "with IDeviceContext::TransitionResourceStates().");
+ GetResourceStateString(RequiredState), ". Actual state: ",
+ GetResourceStateString(pBufferVk->GetState()),
+ ". Call IDeviceContext::TransitionShaderResources(), use RESOURCE_STATE_TRANSITION_MODE_TRANSITION "
+ "when calling IDeviceContext::CommitShaderResources() or explicitly transition the buffer state "
+ "with IDeviceContext::TransitionResourceStates().");
}
}
else
@@ -191,17 +191,19 @@ void ShaderResourceCacheVk::TransitionResources(DeviceContextVkImpl* pCtxVkImpl)
case SPIRVShaderResourceAttribs::ResourceType::StorageTexelBuffer:
{
auto* pBuffViewVk = Res.pObject.RawPtr<BufferViewVkImpl>();
- auto* pBufferVk = pBuffViewVk != nullptr ? ValidatedCast<BufferVkImpl>(pBuffViewVk->GetBuffer()) : nullptr;
+ auto* pBufferVk = pBuffViewVk != nullptr ? ValidatedCast<BufferVkImpl>(pBuffViewVk->GetBuffer()) : nullptr;
if (pBufferVk != nullptr && pBufferVk->IsInKnownState())
{
- const RESOURCE_STATE RequiredState =
- (Res.Type == SPIRVShaderResourceAttribs::ResourceType::RWStorageBuffer ||
+ const RESOURCE_STATE RequiredState =
+ (Res.Type == SPIRVShaderResourceAttribs::ResourceType::RWStorageBuffer ||
Res.Type == SPIRVShaderResourceAttribs::ResourceType::StorageTexelBuffer) ?
- RESOURCE_STATE_UNORDERED_ACCESS : RESOURCE_STATE_SHADER_RESOURCE;
+ RESOURCE_STATE_UNORDERED_ACCESS :
+ RESOURCE_STATE_SHADER_RESOURCE;
#ifdef _DEBUG
- const VkAccessFlags RequiredAccessFlags = (RequiredState == RESOURCE_STATE_SHADER_RESOURCE) ?
- VK_ACCESS_SHADER_READ_BIT : (VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT);
- VERIFY_EXPR( (ResourceStateFlagsToVkAccessFlags(RequiredState) & RequiredAccessFlags) == RequiredAccessFlags);
+ const VkAccessFlags RequiredAccessFlags = (RequiredState == RESOURCE_STATE_SHADER_RESOURCE) ?
+ VK_ACCESS_SHADER_READ_BIT :
+ (VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT);
+ VERIFY_EXPR((ResourceStateFlagsToVkAccessFlags(RequiredState) & RequiredAccessFlags) == RequiredAccessFlags);
#endif
const bool IsInRequiredState = pBufferVk->CheckState(RequiredState);
@@ -210,11 +212,11 @@ void ShaderResourceCacheVk::TransitionResources(DeviceContextVkImpl* pCtxVkImpl)
if (!IsInRequiredState)
{
LOG_ERROR_MESSAGE("State of buffer '", pBufferVk->GetDesc().Name, "' is incorrect. Required state: ",
- GetResourceStateString(RequiredState), ". Actual state: ",
- GetResourceStateString(pBufferVk->GetState()),
- ". Call IDeviceContext::TransitionShaderResources(), use RESOURCE_STATE_TRANSITION_MODE_TRANSITION "
- "when calling IDeviceContext::CommitShaderResources() or explicitly transition the buffer state "
- "with IDeviceContext::TransitionResourceStates().");
+ GetResourceStateString(RequiredState), ". Actual state: ",
+ GetResourceStateString(pBufferVk->GetState()),
+ ". Call IDeviceContext::TransitionShaderResources(), use RESOURCE_STATE_TRANSITION_MODE_TRANSITION "
+ "when calling IDeviceContext::CommitShaderResources() or explicitly transition the buffer state "
+ "with IDeviceContext::TransitionResourceStates().");
}
}
else
@@ -236,13 +238,13 @@ void ShaderResourceCacheVk::TransitionResources(DeviceContextVkImpl* pCtxVkImpl)
case SPIRVShaderResourceAttribs::ResourceType::StorageImage:
{
auto* pTextureViewVk = Res.pObject.RawPtr<TextureViewVkImpl>();
- auto* pTextureVk = pTextureViewVk != nullptr ? ValidatedCast<TextureVkImpl>(pTextureViewVk->GetTexture()) : nullptr;
+ auto* pTextureVk = pTextureViewVk != nullptr ? ValidatedCast<TextureVkImpl>(pTextureViewVk->GetTexture()) : nullptr;
if (pTextureVk != nullptr && pTextureVk->IsInKnownState())
{
- // The image subresources for a storage image must be in the VK_IMAGE_LAYOUT_GENERAL layout in
+ // The image subresources for a storage image must be in the VK_IMAGE_LAYOUT_GENERAL layout in
// order to access its data in a shader (13.1.1)
- // The image subresources for a sampled image or a combined image sampler must be in the
- // VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
+ // The image subresources for a sampled image or a combined image sampler must be in the
+ // VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
// or VK_IMAGE_LAYOUT_GENERAL layout in order to access its data in a shader (13.1.3, 13.1.4).
RESOURCE_STATE RequiredState;
if (Res.Type == SPIRVShaderResourceAttribs::ResourceType::StorageImage)
@@ -254,9 +256,9 @@ void ShaderResourceCacheVk::TransitionResources(DeviceContextVkImpl* pCtxVkImpl)
{
if (pTextureVk->GetDesc().BindFlags & BIND_DEPTH_STENCIL)
{
- // VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL must only be used as a read - only depth / stencil attachment
- // in a VkFramebuffer and/or as a read - only image in a shader (which can be read as a sampled image, combined
- // image / sampler and /or input attachment). This layout is valid only for image subresources of images created
+ // VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL must only be used as a read - only depth / stencil attachment
+ // in a VkFramebuffer and/or as a read - only image in a shader (which can be read as a sampled image, combined
+ // image / sampler and /or input attachment). This layout is valid only for image subresources of images created
// with the VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT usage bit enabled. (11.4)
RequiredState = RESOURCE_STATE_DEPTH_READ;
VERIFY_EXPR(ResourceStateToVkImageLayout(RequiredState) == VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL);
@@ -274,11 +276,11 @@ void ShaderResourceCacheVk::TransitionResources(DeviceContextVkImpl* pCtxVkImpl)
if (!IsInRequiredState)
{
LOG_ERROR_MESSAGE("State of texture '", pTextureVk->GetDesc().Name, "' is incorrect. Required state: ",
- GetResourceStateString(RequiredState), ". Actual state: ",
- GetResourceStateString(pTextureVk->GetState()),
+ GetResourceStateString(RequiredState), ". Actual state: ",
+ GetResourceStateString(pTextureVk->GetState()),
". Call IDeviceContext::TransitionShaderResources(), use RESOURCE_STATE_TRANSITION_MODE_TRANSITION "
- "when calling IDeviceContext::CommitShaderResources() or explicitly transition the texture state "
- "with IDeviceContext::TransitionResourceStates().");
+ "when calling IDeviceContext::CommitShaderResources() or explicitly transition the texture state "
+ "with IDeviceContext::TransitionResourceStates().");
}
}
else
@@ -315,7 +317,7 @@ template void ShaderResourceCacheVk::TransitionResources<false>(DeviceContextVkI
template void ShaderResourceCacheVk::TransitionResources<true>(DeviceContextVkImpl* pCtxVkImpl);
-VkDescriptorBufferInfo ShaderResourceCacheVk::Resource::GetUniformBufferDescriptorWriteInfo()const
+VkDescriptorBufferInfo ShaderResourceCacheVk::Resource::GetUniformBufferDescriptorWriteInfo() const
{
VERIFY(Type == SPIRVShaderResourceAttribs::ResourceType::UniformBuffer, "Uniform buffer resource is expected");
DEV_CHECK_ERR(pObject != nullptr, "Unable to get uniform buffer write info: cached object is null");
@@ -323,41 +325,45 @@ VkDescriptorBufferInfo ShaderResourceCacheVk::Resource::GetUniformBufferDescript
auto* pBuffVk = pObject.RawPtr<const BufferVkImpl>();
// VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER or VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC descriptor type require
// buffer to be created with VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT
- VERIFY_EXPR( (pBuffVk->GetDesc().BindFlags & BIND_UNIFORM_BUFFER) != 0);
+ VERIFY_EXPR((pBuffVk->GetDesc().BindFlags & BIND_UNIFORM_BUFFER) != 0);
VkDescriptorBufferInfo DescrBuffInfo;
DescrBuffInfo.buffer = pBuffVk->GetVkBuffer();
- // If descriptorType is VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER or VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, the offset member
+ // If descriptorType is VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER or VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, the offset member
// of each element of pBufferInfo must be a multiple of VkPhysicalDeviceLimits::minUniformBufferOffsetAlignment (13.2.4)
DescrBuffInfo.offset = 0;
DescrBuffInfo.range = pBuffVk->GetDesc().uiSizeInBytes;
return DescrBuffInfo;
}
-VkDescriptorBufferInfo ShaderResourceCacheVk::Resource::GetStorageBufferDescriptorWriteInfo()const
+VkDescriptorBufferInfo ShaderResourceCacheVk::Resource::GetStorageBufferDescriptorWriteInfo() const
{
- VERIFY(Type == SPIRVShaderResourceAttribs::ResourceType::ROStorageBuffer ||
+ // clang-format off
+ VERIFY(Type == SPIRVShaderResourceAttribs::ResourceType::ROStorageBuffer ||
Type == SPIRVShaderResourceAttribs::ResourceType::RWStorageBuffer,
"Storage buffer resource is expected");
+ // clang-format on
DEV_CHECK_ERR(pObject != nullptr, "Unable to get storage buffer write info: cached object is null");
- auto* pBuffViewVk = pObject.RawPtr<const BufferViewVkImpl>();
- const auto& ViewDesc = pBuffViewVk->GetDesc();
- auto* pBuffVk = pBuffViewVk->GetBufferVk();
+ auto* pBuffViewVk = pObject.RawPtr<const BufferViewVkImpl>();
+ const auto& ViewDesc = pBuffViewVk->GetDesc();
+ auto* pBuffVk = pBuffViewVk->GetBufferVk();
- // VK_DESCRIPTOR_TYPE_STORAGE_BUFFER or VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC descriptor type
+ // VK_DESCRIPTOR_TYPE_STORAGE_BUFFER or VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC descriptor type
// require buffer to be created with VK_BUFFER_USAGE_STORAGE_BUFFER_BIT (13.2.4)
if (Type == SPIRVShaderResourceAttribs::ResourceType::ROStorageBuffer)
{
// HLSL buffer SRVs are mapped to read-only storge buffers in SPIR-V
- VERIFY(ViewDesc.ViewType == BUFFER_VIEW_SHADER_RESOURCE, "Attempting to bind buffer view '", ViewDesc.Name, "' as read-only storage buffer. "
- "Expected view type is BUFFER_VIEW_SHADER_RESOURCE. Actual type: ", GetBufferViewTypeLiteralName(ViewDesc.ViewType));
+ VERIFY(ViewDesc.ViewType == BUFFER_VIEW_SHADER_RESOURCE, "Attempting to bind buffer view '", ViewDesc.Name,
+ "' as read-only storage buffer. Expected view type is BUFFER_VIEW_SHADER_RESOURCE. Actual type: ",
+ GetBufferViewTypeLiteralName(ViewDesc.ViewType));
VERIFY((pBuffVk->GetDesc().BindFlags & BIND_SHADER_RESOURCE) != 0, "Buffer '", pBuffVk->GetDesc().Name, "' being set as read-only storage buffer was not created with BIND_SHADER_RESOURCE flag");
}
else if (Type == SPIRVShaderResourceAttribs::ResourceType::RWStorageBuffer)
{
- VERIFY(ViewDesc.ViewType == BUFFER_VIEW_UNORDERED_ACCESS, "Attempting to bind buffer view '", ViewDesc.Name, "' as writable storage buffer. "
- "Expected view type is BUFFER_VIEW_UNORDERED_ACCESS. Actual type: ", GetBufferViewTypeLiteralName(ViewDesc.ViewType));
+ VERIFY(ViewDesc.ViewType == BUFFER_VIEW_UNORDERED_ACCESS, "Attempting to bind buffer view '", ViewDesc.Name,
+ "' as writable storage buffer. Expected view type is BUFFER_VIEW_UNORDERED_ACCESS. Actual type: ",
+ GetBufferViewTypeLiteralName(ViewDesc.ViewType));
VERIFY((pBuffVk->GetDesc().BindFlags & BIND_UNORDERED_ACCESS) != 0, "Buffer '", pBuffVk->GetDesc().Name, "' being set as writable storage buffer was not created with BIND_UNORDERED_ACCESS flag");
}
else
@@ -374,12 +380,14 @@ VkDescriptorBufferInfo ShaderResourceCacheVk::Resource::GetStorageBufferDescript
return DescrBuffInfo;
}
-VkDescriptorImageInfo ShaderResourceCacheVk::Resource::GetImageDescriptorWriteInfo(bool IsImmutableSampler)const
+VkDescriptorImageInfo ShaderResourceCacheVk::Resource::GetImageDescriptorWriteInfo(bool IsImmutableSampler) const
{
- VERIFY(Type == SPIRVShaderResourceAttribs::ResourceType::StorageImage ||
+ // clang-format off
+ VERIFY(Type == SPIRVShaderResourceAttribs::ResourceType::StorageImage ||
Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage ||
Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage,
"Storage image, separate image or sampled image resource is expected");
+ // clang-format on
DEV_CHECK_ERR(pObject != nullptr, "Unable to get image descriptor write info: cached object is null");
bool IsStorageImage = Type == SPIRVShaderResourceAttribs::ResourceType::StorageImage;
@@ -393,14 +401,14 @@ VkDescriptorImageInfo ShaderResourceCacheVk::Resource::GetImageDescriptorWriteIn
"Immutable sampler can't be assigned to separarate image or storage image");
if (Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage && !IsImmutableSampler)
{
- // Immutable samplers are permanently bound into the set layout; later binding a sampler
+ // Immutable samplers are permanently bound into the set layout; later binding a sampler
// into an immutable sampler slot in a descriptor set is not allowed (13.2.1)
auto* pSamplerVk = ValidatedCast<const SamplerVkImpl>(pTexViewVk->GetSampler());
if (pSamplerVk != nullptr)
{
- // If descriptorType is VK_DESCRIPTOR_TYPE_SAMPLER or VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
- // and dstSet was not allocated with a layout that included immutable samplers for dstBinding with
- // descriptorType, the sampler member of each element of pImageInfo must be a valid VkSampler
+ // If descriptorType is VK_DESCRIPTOR_TYPE_SAMPLER or VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
+ // and dstSet was not allocated with a layout that included immutable samplers for dstBinding with
+ // descriptorType, the sampler member of each element of pImageInfo must be a valid VkSampler
// object (13.2.4)
DescrImgInfo.sampler = pSamplerVk->GetVkSampler();
}
@@ -412,9 +420,9 @@ VkDescriptorImageInfo ShaderResourceCacheVk::Resource::GetImageDescriptorWriteIn
#endif
}
DescrImgInfo.imageView = pTexViewVk->GetVulkanImageView();
-
- // If descriptorType is VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, for each descriptor that will be accessed
- // via load or store operations the imageLayout member for corresponding elements of pImageInfo
+
+ // If descriptorType is VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, for each descriptor that will be accessed
+ // via load or store operations the imageLayout member for corresponding elements of pImageInfo
// MUST be VK_IMAGE_LAYOUT_GENERAL (13.2.4)
if (IsStorageImage)
DescrImgInfo.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
@@ -429,11 +437,13 @@ VkDescriptorImageInfo ShaderResourceCacheVk::Resource::GetImageDescriptorWriteIn
return DescrImgInfo;
}
-VkBufferView ShaderResourceCacheVk::Resource::GetBufferViewWriteInfo()const
+VkBufferView ShaderResourceCacheVk::Resource::GetBufferViewWriteInfo() const
{
+ // clang-format off
VERIFY(Type == SPIRVShaderResourceAttribs::ResourceType::UniformTexelBuffer ||
Type == SPIRVShaderResourceAttribs::ResourceType::StorageTexelBuffer,
"Uniform or storage buffer resource is expected");
+ // clang-format on
DEV_CHECK_ERR(pObject != nullptr, "Unable to get buffer view write info: cached object is null");
// The following bits must have been set at buffer creation time:
@@ -443,12 +453,13 @@ VkBufferView ShaderResourceCacheVk::Resource::GetBufferViewWriteInfo()const
return pBuffViewVk->GetVkBufferView();
}
-VkDescriptorImageInfo ShaderResourceCacheVk::Resource::GetSamplerDescriptorWriteInfo()const
+VkDescriptorImageInfo ShaderResourceCacheVk::Resource::GetSamplerDescriptorWriteInfo() const
{
VERIFY(Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler, "Separate sampler resource is expected");
DEV_CHECK_ERR(pObject != nullptr, "Unable to get separate sampler descriptor write info: cached object is null");
auto* pSamplerVk = pObject.RawPtr<const SamplerVkImpl>();
+
VkDescriptorImageInfo DescrImgInfo;
// For VK_DESCRIPTOR_TYPE_SAMPLER, only the sample member of each element of VkWriteDescriptorSet::pImageInfo is accessed (13.2.4)
DescrImgInfo.sampler = pSamplerVk->GetVkSampler();
@@ -457,4 +468,4 @@ VkDescriptorImageInfo ShaderResourceCacheVk::Resource::GetSamplerDescriptorWrite
return DescrImgInfo;
}
-}
+} // namespace Diligent
diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp
index 0bf676ba..c61f3608 100644
--- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp
@@ -38,7 +38,7 @@
namespace Diligent
{
-
+
static Int32 FindImmutableSampler(SHADER_TYPE ShaderType,
const PipelineResourceLayoutDesc& ResourceLayoutDesc,
const SPIRVShaderResourceAttribs& Attribs,
@@ -59,10 +59,10 @@ static Int32 FindImmutableSampler(SHADER_TYPE ShaderType,
return -1;
}
- for (Uint32 s=0; s < ResourceLayoutDesc.NumStaticSamplers; ++s)
+ for (Uint32 s = 0; s < ResourceLayoutDesc.NumStaticSamplers; ++s)
{
const auto& StSam = ResourceLayoutDesc.StaticSamplers[s];
- if ( ((StSam.ShaderStages & ShaderType) != 0) && StreqSuff(Attribs.Name, StSam.SamplerOrTextureName, SamplerSuffix) )
+ if (((StSam.ShaderStages & ShaderType) != 0) && StreqSuff(Attribs.Name, StSam.SamplerOrTextureName, SamplerSuffix))
return s;
}
@@ -79,8 +79,7 @@ static SHADER_RESOURCE_VARIABLE_TYPE FindShaderVariableType(SHADER_TYPE
// Use texture or sampler name to derive separate sampler type
// When HLSL-style combined image samplers are not used, CombinedSamplerSuffix is null
return GetShaderVariableType(ShaderType, ResourceLayoutDesc.DefaultVariableType, ResourceLayoutDesc.Variables, ResourceLayoutDesc.NumVariables,
- [&](const char* VarName)
- {
+ [&](const char* VarName) {
return StreqSuff(Attribs.Name, VarName, CombinedSamplerSuffix);
});
}
@@ -93,19 +92,19 @@ static SHADER_RESOURCE_VARIABLE_TYPE FindShaderVariableType(SHADER_TYPE
ShaderResourceLayoutVk::~ShaderResourceLayoutVk()
{
- for (Uint32 r=0; r < GetTotalResourceCount(); ++r)
+ for (Uint32 r = 0; r < GetTotalResourceCount(); ++r)
GetResource(r).~VkResource();
- for(Uint32 s=0; s < m_NumImmutableSamplers; ++s)
+ for (Uint32 s = 0; s < m_NumImmutableSamplers; ++s)
GetImmutableSampler(s).~ImmutableSamplerPtrType();
}
-void ShaderResourceLayoutVk::AllocateMemory(std::shared_ptr<const SPIRVShaderResources> pSrcResources,
- IMemoryAllocator& Allocator,
- const PipelineResourceLayoutDesc& ResourceLayoutDesc,
- const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes,
- Uint32 NumAllowedTypes,
- bool AllocateImmutableSamplers)
+void ShaderResourceLayoutVk::AllocateMemory(std::shared_ptr<const SPIRVShaderResources> pSrcResources,
+ IMemoryAllocator& Allocator,
+ const PipelineResourceLayoutDesc& ResourceLayoutDesc,
+ const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes,
+ Uint32 NumAllowedTypes,
+ bool AllocateImmutableSamplers)
{
VERIFY(!m_ResourceBuffer, "Memory has already been initialized");
VERIFY_EXPR(!m_pResources);
@@ -118,31 +117,31 @@ void ShaderResourceLayoutVk::AllocateMemory(std::shared_ptr<const SPIRVShaderRes
const auto* CombinedSamplerSuffix = m_pResources->GetCombinedSamplerSuffix();
// Count the number of resources to allocate all needed memory
m_pResources->ProcessResources(
- [&](const SPIRVShaderResourceAttribs& ResAttribs, Uint32)
+ [&](const SPIRVShaderResourceAttribs& ResAttribs, Uint32) //
{
auto VarType = FindShaderVariableType(ShaderType, ResAttribs, ResourceLayoutDesc, CombinedSamplerSuffix);
if (IsAllowedType(VarType, AllowedTypeBits))
{
// For immutable separate samplers we still allocate VkResource instances, but they are never exposed to the app
- VERIFY( Uint32{m_NumResources[VarType]} + 1 <= Uint32{std::numeric_limits<Uint16>::max()}, "Number of resources exceeds Uint16 maximum representable value");
+ VERIFY(Uint32{m_NumResources[VarType]} + 1 <= Uint32{std::numeric_limits<Uint16>::max()}, "Number of resources exceeds Uint16 maximum representable value");
++m_NumResources[VarType];
}
- }
+ } //
);
Uint32 TotalResources = 0;
- for (SHADER_RESOURCE_VARIABLE_TYPE VarType = SHADER_RESOURCE_VARIABLE_TYPE_STATIC; VarType < SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES; VarType = static_cast<SHADER_RESOURCE_VARIABLE_TYPE>(VarType+1))
+ for (SHADER_RESOURCE_VARIABLE_TYPE VarType = SHADER_RESOURCE_VARIABLE_TYPE_STATIC; VarType < SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES; VarType = static_cast<SHADER_RESOURCE_VARIABLE_TYPE>(VarType + 1))
{
TotalResources += m_NumResources[VarType];
}
- VERIFY(TotalResources <= Uint32{std::numeric_limits<Uint16>::max()}, "Total number of resources exceeds Uint16 maximum representable value" );
+ VERIFY(TotalResources <= Uint32{std::numeric_limits<Uint16>::max()}, "Total number of resources exceeds Uint16 maximum representable value");
m_NumResources[SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES] = static_cast<Uint16>(TotalResources);
m_NumImmutableSamplers = 0;
if (AllocateImmutableSamplers)
{
- for (Uint32 s=0; s < ResourceLayoutDesc.NumStaticSamplers; ++s)
+ for (Uint32 s = 0; s < ResourceLayoutDesc.NumStaticSamplers; ++s)
{
const auto& StSamDesc = ResourceLayoutDesc.StaticSamplers[s];
if ((StSamDesc.ShaderStages & ShaderType) != 0)
@@ -151,17 +150,17 @@ void ShaderResourceLayoutVk::AllocateMemory(std::shared_ptr<const SPIRVShaderRes
}
size_t MemSize = TotalResources * sizeof(VkResource) + m_NumImmutableSamplers * sizeof(ImmutableSamplerPtrType);
- static_assert( (sizeof(VkResource) % sizeof(void*)) == 0, "sizeof(VkResource) must be multiple of sizeof(void*)" );
+ static_assert((sizeof(VkResource) % sizeof(void*)) == 0, "sizeof(VkResource) must be multiple of sizeof(void*)");
if (MemSize == 0)
return;
- auto* pRawMem = ALLOCATE_RAW(Allocator, "Raw memory buffer for shader resource layout resources", MemSize);
- m_ResourceBuffer = std::unique_ptr<void, STDDeleterRawMem<void> >(pRawMem, Allocator);
- for (Uint32 s=0; s < m_NumImmutableSamplers; ++s)
+ auto* pRawMem = ALLOCATE_RAW(Allocator, "Raw memory buffer for shader resource layout resources", MemSize);
+ m_ResourceBuffer = std::unique_ptr<void, STDDeleterRawMem<void>>(pRawMem, Allocator);
+ for (Uint32 s = 0; s < m_NumImmutableSamplers; ++s)
{
// We need to initialize immutable samplers
auto& UninitializedImmutableSampler = GetImmutableSampler(s);
- new(std::addressof(UninitializedImmutableSampler)) ImmutableSamplerPtrType;
+ new (std::addressof(UninitializedImmutableSampler)) ImmutableSamplerPtrType;
}
}
@@ -173,11 +172,12 @@ void ShaderResourceLayoutVk::InitializeStaticResourceLayout(std::shared_ptr<cons
{
const auto AllowedVarType = SHADER_RESOURCE_VARIABLE_TYPE_STATIC;
// We do not need immutable samplers in static shader resource layout as they
- // are relevant only when the main layout is initialized
+ // are relevant only when the main layout is initialized
constexpr bool AllocateImmutableSamplers = false;
AllocateMemory(std::move(pSrcResources), LayoutDataAllocator, ResourceLayoutDesc, &AllowedVarType, 1, AllocateImmutableSamplers);
std::array<Uint32, SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES> CurrResInd = {};
+
Uint32 StaticResCacheSize = 0;
const Uint32 AllowedTypeBits = GetAllowedTypeBits(&AllowedVarType, 1);
@@ -185,14 +185,14 @@ void ShaderResourceLayoutVk::InitializeStaticResourceLayout(std::shared_ptr<cons
const auto* CombinedSamplerSuffix = m_pResources->GetCombinedSamplerSuffix();
m_pResources->ProcessResources(
- [&](const SPIRVShaderResourceAttribs& Attribs, Uint32)
+ [&](const SPIRVShaderResourceAttribs& Attribs, Uint32) //
{
auto VarType = FindShaderVariableType(ShaderType, Attribs, ResourceLayoutDesc, CombinedSamplerSuffix);
if (!IsAllowedType(VarType, AllowedTypeBits))
return;
Int32 SrcImmutableSamplerInd = -1;
- if (Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage ||
+ if (Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage ||
Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler)
{
// Only search for the immutable sampler for combined image samplers and separate samplers
@@ -204,7 +204,7 @@ void ShaderResourceLayoutVk::InitializeStaticResourceLayout(std::shared_ptr<cons
Uint32 DescriptorSet = 0;
Uint32 CacheOffset = StaticResCacheSize;
StaticResCacheSize += Attribs.ArraySize;
-
+
Uint32 SamplerInd = VkResource::InvalidSamplerInd;
if (Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage)
{
@@ -213,7 +213,7 @@ void ShaderResourceLayoutVk::InitializeStaticResourceLayout(std::shared_ptr<cons
SamplerInd = FindAssignedSampler(Attribs, CurrResInd[VarType], VarType);
}
::new (&GetResource(VarType, CurrResInd[VarType]++)) VkResource(*this, Attribs, VarType, Binding, DescriptorSet, CacheOffset, SamplerInd, SrcImmutableSamplerInd >= 0);
- }
+ } //
);
#ifdef _DEBUG
@@ -231,14 +231,14 @@ void ShaderResourceLayoutVk::InitializeStaticResourceLayout(std::shared_ptr<cons
}
#ifdef DEVELOPMENT
-void ShaderResourceLayoutVk::dvpVerifyResourceLayoutDesc(Uint32 NumShaders,
- const std::shared_ptr<const SPIRVShaderResources> pShaderResources[],
- const PipelineResourceLayoutDesc& ResourceLayoutDesc)
+void ShaderResourceLayoutVk::dvpVerifyResourceLayoutDesc(Uint32 NumShaders,
+ const std::shared_ptr<const SPIRVShaderResources> pShaderResources[],
+ const PipelineResourceLayoutDesc& ResourceLayoutDesc)
{
- auto GetAllowedShadersString = [&](SHADER_TYPE ShaderStages)
+ auto GetAllowedShadersString = [&](SHADER_TYPE ShaderStages) //
{
std::string ShadersStr;
- for (Uint32 s=0; s < NumShaders; ++s)
+ for (Uint32 s = 0; s < NumShaders; ++s)
{
const auto& Resources = *pShaderResources[s];
if ((ShaderStages & Resources.GetShaderType()) != 0)
@@ -263,15 +263,15 @@ void ShaderResourceLayoutVk::dvpVerifyResourceLayoutDesc(Uint32
}
bool VariableFound = false;
- for (Uint32 s=0; s < NumShaders && !VariableFound; ++s)
+ for (Uint32 s = 0; s < NumShaders && !VariableFound; ++s)
{
const auto& Resources = *pShaderResources[s];
- if ( (VarDesc.ShaderStages & Resources.GetShaderType()) != 0 )
+ if ((VarDesc.ShaderStages & Resources.GetShaderType()) != 0)
{
for (Uint32 res = 0; res < Resources.GetTotalResources() && !VariableFound; ++res)
{
const auto& ResAttribs = Resources.GetResource(res);
- VariableFound = (strcmp(ResAttribs.Name, VarDesc.Name) == 0);
+ VariableFound = (strcmp(ResAttribs.Name, VarDesc.Name) == 0);
}
}
}
@@ -293,10 +293,10 @@ void ShaderResourceLayoutVk::dvpVerifyResourceLayoutDesc(Uint32
}
bool SamplerFound = false;
- for (Uint32 s=0; s < NumShaders && !SamplerFound; ++s)
+ for (Uint32 s = 0; s < NumShaders && !SamplerFound; ++s)
{
const auto& Resources = *pShaderResources[s];
- if ( (StSamDesc.ShaderStages & Resources.GetShaderType()) == 0 )
+ if ((StSamDesc.ShaderStages & Resources.GetShaderType()) == 0)
continue;
// Irrespective of whether HLSL-style combined image samplers are used,
@@ -304,19 +304,19 @@ void ShaderResourceLayoutVk::dvpVerifyResourceLayoutDesc(Uint32
for (Uint32 i = 0; i < Resources.GetNumSmpldImgs() && !SamplerFound; ++i)
{
const auto& SmplImg = Resources.GetSmpldImg(i);
- SamplerFound = (strcmp(SmplImg.Name, StSamDesc.SamplerOrTextureName) == 0);
+ SamplerFound = (strcmp(SmplImg.Name, StSamDesc.SamplerOrTextureName) == 0);
}
if (!SamplerFound)
{
- // Check if static sampler is assigned to a separate sampler.
+ // Check if static sampler is assigned to a separate sampler.
// In case HLSL-style combined image samplers are used, the condition is SepSmpl.Name == "g_Texture" + "_sampler".
// Otherwise the condition is SepSmpl.Name == "g_Texture_sampler" + "".
const auto* CombinedSamplerSuffix = Resources.GetCombinedSamplerSuffix();
for (Uint32 i = 0; i < Resources.GetNumSepSmplrs() && !SamplerFound; ++i)
{
const auto& SepSmpl = Resources.GetSepSmplr(i);
- SamplerFound = StreqSuff(SepSmpl.Name, StSamDesc.SamplerOrTextureName, CombinedSamplerSuffix);
+ SamplerFound = StreqSuff(SepSmpl.Name, StSamDesc.SamplerOrTextureName, CombinedSamplerSuffix);
}
}
}
@@ -331,14 +331,14 @@ void ShaderResourceLayoutVk::dvpVerifyResourceLayoutDesc(Uint32
}
#endif
-void ShaderResourceLayoutVk::Initialize(IRenderDevice* pRenderDevice,
- Uint32 NumShaders,
- ShaderResourceLayoutVk Layouts[],
- std::shared_ptr<const SPIRVShaderResources> pShaderResources[],
- IMemoryAllocator& LayoutDataAllocator,
- const PipelineResourceLayoutDesc& ResourceLayoutDesc,
- std::vector<uint32_t> SPIRVs[],
- class PipelineLayout& PipelineLayout)
+void ShaderResourceLayoutVk::Initialize(IRenderDevice* pRenderDevice,
+ Uint32 NumShaders,
+ ShaderResourceLayoutVk Layouts[],
+ std::shared_ptr<const SPIRVShaderResources> pShaderResources[],
+ IMemoryAllocator& LayoutDataAllocator,
+ const PipelineResourceLayoutDesc& ResourceLayoutDesc,
+ std::vector<uint32_t> SPIRVs[],
+ class PipelineLayout& PipelineLayout)
{
#ifdef DEVELOPMENT
dvpVerifyResourceLayoutDesc(NumShaders, pShaderResources, ResourceLayoutDesc);
@@ -348,26 +348,26 @@ void ShaderResourceLayoutVk::Initialize(IRenderDevice*
const Uint32 NumAllowedTypes = 0;
const Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes);
- for (Uint32 s=0; s < NumShaders; ++s)
+ for (Uint32 s = 0; s < NumShaders; ++s)
{
constexpr bool AllocateImmutableSamplers = true;
Layouts[s].AllocateMemory(std::move(pShaderResources[s]), LayoutDataAllocator, ResourceLayoutDesc, AllowedVarTypes, NumAllowedTypes, AllocateImmutableSamplers);
}
-
+
VERIFY_EXPR(NumShaders <= MaxShadersInPipeline);
- std::array<std::array<Uint32, SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES>, MaxShadersInPipeline> CurrResInd = {};
- std::array<Uint32, MaxShadersInPipeline> CurrImmutableSamplerInd = {};
+ std::array<std::array<Uint32, SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES>, MaxShadersInPipeline> CurrResInd = {};
+ std::array<Uint32, MaxShadersInPipeline> CurrImmutableSamplerInd = {};
#ifdef _DEBUG
std::unordered_map<Uint32, std::pair<Uint32, Uint32>> dbgBindings_CacheOffsets;
#endif
auto AddResource = [&](Uint32 ShaderInd,
ShaderResourceLayoutVk& ResLayout,
- const SPIRVShaderResources& Resources,
- const SPIRVShaderResourceAttribs& Attribs)
+ const SPIRVShaderResources& Resources,
+ const SPIRVShaderResourceAttribs& Attribs) //
{
- const auto ShaderType = Resources.GetShaderType();
- const SHADER_RESOURCE_VARIABLE_TYPE VarType = FindShaderVariableType(ShaderType, Attribs, ResourceLayoutDesc, Resources.GetCombinedSamplerSuffix());
+ const auto ShaderType = Resources.GetShaderType();
+ const SHADER_RESOURCE_VARIABLE_TYPE VarType = FindShaderVariableType(ShaderType, Attribs, ResourceLayoutDesc, Resources.GetCombinedSamplerSuffix());
if (!IsAllowedType(VarType, AllowedTypeBits))
return;
@@ -375,7 +375,7 @@ void ShaderResourceLayoutVk::Initialize(IRenderDevice*
Uint32 DescriptorSet = 0;
Uint32 CacheOffset = 0;
Uint32 SamplerInd = VkResource::InvalidSamplerInd;
-
+
if (Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage)
{
// Separate samplers are enumerated before separate images, so the sampler
@@ -384,7 +384,7 @@ void ShaderResourceLayoutVk::Initialize(IRenderDevice*
}
VkSampler vkImmutableSampler = VK_NULL_HANDLE;
- if (Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage ||
+ if (Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage ||
Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler)
{
// Only search for the immutable sampler for combined image samplers and separate samplers
@@ -398,18 +398,18 @@ void ShaderResourceLayoutVk::Initialize(IRenderDevice*
vkImmutableSampler = ImmutableSampler.RawPtr<SamplerVkImpl>()->GetVkSampler();
}
}
-
+
auto& ShaderSPIRV = SPIRVs[ShaderInd];
PipelineLayout.AllocateResourceSlot(Attribs, VarType, vkImmutableSampler, Resources.GetShaderType(), DescriptorSet, Binding, CacheOffset, ShaderSPIRV);
VERIFY(DescriptorSet <= std::numeric_limits<decltype(VkResource::DescriptorSet)>::max(), "Descriptor set (", DescriptorSet, ") excceeds maximum representable value");
- VERIFY(Binding <= std::numeric_limits<decltype(VkResource::Binding)> ::max(), "Binding (", Binding, ") excceeds maximum representable value");
+ VERIFY(Binding <= std::numeric_limits<decltype(VkResource::Binding)>::max(), "Binding (", Binding, ") excceeds maximum representable value");
#ifdef _DEBUG
// Verify that bindings and cache offsets monotonically increase in every descriptor set
auto Binding_OffsetIt = dbgBindings_CacheOffsets.find(DescriptorSet);
- if(Binding_OffsetIt != dbgBindings_CacheOffsets.end())
+ if (Binding_OffsetIt != dbgBindings_CacheOffsets.end())
{
- VERIFY(Binding > Binding_OffsetIt->second.first, "Binding for descriptor set ", DescriptorSet, " is not strictly monotonic");
+ VERIFY(Binding > Binding_OffsetIt->second.first, "Binding for descriptor set ", DescriptorSet, " is not strictly monotonic");
VERIFY(CacheOffset > Binding_OffsetIt->second.second, "Cache offset for descriptor set ", DescriptorSet, " is not strictly monotonic");
}
dbgBindings_CacheOffsets[DescriptorSet] = std::make_pair(Binding, CacheOffset);
@@ -422,12 +422,12 @@ void ShaderResourceLayoutVk::Initialize(IRenderDevice*
// First process uniform buffers for all shader stages to make sure all UBs go first in every descriptor set
for (Uint32 s = 0; s < NumShaders; ++s)
{
- auto& Layout = Layouts[s];
+ auto& Layout = Layouts[s];
const auto& Resources = *Layout.m_pResources;
for (Uint32 n = 0; n < Resources.GetNumUBs(); ++n)
{
- const auto& UB = Resources.GetUB(n);
- auto VarType = GetShaderVariableType(Resources.GetShaderType(), UB.Name, ResourceLayoutDesc);
+ const auto& UB = Resources.GetUB(n);
+ auto VarType = GetShaderVariableType(Resources.GetShaderType(), UB.Name, ResourceLayoutDesc);
if (IsAllowedType(VarType, AllowedTypeBits))
{
AddResource(s, Layout, Resources, UB);
@@ -438,12 +438,12 @@ void ShaderResourceLayoutVk::Initialize(IRenderDevice*
// Second, process all storage buffers
for (Uint32 s = 0; s < NumShaders; ++s)
{
- auto& Layout = Layouts[s];
+ auto& Layout = Layouts[s];
const auto& Resources = *Layout.m_pResources;
for (Uint32 n = 0; n < Resources.GetNumSBs(); ++n)
{
- const auto& SB = Resources.GetSB(n);
- auto VarType = GetShaderVariableType(Resources.GetShaderType(), SB.Name, ResourceLayoutDesc);
+ const auto& SB = Resources.GetSB(n);
+ auto VarType = GetShaderVariableType(Resources.GetShaderType(), SB.Name, ResourceLayoutDesc);
if (IsAllowedType(VarType, AllowedTypeBits))
{
AddResource(s, Layout, Resources, SB);
@@ -454,8 +454,9 @@ void ShaderResourceLayoutVk::Initialize(IRenderDevice*
// Finally, process all other resource types
for (Uint32 s = 0; s < NumShaders; ++s)
{
- auto& Layout = Layouts[s];
+ auto& Layout = Layouts[s];
const auto& Resources = *Layout.m_pResources;
+ // clang-format off
Resources.ProcessResources(
[&](const SPIRVShaderResourceAttribs& UB, Uint32)
{
@@ -493,6 +494,7 @@ void ShaderResourceLayoutVk::Initialize(IRenderDevice*
AddResource(s, Layout, Resources, SepImg);
}
);
+ // clang-format on
}
#ifdef _DEBUG
@@ -512,10 +514,10 @@ void ShaderResourceLayoutVk::Initialize(IRenderDevice*
Uint32 ShaderResourceLayoutVk::FindAssignedSampler(const SPIRVShaderResourceAttribs& SepImg,
Uint32 CurrResourceCount,
- SHADER_RESOURCE_VARIABLE_TYPE ImgVarType)const
+ SHADER_RESOURCE_VARIABLE_TYPE ImgVarType) const
{
VERIFY_EXPR(SepImg.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage);
-
+
Uint32 SamplerInd = VkResource::InvalidSamplerInd;
if (m_pResources->IsUsingCombinedSamplers() && SepImg.IsValidSepSamplerAssigned())
{
@@ -523,13 +525,14 @@ Uint32 ShaderResourceLayoutVk::FindAssignedSampler(const SPIRVShaderResourceAttr
for (SamplerInd = 0; SamplerInd < CurrResourceCount; ++SamplerInd)
{
const auto& Res = GetResource(ImgVarType, SamplerInd);
- if (Res.SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler &&
+ if (Res.SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler &&
strcmp(Res.SpirvAttribs.Name, SepSampler.Name) == 0)
{
VERIFY(ImgVarType == Res.GetVariableType(),
- "The type (", GetShaderVariableTypeLiteralName(ImgVarType),") of separate image variable '", SepImg.Name,
+ "The type (", GetShaderVariableTypeLiteralName(ImgVarType), ") of separate image variable '", SepImg.Name,
"' is not consistent with the type (", GetShaderVariableTypeLiteralName(Res.GetVariableType()),
- ") of the separate sampler '", SepSampler.Name, "' that is assigned to it. "
+ ") of the separate sampler '", SepSampler.Name,
+ "' that is assigned to it. "
"This should never happen as when HLSL-style combined texture samplers are used, the type of the sampler "
"is derived from the type of the corresponding separate image.");
break;
@@ -545,22 +548,22 @@ Uint32 ShaderResourceLayoutVk::FindAssignedSampler(const SPIRVShaderResourceAttr
}
-void ShaderResourceLayoutVk::VkResource::UpdateDescriptorHandle(VkDescriptorSet vkDescrSet,
- uint32_t ArrayElement,
- const VkDescriptorImageInfo* pImageInfo,
- const VkDescriptorBufferInfo* pBufferInfo,
- const VkBufferView* pTexelBufferView)const
+void ShaderResourceLayoutVk::VkResource::UpdateDescriptorHandle(VkDescriptorSet vkDescrSet,
+ uint32_t ArrayElement,
+ const VkDescriptorImageInfo* pImageInfo,
+ const VkDescriptorBufferInfo* pBufferInfo,
+ const VkBufferView* pTexelBufferView) const
{
VERIFY_EXPR(vkDescrSet != VK_NULL_HANDLE);
VkWriteDescriptorSet WriteDescrSet;
- WriteDescrSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
- WriteDescrSet.pNext = nullptr;
- WriteDescrSet.dstSet = vkDescrSet;
- WriteDescrSet.dstBinding = Binding;
- WriteDescrSet.dstArrayElement = ArrayElement;
- WriteDescrSet.descriptorCount = 1;
- // descriptorType must be the same type as that specified in VkDescriptorSetLayoutBinding for dstSet at dstBinding.
+ WriteDescrSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+ WriteDescrSet.pNext = nullptr;
+ WriteDescrSet.dstSet = vkDescrSet;
+ WriteDescrSet.dstBinding = Binding;
+ WriteDescrSet.dstArrayElement = ArrayElement;
+ WriteDescrSet.descriptorCount = 1;
+ // descriptorType must be the same type as that specified in VkDescriptorSetLayoutBinding for dstSet at dstBinding.
// The type of the descriptor also controls which array the descriptors are taken from. (13.2.4)
WriteDescrSet.descriptorType = PipelineLayout::GetVkDescriptorType(SpirvAttribs);
WriteDescrSet.pImageInfo = pImageInfo;
@@ -570,10 +573,10 @@ void ShaderResourceLayoutVk::VkResource::UpdateDescriptorHandle(VkDescriptorSet
ParentResLayout.m_LogicalDevice.UpdateDescriptorSets(1, &WriteDescrSet, 0, nullptr);
}
-template<typename ObjectType, typename TPreUpdateObject>
+template <typename ObjectType, typename TPreUpdateObject>
bool ShaderResourceLayoutVk::VkResource::UpdateCachedResource(ShaderResourceCacheVk::Resource& DstRes,
RefCntAutoPtr<ObjectType>&& pObject,
- TPreUpdateObject PreUpdateObject)const
+ TPreUpdateObject PreUpdateObject) const
{
// We cannot use ValidatedCast<> here as the resource retrieved from the
// resource mapping can be of wrong type
@@ -581,7 +584,7 @@ bool ShaderResourceLayoutVk::VkResource::UpdateCachedResource(ShaderResourceCach
{
if (GetVariableType() != SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC && DstRes.pObject != nullptr)
{
- // Do not update resource if one is already bound unless it is dynamic. This may be
+ // Do not update resource if one is already bound unless it is dynamic. This may be
// dangerous as writing descriptors while they are used by the GPU is an undefined behavior
return false;
}
@@ -596,11 +599,11 @@ bool ShaderResourceLayoutVk::VkResource::UpdateCachedResource(ShaderResourceCach
}
}
-void ShaderResourceLayoutVk::VkResource::CacheUniformBuffer(IDeviceObject* pBuffer,
- ShaderResourceCacheVk::Resource& DstRes,
- VkDescriptorSet vkDescrSet,
- Uint32 ArrayInd,
- Uint16& DynamicBuffersCounter)const
+void ShaderResourceLayoutVk::VkResource::CacheUniformBuffer(IDeviceObject* pBuffer,
+ ShaderResourceCacheVk::Resource& DstRes,
+ VkDescriptorSet vkDescrSet,
+ Uint32 ArrayInd,
+ Uint16& DynamicBuffersCounter) const
{
VERIFY(SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::UniformBuffer, "Uniform buffer resource is expected");
RefCntAutoPtr<BufferVkImpl> pBufferVk(pBuffer, IID_BufferVk);
@@ -608,8 +611,7 @@ void ShaderResourceLayoutVk::VkResource::CacheUniformBuffer(IDeviceObject*
VerifyConstantBufferBinding(SpirvAttribs, GetVariableType(), ArrayInd, pBuffer, pBufferVk.RawPtr(), DstRes.pObject.RawPtr(), ParentResLayout.GetShaderName());
#endif
- auto UpdateDynamicBuffersCounter = [&DynamicBuffersCounter](const BufferVkImpl* pOldBuffer, const BufferVkImpl* pNewBuffer)
- {
+ auto UpdateDynamicBuffersCounter = [&DynamicBuffersCounter](const BufferVkImpl* pOldBuffer, const BufferVkImpl* pNewBuffer) {
if (pOldBuffer != nullptr && pOldBuffer->GetDesc().Usage == USAGE_DYNAMIC)
{
VERIFY(DynamicBuffersCounter > 0, "Dynamic buffers counter must be greater than zero when there is at least one dynamic buffer bound in the resource cache");
@@ -623,7 +625,7 @@ void ShaderResourceLayoutVk::VkResource::CacheUniformBuffer(IDeviceObject*
// VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER or VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC descriptor type require
// buffer to be created with VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT
- // Do not update descriptor for a dynamic uniform buffer. All dynamic resource
+ // Do not update descriptor for a dynamic uniform buffer. All dynamic resource
// descriptors are updated at once by CommitDynamicResources() when SRB is committed.
if (vkDescrSet != VK_NULL_HANDLE && GetVariableType() != SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC)
{
@@ -633,15 +635,17 @@ void ShaderResourceLayoutVk::VkResource::CacheUniformBuffer(IDeviceObject*
}
}
-void ShaderResourceLayoutVk::VkResource::CacheStorageBuffer(IDeviceObject* pBufferView,
- ShaderResourceCacheVk::Resource& DstRes,
- VkDescriptorSet vkDescrSet,
- Uint32 ArrayInd,
- Uint16& DynamicBuffersCounter)const
+void ShaderResourceLayoutVk::VkResource::CacheStorageBuffer(IDeviceObject* pBufferView,
+ ShaderResourceCacheVk::Resource& DstRes,
+ VkDescriptorSet vkDescrSet,
+ Uint32 ArrayInd,
+ Uint16& DynamicBuffersCounter) const
{
+ // clang-format off
VERIFY(SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::ROStorageBuffer ||
SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::RWStorageBuffer,
"Storage buffer resource is expected");
+ // clang-format on
RefCntAutoPtr<BufferViewVkImpl> pBufferViewVk(pBufferView, IID_BufferViewVk);
#ifdef DEVELOPMENT
@@ -652,8 +656,7 @@ void ShaderResourceLayoutVk::VkResource::CacheStorageBuffer(IDeviceObject*
}
#endif
- auto UpdateDynamicBuffersCounter = [&DynamicBuffersCounter](const BufferViewVkImpl* pOldBufferView, const BufferViewVkImpl* pNewBufferView)
- {
+ auto UpdateDynamicBuffersCounter = [&DynamicBuffersCounter](const BufferViewVkImpl* pOldBufferView, const BufferViewVkImpl* pNewBufferView) {
if (pOldBufferView != nullptr && pOldBufferView->GetBuffer<const BufferVkImpl>()->GetDesc().Usage == USAGE_DYNAMIC)
{
VERIFY(DynamicBuffersCounter > 0, "Dynamic buffers counter must be greater than zero when there is at least one dynamic buffer bound in the resource cache");
@@ -665,10 +668,10 @@ void ShaderResourceLayoutVk::VkResource::CacheStorageBuffer(IDeviceObject*
if (UpdateCachedResource(DstRes, std::move(pBufferViewVk), UpdateDynamicBuffersCounter))
{
- // VK_DESCRIPTOR_TYPE_STORAGE_BUFFER or VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC descriptor type
+ // VK_DESCRIPTOR_TYPE_STORAGE_BUFFER or VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC descriptor type
// require buffer to be created with VK_BUFFER_USAGE_STORAGE_BUFFER_BIT (13.2.4)
- // Do not update descriptor for a dynamic storage buffer. All dynamic resource
+ // Do not update descriptor for a dynamic storage buffer. All dynamic resource
// descriptors are updated at once by CommitDynamicResources() when SRB is committed.
if (vkDescrSet != VK_NULL_HANDLE && GetVariableType() != SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC)
{
@@ -678,15 +681,17 @@ void ShaderResourceLayoutVk::VkResource::CacheStorageBuffer(IDeviceObject*
}
}
-void ShaderResourceLayoutVk::VkResource::CacheTexelBuffer(IDeviceObject* pBufferView,
- ShaderResourceCacheVk::Resource& DstRes,
- VkDescriptorSet vkDescrSet,
- Uint32 ArrayInd,
- Uint16& DynamicBuffersCounter)const
+void ShaderResourceLayoutVk::VkResource::CacheTexelBuffer(IDeviceObject* pBufferView,
+ ShaderResourceCacheVk::Resource& DstRes,
+ VkDescriptorSet vkDescrSet,
+ Uint32 ArrayInd,
+ Uint16& DynamicBuffersCounter) const
{
+ // clang-format off
VERIFY(SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::UniformTexelBuffer ||
SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::StorageTexelBuffer,
"Uniform or storage buffer resource is expected");
+ // clang-format on
RefCntAutoPtr<BufferViewVkImpl> pBufferViewVk(pBufferView, IID_BufferViewVk);
#ifdef DEVELOPMENT
@@ -697,8 +702,7 @@ void ShaderResourceLayoutVk::VkResource::CacheTexelBuffer(IDeviceObject*
}
#endif
- auto UpdateDynamicBuffersCounter = [&DynamicBuffersCounter](const BufferViewVkImpl* pOldBufferView, const BufferViewVkImpl* pNewBufferView)
- {
+ auto UpdateDynamicBuffersCounter = [&DynamicBuffersCounter](const BufferViewVkImpl* pOldBufferView, const BufferViewVkImpl* pNewBufferView) {
if (pOldBufferView != nullptr && pOldBufferView->GetBuffer<const BufferVkImpl>()->GetDesc().Usage == USAGE_DYNAMIC)
{
VERIFY(DynamicBuffersCounter > 0, "Dynamic buffers counter must be greater than zero when there is at least one dynamic buffer bound in the resource cache");
@@ -714,7 +718,7 @@ void ShaderResourceLayoutVk::VkResource::CacheTexelBuffer(IDeviceObject*
// * VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER -> VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT
// * VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER -> VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT
- // Do not update descriptor for a dynamic texel buffer. All dynamic resource descriptors
+ // Do not update descriptor for a dynamic texel buffer. All dynamic resource descriptors
// are updated at once by CommitDynamicResources() when SRB is committed.
if (vkDescrSet != VK_NULL_HANDLE && GetVariableType() != SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC)
{
@@ -724,17 +728,19 @@ void ShaderResourceLayoutVk::VkResource::CacheTexelBuffer(IDeviceObject*
}
}
-template<typename TCacheSampler>
+template <typename TCacheSampler>
void ShaderResourceLayoutVk::VkResource::CacheImage(IDeviceObject* pTexView,
ShaderResourceCacheVk::Resource& DstRes,
VkDescriptorSet vkDescrSet,
Uint32 ArrayInd,
- TCacheSampler CacheSampler)const
+ TCacheSampler CacheSampler) const
{
+ // clang-format off
VERIFY(SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::StorageImage ||
SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage ||
SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage,
"Storage image, separate image or sampled image resource is expected");
+ // clang-format on
RefCntAutoPtr<TextureViewVkImpl> pTexViewVk0(pTexView, IID_TextureViewVk);
#ifdef DEVELOPMENT
@@ -744,7 +750,7 @@ void ShaderResourceLayoutVk::VkResource::CacheImage(IDeviceObject*
VerifyResourceViewBinding(SpirvAttribs, GetVariableType(), ArrayInd, pTexView, pTexViewVk0.RawPtr(), {RequiredViewType}, DstRes.pObject.RawPtr(), ParentResLayout.GetShaderName());
}
#endif
- if (UpdateCachedResource(DstRes, std::move(pTexViewVk0), [](const TextureViewVkImpl*, const TextureViewVkImpl*){}))
+ if (UpdateCachedResource(DstRes, std::move(pTexViewVk0), [](const TextureViewVkImpl*, const TextureViewVkImpl*) {}))
{
// We can do RawPtr here safely since UpdateCachedResource() returned true
auto* pTexViewVk = DstRes.pObject.RawPtr<TextureViewVkImpl>();
@@ -759,7 +765,7 @@ void ShaderResourceLayoutVk::VkResource::CacheImage(IDeviceObject*
}
#endif
- // Do not update descriptor for a dynamic image. All dynamic resource descriptors
+ // Do not update descriptor for a dynamic image. All dynamic resource descriptors
// are updated at once by CommitDynamicResources() when SRB is committed.
if (vkDescrSet != VK_NULL_HANDLE && GetVariableType() != SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC)
{
@@ -783,19 +789,19 @@ void ShaderResourceLayoutVk::VkResource::CacheImage(IDeviceObject*
}
else
{
- LOG_ERROR_MESSAGE( "Failed to bind sampler to sampler variable '", SamplerAttribs.SpirvAttribs.Name,
- "' assigned to separate image '", SpirvAttribs.GetPrintName(ArrayInd), "' in shader '",
- ParentResLayout.GetShaderName(), "': no sampler is set in texture view '", pTexViewVk->GetDesc().Name, '\''); \
+ LOG_ERROR_MESSAGE("Failed to bind sampler to sampler variable '", SamplerAttribs.SpirvAttribs.Name,
+ "' assigned to separate image '", SpirvAttribs.GetPrintName(ArrayInd), "' in shader '",
+ ParentResLayout.GetShaderName(), "': no sampler is set in texture view '", pTexViewVk->GetDesc().Name, '\'');
}
}
}
}
}
-void ShaderResourceLayoutVk::VkResource::CacheSeparateSampler(IDeviceObject* pSampler,
- ShaderResourceCacheVk::Resource& DstRes,
- VkDescriptorSet vkDescrSet,
- Uint32 ArrayInd)const
+void ShaderResourceLayoutVk::VkResource::CacheSeparateSampler(IDeviceObject* pSampler,
+ ShaderResourceCacheVk::Resource& DstRes,
+ VkDescriptorSet vkDescrSet,
+ Uint32 ArrayInd) const
{
VERIFY(SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler, "Separate sampler resource is expected");
VERIFY(!IsImmutableSamplerAssigned(), "This separate sampler is assigned an immutable sampler");
@@ -811,13 +817,14 @@ void ShaderResourceLayoutVk::VkResource::CacheSeparateSampler(IDeviceObject*
{
auto VarTypeStr = GetShaderVariableTypeLiteralName(GetVariableType());
LOG_ERROR_MESSAGE("Non-null sampler is already bound to ", VarTypeStr, " shader variable '", SpirvAttribs.GetPrintName(ArrayInd),
- "' in shader '", ParentResLayout.GetShaderName(), "'. Attempting to bind another sampler or null is an error and may "
+ "' in shader '", ParentResLayout.GetShaderName(),
+ "'. Attempting to bind another sampler or null is an error and may "
"cause unpredicted behavior. Use another shader resource binding instance or label the variable as dynamic.");
}
#endif
- if (UpdateCachedResource(DstRes, std::move(pSamplerVk), [](const SamplerVkImpl*, const SamplerVkImpl*){}))
+ if (UpdateCachedResource(DstRes, std::move(pSamplerVk), [](const SamplerVkImpl*, const SamplerVkImpl*) {}))
{
- // Do not update descriptor for a dynamic sampler. All dynamic resource descriptors
+ // Do not update descriptor for a dynamic sampler. All dynamic resource descriptors
// are updated at once by CommitDynamicResources() when SRB is committed.
if (vkDescrSet != VK_NULL_HANDLE && GetVariableType() != SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC)
{
@@ -828,16 +835,16 @@ void ShaderResourceLayoutVk::VkResource::CacheSeparateSampler(IDeviceObject*
}
-void ShaderResourceLayoutVk::VkResource::BindResource(IDeviceObject* pObj, Uint32 ArrayIndex, ShaderResourceCacheVk& ResourceCache)const
+void ShaderResourceLayoutVk::VkResource::BindResource(IDeviceObject* pObj, Uint32 ArrayIndex, ShaderResourceCacheVk& ResourceCache) const
{
VERIFY_EXPR(ArrayIndex < SpirvAttribs.ArraySize);
auto& DstDescrSet = ResourceCache.GetDescriptorSet(DescriptorSet);
- auto vkDescrSet = DstDescrSet.GetVkDescriptorSet();
+ auto vkDescrSet = DstDescrSet.GetVkDescriptorSet();
#ifdef _DEBUG
if (ResourceCache.DbgGetContentType() == ShaderResourceCacheVk::DbgCacheContentType::SRBResources)
{
- if(VariableType == SHADER_RESOURCE_VARIABLE_TYPE_STATIC || VariableType == SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE)
+ if (VariableType == SHADER_RESOURCE_VARIABLE_TYPE_STATIC || VariableType == SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE)
{
VERIFY(vkDescrSet != VK_NULL_HANDLE, "Static and mutable variables must have valid vulkan descriptor set assigned");
// Dynamic variables do not have vulkan descriptor set only until they are assigned one the first time
@@ -855,18 +862,18 @@ void ShaderResourceLayoutVk::VkResource::BindResource(IDeviceObject* pObj, Uint3
auto& DstRes = DstDescrSet.GetResource(CacheOffset + ArrayIndex);
VERIFY(DstRes.Type == SpirvAttribs.Type, "Inconsistent types");
- if( pObj )
+ if (pObj)
{
switch (SpirvAttribs.Type)
{
case SPIRVShaderResourceAttribs::ResourceType::UniformBuffer:
CacheUniformBuffer(pObj, DstRes, vkDescrSet, ArrayIndex, ResourceCache.GetDynamicBuffersCounter());
- break;
+ break;
case SPIRVShaderResourceAttribs::ResourceType::ROStorageBuffer:
case SPIRVShaderResourceAttribs::ResourceType::RWStorageBuffer:
CacheStorageBuffer(pObj, DstRes, vkDescrSet, ArrayIndex, ResourceCache.GetDynamicBuffersCounter());
- break;
+ break;
case SPIRVShaderResourceAttribs::ResourceType::UniformTexelBuffer:
case SPIRVShaderResourceAttribs::ResourceType::StorageTexelBuffer:
@@ -876,20 +883,20 @@ void ShaderResourceLayoutVk::VkResource::BindResource(IDeviceObject* pObj, Uint3
case SPIRVShaderResourceAttribs::ResourceType::StorageImage:
case SPIRVShaderResourceAttribs::ResourceType::SeparateImage:
case SPIRVShaderResourceAttribs::ResourceType::SampledImage:
- CacheImage(pObj, DstRes, vkDescrSet, ArrayIndex,
- [&](const VkResource& SeparateSampler, ISampler* pSampler)
- {
- VERIFY(!SeparateSampler.IsImmutableSamplerAssigned(), "Separate sampler '", SeparateSampler.SpirvAttribs.Name, "' is assigned an immutable sampler");
- VERIFY_EXPR(SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage);
- DEV_CHECK_ERR(SeparateSampler.SpirvAttribs.ArraySize == 1 || SeparateSampler.SpirvAttribs.ArraySize == SpirvAttribs.ArraySize,
- "Array size (", SeparateSampler.SpirvAttribs.ArraySize,") of separate sampler variable '",
- SeparateSampler.SpirvAttribs.Name, "' must be one or the same as the array size (", SpirvAttribs.ArraySize,
- ") of separate image variable '", SpirvAttribs.Name, "' it is assigned to");
- Uint32 SamplerArrInd = SeparateSampler.SpirvAttribs.ArraySize == 1 ? 0 : ArrayIndex;
- SeparateSampler.BindResource(pSampler, SamplerArrInd, ResourceCache);
- }
- );
- break;
+ CacheImage(pObj, DstRes, vkDescrSet, ArrayIndex,
+ [&](const VkResource& SeparateSampler, ISampler* pSampler) {
+ VERIFY(!SeparateSampler.IsImmutableSamplerAssigned(), "Separate sampler '", SeparateSampler.SpirvAttribs.Name, "' is assigned an immutable sampler");
+ VERIFY_EXPR(SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage);
+ DEV_CHECK_ERR(SeparateSampler.SpirvAttribs.ArraySize == 1 || SeparateSampler.SpirvAttribs.ArraySize == SpirvAttribs.ArraySize,
+ "Array size (", SeparateSampler.SpirvAttribs.ArraySize,
+ ") of separate sampler variable '",
+ SeparateSampler.SpirvAttribs.Name,
+ "' must be one or the same as the array size (", SpirvAttribs.ArraySize,
+ ") of separate image variable '", SpirvAttribs.Name, "' it is assigned to");
+ Uint32 SamplerArrInd = SeparateSampler.SpirvAttribs.ArraySize == 1 ? 0 : ArrayIndex;
+ SeparateSampler.BindResource(pSampler, SamplerArrInd, ResourceCache);
+ });
+ break;
case SPIRVShaderResourceAttribs::ResourceType::SeparateSampler:
if (!IsImmutableSamplerAssigned())
@@ -898,11 +905,11 @@ void ShaderResourceLayoutVk::VkResource::BindResource(IDeviceObject* pObj, Uint3
}
else
{
- // Immutable samplers are permanently bound into the set layout; later binding a sampler
+ // Immutable samplers are permanently bound into the set layout; later binding a sampler
// into an immutable sampler slot in a descriptor set is not allowed (13.2.1)
LOG_ERROR_MESSAGE("Attempting to assign a sampler to an immutable sampler '", SpirvAttribs.Name, '\'');
}
- break;
+ break;
default: UNEXPECTED("Unknown resource type ", static_cast<Int32>(SpirvAttribs.Type));
}
@@ -911,14 +918,16 @@ void ShaderResourceLayoutVk::VkResource::BindResource(IDeviceObject* pObj, Uint3
{
if (DstRes.pObject && GetVariableType() != SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC)
{
- LOG_ERROR_MESSAGE( "Shader variable '", SpirvAttribs.Name, "' in shader '", ParentResLayout.GetShaderName(), "' is not dynamic but being unbound. This is an error and may cause unpredicted behavior. Use another shader resource binding instance or label shader variable as dynamic if you need to bind another resource." );
+ LOG_ERROR_MESSAGE("Shader variable '", SpirvAttribs.Name, "' in shader '", ParentResLayout.GetShaderName(),
+ "' is not dynamic but being unbound. This is an error and may cause unpredicted behavior. "
+ "Use another shader resource binding instance or label shader variable as dynamic if you need to bind another resource.");
}
DstRes.pObject.Release();
}
}
-bool ShaderResourceLayoutVk::VkResource::IsBound(Uint32 ArrayIndex, const ShaderResourceCacheVk& ResourceCache)const
+bool ShaderResourceLayoutVk::VkResource::IsBound(Uint32 ArrayIndex, const ShaderResourceCacheVk& ResourceCache) const
{
VERIFY_EXPR(ArrayIndex < SpirvAttribs.ArraySize);
@@ -938,14 +947,14 @@ bool ShaderResourceLayoutVk::VkResource::IsBound(Uint32 ArrayIndex, const Shader
void ShaderResourceLayoutVk::InitializeStaticResources(const ShaderResourceLayoutVk& SrcLayout,
const ShaderResourceCacheVk& SrcResourceCache,
- ShaderResourceCacheVk& DstResourceCache)const
+ ShaderResourceCacheVk& DstResourceCache) const
{
auto NumStaticResources = m_NumResources[SHADER_RESOURCE_VARIABLE_TYPE_STATIC];
VERIFY(NumStaticResources == SrcLayout.m_NumResources[SHADER_RESOURCE_VARIABLE_TYPE_STATIC], "Inconsistent number of static resources");
VERIFY(SrcLayout.m_pResources->GetShaderType() == m_pResources->GetShaderType(), "Incosistent shader types");
// Static shader resources are stored in one large continuous descriptor set
- for (Uint32 r=0; r < NumStaticResources; ++r)
+ for (Uint32 r = 0; r < NumStaticResources; ++r)
{
// Get resource attributes
const auto& DstRes = GetResource(SHADER_RESOURCE_VARIABLE_TYPE_STATIC, r);
@@ -953,20 +962,20 @@ void ShaderResourceLayoutVk::InitializeStaticResources(const ShaderResourceLayou
VERIFY(SrcRes.Binding == SrcRes.SpirvAttribs.Type, "Unexpected binding");
VERIFY(SrcRes.SpirvAttribs.ArraySize == DstRes.SpirvAttribs.ArraySize, "Inconsistent array size");
- if (DstRes.SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler &&
+ if (DstRes.SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler &&
DstRes.IsImmutableSamplerAssigned())
continue; // Skip immutable samplers
for (Uint32 ArrInd = 0; ArrInd < DstRes.SpirvAttribs.ArraySize; ++ArrInd)
{
- auto SrcOffset = SrcRes.CacheOffset + ArrInd;
- const auto& SrcCachedSet = SrcResourceCache.GetDescriptorSet(SrcRes.DescriptorSet);
- const auto& SrcCachedRes = SrcCachedSet.GetResource(SrcOffset);
- IDeviceObject* pObject = SrcCachedRes.pObject.RawPtr<IDeviceObject>();
+ auto SrcOffset = SrcRes.CacheOffset + ArrInd;
+ const auto& SrcCachedSet = SrcResourceCache.GetDescriptorSet(SrcRes.DescriptorSet);
+ const auto& SrcCachedRes = SrcCachedSet.GetResource(SrcOffset);
+ IDeviceObject* pObject = SrcCachedRes.pObject.RawPtr<IDeviceObject>();
if (!pObject)
LOG_ERROR_MESSAGE("No resource is assigned to static shader variable '", SrcRes.SpirvAttribs.GetPrintName(ArrInd), "' in shader '", GetShaderName(), "'.");
-
- auto DstOffset = DstRes.CacheOffset + ArrInd;
+
+ auto DstOffset = DstRes.CacheOffset + ArrInd;
IDeviceObject* pCachedResource = DstResourceCache.GetDescriptorSet(DstRes.DescriptorSet).GetResource(DstOffset).pObject;
if (pCachedResource != pObject)
{
@@ -979,28 +988,28 @@ void ShaderResourceLayoutVk::InitializeStaticResources(const ShaderResourceLayou
#ifdef DEVELOPMENT
-bool ShaderResourceLayoutVk::dvpVerifyBindings(const ShaderResourceCacheVk& ResourceCache)const
+bool ShaderResourceLayoutVk::dvpVerifyBindings(const ShaderResourceCacheVk& ResourceCache) const
{
bool BindingsOK = true;
- for(SHADER_RESOURCE_VARIABLE_TYPE VarType = SHADER_RESOURCE_VARIABLE_TYPE_STATIC; VarType < SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES; VarType = static_cast<SHADER_RESOURCE_VARIABLE_TYPE>(VarType+1))
+ for (SHADER_RESOURCE_VARIABLE_TYPE VarType = SHADER_RESOURCE_VARIABLE_TYPE_STATIC; VarType < SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES; VarType = static_cast<SHADER_RESOURCE_VARIABLE_TYPE>(VarType + 1))
{
- for(Uint32 r=0; r < m_NumResources[VarType]; ++r)
+ for (Uint32 r = 0; r < m_NumResources[VarType]; ++r)
{
const auto& Res = GetResource(VarType, r);
VERIFY(Res.GetVariableType() == VarType, "Unexpected variable type");
- for(Uint32 ArrInd = 0; ArrInd < Res.SpirvAttribs.ArraySize; ++ArrInd)
+ for (Uint32 ArrInd = 0; ArrInd < Res.SpirvAttribs.ArraySize; ++ArrInd)
{
const auto& CachedDescrSet = ResourceCache.GetDescriptorSet(Res.DescriptorSet);
- const auto& CachedRes = CachedDescrSet.GetResource(Res.CacheOffset + ArrInd);
+ const auto& CachedRes = CachedDescrSet.GetResource(Res.CacheOffset + ArrInd);
VERIFY(CachedRes.Type == Res.SpirvAttribs.Type, "Inconsistent types");
- if (CachedRes.pObject == nullptr &&
- !(Res.SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler && Res.IsImmutableSamplerAssigned()))
+ if (CachedRes.pObject == nullptr &&
+ !(Res.SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler && Res.IsImmutableSamplerAssigned()))
{
LOG_ERROR_MESSAGE("No resource is bound to ", GetShaderVariableTypeLiteralName(Res.GetVariableType()), " variable '", Res.SpirvAttribs.GetPrintName(ArrInd), "' in shader '", GetShaderName(), "'");
BindingsOK = false;
}
-#ifdef _DEBUG
- auto vkDescSet = CachedDescrSet.GetVkDescriptorSet();
+# ifdef _DEBUG
+ auto vkDescSet = CachedDescrSet.GetVkDescriptorSet();
auto dbgCacheContentType = ResourceCache.DbgGetContentType();
if (dbgCacheContentType == ShaderResourceCacheVk::DbgCacheContentType::StaticShaderResources)
VERIFY(vkDescSet == VK_NULL_HANDLE, "Static resource cache should never have vulkan descriptor set");
@@ -1017,7 +1026,7 @@ bool ShaderResourceLayoutVk::dvpVerifyBindings(const ShaderResourceCacheVk& Reso
}
else
UNEXPECTED("Unexpected cache content type");
-#endif
+# endif
}
}
}
@@ -1025,7 +1034,7 @@ bool ShaderResourceLayoutVk::dvpVerifyBindings(const ShaderResourceCacheVk& Reso
}
#endif
-void ShaderResourceLayoutVk::InitializeResourceMemoryInCache(ShaderResourceCacheVk& ResourceCache)const
+void ShaderResourceLayoutVk::InitializeResourceMemoryInCache(ShaderResourceCacheVk& ResourceCache) const
{
auto TotalResources = GetTotalResourceCount();
for (Uint32 r = 0; r < TotalResources; ++r)
@@ -1035,8 +1044,8 @@ void ShaderResourceLayoutVk::InitializeResourceMemoryInCache(ShaderResourceCache
}
}
-void ShaderResourceLayoutVk::CommitDynamicResources(const ShaderResourceCacheVk& ResourceCache,
- VkDescriptorSet vkDynamicDescriptorSet)const
+void ShaderResourceLayoutVk::CommitDynamicResources(const ShaderResourceCacheVk& ResourceCache,
+ VkDescriptorSet vkDynamicDescriptorSet) const
{
Uint32 NumDynamicResources = m_NumResources[SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC];
VERIFY(NumDynamicResources != 0, "This shader resource layout does not contain dynamic resources");
@@ -1055,43 +1064,43 @@ void ShaderResourceLayoutVk::CommitDynamicResources(const ShaderResourceCacheVk&
#endif
// Do not zero-initiaize arrays!
- std::array<VkDescriptorImageInfo, ImgUpdateBatchSize> DescrImgInfoArr;
- std::array<VkDescriptorBufferInfo, BuffUpdateBatchSize> DescrBuffInfoArr;
- std::array<VkBufferView, TexelBuffUpdateBatchSize> DescrBuffViewArr;
- std::array<VkWriteDescriptorSet, WriteDescriptorSetBatchSize> WriteDescrSetArr;
+ std::array<VkDescriptorImageInfo, ImgUpdateBatchSize> DescrImgInfoArr;
+ std::array<VkDescriptorBufferInfo, BuffUpdateBatchSize> DescrBuffInfoArr;
+ std::array<VkBufferView, TexelBuffUpdateBatchSize> DescrBuffViewArr;
+ std::array<VkWriteDescriptorSet, WriteDescriptorSetBatchSize> WriteDescrSetArr;
Uint32 ResNum = 0, ArrElem = 0;
- auto DescrImgIt = DescrImgInfoArr.begin();
- auto DescrBuffIt = DescrBuffInfoArr.begin();
- auto BuffViewIt = DescrBuffViewArr.begin();
- auto WriteDescrSetIt = WriteDescrSetArr.begin();
+ auto DescrImgIt = DescrImgInfoArr.begin();
+ auto DescrBuffIt = DescrBuffInfoArr.begin();
+ auto BuffViewIt = DescrBuffViewArr.begin();
+ auto WriteDescrSetIt = WriteDescrSetArr.begin();
#ifdef _DEBUG
Int32 DynamicDescrSetIndex = -1;
#endif
- while(ResNum < NumDynamicResources)
+ while (ResNum < NumDynamicResources)
{
const auto& Res = GetResource(SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC, ResNum);
VERIFY_EXPR(Res.GetVariableType() == SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC);
#ifdef _DEBUG
- if(DynamicDescrSetIndex < 0)
+ if (DynamicDescrSetIndex < 0)
DynamicDescrSetIndex = Res.DescriptorSet;
else
VERIFY(DynamicDescrSetIndex == Res.DescriptorSet, "Inconsistent dynamic resource desriptor set index");
#endif
const auto& SetResources = ResourceCache.GetDescriptorSet(Res.DescriptorSet);
- WriteDescrSetIt->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
- WriteDescrSetIt->pNext = nullptr;
+ WriteDescrSetIt->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+ WriteDescrSetIt->pNext = nullptr;
VERIFY(SetResources.GetVkDescriptorSet() == VK_NULL_HANDLE, "Dynamic descriptor set must not be assigned to the resource cache");
WriteDescrSetIt->dstSet = vkDynamicDescriptorSet;
VERIFY(WriteDescrSetIt->dstSet != VK_NULL_HANDLE, "Vulkan descriptor set must not be null");
- WriteDescrSetIt->dstBinding = Res.Binding;
+ WriteDescrSetIt->dstBinding = Res.Binding;
WriteDescrSetIt->dstArrayElement = ArrElem;
- // descriptorType must be the same type as that specified in VkDescriptorSetLayoutBinding for dstSet at dstBinding.
+ // descriptorType must be the same type as that specified in VkDescriptorSetLayoutBinding for dstSet at dstBinding.
// The type of the descriptor also controls which array the descriptors are taken from. (13.2.4)
WriteDescrSetIt->descriptorType = PipelineLayout::GetVkDescriptorType(Res.SpirvAttribs);
-
+
// For every resource type, try to batch as many descriptor updates as we can
switch (Res.SpirvAttribs.Type)
{
@@ -1100,23 +1109,23 @@ void ShaderResourceLayoutVk::CommitDynamicResources(const ShaderResourceCacheVk&
while (ArrElem < Res.SpirvAttribs.ArraySize && DescrBuffIt != DescrBuffInfoArr.end())
{
const auto& CachedRes = SetResources.GetResource(Res.CacheOffset + ArrElem);
- *DescrBuffIt = CachedRes.GetUniformBufferDescriptorWriteInfo();
+ *DescrBuffIt = CachedRes.GetUniformBufferDescriptorWriteInfo();
++DescrBuffIt;
++ArrElem;
}
- break;
-
+ break;
+
case SPIRVShaderResourceAttribs::ResourceType::ROStorageBuffer:
case SPIRVShaderResourceAttribs::ResourceType::RWStorageBuffer:
WriteDescrSetIt->pBufferInfo = &(*DescrBuffIt);
while (ArrElem < Res.SpirvAttribs.ArraySize && DescrBuffIt != DescrBuffInfoArr.end())
{
const auto& CachedRes = SetResources.GetResource(Res.CacheOffset + ArrElem);
- *DescrBuffIt = CachedRes.GetStorageBufferDescriptorWriteInfo();
+ *DescrBuffIt = CachedRes.GetStorageBufferDescriptorWriteInfo();
++DescrBuffIt;
++ArrElem;
}
- break;
+ break;
case SPIRVShaderResourceAttribs::ResourceType::UniformTexelBuffer:
case SPIRVShaderResourceAttribs::ResourceType::StorageTexelBuffer:
@@ -1124,11 +1133,11 @@ void ShaderResourceLayoutVk::CommitDynamicResources(const ShaderResourceCacheVk&
while (ArrElem < Res.SpirvAttribs.ArraySize && BuffViewIt != DescrBuffViewArr.end())
{
const auto& CachedRes = SetResources.GetResource(Res.CacheOffset + ArrElem);
- *BuffViewIt = CachedRes.GetBufferViewWriteInfo();
+ *BuffViewIt = CachedRes.GetBufferViewWriteInfo();
++BuffViewIt;
++ArrElem;
}
- break;
+ break;
case SPIRVShaderResourceAttribs::ResourceType::SeparateImage:
case SPIRVShaderResourceAttribs::ResourceType::StorageImage:
@@ -1137,19 +1146,19 @@ void ShaderResourceLayoutVk::CommitDynamicResources(const ShaderResourceCacheVk&
while (ArrElem < Res.SpirvAttribs.ArraySize && DescrImgIt != DescrImgInfoArr.end())
{
const auto& CachedRes = SetResources.GetResource(Res.CacheOffset + ArrElem);
- *DescrImgIt = CachedRes.GetImageDescriptorWriteInfo(Res.IsImmutableSamplerAssigned());
+ *DescrImgIt = CachedRes.GetImageDescriptorWriteInfo(Res.IsImmutableSamplerAssigned());
++DescrImgIt;
++ArrElem;
}
- break;
+ break;
case SPIRVShaderResourceAttribs::ResourceType::AtomicCounter:
// Do nothing
- break;
-
+ break;
+
case SPIRVShaderResourceAttribs::ResourceType::SeparateSampler:
- // Immutable samplers are permanently bound into the set layout; later binding a sampler
+ // Immutable samplers are permanently bound into the set layout; later binding a sampler
// into an immutable sampler slot in a descriptor set is not allowed (13.2.1)
if (!Res.IsImmutableSamplerAssigned())
{
@@ -1157,17 +1166,17 @@ void ShaderResourceLayoutVk::CommitDynamicResources(const ShaderResourceCacheVk&
while (ArrElem < Res.SpirvAttribs.ArraySize && DescrImgIt != DescrImgInfoArr.end())
{
const auto& CachedRes = SetResources.GetResource(Res.CacheOffset + ArrElem);
- *DescrImgIt = CachedRes.GetSamplerDescriptorWriteInfo();
+ *DescrImgIt = CachedRes.GetSamplerDescriptorWriteInfo();
++DescrImgIt;
++ArrElem;
}
}
else
{
- ArrElem = Res.SpirvAttribs.ArraySize;
+ ArrElem = Res.SpirvAttribs.ArraySize;
WriteDescrSetIt->dstArrayElement = Res.SpirvAttribs.ArraySize;
}
- break;
+ break;
default:
UNEXPECTED("Unexpected resource type");
@@ -1185,22 +1194,22 @@ void ShaderResourceLayoutVk::CommitDynamicResources(const ShaderResourceCacheVk&
// If we ran out of space in any of the arrays or if we processed all resources,
// flush pending updates and reset iterators
- if (ResNum == NumDynamicResources ||
- DescrImgIt == DescrImgInfoArr.end() ||
- DescrBuffIt == DescrBuffInfoArr.end() ||
- BuffViewIt == DescrBuffViewArr.end() ||
+ if (ResNum == NumDynamicResources ||
+ DescrImgIt == DescrImgInfoArr.end() ||
+ DescrBuffIt == DescrBuffInfoArr.end() ||
+ BuffViewIt == DescrBuffViewArr.end() ||
WriteDescrSetIt == WriteDescrSetArr.end())
{
auto DescrWriteCount = static_cast<Uint32>(std::distance(WriteDescrSetArr.begin(), WriteDescrSetIt));
if (DescrWriteCount > 0)
m_LogicalDevice.UpdateDescriptorSets(DescrWriteCount, WriteDescrSetArr.data(), 0, nullptr);
- DescrImgIt = DescrImgInfoArr.begin();
- DescrBuffIt = DescrBuffInfoArr.begin();
- BuffViewIt = DescrBuffViewArr.begin();
+ DescrImgIt = DescrImgInfoArr.begin();
+ DescrBuffIt = DescrBuffInfoArr.begin();
+ BuffViewIt = DescrBuffViewArr.begin();
WriteDescrSetIt = WriteDescrSetArr.begin();
}
}
}
-}
+} // namespace Diligent
diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderVariableVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderVariableVk.cpp
index 02bdfa93..ae7ee32e 100644
--- a/Graphics/GraphicsEngineVulkan/src/ShaderVariableVk.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/ShaderVariableVk.cpp
@@ -29,74 +29,76 @@
namespace Diligent
{
-size_t ShaderVariableManagerVk::GetRequiredMemorySize(const ShaderResourceLayoutVk& Layout,
- const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes,
- Uint32 NumAllowedTypes,
- Uint32& NumVariables)
+size_t ShaderVariableManagerVk::GetRequiredMemorySize(const ShaderResourceLayoutVk& Layout,
+ const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes,
+ Uint32 NumAllowedTypes,
+ Uint32& NumVariables)
{
- NumVariables = 0;
- const Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes);
- const bool UsingSeparateSamplers = Layout.IsUsingSeparateSamplers();
- for (SHADER_RESOURCE_VARIABLE_TYPE VarType = SHADER_RESOURCE_VARIABLE_TYPE_STATIC; VarType < SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES; VarType = static_cast<SHADER_RESOURCE_VARIABLE_TYPE>(VarType+1))
+ NumVariables = 0;
+ const Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes);
+ const bool UsingSeparateSamplers = Layout.IsUsingSeparateSamplers();
+ for (SHADER_RESOURCE_VARIABLE_TYPE VarType = SHADER_RESOURCE_VARIABLE_TYPE_STATIC; VarType < SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES; VarType = static_cast<SHADER_RESOURCE_VARIABLE_TYPE>(VarType + 1))
{
if (IsAllowedType(VarType, AllowedTypeBits))
{
auto NumResources = Layout.GetResourceCount(VarType);
- for (Uint32 r=0; r < NumResources; ++r)
+ for (Uint32 r = 0; r < NumResources; ++r)
{
const auto& SrcRes = Layout.GetResource(VarType, r);
// When using HLSL-style combined image samplers, we need to skip separate samplers.
// Also always skip immutable separate samplers.
- if (SrcRes.SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler &&
- (!UsingSeparateSamplers || SrcRes.IsImmutableSamplerAssigned()) )
+ if (SrcRes.SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler &&
+ (!UsingSeparateSamplers || SrcRes.IsImmutableSamplerAssigned()))
continue;
++NumVariables;
}
}
}
-
+
return NumVariables * sizeof(ShaderVariableVkImpl);
}
// Creates shader variable for every resource from SrcLayout whose type is one AllowedVarTypes
-ShaderVariableManagerVk::ShaderVariableManagerVk(IObject& Owner,
- const ShaderResourceLayoutVk& SrcLayout,
- IMemoryAllocator& Allocator,
- const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes,
- Uint32 NumAllowedTypes,
- ShaderResourceCacheVk& ResourceCache) :
+ShaderVariableManagerVk::ShaderVariableManagerVk(IObject& Owner,
+ const ShaderResourceLayoutVk& SrcLayout,
+ IMemoryAllocator& Allocator,
+ const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes,
+ Uint32 NumAllowedTypes,
+ ShaderResourceCacheVk& ResourceCache) :
+ // clang-format off
m_Owner {Owner },
m_ResourceCache{ResourceCache}
#ifdef _DEBUG
, m_DbgAllocator {Allocator}
#endif
+// clang-format on
{
const Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes);
VERIFY_EXPR(m_NumVariables == 0);
auto MemSize = GetRequiredMemorySize(SrcLayout, AllowedVarTypes, NumAllowedTypes, m_NumVariables);
-
- if(m_NumVariables == 0)
+
+ if (m_NumVariables == 0)
return;
-
+
auto* pRawMem = ALLOCATE_RAW(Allocator, "Raw memory buffer for shader variables", MemSize);
- m_pVariables = reinterpret_cast<ShaderVariableVkImpl*>(pRawMem);
+ m_pVariables = reinterpret_cast<ShaderVariableVkImpl*>(pRawMem);
- Uint32 VarInd = 0;
+ Uint32 VarInd = 0;
const bool UsingSeparateSamplers = SrcLayout.IsUsingSeparateSamplers();
- for (SHADER_RESOURCE_VARIABLE_TYPE VarType = SHADER_RESOURCE_VARIABLE_TYPE_STATIC; VarType < SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES; VarType = static_cast<SHADER_RESOURCE_VARIABLE_TYPE>(VarType+1))
+ for (SHADER_RESOURCE_VARIABLE_TYPE VarType = SHADER_RESOURCE_VARIABLE_TYPE_STATIC; VarType < SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES; VarType = static_cast<SHADER_RESOURCE_VARIABLE_TYPE>(VarType + 1))
{
if (!IsAllowedType(VarType, AllowedTypeBits))
continue;
Uint32 NumResources = SrcLayout.GetResourceCount(VarType);
- for (Uint32 r=0; r < NumResources; ++r)
+ for (Uint32 r = 0; r < NumResources; ++r)
{
const auto& SrcRes = SrcLayout.GetResource(VarType, r);
// Skip separate samplers when using combined HLSL-style image samplers. Also always skip immutable separate samplers.
- if (SrcRes.SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler &&
- (!UsingSeparateSamplers || SrcRes.IsImmutableSamplerAssigned()) )
+ if (SrcRes.SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler &&
+ (!UsingSeparateSamplers || SrcRes.IsImmutableSamplerAssigned()))
continue;
::new (m_pVariables + VarInd) ShaderVariableVkImpl(*this, SrcRes);
@@ -117,7 +119,7 @@ void ShaderVariableManagerVk::DestroyVariables(IMemoryAllocator& Allocator)
if (m_pVariables != nullptr)
{
- for (Uint32 v=0; v < m_NumVariables; ++v)
+ for (Uint32 v = 0; v < m_NumVariables; ++v)
m_pVariables[v].~ShaderVariableVkImpl();
Allocator.Free(m_pVariables);
m_pVariables = nullptr;
@@ -129,7 +131,7 @@ ShaderVariableVkImpl* ShaderVariableManagerVk::GetVariable(const Char* Name)
ShaderVariableVkImpl* pVar = nullptr;
for (Uint32 v = 0; v < m_NumVariables; ++v)
{
- auto& Var = m_pVariables[v];
+ auto& Var = m_pVariables[v];
const auto& Res = Var.m_Resource;
if (strcmp(Res.SpirvAttribs.Name, Name) == 0)
{
@@ -176,45 +178,48 @@ void ShaderVariableManagerVk::BindResources(IResourceMapping* pResourceMapping,
{
if (!pResourceMapping)
{
- LOG_ERROR_MESSAGE( "Failed to bind resources: resource mapping is null" );
+ LOG_ERROR_MESSAGE("Failed to bind resources: resource mapping is null");
return;
}
- if ( (Flags & BIND_SHADER_RESOURCES_UPDATE_ALL) == 0 )
+ if ((Flags & BIND_SHADER_RESOURCES_UPDATE_ALL) == 0)
Flags |= BIND_SHADER_RESOURCES_UPDATE_ALL;
- for (Uint32 v=0; v < m_NumVariables; ++v)
+ for (Uint32 v = 0; v < m_NumVariables; ++v)
{
- auto& Var = m_pVariables[v];
+ auto& Var = m_pVariables[v];
const auto& Res = Var.m_Resource;
-
+
// There should be no immutable separate samplers
VERIFY(Res.SpirvAttribs.Type != SPIRVShaderResourceAttribs::ResourceType::SeparateSampler || !Res.IsImmutableSamplerAssigned(),
"There must be no shader resource variables for immutable separate samplers");
- if ( (Flags & (1 << Res.GetVariableType())) == 0 )
+ if ((Flags & (1 << Res.GetVariableType())) == 0)
continue;
for (Uint32 ArrInd = 0; ArrInd < Res.SpirvAttribs.ArraySize; ++ArrInd)
{
- if ( (Flags & BIND_SHADER_RESOURCES_KEEP_EXISTING) && Res.IsBound(ArrInd, m_ResourceCache) )
+ if ((Flags & BIND_SHADER_RESOURCES_KEEP_EXISTING) && Res.IsBound(ArrInd, m_ResourceCache))
continue;
- const auto* VarName = Res.SpirvAttribs.Name;
+ const auto* VarName = Res.SpirvAttribs.Name;
RefCntAutoPtr<IDeviceObject> pObj;
- pResourceMapping->GetResource( VarName, &pObj, ArrInd );
+ pResourceMapping->GetResource(VarName, &pObj, ArrInd);
if (pObj)
{
Res.BindResource(pObj, ArrInd, m_ResourceCache);
}
else
{
- if ( (Flags & BIND_SHADER_RESOURCES_VERIFY_ALL_RESOLVED) && !Res.IsBound(ArrInd, m_ResourceCache) )
- LOG_ERROR_MESSAGE( "Unable to bind resource to shader variable '", Res.SpirvAttribs.GetPrintName(ArrInd), "': resource is not found in the resource mapping. "
- "Do not use BIND_SHADER_RESOURCES_VERIFY_ALL_RESOLVED flag to suppress the message if this is not an issue." );
+ if ((Flags & BIND_SHADER_RESOURCES_VERIFY_ALL_RESOLVED) && !Res.IsBound(ArrInd, m_ResourceCache))
+ {
+ LOG_ERROR_MESSAGE("Unable to bind resource to shader variable '", Res.SpirvAttribs.GetPrintName(ArrInd),
+ "': resource is not found in the resource mapping. "
+ "Do not use BIND_SHADER_RESOURCES_VERIFY_ALL_RESOLVED flag to suppress the message if this is not an issue.");
+ }
}
}
}
}
-}
+} // namespace Diligent
diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderVkImpl.cpp
index 75bd3001..8ad01c6b 100644
--- a/Graphics/GraphicsEngineVulkan/src/ShaderVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/ShaderVkImpl.cpp
@@ -31,7 +31,7 @@
#include "GLSLSourceBuilder.h"
#if !NO_GLSLANG
-#include "SPIRVUtils.h"
+# include "SPIRVUtils.h"
#endif
namespace Diligent
@@ -39,13 +39,15 @@ namespace Diligent
ShaderVkImpl::ShaderVkImpl(IReferenceCounters* pRefCounters,
RenderDeviceVkImpl* pRenderDeviceVk,
- const ShaderCreateInfo& CreationAttribs) :
+ const ShaderCreateInfo& CreationAttribs) :
+ // clang-format off
TShaderBase
{
pRefCounters,
pRenderDeviceVk,
CreationAttribs.Desc
}
+// clang-format on
{
if (CreationAttribs.Source != nullptr || CreationAttribs.FilePath != nullptr)
{
@@ -62,9 +64,9 @@ ShaderVkImpl::ShaderVkImpl(IReferenceCounters* pRefCounters,
else
{
auto GLSLSource = BuildGLSLSourceString(CreationAttribs, pRenderDeviceVk->GetDeviceCaps(), TargetGLSLCompiler::glslang, "#define TARGET_API_VULKAN 1\n");
- m_SPIRV = GLSLtoSPIRV(m_Desc.ShaderType, GLSLSource.c_str(), static_cast<int>(GLSLSource.length()), CreationAttribs.ppCompilerOutput);
+ m_SPIRV = GLSLtoSPIRV(m_Desc.ShaderType, GLSLSource.c_str(), static_cast<int>(GLSLSource.length()), CreationAttribs.ppCompilerOutput);
}
-
+
if (m_SPIRV.empty())
{
LOG_ERROR_AND_THROW("Failed to compile shader");
@@ -75,24 +77,24 @@ ShaderVkImpl::ShaderVkImpl(IReferenceCounters* pRefCounters,
{
DEV_CHECK_ERR(CreationAttribs.ByteCodeSize != 0, "ByteCodeSize must not be 0");
DEV_CHECK_ERR(CreationAttribs.ByteCodeSize % 4 == 0, "Byte code size (", CreationAttribs.ByteCodeSize, ") is not multiple of 4");
- m_SPIRV.resize(CreationAttribs.ByteCodeSize/4);
+ m_SPIRV.resize(CreationAttribs.ByteCodeSize / 4);
memcpy(m_SPIRV.data(), CreationAttribs.ByteCode, CreationAttribs.ByteCodeSize);
}
- else
+ else
{
LOG_ERROR_AND_THROW("Shader source must be provided through one of the 'Source', 'FilePath' or 'ByteCode' members");
}
// We cannot create shader module here because resource bindings are assigned when
// pipeline state is created
-
+
// Load shader resources
- auto& Allocator = GetRawAllocator();
- auto* pRawMem = ALLOCATE(Allocator, "Allocator for ShaderResources", SPIRVShaderResources, 1);
- bool IsHLSLVertexShader = CreationAttribs.SourceLanguage == SHADER_SOURCE_LANGUAGE_HLSL && m_Desc.ShaderType == SHADER_TYPE_VERTEX;
- auto* pResources = new (pRawMem) SPIRVShaderResources(Allocator, pRenderDeviceVk, m_SPIRV, m_Desc, CreationAttribs.UseCombinedTextureSamplers ? CreationAttribs.CombinedSamplerSuffix : nullptr, IsHLSLVertexShader, m_EntryPoint);
+ auto& Allocator = GetRawAllocator();
+ auto* pRawMem = ALLOCATE(Allocator, "Allocator for ShaderResources", SPIRVShaderResources, 1);
+ bool IsHLSLVertexShader = CreationAttribs.SourceLanguage == SHADER_SOURCE_LANGUAGE_HLSL && m_Desc.ShaderType == SHADER_TYPE_VERTEX;
+ auto* pResources = new (pRawMem) SPIRVShaderResources(Allocator, pRenderDeviceVk, m_SPIRV, m_Desc, CreationAttribs.UseCombinedTextureSamplers ? CreationAttribs.CombinedSamplerSuffix : nullptr, IsHLSLVertexShader, m_EntryPoint);
m_pShaderResources.reset(pResources, STDDeleterRawMem<SPIRVShaderResources>(Allocator));
-
+
if (IsHLSLVertexShader)
{
MapHLSLVertexShaderInputs();
@@ -103,11 +105,11 @@ void ShaderVkImpl::MapHLSLVertexShaderInputs()
{
for (Uint32 i = 0; i < m_pShaderResources->GetNumShaderStageInputs(); ++i)
{
- const auto& Input = m_pShaderResources->GetShaderStageInputAttribs(i);
- const char* s = Input.Semantic;
+ const auto& Input = m_pShaderResources->GetShaderStageInputAttribs(i);
+ const char* s = Input.Semantic;
static const char* Prefix = "attrib";
- const char* p = Prefix;
- while(*s != 0 && *p != 0 && *p == std::tolower(static_cast<unsigned char>(*s)) )
+ const char* p = Prefix;
+ while (*s != 0 && *p != 0 && *p == std::tolower(static_cast<unsigned char>(*s)))
{
++p;
++s;
@@ -119,8 +121,8 @@ void ShaderVkImpl::MapHLSLVertexShaderInputs()
continue;
}
- char* EndPtr = nullptr;
- auto Location = static_cast<uint32_t>(strtol(s, &EndPtr, 10));
+ char* EndPtr = nullptr;
+ auto Location = static_cast<uint32_t>(strtol(s, &EndPtr, 10));
if (*EndPtr != 0)
{
LOG_ERROR_MESSAGE("Unable to map semantic '", Input.Semantic, "' to input location: semantics must have 'ATTRIBx' format.");
@@ -134,7 +136,7 @@ ShaderVkImpl::~ShaderVkImpl()
{
}
-ShaderResourceDesc ShaderVkImpl::GetResource(Uint32 Index)const
+ShaderResourceDesc ShaderVkImpl::GetResource(Uint32 Index) const
{
auto ResCount = GetResourceCount();
DEV_CHECK_ERR(Index < ResCount, "Resource index (", Index, ") is out of range");
@@ -142,9 +144,9 @@ ShaderResourceDesc ShaderVkImpl::GetResource(Uint32 Index)const
if (Index < ResCount)
{
const auto& SPIRVResource = m_pShaderResources->GetResource(Index);
- ResourceDesc = SPIRVResource.GetResourceDesc();
+ ResourceDesc = SPIRVResource.GetResourceDesc();
}
return ResourceDesc;
}
-}
+} // namespace Diligent
diff --git a/Graphics/GraphicsEngineVulkan/src/SwapChainVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/SwapChainVkImpl.cpp
index e1d3a8cd..f63504ca 100644
--- a/Graphics/GraphicsEngineVulkan/src/SwapChainVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/SwapChainVkImpl.cpp
@@ -32,64 +32,78 @@
namespace Diligent
{
-SwapChainVkImpl::SwapChainVkImpl(IReferenceCounters* pRefCounters,
- const SwapChainDesc& SCDesc,
- RenderDeviceVkImpl* pRenderDeviceVk,
- DeviceContextVkImpl* pDeviceContextVk,
- void* pNativeWndHandle) :
+SwapChainVkImpl::SwapChainVkImpl(IReferenceCounters* pRefCounters,
+ const SwapChainDesc& SCDesc,
+ RenderDeviceVkImpl* pRenderDeviceVk,
+ DeviceContextVkImpl* pDeviceContextVk,
+ void* pNativeWndHandle) :
+ // clang-format off
TSwapChainBase {pRefCounters, pRenderDeviceVk, pDeviceContextVk, SCDesc},
m_VulkanInstance {pRenderDeviceVk->GetVulkanInstance()},
m_pBackBufferRTV {STD_ALLOCATOR_RAW_MEM(RefCntAutoPtr<ITextureView>, GetRawAllocator(), "Allocator for vector<RefCntAutoPtr<ITextureView>>")},
m_SwapChainImagesInitialized {STD_ALLOCATOR_RAW_MEM(bool, GetRawAllocator(), "Allocator for vector<bool>")},
m_ImageAcquiredFenceSubmitted{STD_ALLOCATOR_RAW_MEM(bool, GetRawAllocator(), "Allocator for vector<bool>")}
+// clang-format on
{
// Create OS-specific surface
#if defined(VK_USE_PLATFORM_WIN32_KHR)
VkWin32SurfaceCreateInfoKHR surfaceCreateInfo = {};
- surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
+
+ surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
surfaceCreateInfo.hinstance = GetModuleHandle(NULL);
- surfaceCreateInfo.hwnd = (HWND)pNativeWndHandle;
+ surfaceCreateInfo.hwnd = (HWND)pNativeWndHandle;
+
auto err = vkCreateWin32SurfaceKHR(m_VulkanInstance->GetVkInstance(), &surfaceCreateInfo, nullptr, &m_VkSurface);
#elif defined(VK_USE_PLATFORM_ANDROID_KHR)
VkAndroidSurfaceCreateInfoKHR surfaceCreateInfo = {};
- surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR;
- surfaceCreateInfo.window = (ANativeWindow*) pNativeWndHandle;
+
+ surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR;
+ surfaceCreateInfo.window = (ANativeWindow*)pNativeWndHandle;
+
auto err = vkCreateAndroidSurfaceKHR(m_VulkanInstance->GetVkInstance(), &surfaceCreateInfo, NULL, &m_VkSurface);
#elif defined(VK_USE_PLATFORM_IOS_MVK)
VkIOSSurfaceCreateInfoMVK surfaceCreateInfo = {};
+
surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_IOS_SURFACE_CREATE_INFO_MVK;
surfaceCreateInfo.pView = pNativeWndHandle;
+
auto err = vkCreateIOSSurfaceMVK(m_VulkanInstance->GetVkInstance(), &surfaceCreateInfo, nullptr, &m_VkSurface);
#elif defined(VK_USE_PLATFORM_MACOS_MVK)
VkMacOSSurfaceCreateInfoMVK surfaceCreateInfo = {};
+
surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK;
surfaceCreateInfo.pView = pNativeWndHandle;
+
auto err = vkCreateMacOSSurfaceMVK(m_VulkanInstance->GetVkInstance(), &surfaceCreateInfo, NULL, &m_VkSurface);
#elif defined(VK_USE_PLATFORM_WAYLAND_KHR)
VkWaylandSurfaceCreateInfoKHR surfaceCreateInfo = {};
- surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR;
+
+ surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR;
surfaceCreateInfo.display = display;
- surfaceCreatem_VkSurface = window;
+ surfaceCreatem_VkSurface = window;
+
err = vkCreateWaylandSurfaceKHR(m_VulkanInstance->GetVkInstance(), &surfaceCreateInfo, nullptr, &m_VkSurface);
#elif defined(VK_USE_PLATFORM_XCB_KHR)
VkXcbSurfaceCreateInfoKHR surfaceCreateInfo = {};
+
surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR;
struct XCBInfo
{
xcb_connection_t* connection = nullptr;
- uint32_t window = 0;
+ uint32_t window = 0;
};
- XCBInfo& info = *reinterpret_cast<XCBInfo*>(pNativeWndHandle);
+ XCBInfo& info = *reinterpret_cast<XCBInfo*>(pNativeWndHandle);
surfaceCreateInfo.connection = info.connection;
- surfaceCreateInfo.window = info.window;
+ surfaceCreateInfo.window = info.window;
+
auto err = vkCreateXcbSurfaceKHR(m_VulkanInstance->GetVkInstance(), &surfaceCreateInfo, nullptr, &m_VkSurface);
#endif
CHECK_VK_ERROR_AND_THROW(err, "Failed to create OS-specific surface");
- const auto& PhysicalDevice = pRenderDeviceVk->GetPhysicalDevice();
- auto& CmdQueueVK = pRenderDeviceVk->GetCommandQueue(0);
- auto QueueFamilyIndex = CmdQueueVK.GetQueueFamilyIndex();
- if( !PhysicalDevice.CheckPresentSupport(QueueFamilyIndex, m_VkSurface) )
+ const auto& PhysicalDevice = pRenderDeviceVk->GetPhysicalDevice();
+ auto& CmdQueueVK = pRenderDeviceVk->GetCommandQueue(0);
+ auto QueueFamilyIndex = CmdQueueVK.GetQueueFamilyIndex();
+ if (!PhysicalDevice.CheckPresentSupport(QueueFamilyIndex, m_VkSurface))
{
LOG_ERROR_AND_THROW("Selected physical device does not support present capability.\n"
"There could be few ways to mitigate this problem. One is to try to find another queue that supports present, but does not support graphics and compute capabilities."
@@ -99,16 +113,18 @@ SwapChainVkImpl::SwapChainVkImpl(IReferenceCounters* pRefCounters,
CreateVulkanSwapChain();
InitBuffersAndViews();
auto res = AcquireNextImage(pDeviceContextVk);
- DEV_CHECK_ERR(res == VK_SUCCESS, "Failed to acquire next image for the newly created swap chain"); (void)res;
+ DEV_CHECK_ERR(res == VK_SUCCESS, "Failed to acquire next image for the newly created swap chain");
+ (void)res;
}
void SwapChainVkImpl::CreateVulkanSwapChain()
{
- auto* pRenderDeviceVk = m_pRenderDevice.RawPtr<RenderDeviceVkImpl>();
- const auto& PhysicalDevice = pRenderDeviceVk->GetPhysicalDevice();
- auto vkDeviceHandle = PhysicalDevice.GetVkDeviceHandle();
+ auto* pRenderDeviceVk = m_pRenderDevice.RawPtr<RenderDeviceVkImpl>();
+ const auto& PhysicalDevice = pRenderDeviceVk->GetPhysicalDevice();
+ auto vkDeviceHandle = PhysicalDevice.GetVkDeviceHandle();
// Get the list of VkFormats that are supported:
uint32_t formatCount = 0;
+
auto err = vkGetPhysicalDeviceSurfaceFormatsKHR(vkDeviceHandle, m_VkSurface, &formatCount, NULL);
CHECK_VK_ERROR_AND_THROW(err, "Failed to query number of supported formats");
VERIFY_EXPR(formatCount > 0);
@@ -117,8 +133,9 @@ void SwapChainVkImpl::CreateVulkanSwapChain()
CHECK_VK_ERROR_AND_THROW(err, "Failed to query supported format properties");
VERIFY_EXPR(formatCount == SupportedFormats.size());
m_VkColorFormat = TexFormatToVkFormat(m_SwapChainDesc.ColorBufferFormat);
+
VkColorSpaceKHR ColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
- if (formatCount == 1 && SupportedFormats[0].format == VK_FORMAT_UNDEFINED)
+ if (formatCount == 1 && SupportedFormats[0].format == VK_FORMAT_UNDEFINED)
{
// If the format list includes just one entry of VK_FORMAT_UNDEFINED,
// the surface has no preferred format. Otherwise, at least one
@@ -126,28 +143,30 @@ void SwapChainVkImpl::CreateVulkanSwapChain()
// Do nothing
}
- else
+ else
{
bool FmtFound = false;
- for(const auto& SrfFmt : SupportedFormats)
+ for (const auto& SrfFmt : SupportedFormats)
{
- if(SrfFmt.format == m_VkColorFormat)
+ if (SrfFmt.format == m_VkColorFormat)
{
- FmtFound = true;
+ FmtFound = true;
ColorSpace = SrfFmt.colorSpace;
break;
}
}
- if(!FmtFound)
+ if (!FmtFound)
{
VkFormat VkReplacementColorFormat = VK_FORMAT_UNDEFINED;
- switch(m_VkColorFormat)
+ switch (m_VkColorFormat)
{
+ // clang-format off
case VK_FORMAT_R8G8B8A8_UNORM: VkReplacementColorFormat = VK_FORMAT_B8G8R8A8_UNORM; break;
case VK_FORMAT_B8G8R8A8_UNORM: VkReplacementColorFormat = VK_FORMAT_R8G8B8A8_UNORM; break;
case VK_FORMAT_B8G8R8A8_SRGB: VkReplacementColorFormat = VK_FORMAT_R8G8B8A8_SRGB; break;
case VK_FORMAT_R8G8B8A8_SRGB: VkReplacementColorFormat = VK_FORMAT_B8G8R8A8_SRGB; break;
default: VkReplacementColorFormat = VK_FORMAT_UNDEFINED;
+ // clang-format on
}
bool ReplacementFmtFound = false;
@@ -156,30 +175,32 @@ void SwapChainVkImpl::CreateVulkanSwapChain()
if (SrfFmt.format == VkReplacementColorFormat)
{
ReplacementFmtFound = true;
- ColorSpace = SrfFmt.colorSpace;
+ ColorSpace = SrfFmt.colorSpace;
break;
}
}
- if(ReplacementFmtFound)
+ if (ReplacementFmtFound)
{
- m_VkColorFormat = VkReplacementColorFormat;
+ m_VkColorFormat = VkReplacementColorFormat;
auto NewColorBufferFormat = VkFormatToTexFormat(VkReplacementColorFormat);
LOG_INFO_MESSAGE("Requested color buffer format ", GetTextureFormatAttribs(m_SwapChainDesc.ColorBufferFormat).Name, " is not supported by the surface and will be replaced with ", GetTextureFormatAttribs(NewColorBufferFormat).Name);
m_SwapChainDesc.ColorBufferFormat = NewColorBufferFormat;
}
else
{
- LOG_WARNING_MESSAGE("Requested color buffer format ", GetTextureFormatAttribs(m_SwapChainDesc.ColorBufferFormat).Name ,"is not supported by the surface");
+ LOG_WARNING_MESSAGE("Requested color buffer format ", GetTextureFormatAttribs(m_SwapChainDesc.ColorBufferFormat).Name, "is not supported by the surface");
}
}
}
-
+
VkSurfaceCapabilitiesKHR surfCapabilities = {};
+
err = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(vkDeviceHandle, m_VkSurface, &surfCapabilities);
CHECK_VK_ERROR_AND_THROW(err, "Failed to query physical device surface capabilities");
uint32_t presentModeCount = 0;
+
err = vkGetPhysicalDeviceSurfacePresentModesKHR(vkDeviceHandle, m_VkSurface, &presentModeCount, NULL);
CHECK_VK_ERROR_AND_THROW(err, "Failed to query surface present mode count");
VERIFY_EXPR(presentModeCount > 0);
@@ -194,27 +215,28 @@ void SwapChainVkImpl::CreateVulkanSwapChain()
{
// If the surface size is undefined, the size is set to
// the size of the images requested.
- swapchainExtent.width = std::min(std::max(m_SwapChainDesc.Width, surfCapabilities.minImageExtent.width), surfCapabilities.maxImageExtent.width);
+ swapchainExtent.width = std::min(std::max(m_SwapChainDesc.Width, surfCapabilities.minImageExtent.width), surfCapabilities.maxImageExtent.width);
swapchainExtent.height = std::min(std::max(m_SwapChainDesc.Height, surfCapabilities.minImageExtent.height), surfCapabilities.maxImageExtent.height);
}
- else
+ else
{
// If the surface size is defined, the swap chain size must match
swapchainExtent = surfCapabilities.currentExtent;
}
- swapchainExtent.width = std::max(swapchainExtent.width, 1u);
+ swapchainExtent.width = std::max(swapchainExtent.width, 1u);
swapchainExtent.height = std::max(swapchainExtent.height, 1u);
m_SwapChainDesc.Width = swapchainExtent.width;
m_SwapChainDesc.Height = swapchainExtent.height;
// Mailbox is the lowest latency non-tearing presentation mode
VkPresentModeKHR swapchainPresentMode = VK_PRESENT_MODE_MAILBOX_KHR;
+
bool PresentModeSupported = std::find(presentModes.begin(), presentModes.end(), swapchainPresentMode) != presentModes.end();
- if(!PresentModeSupported)
+ if (!PresentModeSupported)
{
swapchainPresentMode = VK_PRESENT_MODE_FIFO_KHR;
// The FIFO present mode is guaranteed by the spec to be supported
- VERIFY(std::find(presentModes.begin(), presentModes.end(), swapchainPresentMode) != presentModes.end(), "FIFO present mode must be supported" );
+ VERIFY(std::find(presentModes.begin(), presentModes.end(), swapchainPresentMode) != presentModes.end(), "FIFO present mode must be supported");
}
// Determine the number of VkImage's to use in the swap chain.
@@ -222,7 +244,7 @@ void SwapChainVkImpl::CreateVulkanSwapChain()
// Asking for minImageCount images ensures that we can acquire
// 1 presentable image as long as we present it before attempting
// to acquire another.
- if(m_SwapChainDesc.BufferCount < surfCapabilities.minImageCount)
+ if (m_SwapChainDesc.BufferCount < surfCapabilities.minImageCount)
{
LOG_INFO_MESSAGE("Requested back buffer count (", m_SwapChainDesc.BufferCount, ") is smaller than the minimal image count supported for this surface (", surfCapabilities.minImageCount, "). Resetting to ", surfCapabilities.minImageCount);
m_SwapChainDesc.BufferCount = surfCapabilities.minImageCount;
@@ -234,29 +256,34 @@ void SwapChainVkImpl::CreateVulkanSwapChain()
}
uint32_t desiredNumberOfSwapChainImages = m_SwapChainDesc.BufferCount;
- VkSurfaceTransformFlagBitsKHR preTransform =
- (surfCapabilities.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) ?
- VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR :
- surfCapabilities.currentTransform;
+ VkSurfaceTransformFlagBitsKHR preTransform =
+ (surfCapabilities.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) ?
+ VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR :
+ surfCapabilities.currentTransform;
// Find a supported composite alpha mode - one of these is guaranteed to be set
- VkCompositeAlphaFlagBitsKHR compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
- VkCompositeAlphaFlagBitsKHR compositeAlphaFlags[4] = {
- VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
- VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR,
- VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR,
- VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR,
- };
- for (uint32_t i = 0; i < _countof(compositeAlphaFlags); i++) {
- if (surfCapabilities.supportedCompositeAlpha & compositeAlphaFlags[i]) {
+ VkCompositeAlphaFlagBitsKHR compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
+ VkCompositeAlphaFlagBitsKHR compositeAlphaFlags[4] = //
+ {
+ VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
+ VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR,
+ VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR,
+ VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR,
+ };
+ for (uint32_t i = 0; i < _countof(compositeAlphaFlags); i++)
+ {
+ if (surfCapabilities.supportedCompositeAlpha & compositeAlphaFlags[i])
+ {
compositeAlpha = compositeAlphaFlags[i];
break;
}
}
auto oldSwapchain = m_VkSwapChain;
- m_VkSwapChain = VK_NULL_HANDLE;
+ m_VkSwapChain = VK_NULL_HANDLE;
+
VkSwapchainCreateInfoKHR swapchain_ci = {};
+
swapchain_ci.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
swapchain_ci.pNext = NULL;
swapchain_ci.surface = m_VkSurface;
@@ -271,7 +298,7 @@ void SwapChainVkImpl::CreateVulkanSwapChain()
swapchain_ci.oldSwapchain = oldSwapchain;
swapchain_ci.clipped = VK_TRUE;
swapchain_ci.imageColorSpace = ColorSpace;
-
+
DEV_CHECK_ERR(m_SwapChainDesc.Usage != 0, "No swap chain usage flags defined");
if (m_SwapChainDesc.Usage & SWAP_CHAIN_USAGE_RENDER_TARGET)
swapchain_ci.imageUsage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
@@ -282,9 +309,9 @@ void SwapChainVkImpl::CreateVulkanSwapChain()
// vkCmdClearColorImage() command requires the image to use VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL layout
// that requires VK_IMAGE_USAGE_TRANSFER_DST_BIT to be set
- swapchain_ci.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
+ swapchain_ci.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
swapchain_ci.queueFamilyIndexCount = 0;
- swapchain_ci.pQueueFamilyIndices = NULL;
+ swapchain_ci.pQueueFamilyIndices = NULL;
//uint32_t queueFamilyIndices[] = { (uint32_t)info.graphics_queue_family_index, (uint32_t)info.present_queue_family_index };
//if (info.graphics_queue_family_index != info.present_queue_family_index) {
// // If the graphics and present queues are from different queue families,
@@ -297,16 +324,18 @@ void SwapChainVkImpl::CreateVulkanSwapChain()
//}
const auto& LogicalDevice = pRenderDeviceVk->GetLogicalDevice();
- auto vkDevice = pRenderDeviceVk->GetVkDevice();
+ auto vkDevice = pRenderDeviceVk->GetVkDevice();
+
err = vkCreateSwapchainKHR(vkDevice, &swapchain_ci, NULL, &m_VkSwapChain);
CHECK_VK_ERROR_AND_THROW(err, "Failed to create Vulkan swapchain");
- if(oldSwapchain != VK_NULL_HANDLE)
+ if (oldSwapchain != VK_NULL_HANDLE)
{
vkDestroySwapchainKHR(vkDevice, oldSwapchain, NULL);
}
uint32_t swapchainImageCount = 0;
+
err = vkGetSwapchainImagesKHR(vkDevice, m_VkSwapChain, &swapchainImageCount, NULL);
CHECK_VK_ERROR_AND_THROW(err, "Failed to request swap chain image count");
VERIFY_EXPR(swapchainImageCount > 0);
@@ -319,19 +348,23 @@ void SwapChainVkImpl::CreateVulkanSwapChain()
m_ImageAcquiredSemaphores.resize(swapchainImageCount);
m_DrawCompleteSemaphores.resize(swapchainImageCount);
m_ImageAcquiredFences.resize(swapchainImageCount);
- for(uint32_t i = 0; i < swapchainImageCount; ++i)
+ for (uint32_t i = 0; i < swapchainImageCount; ++i)
{
VkSemaphoreCreateInfo SemaphoreCI = {};
+
SemaphoreCI.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
SemaphoreCI.pNext = nullptr;
SemaphoreCI.flags = 0; // reserved for future use
+
m_ImageAcquiredSemaphores[i] = LogicalDevice.CreateSemaphore(SemaphoreCI);
m_DrawCompleteSemaphores[i] = LogicalDevice.CreateSemaphore(SemaphoreCI);
+
VkFenceCreateInfo FenceCI = {};
- FenceCI.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
- FenceCI.pNext = nullptr;
- FenceCI.flags = 0;
+
+ FenceCI.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
+ FenceCI.pNext = nullptr;
+ FenceCI.flags = 0;
m_ImageAcquiredFences[i] = LogicalDevice.CreateFence(FenceCI);
}
}
@@ -340,7 +373,7 @@ SwapChainVkImpl::~SwapChainVkImpl()
{
if (m_VkSwapChain != VK_NULL_HANDLE)
{
- auto *pDeviceVkImpl = m_pRenderDevice.RawPtr<RenderDeviceVkImpl>();
+ auto* pDeviceVkImpl = m_pRenderDevice.RawPtr<RenderDeviceVkImpl>();
pDeviceVkImpl->IdleGPU();
// We need to explicitly wait for all submitted Image Acquired Fences to signal.
@@ -358,13 +391,13 @@ SwapChainVkImpl::~SwapChainVkImpl()
void SwapChainVkImpl::InitBuffersAndViews()
{
- auto* pDeviceVkImpl = m_pRenderDevice.RawPtr<RenderDeviceVkImpl>();
- auto LogicalVkDevice = pDeviceVkImpl->GetVkDevice();
+ auto* pDeviceVkImpl = m_pRenderDevice.RawPtr<RenderDeviceVkImpl>();
+ auto LogicalVkDevice = pDeviceVkImpl->GetVkDevice();
#ifdef _DEBUG
{
uint32_t swapchainImageCount = 0;
- auto err = vkGetSwapchainImagesKHR(LogicalVkDevice, m_VkSwapChain, &swapchainImageCount, NULL);
+ auto err = vkGetSwapchainImagesKHR(LogicalVkDevice, m_VkSwapChain, &swapchainImageCount, NULL);
VERIFY_EXPR(err == VK_SUCCESS);
VERIFY(swapchainImageCount == m_SwapChainDesc.BufferCount, "Unexpected swap chain buffer count");
}
@@ -374,30 +407,30 @@ void SwapChainVkImpl::InitBuffersAndViews()
m_SwapChainImagesInitialized.resize(m_pBackBufferRTV.size(), false);
m_ImageAcquiredFenceSubmitted.resize(m_pBackBufferRTV.size(), false);
- uint32_t swapchainImageCount = m_SwapChainDesc.BufferCount;
+ uint32_t swapchainImageCount = m_SwapChainDesc.BufferCount;
std::vector<VkImage> swapchainImages(swapchainImageCount);
- auto err = vkGetSwapchainImagesKHR(LogicalVkDevice, m_VkSwapChain, &swapchainImageCount, swapchainImages.data());
+ auto err = vkGetSwapchainImagesKHR(LogicalVkDevice, m_VkSwapChain, &swapchainImageCount, swapchainImages.data());
CHECK_VK_ERROR_AND_THROW(err, "Failed to get swap chain images");
VERIFY_EXPR(swapchainImageCount == swapchainImages.size());
- for (uint32_t i = 0; i < swapchainImageCount; i++)
+ for (uint32_t i = 0; i < swapchainImageCount; i++)
{
TextureDesc BackBufferDesc;
BackBufferDesc.Format = m_SwapChainDesc.ColorBufferFormat;
std::stringstream name_ss;
name_ss << "Main back buffer " << i;
- auto name = name_ss.str();
- BackBufferDesc.Name = name.c_str();
- BackBufferDesc.Type = RESOURCE_DIM_TEX_2D;
- BackBufferDesc.Width = m_SwapChainDesc.Width;
- BackBufferDesc.Height = m_SwapChainDesc.Height;
- BackBufferDesc.Format = m_SwapChainDesc.ColorBufferFormat;
+ auto name = name_ss.str();
+ BackBufferDesc.Name = name.c_str();
+ BackBufferDesc.Type = RESOURCE_DIM_TEX_2D;
+ BackBufferDesc.Width = m_SwapChainDesc.Width;
+ BackBufferDesc.Height = m_SwapChainDesc.Height;
+ BackBufferDesc.Format = m_SwapChainDesc.ColorBufferFormat;
BackBufferDesc.BindFlags = BIND_RENDER_TARGET;
BackBufferDesc.MipLevels = 1;
RefCntAutoPtr<TextureVkImpl> pBackBufferTex;
m_pRenderDevice.RawPtr<RenderDeviceVkImpl>()->CreateTexture(BackBufferDesc, swapchainImages[i], RESOURCE_STATE_UNDEFINED, &pBackBufferTex);
-
+
TextureViewDesc RTVDesc;
RTVDesc.ViewType = TEXTURE_VIEW_RENDER_TARGET;
RefCntAutoPtr<ITextureView> pRTV;
@@ -419,17 +452,17 @@ void SwapChainVkImpl::InitBuffersAndViews()
DepthBufferDesc.ClearValue.Format = DepthBufferDesc.Format;
DepthBufferDesc.ClearValue.DepthStencil.Depth = m_SwapChainDesc.DefaultDepthValue;
DepthBufferDesc.ClearValue.DepthStencil.Stencil = m_SwapChainDesc.DefaultStencilValue;
- DepthBufferDesc.Name = "Main depth buffer";
+ DepthBufferDesc.Name = "Main depth buffer";
RefCntAutoPtr<ITexture> pDepthBufferTex;
- m_pRenderDevice->CreateTexture(DepthBufferDesc, nullptr, static_cast<ITexture**>(&pDepthBufferTex) );
- auto pDSV = pDepthBufferTex->GetDefaultView(TEXTURE_VIEW_DEPTH_STENCIL);
+ m_pRenderDevice->CreateTexture(DepthBufferDesc, nullptr, static_cast<ITexture**>(&pDepthBufferTex));
+ auto pDSV = pDepthBufferTex->GetDefaultView(TEXTURE_VIEW_DEPTH_STENCIL);
m_pDepthBufferDSV = RefCntAutoPtr<ITextureViewVk>(pDSV, IID_TextureViewVk);
}
}
VkResult SwapChainVkImpl::AcquireNextImage(DeviceContextVkImpl* pDeviceCtxVk)
{
- auto* pDeviceVk = m_pRenderDevice.RawPtr<RenderDeviceVkImpl>();
+ auto* pDeviceVk = m_pRenderDevice.RawPtr<RenderDeviceVkImpl>();
const auto& LogicalDevice = pDeviceVk->GetLogicalDevice();
// Applications should not rely on vkAcquireNextImageKHR blocking in order to
@@ -459,15 +492,18 @@ VkResult SwapChainVkImpl::AcquireNextImage(DeviceContextVkImpl* pDeviceCtxVk)
if (LogicalDevice.GetFenceStatus(OldestSubmittedFence) == VK_NOT_READY)
{
auto res = LogicalDevice.WaitForFences(1, &OldestSubmittedFence, VK_TRUE, UINT64_MAX);
- VERIFY_EXPR(res == VK_SUCCESS); (void)res;
+ VERIFY_EXPR(res == VK_SUCCESS);
+ (void)res;
}
LogicalDevice.ResetFence(OldestSubmittedFence);
m_ImageAcquiredFenceSubmitted[OldestSubmittedImageFenceInd] = false;
}
- VkFence ImageAcquiredFence = m_ImageAcquiredFences [m_SemaphoreIndex];
+ VkFence ImageAcquiredFence = m_ImageAcquiredFences[m_SemaphoreIndex];
VkSemaphore ImageAcquiredSemaphore = m_ImageAcquiredSemaphores[m_SemaphoreIndex];
+
auto res = vkAcquireNextImageKHR(LogicalDevice.GetVkDevice(), m_VkSwapChain, UINT64_MAX, ImageAcquiredSemaphore, ImageAcquiredFence, &m_BackBufferIndex);
+
m_ImageAcquiredFenceSubmitted[m_SemaphoreIndex] = (res == VK_SUCCESS);
if (res == VK_SUCCESS)
{
@@ -486,20 +522,20 @@ VkResult SwapChainVkImpl::AcquireNextImage(DeviceContextVkImpl* pDeviceCtxVk)
return res;
}
-IMPLEMENT_QUERY_INTERFACE( SwapChainVkImpl, IID_SwapChainVk, TSwapChainBase )
+IMPLEMENT_QUERY_INTERFACE(SwapChainVkImpl, IID_SwapChainVk, TSwapChainBase)
void SwapChainVkImpl::Present(Uint32 SyncInterval)
{
auto pDeviceContext = m_wpDeviceContext.Lock();
- if( !pDeviceContext )
+ if (!pDeviceContext)
{
- LOG_ERROR_MESSAGE( "Immediate context has been released" );
+ LOG_ERROR_MESSAGE("Immediate context has been released");
return;
}
auto* pImmediateCtxVk = pDeviceContext.RawPtr<DeviceContextVkImpl>();
- auto* pDeviceVk = m_pRenderDevice.RawPtr<RenderDeviceVkImpl>();
+ auto* pDeviceVk = m_pRenderDevice.RawPtr<RenderDeviceVkImpl>();
if (!m_IsMinimized)
{
@@ -517,28 +553,30 @@ void SwapChainVkImpl::Present(Uint32 SyncInterval)
if (!m_IsMinimized)
{
VkPresentInfoKHR PresentInfo = {};
- PresentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
- PresentInfo.pNext = nullptr;
+
+ PresentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
+ PresentInfo.pNext = nullptr;
PresentInfo.waitSemaphoreCount = 1;
// Unlike fences or events, the act of waiting for a semaphore also unsignals that semaphore (6.4.2)
- VkSemaphore WaitSemaphore[] = { m_DrawCompleteSemaphores[m_SemaphoreIndex] };
+ VkSemaphore WaitSemaphore[] = {m_DrawCompleteSemaphores[m_SemaphoreIndex]};
PresentInfo.pWaitSemaphores = WaitSemaphore;
- PresentInfo.swapchainCount = 1;
- PresentInfo.pSwapchains = &m_VkSwapChain;
- PresentInfo.pImageIndices = &m_BackBufferIndex;
- VkResult Result = VK_SUCCESS;
- PresentInfo.pResults = &Result;
- pDeviceVk->LockCmdQueueAndRun(0,
- [&PresentInfo](ICommandQueueVk* pCmdQueueVk)
+ PresentInfo.swapchainCount = 1;
+ PresentInfo.pSwapchains = &m_VkSwapChain;
+ PresentInfo.pImageIndices = &m_BackBufferIndex;
+ VkResult Result = VK_SUCCESS;
+ PresentInfo.pResults = &Result;
+ pDeviceVk->LockCmdQueueAndRun(
+ 0,
+ [&PresentInfo](ICommandQueueVk* pCmdQueueVk) //
{
pCmdQueueVk->Present(PresentInfo);
- }
+ } //
);
if (Result == VK_SUBOPTIMAL_KHR || Result == VK_ERROR_OUT_OF_DATE_KHR)
{
RecreateVulkanSwapchain(pImmediateCtxVk);
- m_SemaphoreIndex = m_SwapChainDesc.BufferCount-1; // To start with 0 index when acquire next image
+ m_SemaphoreIndex = m_SwapChainDesc.BufferCount - 1; // To start with 0 index when acquire next image
}
else
{
@@ -562,7 +600,8 @@ void SwapChainVkImpl::Present(Uint32 SyncInterval)
if (res == VK_SUBOPTIMAL_KHR || res == VK_ERROR_OUT_OF_DATE_KHR)
{
RecreateVulkanSwapchain(pImmediateCtxVk);
- m_SemaphoreIndex = m_SwapChainDesc.BufferCount-1; // To start with 0 index when acquire next image
+ m_SemaphoreIndex = m_SwapChainDesc.BufferCount - 1; // To start with 0 index when acquire next image
+
res = AcquireNextImage(pImmediateCtxVk);
}
DEV_CHECK_ERR(res == VK_SUCCESS, "Failed to acquire next swap chain image");
@@ -579,7 +618,7 @@ void SwapChainVkImpl::Present(Uint32 SyncInterval)
void SwapChainVkImpl::WaitForImageAcquiredFences()
{
const auto& LogicalDevice = m_pRenderDevice.RawPtr<RenderDeviceVkImpl>()->GetLogicalDevice();
- for (size_t i=0; i < m_ImageAcquiredFences.size(); ++i)
+ for (size_t i = 0; i < m_ImageAcquiredFences.size(); ++i)
{
if (m_ImageAcquiredFenceSubmitted[i])
{
@@ -593,12 +632,12 @@ void SwapChainVkImpl::WaitForImageAcquiredFences()
void SwapChainVkImpl::RecreateVulkanSwapchain(DeviceContextVkImpl* pImmediateCtxVk)
{
std::vector<ITextureView*> pBackBufferRTVs(m_pBackBufferRTV.size());
- for(size_t i=0; i < m_pBackBufferRTV.size(); ++i)
+ for (size_t i = 0; i < m_pBackBufferRTV.size(); ++i)
pBackBufferRTVs[i] = m_pBackBufferRTV[i];
UnbindRenderTargets(pImmediateCtxVk, pBackBufferRTVs.data(), static_cast<Uint32>(m_pBackBufferRTV.size()), m_pDepthBufferDSV);
RenderDeviceVkImpl* pDeviceVk = m_pRenderDevice.RawPtr<RenderDeviceVkImpl>();
-
+
// This will release references to Vk swap chain buffers hold by
// m_pBackBufferRTV[].
pDeviceVk->IdleGPU();
@@ -625,36 +664,37 @@ void SwapChainVkImpl::RecreateVulkanSwapchain(DeviceContextVkImpl* pImmediateCtx
InitBuffersAndViews();
}
-void SwapChainVkImpl::Resize( Uint32 NewWidth, Uint32 NewHeight )
+void SwapChainVkImpl::Resize(Uint32 NewWidth, Uint32 NewHeight)
{
- if( TSwapChainBase::Resize(NewWidth, NewHeight) )
+ if (TSwapChainBase::Resize(NewWidth, NewHeight))
{
auto pDeviceContext = m_wpDeviceContext.Lock();
- VERIFY( pDeviceContext, "Immediate context has been released" );
- if( pDeviceContext )
+ VERIFY(pDeviceContext, "Immediate context has been released");
+ if (pDeviceContext)
{
pDeviceContext->Flush();
try
{
- auto* pImmediateCtxVk = pDeviceContext.RawPtr<DeviceContextVkImpl>();
+ auto* pImmediateCtxVk = pDeviceContext.RawPtr<DeviceContextVkImpl>();
// RecreateVulkanSwapchain() unbinds default FB
bool bIsDefaultFBBound = pImmediateCtxVk->IsDefaultFBBound();
RecreateVulkanSwapchain(pImmediateCtxVk);
auto res = AcquireNextImage(pImmediateCtxVk);
- DEV_CHECK_ERR(res == VK_SUCCESS, "Failed to acquire next image for the just resized swap chain"); (void)res;
+ DEV_CHECK_ERR(res == VK_SUCCESS, "Failed to acquire next image for the just resized swap chain");
+ (void)res;
if (m_SwapChainDesc.IsPrimary && bIsDefaultFBBound)
{
// Set default render target and viewport
- pDeviceContext->SetRenderTargets( 0, nullptr, nullptr, RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
- pDeviceContext->SetViewports( 1, nullptr, 0, 0 );
+ pDeviceContext->SetRenderTargets(0, nullptr, nullptr, RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
+ pDeviceContext->SetViewports(1, nullptr, 0, 0);
}
}
- catch( const std::runtime_error & )
+ catch (const std::runtime_error&)
{
- LOG_ERROR( "Failed to resize the swap chain" );
+ LOG_ERROR("Failed to resize the swap chain");
}
}
}
@@ -663,7 +703,7 @@ void SwapChainVkImpl::Resize( Uint32 NewWidth, Uint32 NewHeight )
}
-void SwapChainVkImpl::SetFullscreenMode(const DisplayModeAttribs &DisplayMode)
+void SwapChainVkImpl::SetFullscreenMode(const DisplayModeAttribs& DisplayMode)
{
}
@@ -671,4 +711,4 @@ void SwapChainVkImpl::SetWindowedMode()
{
}
-}
+} // namespace Diligent
diff --git a/Graphics/GraphicsEngineVulkan/src/TextureViewVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/TextureViewVkImpl.cpp
index 701c01c9..a3c46174 100644
--- a/Graphics/GraphicsEngineVulkan/src/TextureViewVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/TextureViewVkImpl.cpp
@@ -29,12 +29,13 @@
namespace Diligent
{
-TextureViewVkImpl::TextureViewVkImpl( IReferenceCounters* pRefCounters,
- RenderDeviceVkImpl* pDevice,
- const TextureViewDesc& ViewDesc,
- ITexture* pTexture,
- VulkanUtilities::ImageViewWrapper&& ImgView,
- bool bIsDefaultView) :
+TextureViewVkImpl::TextureViewVkImpl(IReferenceCounters* pRefCounters,
+ RenderDeviceVkImpl* pDevice,
+ const TextureViewDesc& ViewDesc,
+ ITexture* pTexture,
+ VulkanUtilities::ImageViewWrapper&& ImgView,
+ bool bIsDefaultView) :
+ // clang-format off
TTextureViewBase
{
pRefCounters,
@@ -44,6 +45,7 @@ TextureViewVkImpl::TextureViewVkImpl( IReferenceCounters* pRefCo
bIsDefaultView
},
m_ImageView{std::move(ImgView)}
+// clang-format on
{
}
@@ -51,7 +53,7 @@ TextureViewVkImpl::~TextureViewVkImpl()
{
if (m_MipLevelViews != nullptr)
{
- for (Uint32 MipView=0; MipView < m_Desc.NumMipLevels * 2; ++MipView)
+ for (Uint32 MipView = 0; MipView < m_Desc.NumMipLevels * 2; ++MipView)
{
m_MipLevelViews[MipView].~MipLevelViewAutoPtrType();
}
@@ -59,11 +61,11 @@ TextureViewVkImpl::~TextureViewVkImpl()
GetRawAllocator().Free(m_MipLevelViews);
}
- if(m_Desc.ViewType == TEXTURE_VIEW_DEPTH_STENCIL || m_Desc.ViewType == TEXTURE_VIEW_RENDER_TARGET)
+ if (m_Desc.ViewType == TEXTURE_VIEW_DEPTH_STENCIL || m_Desc.ViewType == TEXTURE_VIEW_RENDER_TARGET)
m_pDevice->GetFramebufferCache().OnDestroyImageView(m_ImageView);
m_pDevice->SafeReleaseDeviceObject(std::move(m_ImageView), m_pTexture->GetDesc().CommandQueueMask);
}
-IMPLEMENT_QUERY_INTERFACE( TextureViewVkImpl, IID_TextureViewVk, TTextureViewBase )
+IMPLEMENT_QUERY_INTERFACE(TextureViewVkImpl, IID_TextureViewVk, TTextureViewBase)
-}
+} // namespace Diligent
diff --git a/Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp
index 12deef67..13c090e0 100644
--- a/Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp
@@ -35,11 +35,12 @@
namespace Diligent
{
-TextureVkImpl :: TextureVkImpl(IReferenceCounters* pRefCounters,
- FixedBlockMemoryAllocator& TexViewObjAllocator,
- RenderDeviceVkImpl* pRenderDeviceVk,
- const TextureDesc& TexDesc,
- const TextureData* pInitData /*= nullptr*/) :
+TextureVkImpl ::TextureVkImpl(IReferenceCounters* pRefCounters,
+ FixedBlockMemoryAllocator& TexViewObjAllocator,
+ RenderDeviceVkImpl* pRenderDeviceVk,
+ const TextureDesc& TexDesc,
+ const TextureData* pInitData /*= nullptr*/) :
+ // clang-format off
TTextureBase
{
pRefCounters,
@@ -47,23 +48,25 @@ TextureVkImpl :: TextureVkImpl(IReferenceCounters* pRefCounters,
pRenderDeviceVk,
TexDesc
}
+// clang-format on
{
if (m_Desc.Usage == USAGE_STATIC && (pInitData == nullptr || pInitData->pSubResources == nullptr))
LOG_ERROR_AND_THROW("Static textures must be initialized with data at creation time: pInitData can't be null");
- const auto& FmtAttribs = GetTextureFormatAttribs(m_Desc.Format);
+ const auto& FmtAttribs = GetTextureFormatAttribs(m_Desc.Format);
const auto& LogicalDevice = pRenderDeviceVk->GetLogicalDevice();
if (m_Desc.Usage == USAGE_STATIC || m_Desc.Usage == USAGE_DEFAULT || m_Desc.Usage == USAGE_DYNAMIC)
{
VkImageCreateInfo ImageCI = {};
+
ImageCI.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
ImageCI.pNext = nullptr;
ImageCI.flags = 0;
- if(m_Desc.Type == RESOURCE_DIM_TEX_CUBE || m_Desc.Type == RESOURCE_DIM_TEX_CUBE_ARRAY)
+ if (m_Desc.Type == RESOURCE_DIM_TEX_CUBE || m_Desc.Type == RESOURCE_DIM_TEX_CUBE_ARRAY)
ImageCI.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
- if(FmtAttribs.IsTypeless)
- ImageCI.flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT; // Specifies that the image can be used to create a
+ if (FmtAttribs.IsTypeless)
+ ImageCI.flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT; // Specifies that the image can be used to create a
// VkImageView with a different format from the image.
if (m_Desc.Type == RESOURCE_DIM_TEX_1D || m_Desc.Type == RESOURCE_DIM_TEX_1D_ARRAY)
@@ -94,24 +97,24 @@ TextureVkImpl :: TextureVkImpl(IReferenceCounters* pRefCounters,
PrimaryViewType = TEXTURE_VIEW_SHADER_RESOURCE;
InternalTexFmt = GetDefaultTextureViewFormat(m_Desc, PrimaryViewType);
}
-
+
ImageCI.format = TexFormatToVkFormat(InternalTexFmt);
ImageCI.extent.width = m_Desc.Width;
ImageCI.extent.height = (m_Desc.Type == RESOURCE_DIM_TEX_1D || m_Desc.Type == RESOURCE_DIM_TEX_1D_ARRAY) ? 1 : m_Desc.Height;
ImageCI.extent.depth = (m_Desc.Type == RESOURCE_DIM_TEX_3D) ? m_Desc.Depth : 1;
-
+
ImageCI.mipLevels = m_Desc.MipLevels;
- if (m_Desc.Type == RESOURCE_DIM_TEX_1D_ARRAY ||
- m_Desc.Type == RESOURCE_DIM_TEX_2D_ARRAY ||
- m_Desc.Type == RESOURCE_DIM_TEX_CUBE ||
+ if (m_Desc.Type == RESOURCE_DIM_TEX_1D_ARRAY ||
+ m_Desc.Type == RESOURCE_DIM_TEX_2D_ARRAY ||
+ m_Desc.Type == RESOURCE_DIM_TEX_CUBE ||
m_Desc.Type == RESOURCE_DIM_TEX_CUBE_ARRAY)
ImageCI.arrayLayers = m_Desc.ArraySize;
else
ImageCI.arrayLayers = 1;
ImageCI.samples = static_cast<VkSampleCountFlagBits>(m_Desc.SampleCount);
- ImageCI.tiling = VK_IMAGE_TILING_OPTIMAL;
+ ImageCI.tiling = VK_IMAGE_TILING_OPTIMAL;
ImageCI.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
if (m_Desc.BindFlags & BIND_RENDER_TARGET)
@@ -140,28 +143,30 @@ TextureVkImpl :: TextureVkImpl(IReferenceCounters* pRefCounters,
ImageCI.usage |= VK_IMAGE_USAGE_STORAGE_BIT;
m_bCSBasedMipGenerationSupported = true;
}
- else
+ else
{
const auto& PhysicalDevice = pRenderDeviceVk->GetPhysicalDevice();
- auto FmtProperties = PhysicalDevice.GetPhysicalDeviceFormatProperties(ImageCI.format); (void)FmtProperties;
+ auto FmtProperties = PhysicalDevice.GetPhysicalDeviceFormatProperties(ImageCI.format);
+ (void)FmtProperties;
DEV_CHECK_ERR((FmtProperties.optimalTilingFeatures & (VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT)) == (VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT),
- "Texture format ", GetTextureFormatAttribs(InternalTexFmt).Name, " does not support blitting. "
- "Automatic mipmap generation can't be done neither by CS nor by blitting.");
+ "Texture format ", GetTextureFormatAttribs(InternalTexFmt).Name,
+ " does not support blitting. Automatic mipmap generation can't be done neither by CS nor by blitting.");
DEV_CHECK_ERR((FmtProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT) != 0,
- "Texture format ", GetTextureFormatAttribs(InternalTexFmt).Name, " does not support linear filtering. "
- "Automatic mipmap generation can't be done neither by CS nor by blitting.");
+ "Texture format ", GetTextureFormatAttribs(InternalTexFmt).Name,
+ " does not support linear filtering. Automatic mipmap generation can't be "
+ "done neither by CS nor by blitting.");
}
}
- ImageCI.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
+ ImageCI.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
ImageCI.queueFamilyIndexCount = 0;
- ImageCI.pQueueFamilyIndices = nullptr;
+ ImageCI.pQueueFamilyIndices = nullptr;
// initialLayout must be either VK_IMAGE_LAYOUT_UNDEFINED or VK_IMAGE_LAYOUT_PREINITIALIZED (11.4)
- // If it is VK_IMAGE_LAYOUT_PREINITIALIZED, then the image data can be preinitialized by the host
- // while using this layout, and the transition away from this layout will preserve that data.
- // If it is VK_IMAGE_LAYOUT_UNDEFINED, then the contents of the data are considered to be undefined,
+ // If it is VK_IMAGE_LAYOUT_PREINITIALIZED, then the image data can be preinitialized by the host
+ // while using this layout, and the transition away from this layout will preserve that data.
+ // If it is VK_IMAGE_LAYOUT_UNDEFINED, then the contents of the data are considered to be undefined,
// and the transition away from this layout is not guaranteed to preserve that data.
ImageCI.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
@@ -170,27 +175,27 @@ TextureVkImpl :: TextureVkImpl(IReferenceCounters* pRefCounters,
m_VulkanImage = LogicalDevice.CreateImage(ImageCI, m_Desc.Name);
VkMemoryRequirements MemReqs = LogicalDevice.GetImageMemoryRequirements(m_VulkanImage);
-
+
VkMemoryPropertyFlags ImageMemoryFlags = 0;
if (m_Desc.Usage == USAGE_STAGING)
ImageMemoryFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
else
ImageMemoryFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
- VERIFY( IsPowerOfTwo(MemReqs.alignment), "Alignment is not power of 2!");
+ VERIFY(IsPowerOfTwo(MemReqs.alignment), "Alignment is not power of 2!");
m_MemoryAllocation = pRenderDeviceVk->AllocateMemory(MemReqs, ImageMemoryFlags);
auto AlignedOffset = Align(m_MemoryAllocation.UnalignedOffset, MemReqs.alignment);
VERIFY_EXPR(m_MemoryAllocation.Size >= MemReqs.size + (AlignedOffset - m_MemoryAllocation.UnalignedOffset));
auto Memory = m_MemoryAllocation.Page->GetVkMemory();
- auto err = LogicalDevice.BindImageMemory(m_VulkanImage, Memory, AlignedOffset);
+ auto err = LogicalDevice.BindImageMemory(m_VulkanImage, Memory, AlignedOffset);
CHECK_VK_ERROR_AND_THROW(err, "Failed to bind image memory");
-
+
// Vulkan validation layers do not like uninitialized memory, so if no initial data
// is provided, we will clear the memory
VulkanUtilities::CommandPoolWrapper CmdPool;
- VkCommandBuffer vkCmdBuff;
+ VkCommandBuffer vkCmdBuff;
pRenderDeviceVk->AllocateTransientCmdPool(CmdPool, vkCmdBuff, "Transient command pool to copy staging data to a device buffer");
VkImageAspectFlags aspectMask = 0;
@@ -198,7 +203,7 @@ TextureVkImpl :: TextureVkImpl(IReferenceCounters* pRefCounters,
aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
else if (FmtAttribs.ComponentType == COMPONENT_TYPE_DEPTH_STENCIL)
{
- if(bInitializeTexture)
+ if (bInitializeTexture)
{
UNSUPPORTED("Initializing depth-stencil texture is not currently supported");
// Only single aspect bit must be specified when copying texture data
@@ -210,40 +215,41 @@ TextureVkImpl :: TextureVkImpl(IReferenceCounters* pRefCounters,
// For either clear or copy command, dst layout must be VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
VkImageSubresourceRange SubresRange;
- SubresRange.aspectMask = aspectMask;
- SubresRange.baseArrayLayer = 0;
- SubresRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
- SubresRange.baseMipLevel = 0;
- SubresRange.levelCount = VK_REMAINING_MIP_LEVELS;
+ SubresRange.aspectMask = aspectMask;
+ SubresRange.baseArrayLayer = 0;
+ SubresRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
+ SubresRange.baseMipLevel = 0;
+ SubresRange.levelCount = VK_REMAINING_MIP_LEVELS;
auto EnabledGraphicsShaderStages = LogicalDevice.GetEnabledGraphicsShaderStages();
VulkanUtilities::VulkanCommandBuffer::TransitionImageLayout(vkCmdBuff, m_VulkanImage, ImageCI.initialLayout, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, SubresRange, EnabledGraphicsShaderStages);
SetState(RESOURCE_STATE_COPY_DEST);
const auto CurrentLayout = GetLayout();
VERIFY_EXPR(CurrentLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
- if(bInitializeTexture)
+ if (bInitializeTexture)
{
Uint32 ExpectedNumSubresources = ImageCI.mipLevels * ImageCI.arrayLayers;
- if (pInitData->NumSubresources != ExpectedNumSubresources )
+ if (pInitData->NumSubresources != ExpectedNumSubresources)
LOG_ERROR_AND_THROW("Incorrect number of subresources in init data. ", ExpectedNumSubresources, " expected, while ", pInitData->NumSubresources, " provided");
std::vector<VkBufferImageCopy> Regions(pInitData->NumSubresources);
Uint64 uploadBufferSize = 0;
- Uint32 subres = 0;
- for(Uint32 layer = 0; layer < ImageCI.arrayLayers; ++layer)
+ Uint32 subres = 0;
+ for (Uint32 layer = 0; layer < ImageCI.arrayLayers; ++layer)
{
- for(Uint32 mip = 0; mip < ImageCI.mipLevels; ++mip)
+ for (Uint32 mip = 0; mip < ImageCI.mipLevels; ++mip)
{
- const auto& SubResData = pInitData->pSubResources[subres]; (void)SubResData;
+ const auto& SubResData = pInitData->pSubResources[subres];
+ (void)SubResData;
auto& CopyRegion = Regions[subres];
auto MipInfo = GetMipLevelProperties(m_Desc, mip);
CopyRegion.bufferOffset = uploadBufferSize; // offset in bytes from the start of the buffer object
- // bufferRowLength and bufferImageHeight specify the data in buffer memory as a subregion
- // of a larger two- or three-dimensional image, and control the addressing calculations of
- // data in buffer memory. If either of these values is zero, that aspect of the buffer memory
+ // bufferRowLength and bufferImageHeight specify the data in buffer memory as a subregion
+ // of a larger two- or three-dimensional image, and control the addressing calculations of
+ // data in buffer memory. If either of these values is zero, that aspect of the buffer memory
// is considered to be tightly packed according to the imageExtent. (18.4)
CopyRegion.bufferRowLength = 0;
CopyRegion.bufferImageHeight = 0;
@@ -261,7 +267,7 @@ TextureVkImpl :: TextureVkImpl(IReferenceCounters* pRefCounters,
VERIFY(SubResData.DepthStride == 0 || SubResData.DepthStride >= (MipInfo.StorageHeight / FmtAttribs.BlockHeight) * MipInfo.RowSize, "Depth stride is too small");
// bufferOffset must be a multiple of 4 (18.4)
- // If the calling command's VkImage parameter is a compressed image, bufferOffset
+ // If the calling command's VkImage parameter is a compressed image, bufferOffset
// must be a multiple of the compressed texel block size in bytes (18.4). This
// is automatically guaranteed as MipWidth and MipHeight are rounded to block size
uploadBufferSize += (MipInfo.MipSize + 3) & (~3);
@@ -270,15 +276,15 @@ TextureVkImpl :: TextureVkImpl(IReferenceCounters* pRefCounters,
}
VERIFY_EXPR(subres == pInitData->NumSubresources);
- VkBufferCreateInfo VkStaginBuffCI = {};
- VkStaginBuffCI.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
- VkStaginBuffCI.pNext = nullptr;
- VkStaginBuffCI.flags = 0;
- VkStaginBuffCI.size = uploadBufferSize;
- VkStaginBuffCI.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
- VkStaginBuffCI.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
+ VkBufferCreateInfo VkStaginBuffCI = {};
+ VkStaginBuffCI.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
+ VkStaginBuffCI.pNext = nullptr;
+ VkStaginBuffCI.flags = 0;
+ VkStaginBuffCI.size = uploadBufferSize;
+ VkStaginBuffCI.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
+ VkStaginBuffCI.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
VkStaginBuffCI.queueFamilyIndexCount = 0;
- VkStaginBuffCI.pQueueFamilyIndices = nullptr;
+ VkStaginBuffCI.pQueueFamilyIndices = nullptr;
std::string StagingBufferName = "Upload buffer for '";
StagingBufferName += m_Desc.Name;
@@ -286,48 +292,48 @@ TextureVkImpl :: TextureVkImpl(IReferenceCounters* pRefCounters,
VulkanUtilities::BufferWrapper StagingBuffer = LogicalDevice.CreateBuffer(VkStaginBuffCI, StagingBufferName.c_str());
VkMemoryRequirements StagingBufferMemReqs = LogicalDevice.GetBufferMemoryRequirements(StagingBuffer);
- VERIFY( IsPowerOfTwo(StagingBufferMemReqs.alignment), "Alignment is not power of 2!");
- // VK_MEMORY_PROPERTY_HOST_COHERENT_BIT bit specifies that the host cache management commands vkFlushMappedMemoryRanges
+ VERIFY(IsPowerOfTwo(StagingBufferMemReqs.alignment), "Alignment is not power of 2!");
+ // VK_MEMORY_PROPERTY_HOST_COHERENT_BIT bit specifies that the host cache management commands vkFlushMappedMemoryRanges
// and vkInvalidateMappedMemoryRanges are NOT needed to flush host writes to the device or make device writes visible
// to the host (10.2)
auto StagingMemoryAllocation = pRenderDeviceVk->AllocateMemory(StagingBufferMemReqs, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
- auto StagingBufferMemory = StagingMemoryAllocation.Page->GetVkMemory();
+ auto StagingBufferMemory = StagingMemoryAllocation.Page->GetVkMemory();
auto AlignedStagingMemOffset = Align(StagingMemoryAllocation.UnalignedOffset, StagingBufferMemReqs.alignment);
VERIFY_EXPR(StagingMemoryAllocation.Size >= StagingBufferMemReqs.size + (AlignedStagingMemOffset - StagingMemoryAllocation.UnalignedOffset));
- auto *StagingData = reinterpret_cast<uint8_t*>(StagingMemoryAllocation.Page->GetCPUMemory());
+ auto* StagingData = reinterpret_cast<uint8_t*>(StagingMemoryAllocation.Page->GetCPUMemory());
VERIFY_EXPR(StagingData != nullptr);
StagingData += AlignedStagingMemOffset;
subres = 0;
- for(Uint32 layer = 0; layer < ImageCI.arrayLayers; ++layer)
+ for (Uint32 layer = 0; layer < ImageCI.arrayLayers; ++layer)
{
- for(Uint32 mip = 0; mip < ImageCI.mipLevels; ++mip)
+ for (Uint32 mip = 0; mip < ImageCI.mipLevels; ++mip)
{
- const auto &SubResData = pInitData->pSubResources[subres];
- const auto &CopyRegion = Regions[subres];
+ const auto& SubResData = pInitData->pSubResources[subres];
+ const auto& CopyRegion = Regions[subres];
auto MipInfo = GetMipLevelProperties(m_Desc, mip);
- VERIFY_EXPR(MipInfo.LogicalWidth == CopyRegion.imageExtent.width);
+ VERIFY_EXPR(MipInfo.LogicalWidth == CopyRegion.imageExtent.width);
VERIFY_EXPR(MipInfo.LogicalHeight == CopyRegion.imageExtent.height);
- VERIFY_EXPR(MipInfo.Depth == CopyRegion.imageExtent.depth);
+ VERIFY_EXPR(MipInfo.Depth == CopyRegion.imageExtent.depth);
VERIFY(SubResData.Stride == 0 || SubResData.Stride >= MipInfo.RowSize, "Stride is too small");
// For compressed-block formats, MipInfo.RowSize is the size of one row of blocks
VERIFY(SubResData.DepthStride == 0 || SubResData.DepthStride >= (MipInfo.StorageHeight / FmtAttribs.BlockHeight) * MipInfo.RowSize, "Depth stride is too small");
- for(Uint32 z=0; z < MipInfo.Depth; ++z)
+ for (Uint32 z = 0; z < MipInfo.Depth; ++z)
{
- for(Uint32 y=0; y < MipInfo.StorageHeight; y += FmtAttribs.BlockHeight)
+ for (Uint32 y = 0; y < MipInfo.StorageHeight; y += FmtAttribs.BlockHeight)
{
memcpy(StagingData + CopyRegion.bufferOffset + ((y + z * MipInfo.StorageHeight) / FmtAttribs.BlockHeight) * MipInfo.RowSize,
// SubResData.Stride must be the stride of one row of compressed blocks
- reinterpret_cast<const uint8_t*>(SubResData.pData) + (y/FmtAttribs.BlockHeight) * SubResData.Stride + z * SubResData.DepthStride,
+ reinterpret_cast<const uint8_t*>(SubResData.pData) + (y / FmtAttribs.BlockHeight) * SubResData.Stride + z * SubResData.DepthStride,
MipInfo.RowSize);
}
}
-
+
++subres;
}
}
@@ -341,16 +347,16 @@ TextureVkImpl :: TextureVkImpl(IReferenceCounters* pRefCounters,
// Copy commands MUST be recorded outside of a render pass instance. This is OK here
// as copy will be the only command in the cmd buffer
vkCmdCopyBufferToImage(vkCmdBuff, StagingBuffer, m_VulkanImage,
- CurrentLayout, // dstImageLayout must be VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL or VK_IMAGE_LAYOUT_GENERAL (18.4)
- static_cast<uint32_t>(Regions.size()), Regions.data());
+ CurrentLayout, // dstImageLayout must be VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL or VK_IMAGE_LAYOUT_GENERAL (18.4)
+ static_cast<uint32_t>(Regions.size()), Regions.data());
Uint32 QueueIndex = 0;
- pRenderDeviceVk->ExecuteAndDisposeTransientCmdBuff(QueueIndex, vkCmdBuff, std::move(CmdPool));
+ pRenderDeviceVk->ExecuteAndDisposeTransientCmdBuff(QueueIndex, vkCmdBuff, std::move(CmdPool));
// After command buffer is submitted, safe-release resources. This strategy
// is little overconservative as the resources will be released after the first
// command buffer submitted through the immediate context will be completed
- pRenderDeviceVk->SafeReleaseDeviceObject(std::move(StagingBuffer), Uint64{1} << Uint64{QueueIndex});
+ pRenderDeviceVk->SafeReleaseDeviceObject(std::move(StagingBuffer), Uint64{1} << Uint64{QueueIndex});
pRenderDeviceVk->SafeReleaseDeviceObject(std::move(StagingMemoryAllocation), Uint64{1} << Uint64{QueueIndex});
}
else
@@ -361,23 +367,23 @@ TextureVkImpl :: TextureVkImpl(IReferenceCounters* pRefCounters,
Subresource.levelCount = VK_REMAINING_MIP_LEVELS;
Subresource.baseArrayLayer = 0;
Subresource.layerCount = VK_REMAINING_ARRAY_LAYERS;
- if(aspectMask == VK_IMAGE_ASPECT_COLOR_BIT)
+ if (aspectMask == VK_IMAGE_ASPECT_COLOR_BIT)
{
- if(FmtAttribs.ComponentType != COMPONENT_TYPE_COMPRESSED)
+ if (FmtAttribs.ComponentType != COMPONENT_TYPE_COMPRESSED)
{
VkClearColorValue ClearColor = {};
vkCmdClearColorImage(vkCmdBuff, m_VulkanImage,
- CurrentLayout, // must be VK_IMAGE_LAYOUT_GENERAL or VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
- &ClearColor, 1, &Subresource);
+ CurrentLayout, // must be VK_IMAGE_LAYOUT_GENERAL or VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
+ &ClearColor, 1, &Subresource);
}
}
- else if(aspectMask == VK_IMAGE_ASPECT_DEPTH_BIT ||
- aspectMask == (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT) )
+ else if (aspectMask == VK_IMAGE_ASPECT_DEPTH_BIT ||
+ aspectMask == (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT))
{
VkClearDepthStencilValue ClearValue = {};
vkCmdClearDepthStencilImage(vkCmdBuff, m_VulkanImage,
- CurrentLayout, // must be VK_IMAGE_LAYOUT_GENERAL or VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
- &ClearValue, 1, &Subresource);
+ CurrentLayout, // must be VK_IMAGE_LAYOUT_GENERAL or VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
+ &ClearValue, 1, &Subresource);
}
else
{
@@ -387,36 +393,39 @@ TextureVkImpl :: TextureVkImpl(IReferenceCounters* pRefCounters,
pRenderDeviceVk->ExecuteAndDisposeTransientCmdBuff(QueueIndex, vkCmdBuff, std::move(CmdPool));
}
}
- else if(m_Desc.Usage == USAGE_STAGING)
+ else if (m_Desc.Usage == USAGE_STAGING)
{
VkBufferCreateInfo VkStaginBuffCI = {};
+
VkStaginBuffCI.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
VkStaginBuffCI.pNext = nullptr;
VkStaginBuffCI.flags = 0;
VkStaginBuffCI.size = GetStagingDataOffset(m_Desc, m_Desc.ArraySize, 0);
- DEV_CHECK_ERR( (m_Desc.CPUAccessFlags & (CPU_ACCESS_READ | CPU_ACCESS_WRITE)) == CPU_ACCESS_READ ||
- (m_Desc.CPUAccessFlags & (CPU_ACCESS_READ | CPU_ACCESS_WRITE)) == CPU_ACCESS_WRITE,
+ // clang-format off
+ DEV_CHECK_ERR((m_Desc.CPUAccessFlags & (CPU_ACCESS_READ | CPU_ACCESS_WRITE)) == CPU_ACCESS_READ ||
+ (m_Desc.CPUAccessFlags & (CPU_ACCESS_READ | CPU_ACCESS_WRITE)) == CPU_ACCESS_WRITE,
"Exactly one of CPU_ACCESS_READ or CPU_ACCESS_WRITE flags must be specified");
+ // clang-format on
VkMemoryPropertyFlags MemProperties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
if (m_Desc.CPUAccessFlags & CPU_ACCESS_READ)
{
VkStaginBuffCI.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT;
- MemProperties |= VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
+ MemProperties |= VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
SetState(RESOURCE_STATE_COPY_DEST);
}
else if (m_Desc.CPUAccessFlags & CPU_ACCESS_WRITE)
{
VkStaginBuffCI.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
- // VK_MEMORY_PROPERTY_HOST_COHERENT_BIT bit specifies that the host cache management commands vkFlushMappedMemoryRanges
+ // VK_MEMORY_PROPERTY_HOST_COHERENT_BIT bit specifies that the host cache management commands vkFlushMappedMemoryRanges
// and vkInvalidateMappedMemoryRanges are NOT needed to flush host writes to the device or make device writes visible
// to the host (10.2)
- MemProperties |= VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
+ MemProperties |= VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
SetState(RESOURCE_STATE_COPY_SOURCE);
}
else
UNEXPECTED("Unexpected CPU access");
-
+
VkStaginBuffCI.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
VkStaginBuffCI.queueFamilyIndexCount = 0;
VkStaginBuffCI.pQueueFamilyIndices = nullptr;
@@ -427,16 +436,16 @@ TextureVkImpl :: TextureVkImpl(IReferenceCounters* pRefCounters,
m_StagingBuffer = LogicalDevice.CreateBuffer(VkStaginBuffCI, StagingBufferName.c_str());
VkMemoryRequirements StagingBufferMemReqs = LogicalDevice.GetBufferMemoryRequirements(m_StagingBuffer);
- VERIFY( IsPowerOfTwo(StagingBufferMemReqs.alignment), "Alignment is not power of 2!");
+ VERIFY(IsPowerOfTwo(StagingBufferMemReqs.alignment), "Alignment is not power of 2!");
- m_MemoryAllocation = pRenderDeviceVk->AllocateMemory(StagingBufferMemReqs, MemProperties);
- auto StagingBufferMemory = m_MemoryAllocation.Page->GetVkMemory();
+ m_MemoryAllocation = pRenderDeviceVk->AllocateMemory(StagingBufferMemReqs, MemProperties);
+ auto StagingBufferMemory = m_MemoryAllocation.Page->GetVkMemory();
auto AlignedStagingMemOffset = Align(m_MemoryAllocation.UnalignedOffset, StagingBufferMemReqs.alignment);
VERIFY_EXPR(m_MemoryAllocation.Size >= StagingBufferMemReqs.size + (AlignedStagingMemOffset - m_MemoryAllocation.UnalignedOffset));
auto err = LogicalDevice.BindBufferMemory(m_StagingBuffer, StagingBufferMemory, AlignedStagingMemOffset);
CHECK_VK_ERROR_AND_THROW(err, "Failed to bind staging bufer memory");
-
+
m_StagingDataAlignedOffset = AlignedStagingMemOffset;
}
else
@@ -459,16 +468,16 @@ Uint32 GetStagingDataOffset(const TextureDesc& TexDesc, Uint32 ArraySlice, Uint3
{
auto MipInfo = GetMipLevelProperties(TexDesc, mip);
// bufferOffset must be a multiple of 4 (18.4)
- // If the calling command's VkImage parameter is a compressed image, bufferOffset
+ // If the calling command's VkImage parameter is a compressed image, bufferOffset
// must be a multiple of the compressed texel block size in bytes (18.4). This
// is automatically guaranteed as MipWidth and MipHeight are rounded to block size
ArraySliceSize += (MipInfo.MipSize + 3) & (~3);
}
Offset = ArraySliceSize;
- if (TexDesc.Type == RESOURCE_DIM_TEX_1D_ARRAY ||
- TexDesc.Type == RESOURCE_DIM_TEX_2D_ARRAY ||
- TexDesc.Type == RESOURCE_DIM_TEX_CUBE ||
+ if (TexDesc.Type == RESOURCE_DIM_TEX_1D_ARRAY ||
+ TexDesc.Type == RESOURCE_DIM_TEX_2D_ARRAY ||
+ TexDesc.Type == RESOURCE_DIM_TEX_CUBE ||
TexDesc.Type == RESOURCE_DIM_TEX_CUBE_ARRAY)
Offset *= TexDesc.ArraySize;
}
@@ -483,67 +492,65 @@ Uint32 GetStagingDataOffset(const TextureDesc& TexDesc, Uint32 ArraySlice, Uint3
return Offset;
}
-TextureVkImpl::TextureVkImpl(IReferenceCounters* pRefCounters,
- FixedBlockMemoryAllocator& TexViewObjAllocator,
- RenderDeviceVkImpl* pDeviceVk,
- const TextureDesc& TexDesc,
- RESOURCE_STATE InitialState,
- VkImage VkImageHandle) :
- TTextureBase(pRefCounters, TexViewObjAllocator, pDeviceVk, TexDesc),
- m_VulkanImage(VkImageHandle)
+TextureVkImpl::TextureVkImpl(IReferenceCounters* pRefCounters,
+ FixedBlockMemoryAllocator& TexViewObjAllocator,
+ RenderDeviceVkImpl* pDeviceVk,
+ const TextureDesc& TexDesc,
+ RESOURCE_STATE InitialState,
+ VkImage VkImageHandle) :
+ TTextureBase{pRefCounters, TexViewObjAllocator, pDeviceVk, TexDesc},
+ m_VulkanImage{VkImageHandle}
{
SetState(InitialState);
}
-IMPLEMENT_QUERY_INTERFACE( TextureVkImpl, IID_TextureVk, TTextureBase )
+IMPLEMENT_QUERY_INTERFACE(TextureVkImpl, IID_TextureVk, TTextureBase)
void TextureVkImpl::CreateViewInternal(const TextureViewDesc& ViewDesc, ITextureView** ppView, bool bIsDefaultView)
{
- VERIFY( ppView != nullptr, "View pointer address is null" );
- if( !ppView )return;
- VERIFY( *ppView == nullptr, "Overwriting reference to existing object may cause memory leaks" );
-
+ VERIFY(ppView != nullptr, "View pointer address is null");
+ if (!ppView) return;
+ VERIFY(*ppView == nullptr, "Overwriting reference to existing object may cause memory leaks");
+
*ppView = nullptr;
try
{
auto& TexViewAllocator = m_pDevice->GetTexViewObjAllocator();
- VERIFY( &TexViewAllocator == &m_dbgTexViewObjAllocator, "Texture view allocator does not match allocator provided during texture initialization" );
+ VERIFY(&TexViewAllocator == &m_dbgTexViewObjAllocator, "Texture view allocator does not match allocator provided during texture initialization");
auto UpdatedViewDesc = ViewDesc;
- CorrectTextureViewDesc( UpdatedViewDesc );
+ CorrectTextureViewDesc(UpdatedViewDesc);
VulkanUtilities::ImageViewWrapper ImgView = CreateImageView(UpdatedViewDesc);
- auto pViewVk = NEW_RC_OBJ(TexViewAllocator, "TextureViewVkImpl instance", TextureViewVkImpl, bIsDefaultView ? this : nullptr)
- (GetDevice(), UpdatedViewDesc, this, std::move(ImgView), bIsDefaultView);
- VERIFY( pViewVk->GetDesc().ViewType == ViewDesc.ViewType, "Incorrect view type" );
+ auto pViewVk = NEW_RC_OBJ(TexViewAllocator, "TextureViewVkImpl instance", TextureViewVkImpl, bIsDefaultView ? this : nullptr)(GetDevice(), UpdatedViewDesc, this, std::move(ImgView), bIsDefaultView);
+ VERIFY(pViewVk->GetDesc().ViewType == ViewDesc.ViewType, "Incorrect view type");
if (bIsDefaultView)
*ppView = pViewVk;
else
- pViewVk->QueryInterface(IID_TextureView, reinterpret_cast<IObject**>(ppView) );
+ pViewVk->QueryInterface(IID_TextureView, reinterpret_cast<IObject**>(ppView));
- if ((UpdatedViewDesc.Flags & TEXTURE_VIEW_FLAG_ALLOW_MIP_MAP_GENERATION) != 0 &&
+ if ((UpdatedViewDesc.Flags & TEXTURE_VIEW_FLAG_ALLOW_MIP_MAP_GENERATION) != 0 &&
m_bCSBasedMipGenerationSupported &&
CheckCSBasedMipGenerationSupport(TexFormatToVkFormat(pViewVk->GetDesc().Format)))
{
auto* pMipLevelViews = ALLOCATE(GetRawAllocator(), "Raw memory for mip level views", TextureViewVkImpl::MipLevelViewAutoPtrType, UpdatedViewDesc.NumMipLevels * 2);
for (Uint32 MipLevel = 0; MipLevel < UpdatedViewDesc.NumMipLevels; ++MipLevel)
{
- auto CreateMipLevelView = [&](TEXTURE_VIEW_TYPE ViewType, Uint32 MipLevel, TextureViewVkImpl::MipLevelViewAutoPtrType* ppMipLevelView)
- {
+ auto CreateMipLevelView = [&](TEXTURE_VIEW_TYPE ViewType, Uint32 MipLevel, TextureViewVkImpl::MipLevelViewAutoPtrType* ppMipLevelView) {
TextureViewDesc MipLevelViewDesc = pViewVk->GetDesc();
// Always create texture array views
std::stringstream name_ss;
- name_ss << "Internal " << (ViewType == TEXTURE_VIEW_SHADER_RESOURCE ? "SRV" : "UAV")
+ name_ss << "Internal " << (ViewType == TEXTURE_VIEW_SHADER_RESOURCE ? "SRV" : "UAV")
<< " of mip level " << MipLevel << " of texture view '" << pViewVk->GetDesc().Name << "'";
- auto name = name_ss.str();
- MipLevelViewDesc.Name = name.c_str();
- MipLevelViewDesc.TextureDim = RESOURCE_DIM_TEX_2D_ARRAY;
- MipLevelViewDesc.ViewType = ViewType;
+ auto name = name_ss.str();
+ MipLevelViewDesc.Name = name.c_str();
+ MipLevelViewDesc.TextureDim = RESOURCE_DIM_TEX_2D_ARRAY;
+ MipLevelViewDesc.ViewType = ViewType;
MipLevelViewDesc.MostDetailedMip += MipLevel;
- MipLevelViewDesc.NumMipLevels = 1;
+ MipLevelViewDesc.NumMipLevels = 1;
if (ViewType == TEXTURE_VIEW_UNORDERED_ACCESS)
{
@@ -553,12 +560,11 @@ void TextureVkImpl::CreateViewInternal(const TextureViewDesc& ViewDesc, ITexture
VulkanUtilities::ImageViewWrapper ImgView = CreateImageView(MipLevelViewDesc);
// Attach to parent view
- auto pMipLevelViewVk = NEW_RC_OBJ(TexViewAllocator, "TextureViewVkImpl instance", TextureViewVkImpl, pViewVk)
- (GetDevice(), MipLevelViewDesc, this, std::move(ImgView), bIsDefaultView);
+ auto pMipLevelViewVk = NEW_RC_OBJ(TexViewAllocator, "TextureViewVkImpl instance", TextureViewVkImpl, pViewVk)(GetDevice(), MipLevelViewDesc, this, std::move(ImgView), bIsDefaultView);
new (ppMipLevelView) TextureViewVkImpl::MipLevelViewAutoPtrType(pMipLevelViewVk, STDDeleter<TextureViewVkImpl, FixedBlockMemoryAllocator>(TexViewAllocator));
};
- CreateMipLevelView(TEXTURE_VIEW_SHADER_RESOURCE, MipLevel, &pMipLevelViews[MipLevel * 2]);
+ CreateMipLevelView(TEXTURE_VIEW_SHADER_RESOURCE, MipLevel, &pMipLevelViews[MipLevel * 2]);
CreateMipLevelView(TEXTURE_VIEW_UNORDERED_ACCESS, MipLevel, &pMipLevelViews[MipLevel * 2 + 1]);
}
@@ -571,19 +577,19 @@ void TextureVkImpl::CreateViewInternal(const TextureViewDesc& ViewDesc, ITexture
pViewVk->AssignMipLevelViews(pMipLevelViews);
}
}
- catch( const std::runtime_error & )
+ catch (const std::runtime_error&)
{
- const auto *ViewTypeName = GetTexViewTypeLiteralName(ViewDesc.ViewType);
- LOG_ERROR("Failed to create view \"", ViewDesc.Name ? ViewDesc.Name : "", "\" (", ViewTypeName, ") for texture \"", m_Desc.Name ? m_Desc.Name : "", "\"" );
+ const auto* ViewTypeName = GetTexViewTypeLiteralName(ViewDesc.ViewType);
+ LOG_ERROR("Failed to create view \"", ViewDesc.Name ? ViewDesc.Name : "", "\" (", ViewTypeName, ") for texture \"", m_Desc.Name ? m_Desc.Name : "", "\"");
}
}
-TextureVkImpl :: ~TextureVkImpl()
+TextureVkImpl ::~TextureVkImpl()
{
// Vk object can only be destroyed when it is no longer used by the GPU
// Wrappers for external texture will not be destroyed as they are created with null device pointer
if (m_VulkanImage)
- m_pDevice->SafeReleaseDeviceObject(std::move(m_VulkanImage), m_Desc.CommandQueueMask);
+ m_pDevice->SafeReleaseDeviceObject(std::move(m_VulkanImage), m_Desc.CommandQueueMask);
if (m_StagingBuffer)
m_pDevice->SafeReleaseDeviceObject(std::move(m_StagingBuffer), m_Desc.CommandQueueMask);
m_pDevice->SafeReleaseDeviceObject(std::move(m_MemoryAllocation), m_Desc.CommandQueueMask);
@@ -591,83 +597,88 @@ TextureVkImpl :: ~TextureVkImpl()
VulkanUtilities::ImageViewWrapper TextureVkImpl::CreateImageView(TextureViewDesc& ViewDesc)
{
+ // clang-format off
VERIFY(ViewDesc.ViewType == TEXTURE_VIEW_SHADER_RESOURCE ||
ViewDesc.ViewType == TEXTURE_VIEW_RENDER_TARGET ||
ViewDesc.ViewType == TEXTURE_VIEW_DEPTH_STENCIL ||
- ViewDesc.ViewType == TEXTURE_VIEW_UNORDERED_ACCESS, "Unexpected view type");
+ ViewDesc.ViewType == TEXTURE_VIEW_UNORDERED_ACCESS,
+ "Unexpected view type");
+ // clang-format on
if (ViewDesc.Format == TEX_FORMAT_UNKNOWN)
{
ViewDesc.Format = m_Desc.Format;
}
VkImageViewCreateInfo ImageViewCI = {};
+
ImageViewCI.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
ImageViewCI.pNext = nullptr;
ImageViewCI.flags = 0; // reserved for future use.
ImageViewCI.image = m_VulkanImage;
- switch(ViewDesc.TextureDim)
+ switch (ViewDesc.TextureDim)
{
case RESOURCE_DIM_TEX_1D:
ImageViewCI.viewType = VK_IMAGE_VIEW_TYPE_1D;
- break;
+ break;
case RESOURCE_DIM_TEX_1D_ARRAY:
ImageViewCI.viewType = VK_IMAGE_VIEW_TYPE_1D_ARRAY;
- break;
+ break;
case RESOURCE_DIM_TEX_2D:
ImageViewCI.viewType = VK_IMAGE_VIEW_TYPE_2D;
- break;
+ break;
case RESOURCE_DIM_TEX_2D_ARRAY:
ImageViewCI.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
- break;
+ break;
case RESOURCE_DIM_TEX_3D:
if (ViewDesc.ViewType == TEXTURE_VIEW_RENDER_TARGET || ViewDesc.ViewType == TEXTURE_VIEW_DEPTH_STENCIL)
{
- ViewDesc.TextureDim = RESOURCE_DIM_TEX_2D_ARRAY;
+ ViewDesc.TextureDim = RESOURCE_DIM_TEX_2D_ARRAY;
ImageViewCI.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
}
else
{
ImageViewCI.viewType = VK_IMAGE_VIEW_TYPE_3D;
- Uint32 MipDepth = std::max(Uint32{m_Desc.Depth} >> Uint32{ViewDesc.MostDetailedMip}, 1U);
+ Uint32 MipDepth = std::max(Uint32{m_Desc.Depth} >> Uint32{ViewDesc.MostDetailedMip}, 1U);
if (ViewDesc.FirstDepthSlice != 0 || ViewDesc.NumDepthSlices != MipDepth)
{
LOG_ERROR("3D texture view '", (ViewDesc.Name ? ViewDesc.Name : ""), "' (most detailed mip: ", Uint32{ViewDesc.MostDetailedMip},
"; mip levels: ", Uint32{ViewDesc.NumMipLevels}, "; first slice: ", ViewDesc.FirstDepthSlice,
- "; num depth slices: ", ViewDesc.NumDepthSlices, ") of texture '", m_Desc.Name, "' does not references"
- " all depth slices (", MipDepth, ") in the mip level. 3D texture views in Vulkan must address all depth slices." );
+ "; num depth slices: ", ViewDesc.NumDepthSlices, ") of texture '", m_Desc.Name,
+ "' does not references all depth slices (", MipDepth,
+ ") in the mip level. 3D texture views in Vulkan must address all depth slices.");
ViewDesc.FirstDepthSlice = 0;
ViewDesc.NumDepthSlices = MipDepth;
}
}
- break;
+ break;
case RESOURCE_DIM_TEX_CUBE:
ImageViewCI.viewType = VK_IMAGE_VIEW_TYPE_CUBE;
- break;
+ break;
case RESOURCE_DIM_TEX_CUBE_ARRAY:
ImageViewCI.viewType = VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
- break;
+ break;
default: UNEXPECTED("Unexpcted view dimension");
}
-
+
TEXTURE_FORMAT CorrectedViewFormat = ViewDesc.Format;
if (m_Desc.BindFlags & BIND_DEPTH_STENCIL)
CorrectedViewFormat = GetDefaultTextureViewFormat(CorrectedViewFormat, TEXTURE_VIEW_DEPTH_STENCIL, m_Desc.BindFlags);
- ImageViewCI.format = TexFormatToVkFormat(CorrectedViewFormat);
- ImageViewCI.components = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
- ImageViewCI.subresourceRange.baseMipLevel = ViewDesc.MostDetailedMip;
- ImageViewCI.subresourceRange.levelCount = ViewDesc.NumMipLevels;
- if (ViewDesc.TextureDim == RESOURCE_DIM_TEX_1D_ARRAY ||
+ ImageViewCI.format = TexFormatToVkFormat(CorrectedViewFormat);
+ ImageViewCI.components = {VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A};
+ ImageViewCI.subresourceRange.baseMipLevel = ViewDesc.MostDetailedMip;
+ ImageViewCI.subresourceRange.levelCount = ViewDesc.NumMipLevels;
+ if (ViewDesc.TextureDim == RESOURCE_DIM_TEX_1D_ARRAY ||
ViewDesc.TextureDim == RESOURCE_DIM_TEX_2D_ARRAY ||
- ViewDesc.TextureDim == RESOURCE_DIM_TEX_CUBE ||
- ViewDesc.TextureDim == RESOURCE_DIM_TEX_CUBE_ARRAY )
+ ViewDesc.TextureDim == RESOURCE_DIM_TEX_CUBE ||
+ ViewDesc.TextureDim == RESOURCE_DIM_TEX_CUBE_ARRAY)
{
ImageViewCI.subresourceRange.baseArrayLayer = ViewDesc.FirstArraySlice;
ImageViewCI.subresourceRange.layerCount = ViewDesc.NumArraySlices;
@@ -678,11 +689,11 @@ VulkanUtilities::ImageViewWrapper TextureVkImpl::CreateImageView(TextureViewDesc
ImageViewCI.subresourceRange.layerCount = 1;
}
- const auto &FmtAttribs = GetTextureFormatAttribs(CorrectedViewFormat);
+ const auto& FmtAttribs = GetTextureFormatAttribs(CorrectedViewFormat);
- if(ViewDesc.ViewType == TEXTURE_VIEW_DEPTH_STENCIL)
+ if (ViewDesc.ViewType == TEXTURE_VIEW_DEPTH_STENCIL)
{
- // When an imageView of a depth/stencil image is used as a depth/stencil framebuffer attachment,
+ // When an imageView of a depth/stencil image is used as a depth/stencil framebuffer attachment,
// the aspectMask is ignored and both depth and stencil image subresources are used. (11.5)
if (FmtAttribs.ComponentType == COMPONENT_TYPE_DEPTH)
ImageViewCI.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
@@ -693,16 +704,16 @@ VulkanUtilities::ImageViewWrapper TextureVkImpl::CreateImageView(TextureViewDesc
}
else
{
- // aspectMask must be only VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_ASPECT_DEPTH_BIT or VK_IMAGE_ASPECT_STENCIL_BIT
+ // aspectMask must be only VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_ASPECT_DEPTH_BIT or VK_IMAGE_ASPECT_STENCIL_BIT
// if format is a color, depth-only or stencil-only format, respectively. (11.5)
- if(FmtAttribs.ComponentType == COMPONENT_TYPE_DEPTH )
+ if (FmtAttribs.ComponentType == COMPONENT_TYPE_DEPTH)
{
ImageViewCI.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
}
else if (FmtAttribs.ComponentType == COMPONENT_TYPE_DEPTH_STENCIL)
{
- if(ViewDesc.Format == TEX_FORMAT_D32_FLOAT_S8X24_UINT ||
- ViewDesc.Format == TEX_FORMAT_D24_UNORM_S8_UINT)
+ if (ViewDesc.Format == TEX_FORMAT_D32_FLOAT_S8X24_UINT ||
+ ViewDesc.Format == TEX_FORMAT_D24_UNORM_S8_UINT)
{
ImageViewCI.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
}
@@ -711,7 +722,7 @@ VulkanUtilities::ImageViewWrapper TextureVkImpl::CreateImageView(TextureViewDesc
{
ImageViewCI.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
}
- else if (ViewDesc.Format == TEX_FORMAT_X32_TYPELESS_G8X24_UINT ||
+ else if (ViewDesc.Format == TEX_FORMAT_X32_TYPELESS_G8X24_UINT ||
ViewDesc.Format == TEX_FORMAT_X24_TYPELESS_G8_UINT)
{
ImageViewCI.subresourceRange.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
@@ -722,7 +733,7 @@ VulkanUtilities::ImageViewWrapper TextureVkImpl::CreateImageView(TextureViewDesc
else
ImageViewCI.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
}
-
+
const auto& LogicalDevice = m_pDevice->GetLogicalDevice();
std::string ViewName = "Image view for \'";
@@ -731,13 +742,13 @@ VulkanUtilities::ImageViewWrapper TextureVkImpl::CreateImageView(TextureViewDesc
return LogicalDevice.CreateImageView(ImageViewCI, ViewName.c_str());
}
-bool TextureVkImpl::CheckCSBasedMipGenerationSupport(VkFormat vkFmt)const
+bool TextureVkImpl::CheckCSBasedMipGenerationSupport(VkFormat vkFmt) const
{
VERIFY_EXPR(m_Desc.MiscFlags & MISC_TEXTURE_FLAG_GENERATE_MIPS);
if (m_Desc.Type == RESOURCE_DIM_TEX_2D || m_Desc.Type == RESOURCE_DIM_TEX_2D_ARRAY)
{
const auto& PhysicalDevice = m_pDevice->GetPhysicalDevice();
- auto FmtProperties = PhysicalDevice.GetPhysicalDeviceFormatProperties(vkFmt);
+ auto FmtProperties = PhysicalDevice.GetPhysicalDeviceFormatProperties(vkFmt);
if ((FmtProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT) != 0)
{
return true;
@@ -752,7 +763,7 @@ void TextureVkImpl::SetLayout(VkImageLayout Layout)
SetState(VkImageLayoutToResourceState(Layout));
}
-VkImageLayout TextureVkImpl::GetLayout()const
+VkImageLayout TextureVkImpl::GetLayout() const
{
return ResourceStateToVkImageLayout(GetState());
}
@@ -760,14 +771,18 @@ VkImageLayout TextureVkImpl::GetLayout()const
void TextureVkImpl::InvalidateStagingRange(VkDeviceSize Offset, VkDeviceSize Size)
{
const auto& LogicalDevice = m_pDevice->GetLogicalDevice();
+
VkMappedMemoryRange InvalidateRange = {};
+
InvalidateRange.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;
InvalidateRange.pNext = nullptr;
InvalidateRange.memory = m_MemoryAllocation.Page->GetVkMemory();
InvalidateRange.offset = m_StagingDataAlignedOffset + Offset;
InvalidateRange.size = Size;
+
auto err = LogicalDevice.InvalidateMappedMemoryRanges(1, &InvalidateRange);
- DEV_CHECK_ERR(err == VK_SUCCESS, "Failed to invalidated mapped texture memory range"); (void)err;
+ DEV_CHECK_ERR(err == VK_SUCCESS, "Failed to invalidated mapped texture memory range");
+ (void)err;
}
-}
+} // namespace Diligent
diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanDynamicHeap.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanDynamicHeap.cpp
index 5475f128..7497373e 100644
--- a/Graphics/GraphicsEngineVulkan/src/VulkanDynamicHeap.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/VulkanDynamicHeap.cpp
@@ -32,49 +32,53 @@ namespace Diligent
static VkDeviceSize GetDefaultAlignment(const VulkanUtilities::VulkanPhysicalDevice& PhysicalDevice)
{
- const auto& Props = PhysicalDevice.GetProperties();
+ const auto& Props = PhysicalDevice.GetProperties();
const auto& Limits = Props.limits;
return std::max(std::max(Limits.minUniformBufferOffsetAlignment, Limits.minTexelBufferOffsetAlignment), Limits.minStorageBufferOffsetAlignment);
}
-VulkanDynamicMemoryManager::VulkanDynamicMemoryManager(IMemoryAllocator& Allocator,
- RenderDeviceVkImpl& DeviceVk,
+VulkanDynamicMemoryManager::VulkanDynamicMemoryManager(IMemoryAllocator& Allocator,
+ RenderDeviceVkImpl& DeviceVk,
Uint32 Size,
Uint64 CommandQueueMask) :
+ // clang-format off
TBase {Allocator, Size},
m_DeviceVk {DeviceVk},
m_DefaultAlignment{GetDefaultAlignment(DeviceVk.GetPhysicalDevice())},
m_CommandQueueMask{CommandQueueMask}
+// clang-format on
{
- VERIFY( (Size & (MasterBlockAlignment-1)) == 0, "Heap size (", Size, " is not aligned by the master block alignment (", Uint32{MasterBlockAlignment}, ")");
+ VERIFY((Size & (MasterBlockAlignment - 1)) == 0, "Heap size (", Size, " is not aligned by the master block alignment (", Uint32{MasterBlockAlignment}, ")");
VkBufferCreateInfo VkBuffCI = {};
+
VkBuffCI.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
VkBuffCI.pNext = nullptr;
VkBuffCI.flags = 0; // VK_BUFFER_CREATE_SPARSE_BINDING_BIT, VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT, VK_BUFFER_CREATE_SPARSE_ALIASED_BIT
- VkBuffCI.size = Size;
- VkBuffCI.usage =
- VK_BUFFER_USAGE_TRANSFER_SRC_BIT |
- VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT |
- VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
- VK_BUFFER_USAGE_INDEX_BUFFER_BIT |
- VK_BUFFER_USAGE_VERTEX_BUFFER_BIT |
+ VkBuffCI.size = Size;
+ VkBuffCI.usage =
+ VK_BUFFER_USAGE_TRANSFER_SRC_BIT |
+ VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT |
+ VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
+ VK_BUFFER_USAGE_INDEX_BUFFER_BIT |
+ VK_BUFFER_USAGE_VERTEX_BUFFER_BIT |
VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT;
- VkBuffCI.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
+ VkBuffCI.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
VkBuffCI.queueFamilyIndexCount = 0;
- VkBuffCI.pQueueFamilyIndices = nullptr;
+ VkBuffCI.pQueueFamilyIndices = nullptr;
- const auto& LogicalDevice = DeviceVk.GetLogicalDevice();
- m_VkBuffer = LogicalDevice.CreateBuffer(VkBuffCI, "Dynamic heap buffer");
+ const auto& LogicalDevice = DeviceVk.GetLogicalDevice();
+ m_VkBuffer = LogicalDevice.CreateBuffer(VkBuffCI, "Dynamic heap buffer");
VkMemoryRequirements MemReqs = LogicalDevice.GetBufferMemoryRequirements(m_VkBuffer);
const auto& PhysicalDevice = DeviceVk.GetPhysicalDevice();
VkMemoryAllocateInfo MemAlloc = {};
- MemAlloc.pNext = nullptr;
- MemAlloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
+
+ MemAlloc.pNext = nullptr;
+ MemAlloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
MemAlloc.allocationSize = MemReqs.size;
- // VK_MEMORY_PROPERTY_HOST_COHERENT_BIT bit specifies that the host cache management commands vkFlushMappedMemoryRanges
+ // VK_MEMORY_PROPERTY_HOST_COHERENT_BIT bit specifies that the host cache management commands vkFlushMappedMemoryRanges
// and vkInvalidateMappedMemoryRanges are NOT needed to flush host writes to the device or make device writes visible
// to the host (10.2)
MemAlloc.memoryTypeIndex = PhysicalDevice.GetMemoryTypeIndex(MemReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
@@ -87,8 +91,10 @@ VulkanDynamicMemoryManager::VulkanDynamicMemoryManager(IMemoryAllocator& Alloc
m_BufferMemory = LogicalDevice.AllocateDeviceMemory(MemAlloc, "Host-visible memory for upload buffer");
- void *Data = nullptr;
- auto err = LogicalDevice.MapMemory(m_BufferMemory,
+ void* Data = nullptr;
+
+ auto err = LogicalDevice.MapMemory(
+ m_BufferMemory,
0, // offset
MemAlloc.allocationSize,
0, // flags, reserved for future use
@@ -99,7 +105,7 @@ VulkanDynamicMemoryManager::VulkanDynamicMemoryManager(IMemoryAllocator& Alloc
err = LogicalDevice.BindBufferMemory(m_VkBuffer, m_BufferMemory, 0 /*offset*/);
CHECK_VK_ERROR_AND_THROW(err, "Failed to bind bufer memory");
- LOG_INFO_MESSAGE("GPU dynamic heap created. Total buffer size: ", FormatMemorySize(Size, 2) );
+ LOG_INFO_MESSAGE("GPU dynamic heap created. Total buffer size: ", FormatMemorySize(Size, 2));
}
void VulkanDynamicMemoryManager::Destroy()
@@ -107,7 +113,7 @@ void VulkanDynamicMemoryManager::Destroy()
if (m_VkBuffer)
{
m_DeviceVk.GetLogicalDevice().UnmapMemory(m_BufferMemory);
- m_DeviceVk.SafeReleaseDeviceObject(std::move(m_VkBuffer), m_CommandQueueMask);
+ m_DeviceVk.SafeReleaseDeviceObject(std::move(m_VkBuffer), m_CommandQueueMask);
m_DeviceVk.SafeReleaseDeviceObject(std::move(m_BufferMemory), m_CommandQueueMask);
}
m_CPUAddress = nullptr;
@@ -118,9 +124,11 @@ VulkanDynamicMemoryManager::~VulkanDynamicMemoryManager()
VERIFY(m_BufferMemory == VK_NULL_HANDLE && m_VkBuffer == VK_NULL_HANDLE, "Vulkan resources must be explcitly released with Destroy()");
auto Size = GetSize();
LOG_INFO_MESSAGE("Dynamic memory manager usage stats:\n"
- " Total size: ", FormatMemorySize(Size, 2),
+ " Total size: ",
+ FormatMemorySize(Size, 2),
". Peak allocated size: ", FormatMemorySize(m_TotalPeakSize, 2, Size),
- ". Peak utilization: ", std::fixed, std::setprecision(1), static_cast<double>(m_TotalPeakSize) / static_cast<double>(std::max(Size, size_t{1})) * 100.0, '%' );
+ ". Peak utilization: ",
+ std::fixed, std::setprecision(1), static_cast<double>(m_TotalPeakSize) / static_cast<double>(std::max(Size, size_t{1})) * 100.0, '%');
}
@@ -128,10 +136,12 @@ VulkanDynamicMemoryManager::MasterBlock VulkanDynamicMemoryManager::AllocateMast
{
if (Alignment == 0)
Alignment = MasterBlockAlignment;
-
+
if (SizeInBytes > GetSize())
{
- LOG_ERROR("Requested dynamic allocation size ", SizeInBytes, " exceeds maximum dynamic memory size ", GetSize(), ". The app should increase dynamic heap size.");
+ LOG_ERROR("Requested dynamic allocation size ", SizeInBytes,
+ " exceeds maximum dynamic memory size ", GetSize(),
+ ". The app should increase dynamic heap size.");
return MasterBlock{};
}
@@ -139,11 +149,11 @@ VulkanDynamicMemoryManager::MasterBlock VulkanDynamicMemoryManager::AllocateMast
if (!Block.IsValid())
{
// Allocation failed. Try to wait for GPU to finish pending frames to release some space
- auto StartIdleTime = std::chrono::high_resolution_clock::now();
- static constexpr const auto SleepPeriod = std::chrono::milliseconds(1);
- static constexpr const auto MaxIdleDuration = std::chrono::duration<double>{60.0 / 1000.0}; // 60 ms
+ auto StartIdleTime = std::chrono::high_resolution_clock::now();
+ static constexpr const auto SleepPeriod = std::chrono::milliseconds(1);
+ static constexpr const auto MaxIdleDuration = std::chrono::duration<double>{60.0 / 1000.0}; // 60 ms
std::chrono::duration<double> IdleDuration;
- Uint32 SleepIterations = 0;
+ Uint32 SleepIterations = 0;
while (!Block.IsValid() && IdleDuration < MaxIdleDuration)
{
m_DeviceVk.PurgeReleaseQueues();
@@ -155,7 +165,7 @@ VulkanDynamicMemoryManager::MasterBlock VulkanDynamicMemoryManager::AllocateMast
}
auto CurrTime = std::chrono::high_resolution_clock::now();
- IdleDuration = std::chrono::duration_cast<std::chrono::duration<double>>(CurrTime - StartIdleTime);
+ IdleDuration = std::chrono::duration_cast<std::chrono::duration<double>>(CurrTime - StartIdleTime);
}
if (!Block.IsValid())
@@ -165,22 +175,32 @@ VulkanDynamicMemoryManager::MasterBlock VulkanDynamicMemoryManager::AllocateMast
Block = TBase::AllocateMasterBlock(SizeInBytes, Alignment);
if (!Block.IsValid())
{
- LOG_ERROR_MESSAGE("Space in dynamic heap is exausted! After idling for ", std::fixed, std::setprecision(1), IdleDuration.count()*1000.0, " ms still no space is available. Increase the size of the heap by setting EngineVkCreateInfo::DynamicHeapSize to a greater value or optimize dynamic resource usage");
+ LOG_ERROR_MESSAGE("Space in dynamic heap is exausted! After idling for ",
+ std::fixed, std::setprecision(1), IdleDuration.count() * 1000.0,
+ " ms still no space is available. Increase the size of the heap by setting "
+ "EngineVkCreateInfo::DynamicHeapSize to a greater value or optimize dynamic resource usage");
}
else
{
- LOG_WARNING_MESSAGE("Space in dynamic heap is almost exausted. Allocation forced idling the GPU. Increase the size of the heap by setting EngineVkCreateInfo::DynamicHeapSize to a greater value or optimize dynamic resource usage");
+ LOG_WARNING_MESSAGE("Space in dynamic heap is almost exausted. Allocation forced idling the GPU. "
+ "Increase the size of the heap by setting EngineVkCreateInfo::DynamicHeapSize to a "
+ "greater value or optimize dynamic resource usage");
}
}
else
{
- if(SleepIterations == 0)
+ if (SleepIterations == 0)
{
- LOG_WARNING_MESSAGE("Space in dynamic heap is almost exausted forcing mid-frame shrinkage. Increase the size of the heap buffer by setting EngineVkCreateInfo::DynamicHeapSize to a greater value or optimize dynamic resource usage");
+ LOG_WARNING_MESSAGE("Space in dynamic heap is almost exausted forcing mid-frame shrinkage. "
+ "Increase the size of the heap buffer by setting EngineVkCreateInfo::DynamicHeapSize to a "
+ "greater value or optimize dynamic resource usage");
}
else
{
- LOG_WARNING_MESSAGE("Space in dynamic heap is almost exausted. Allocation forced wait time of ", std::fixed, std::setprecision(1), IdleDuration.count()*1000.0, " ms. Increase the size of the heap by setting EngineVkCreateInfo::DynamicHeapSize to a greater value or optimize dynamic resource usage");
+ LOG_WARNING_MESSAGE("Space in dynamic heap is almost exausted. Allocation forced wait time of ",
+ std::fixed, std::setprecision(1), IdleDuration.count() * 1000.0,
+ " ms. Increase the size of the heap by setting EngineVkCreateInfo::DynamicHeapSize "
+ "to a greater value or optimize dynamic resource usage");
}
}
}
@@ -199,9 +219,9 @@ VulkanDynamicAllocation VulkanDynamicHeap::Allocate(Uint32 SizeInBytes, Uint32 A
VERIFY_EXPR(Alignment > 0);
VERIFY(IsPowerOfTwo(Alignment), "Alignment (", Alignment, ") must be power of 2");
- auto AlignedOffset = InvalidOffset;
- OffsetType AlignedSize = 0;
- if(SizeInBytes > m_MasterBlockSize/2)
+ auto AlignedOffset = InvalidOffset;
+ OffsetType AlignedSize = 0;
+ if (SizeInBytes > m_MasterBlockSize / 2)
{
// Allocate directly from the memory manager
auto MasterBlock = m_GlobalDynamicMemMgr.AllocateMasterBlock(SizeInBytes, Alignment);
@@ -221,9 +241,9 @@ VulkanDynamicAllocation VulkanDynamicHeap::Allocate(Uint32 SizeInBytes, Uint32 A
auto MasterBlock = m_GlobalDynamicMemMgr.AllocateMasterBlock(m_MasterBlockSize, 0);
if (MasterBlock.IsValid())
{
- m_CurrOffset = MasterBlock.UnalignedOffset;
+ m_CurrOffset = MasterBlock.UnalignedOffset;
m_CurrAllocatedSize += static_cast<Uint32>(MasterBlock.Size);
- m_AvailableSize = static_cast<Uint32>(MasterBlock.Size);
+ m_AvailableSize = static_cast<Uint32>(MasterBlock.Size);
m_MasterBlocks.emplace_back(MasterBlock);
}
}
@@ -231,11 +251,11 @@ VulkanDynamicAllocation VulkanDynamicHeap::Allocate(Uint32 SizeInBytes, Uint32 A
if (m_CurrOffset != InvalidOffset)
{
AlignedOffset = Align(m_CurrOffset, size_t{Alignment});
- AlignedSize = SizeInBytes + (AlignedOffset - m_CurrOffset);
+ AlignedSize = SizeInBytes + (AlignedOffset - m_CurrOffset);
if (AlignedSize <= m_AvailableSize)
{
m_AvailableSize -= static_cast<Uint32>(AlignedSize);
- m_CurrOffset += static_cast<Uint32>(AlignedSize);
+ m_CurrOffset += static_cast<Uint32>(AlignedSize);
}
else
AlignedOffset = InvalidOffset;
@@ -243,16 +263,16 @@ VulkanDynamicAllocation VulkanDynamicHeap::Allocate(Uint32 SizeInBytes, Uint32 A
}
// Every device context uses its own dynamic heap, so there is no need to lock
- if(AlignedOffset != InvalidOffset)
+ if (AlignedOffset != InvalidOffset)
{
m_CurrAlignedSize += static_cast<Uint32>(AlignedSize);
- m_CurrUsedSize += SizeInBytes;
- m_PeakAlignedSize = std::max(m_PeakAlignedSize, m_CurrAlignedSize);
- m_PeakUsedSize = std::max(m_PeakUsedSize, m_CurrUsedSize);
- m_PeakAllocatedSize = std::max(m_PeakAllocatedSize, m_CurrAllocatedSize);
-
- VERIFY_EXPR((AlignedOffset & (Alignment-1)) == 0);
- return VulkanDynamicAllocation{ m_GlobalDynamicMemMgr, AlignedOffset, SizeInBytes };
+ m_CurrUsedSize += SizeInBytes;
+ m_PeakAlignedSize = std::max(m_PeakAlignedSize, m_CurrAlignedSize);
+ m_PeakUsedSize = std::max(m_PeakUsedSize, m_CurrUsedSize);
+ m_PeakAllocatedSize = std::max(m_PeakAllocatedSize, m_CurrAllocatedSize);
+
+ VERIFY_EXPR((AlignedOffset & (Alignment - 1)) == 0);
+ return VulkanDynamicAllocation{m_GlobalDynamicMemMgr, AlignedOffset, SizeInBytes};
}
else
return VulkanDynamicAllocation{};
@@ -263,12 +283,12 @@ void VulkanDynamicHeap::ReleaseMasterBlocks(RenderDeviceVkImpl& DeviceVkImpl, Ui
m_GlobalDynamicMemMgr.ReleaseMasterBlocks(m_MasterBlocks, DeviceVkImpl, CmdQueueMask);
m_MasterBlocks.clear();
- m_CurrOffset = InvalidOffset;
- m_AvailableSize = 0;
+ m_CurrOffset = InvalidOffset;
+ m_AvailableSize = 0;
- m_CurrUsedSize = 0;
- m_CurrAlignedSize = 0;
- m_CurrAllocatedSize = 0;
+ m_CurrUsedSize = 0;
+ m_CurrAlignedSize = 0;
+ m_CurrAllocatedSize = 0;
}
VulkanDynamicHeap::~VulkanDynamicHeap()
@@ -276,14 +296,15 @@ VulkanDynamicHeap::~VulkanDynamicHeap()
DEV_CHECK_ERR(m_MasterBlocks.empty(), m_MasterBlocks.size(), " master block(s) have not been returned to dynamic memory manager");
auto PeakAllocatedPages = m_PeakAllocatedSize / m_MasterBlockSize;
- LOG_INFO_MESSAGE(m_HeapName, " usage stats:\n"
- " Peak used/aligned/allocated size: ", FormatMemorySize(m_PeakUsedSize, 2, m_PeakAllocatedSize), " / ",
- FormatMemorySize(m_PeakAlignedSize, 2, m_PeakAllocatedSize), " / ",
- FormatMemorySize(m_PeakAllocatedSize, 2, m_PeakAllocatedSize),
- " (", PeakAllocatedPages, (PeakAllocatedPages == 1 ? " page)" : " pages)"),
- ". Peak efficiency (used/aligned): ", std::fixed, std::setprecision(1), static_cast<double>(m_PeakUsedSize) / static_cast<double>(std::max(m_PeakAlignedSize, 1U)) * 100.0, '%',
- ". Peak utilization (used/allocated): ", std::fixed, std::setprecision(1), static_cast<double>(m_PeakUsedSize) / static_cast<double>(std::max(m_PeakAllocatedSize, 1U)) * 100.0, '%'
- );
+ LOG_INFO_MESSAGE(m_HeapName,
+ " usage stats:\n"
+ " Peak used/aligned/allocated size: ",
+ FormatMemorySize(m_PeakUsedSize, 2, m_PeakAllocatedSize), " / ",
+ FormatMemorySize(m_PeakAlignedSize, 2, m_PeakAllocatedSize), " / ",
+ FormatMemorySize(m_PeakAllocatedSize, 2, m_PeakAllocatedSize),
+ " (", PeakAllocatedPages, (PeakAllocatedPages == 1 ? " page)" : " pages)"),
+ ". Peak efficiency (used/aligned): ", std::fixed, std::setprecision(1), static_cast<double>(m_PeakUsedSize) / static_cast<double>(std::max(m_PeakAlignedSize, 1U)) * 100.0, '%',
+ ". Peak utilization (used/allocated): ", std::fixed, std::setprecision(1), static_cast<double>(m_PeakUsedSize) / static_cast<double>(std::max(m_PeakAllocatedSize, 1U)) * 100.0, '%');
}
-}
+} // namespace Diligent
diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp
index 9987f013..6ade4750 100644
--- a/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp
@@ -36,6 +36,7 @@ class TexFormatToVkFormatMapper
public:
TexFormatToVkFormatMapper()
{
+ // clang-format off
m_FmtToVkFmtMap[TEX_FORMAT_UNKNOWN] = VK_FORMAT_UNDEFINED;
m_FmtToVkFmtMap[TEX_FORMAT_RGBA32_TYPELESS] = VK_FORMAT_R32G32B32A32_SFLOAT;
@@ -154,9 +155,10 @@ public:
m_FmtToVkFmtMap[TEX_FORMAT_BC7_TYPELESS] = VK_FORMAT_BC7_UNORM_BLOCK;
m_FmtToVkFmtMap[TEX_FORMAT_BC7_UNORM] = VK_FORMAT_BC7_UNORM_BLOCK;
m_FmtToVkFmtMap[TEX_FORMAT_BC7_UNORM_SRGB] = VK_FORMAT_BC7_SRGB_BLOCK;
+ // clang-format on
}
- VkFormat operator[](TEXTURE_FORMAT TexFmt)const
+ VkFormat operator[](TEXTURE_FORMAT TexFmt) const
{
VERIFY_EXPR(TexFmt < _countof(m_FmtToVkFmtMap));
return m_FmtToVkFmtMap[TexFmt];
@@ -179,6 +181,7 @@ class VkFormatToTexFormatMapper
public:
VkFormatToTexFormatMapper()
{
+ // clang-format off
m_VkFmtToTexFmtMap[VK_FORMAT_UNDEFINED] = TEX_FORMAT_UNKNOWN;
m_VkFmtToTexFmtMap[VK_FORMAT_R4G4_UNORM_PACK8] = TEX_FORMAT_UNKNOWN;
m_VkFmtToTexFmtMap[VK_FORMAT_R4G4B4A4_UNORM_PACK16] = TEX_FORMAT_UNKNOWN;
@@ -431,11 +434,12 @@ public:
m_VkFmtToTexFmtMapExt[VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG] = TEX_FORMAT_UNKNOWN;
m_VkFmtToTexFmtMapExt[VK_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG] = TEX_FORMAT_UNKNOWN;
m_VkFmtToTexFmtMapExt[VK_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG] = TEX_FORMAT_UNKNOWN;
+ // clang-format on
}
- TEXTURE_FORMAT operator[](VkFormat VkFmt)const
+ TEXTURE_FORMAT operator[](VkFormat VkFmt) const
{
- if(VkFmt < VK_FORMAT_RANGE_SIZE)
+ if (VkFmt < VK_FORMAT_RANGE_SIZE)
{
return m_VkFmtToTexFmtMap[VkFmt];
}
@@ -447,7 +451,7 @@ public:
}
private:
- TEXTURE_FORMAT m_VkFmtToTexFmtMap[VK_FORMAT_RANGE_SIZE] = {};
+ TEXTURE_FORMAT m_VkFmtToTexFmtMap[VK_FORMAT_RANGE_SIZE] = {};
std::unordered_map<VkFormat, TEXTURE_FORMAT> m_VkFmtToTexFmtMapExt;
};
@@ -616,14 +620,16 @@ VkFormat TypeToVkFormat(VALUE_TYPE ValType, Uint32 NumComponents, Bool bIsNormal
VkPolygonMode FillModeToVkPolygonMode(FILL_MODE FillMode)
{
- switch(FillMode)
+ switch (FillMode)
{
- case FILL_MODE_UNDEFINED:
- UNEXPECTED("Undefined fill mode");
+ case FILL_MODE_UNDEFINED:
+ UNEXPECTED("Undefined fill mode");
return VK_POLYGON_MODE_FILL;
+ // clang-format off
case FILL_MODE_SOLID: return VK_POLYGON_MODE_FILL;
case FILL_MODE_WIREFRAME: return VK_POLYGON_MODE_LINE;
+ // clang-format on
default:
UNEXPECTED("Unexpected fill mode");
@@ -633,15 +639,17 @@ VkPolygonMode FillModeToVkPolygonMode(FILL_MODE FillMode)
VkCullModeFlagBits CullModeToVkCullMode(CULL_MODE CullMode)
{
- switch(CullMode)
+ switch (CullMode)
{
case CULL_MODE_UNDEFINED:
UNEXPECTED("Undefined cull mode");
return VK_CULL_MODE_NONE;
+ // clang-format off
case CULL_MODE_NONE: return VK_CULL_MODE_NONE;
case CULL_MODE_FRONT: return VK_CULL_MODE_FRONT_BIT;
case CULL_MODE_BACK: return VK_CULL_MODE_BACK_BIT;
+ // clang-format on
default:
UNEXPECTED("Unexpected cull mode");
@@ -649,42 +657,44 @@ VkCullModeFlagBits CullModeToVkCullMode(CULL_MODE CullMode)
}
}
-VkPipelineRasterizationStateCreateInfo RasterizerStateDesc_To_VkRasterizationStateCI(const RasterizerStateDesc &RasterizerDesc)
+VkPipelineRasterizationStateCreateInfo RasterizerStateDesc_To_VkRasterizationStateCI(const RasterizerStateDesc& RasterizerDesc)
{
VkPipelineRasterizationStateCreateInfo RSStateCI = {};
+
RSStateCI.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
RSStateCI.pNext = nullptr;
RSStateCI.flags = 0; // Reserved for future use.
- // If depth clamping is enabled, before the incoming fragment's zf is compared to za, zf is clamped to
- // [min(n,f), max(n,f)], where n and f are the minDepth and maxDepth depth range values of the viewport
+ // If depth clamping is enabled, before the incoming fragment's zf is compared to za, zf is clamped to
+ // [min(n,f), max(n,f)], where n and f are the minDepth and maxDepth depth range values of the viewport
// used by this fragment, respectively (25.10)
// This value is the opposite of clip enable
RSStateCI.depthClampEnable = RasterizerDesc.DepthClipEnable ? VK_FALSE : VK_TRUE;
-
- RSStateCI.rasterizerDiscardEnable = VK_FALSE; // Whether primitives are discarded immediately before the rasterization stage.
- RSStateCI.polygonMode = FillModeToVkPolygonMode(RasterizerDesc.FillMode); // 24.7.2
- RSStateCI.cullMode = CullModeToVkCullMode(RasterizerDesc.CullMode); // 24.7.1
- RSStateCI.frontFace = RasterizerDesc.FrontCounterClockwise ? VK_FRONT_FACE_COUNTER_CLOCKWISE : VK_FRONT_FACE_CLOCKWISE; // 24.7.1
+
+ RSStateCI.rasterizerDiscardEnable = VK_FALSE; // Whether primitives are discarded immediately before the rasterization stage.
+ RSStateCI.polygonMode = FillModeToVkPolygonMode(RasterizerDesc.FillMode); // 24.7.2
+ RSStateCI.cullMode = CullModeToVkCullMode(RasterizerDesc.CullMode); // 24.7.1
+ RSStateCI.frontFace = RasterizerDesc.FrontCounterClockwise ? VK_FRONT_FACE_COUNTER_CLOCKWISE : VK_FRONT_FACE_CLOCKWISE; // 24.7.1
// Depth bias (24.7.3)
RSStateCI.depthBiasEnable = (RasterizerDesc.DepthBias != 0 || RasterizerDesc.SlopeScaledDepthBias != 0.f) ? VK_TRUE : VK_FALSE;
- RSStateCI.depthBiasConstantFactor =
- static_cast<float>(RasterizerDesc.DepthBias); // a scalar factor applied to an implementation-dependent constant
- // that relates to the usable resolution of the depth buffer
+ RSStateCI.depthBiasConstantFactor =
+ static_cast<float>(RasterizerDesc.DepthBias); // a scalar factor applied to an implementation-dependent constant
+ // that relates to the usable resolution of the depth buffer
RSStateCI.depthBiasClamp = RasterizerDesc.DepthBiasClamp; // maximum (or minimum) depth bias of a fragment.
- RSStateCI.depthBiasSlopeFactor =
+ RSStateCI.depthBiasSlopeFactor =
RasterizerDesc.SlopeScaledDepthBias; // a scalar factor applied to a fragment's slope in depth bias calculations.
- RSStateCI.lineWidth = 1.f; // If the wide lines feature is not enabled, and no element of the pDynamicStates member of
- // pDynamicState is VK_DYNAMIC_STATE_LINE_WIDTH, the lineWidth member of
- // pRasterizationState must be 1.0 (9.2)
+ RSStateCI.lineWidth = 1.f; // If the wide lines feature is not enabled, and no element of the pDynamicStates member of
+ // pDynamicState is VK_DYNAMIC_STATE_LINE_WIDTH, the lineWidth member of
+ // pRasterizationState must be 1.0 (9.2)
return RSStateCI;
}
VkCompareOp ComparisonFuncToVkCompareOp(COMPARISON_FUNCTION CmpFunc)
{
- switch(CmpFunc)
+ switch (CmpFunc)
{
+ // clang-format off
case COMPARISON_FUNC_UNKNOWN:
UNEXPECTED("Comparison function is not specified" );
return VK_COMPARE_OP_ALWAYS;
@@ -697,17 +707,19 @@ VkCompareOp ComparisonFuncToVkCompareOp(COMPARISON_FUNCTION CmpFunc)
case COMPARISON_FUNC_NOT_EQUAL: return VK_COMPARE_OP_NOT_EQUAL;
case COMPARISON_FUNC_GREATER_EQUAL: return VK_COMPARE_OP_GREATER_OR_EQUAL;
case COMPARISON_FUNC_ALWAYS: return VK_COMPARE_OP_ALWAYS;
+ // clang-format on
- default:
- UNEXPECTED("Unknown comparison function" );
+ default:
+ UNEXPECTED("Unknown comparison function");
return VK_COMPARE_OP_ALWAYS;
}
}
VkStencilOp StencilOpToVkStencilOp(STENCIL_OP StencilOp)
{
- switch(StencilOp)
+ switch (StencilOp)
{
+ // clang-format off
case STENCIL_OP_UNDEFINED:
UNEXPECTED("Undefined stencil operation");
return VK_STENCIL_OP_KEEP;
@@ -720,6 +732,7 @@ VkStencilOp StencilOpToVkStencilOp(STENCIL_OP StencilOp)
case STENCIL_OP_INVERT: return VK_STENCIL_OP_INVERT;
case STENCIL_OP_INCR_WRAP: return VK_STENCIL_OP_INCREMENT_AND_WRAP;
case STENCIL_OP_DECR_WRAP: return VK_STENCIL_OP_DECREMENT_AND_WRAP;
+ // clang-format on
default:
UNEXPECTED("Unknown stencil operation");
@@ -731,41 +744,42 @@ VkStencilOpState StencilOpDescToVkStencilOpState(const StencilOpDesc& desc, Uint
{
// Stencil state (25.9)
VkStencilOpState StencilState = {};
- StencilState.failOp = StencilOpToVkStencilOp(desc.StencilFailOp);
- StencilState.passOp = StencilOpToVkStencilOp(desc.StencilPassOp);
- StencilState.depthFailOp = StencilOpToVkStencilOp(desc.StencilDepthFailOp);
- StencilState.compareOp = ComparisonFuncToVkCompareOp(desc.StencilFunc);
+ StencilState.failOp = StencilOpToVkStencilOp(desc.StencilFailOp);
+ StencilState.passOp = StencilOpToVkStencilOp(desc.StencilPassOp);
+ StencilState.depthFailOp = StencilOpToVkStencilOp(desc.StencilDepthFailOp);
+ StencilState.compareOp = ComparisonFuncToVkCompareOp(desc.StencilFunc);
// The s least significant bits of compareMask, where s is the number of bits in the stencil framebuffer attachment,
- // are bitwise ANDed with both the reference and the stored stencil value, and the resulting masked values are those
+ // are bitwise ANDed with both the reference and the stored stencil value, and the resulting masked values are those
// that participate in the comparison controlled by compareOp (25.9)
StencilState.compareMask = StencilReadMask;
- // The least significant s bits of writeMask, where s is the number of bits in the stencil framebuffer
- // attachment, specify an integer mask. Where a 1 appears in this mask, the corresponding bit in the stencil
+ // The least significant s bits of writeMask, where s is the number of bits in the stencil framebuffer
+ // attachment, specify an integer mask. Where a 1 appears in this mask, the corresponding bit in the stencil
// value in the depth / stencil attachment is written; where a 0 appears, the bit is not written (25.9)
StencilState.writeMask = StencilWriteMask;
-
+
StencilState.reference = 0; // Set dynamically
return StencilState;
}
-VkPipelineDepthStencilStateCreateInfo DepthStencilStateDesc_To_VkDepthStencilStateCI(const DepthStencilStateDesc &DepthStencilDesc)
+VkPipelineDepthStencilStateCreateInfo DepthStencilStateDesc_To_VkDepthStencilStateCI(const DepthStencilStateDesc& DepthStencilDesc)
{
// Depth-stencil state (25.7)
VkPipelineDepthStencilStateCreateInfo DSStateCI = {};
- DSStateCI.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
- DSStateCI.pNext = nullptr;
- DSStateCI.flags = 0; // reserved for future use
- DSStateCI.depthTestEnable = DepthStencilDesc.DepthEnable ? VK_TRUE : VK_FALSE;
- DSStateCI.depthWriteEnable = DepthStencilDesc.DepthWriteEnable ? VK_TRUE : VK_FALSE;
- DSStateCI.depthCompareOp = ComparisonFuncToVkCompareOp(DepthStencilDesc.DepthFunc); // 25.10
- DSStateCI.depthBoundsTestEnable = VK_FALSE; // 25.8
- DSStateCI.stencilTestEnable = DepthStencilDesc.StencilEnable ? VK_TRUE : VK_FALSE; // 25.9
- DSStateCI.front = StencilOpDescToVkStencilOpState(DepthStencilDesc.FrontFace, DepthStencilDesc.StencilReadMask, DepthStencilDesc.StencilWriteMask);
- DSStateCI.back = StencilOpDescToVkStencilOpState(DepthStencilDesc.BackFace, DepthStencilDesc.StencilReadMask, DepthStencilDesc.StencilWriteMask);
+
+ DSStateCI.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
+ DSStateCI.pNext = nullptr;
+ DSStateCI.flags = 0; // reserved for future use
+ DSStateCI.depthTestEnable = DepthStencilDesc.DepthEnable ? VK_TRUE : VK_FALSE;
+ DSStateCI.depthWriteEnable = DepthStencilDesc.DepthWriteEnable ? VK_TRUE : VK_FALSE;
+ DSStateCI.depthCompareOp = ComparisonFuncToVkCompareOp(DepthStencilDesc.DepthFunc); // 25.10
+ DSStateCI.depthBoundsTestEnable = VK_FALSE; // 25.8
+ DSStateCI.stencilTestEnable = DepthStencilDesc.StencilEnable ? VK_TRUE : VK_FALSE; // 25.9
+ DSStateCI.front = StencilOpDescToVkStencilOpState(DepthStencilDesc.FrontFace, DepthStencilDesc.StencilReadMask, DepthStencilDesc.StencilWriteMask);
+ DSStateCI.back = StencilOpDescToVkStencilOpState(DepthStencilDesc.BackFace, DepthStencilDesc.StencilReadMask, DepthStencilDesc.StencilWriteMask);
// Depth Bounds Test (25.8)
DSStateCI.minDepthBounds = 0; // must be between 0.0 and 1.0, inclusive
DSStateCI.maxDepthBounds = 1; // must be between 0.0 and 1.0, inclusive
@@ -779,26 +793,26 @@ public:
BlendFactorToVkBlendFactorMapper()
{
// 26.1.1
- m_Map[BLEND_FACTOR_ZERO] = VK_BLEND_FACTOR_ZERO;
- m_Map[BLEND_FACTOR_ONE] = VK_BLEND_FACTOR_ONE;
- m_Map[BLEND_FACTOR_SRC_COLOR] = VK_BLEND_FACTOR_SRC_COLOR;
- m_Map[BLEND_FACTOR_INV_SRC_COLOR] = VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR;
- m_Map[BLEND_FACTOR_SRC_ALPHA] = VK_BLEND_FACTOR_SRC_ALPHA;
- m_Map[BLEND_FACTOR_INV_SRC_ALPHA] = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
- m_Map[BLEND_FACTOR_DEST_ALPHA] = VK_BLEND_FACTOR_DST_ALPHA;
- m_Map[BLEND_FACTOR_INV_DEST_ALPHA] = VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA;
- m_Map[BLEND_FACTOR_DEST_COLOR] = VK_BLEND_FACTOR_DST_COLOR;
- m_Map[BLEND_FACTOR_INV_DEST_COLOR] = VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR;
- m_Map[BLEND_FACTOR_SRC_ALPHA_SAT] = VK_BLEND_FACTOR_SRC_ALPHA_SATURATE;
- m_Map[BLEND_FACTOR_BLEND_FACTOR] = VK_BLEND_FACTOR_CONSTANT_COLOR;
+ m_Map[BLEND_FACTOR_ZERO] = VK_BLEND_FACTOR_ZERO;
+ m_Map[BLEND_FACTOR_ONE] = VK_BLEND_FACTOR_ONE;
+ m_Map[BLEND_FACTOR_SRC_COLOR] = VK_BLEND_FACTOR_SRC_COLOR;
+ m_Map[BLEND_FACTOR_INV_SRC_COLOR] = VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR;
+ m_Map[BLEND_FACTOR_SRC_ALPHA] = VK_BLEND_FACTOR_SRC_ALPHA;
+ m_Map[BLEND_FACTOR_INV_SRC_ALPHA] = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
+ m_Map[BLEND_FACTOR_DEST_ALPHA] = VK_BLEND_FACTOR_DST_ALPHA;
+ m_Map[BLEND_FACTOR_INV_DEST_ALPHA] = VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA;
+ m_Map[BLEND_FACTOR_DEST_COLOR] = VK_BLEND_FACTOR_DST_COLOR;
+ m_Map[BLEND_FACTOR_INV_DEST_COLOR] = VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR;
+ m_Map[BLEND_FACTOR_SRC_ALPHA_SAT] = VK_BLEND_FACTOR_SRC_ALPHA_SATURATE;
+ m_Map[BLEND_FACTOR_BLEND_FACTOR] = VK_BLEND_FACTOR_CONSTANT_COLOR;
m_Map[BLEND_FACTOR_INV_BLEND_FACTOR] = VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR;
- m_Map[BLEND_FACTOR_SRC1_COLOR] = VK_BLEND_FACTOR_SRC1_COLOR;
- m_Map[BLEND_FACTOR_INV_SRC1_COLOR] = VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR;
- m_Map[BLEND_FACTOR_SRC1_ALPHA] = VK_BLEND_FACTOR_SRC1_ALPHA;
- m_Map[BLEND_FACTOR_INV_SRC1_ALPHA] = VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA;
+ m_Map[BLEND_FACTOR_SRC1_COLOR] = VK_BLEND_FACTOR_SRC1_COLOR;
+ m_Map[BLEND_FACTOR_INV_SRC1_COLOR] = VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR;
+ m_Map[BLEND_FACTOR_SRC1_ALPHA] = VK_BLEND_FACTOR_SRC1_ALPHA;
+ m_Map[BLEND_FACTOR_INV_SRC1_ALPHA] = VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA;
}
-
- VkBlendFactor operator[](BLEND_FACTOR bf)const
+
+ VkBlendFactor operator[](BLEND_FACTOR bf) const
{
VERIFY_EXPR(bf > BLEND_FACTOR_UNDEFINED && bf < BLEND_FACTOR_NUM_FACTORS);
return m_Map[static_cast<int>(bf)];
@@ -815,25 +829,25 @@ public:
LogicOperationToVkLogicOp()
{
// 26.2
- m_Map[ LOGIC_OP_CLEAR ] = VK_LOGIC_OP_CLEAR;
- m_Map[ LOGIC_OP_SET ] = VK_LOGIC_OP_SET;
- m_Map[ LOGIC_OP_COPY ] = VK_LOGIC_OP_COPY;
- m_Map[ LOGIC_OP_COPY_INVERTED ] = VK_LOGIC_OP_COPY_INVERTED;
- m_Map[ LOGIC_OP_NOOP ] = VK_LOGIC_OP_NO_OP;
- m_Map[ LOGIC_OP_INVERT ] = VK_LOGIC_OP_INVERT;
- m_Map[ LOGIC_OP_AND ] = VK_LOGIC_OP_AND;
- m_Map[ LOGIC_OP_NAND ] = VK_LOGIC_OP_NAND;
- m_Map[ LOGIC_OP_OR ] = VK_LOGIC_OP_OR;
- m_Map[ LOGIC_OP_NOR ] = VK_LOGIC_OP_NOR;
- m_Map[ LOGIC_OP_XOR ] = VK_LOGIC_OP_XOR;
- m_Map[ LOGIC_OP_EQUIV ] = VK_LOGIC_OP_EQUIVALENT;
- m_Map[ LOGIC_OP_AND_REVERSE ] = VK_LOGIC_OP_AND_REVERSE;
- m_Map[ LOGIC_OP_AND_INVERTED ] = VK_LOGIC_OP_AND_INVERTED;
- m_Map[ LOGIC_OP_OR_REVERSE ] = VK_LOGIC_OP_OR_REVERSE;
- m_Map[ LOGIC_OP_OR_INVERTED ] = VK_LOGIC_OP_OR_INVERTED;
+ m_Map[LOGIC_OP_CLEAR] = VK_LOGIC_OP_CLEAR;
+ m_Map[LOGIC_OP_SET] = VK_LOGIC_OP_SET;
+ m_Map[LOGIC_OP_COPY] = VK_LOGIC_OP_COPY;
+ m_Map[LOGIC_OP_COPY_INVERTED] = VK_LOGIC_OP_COPY_INVERTED;
+ m_Map[LOGIC_OP_NOOP] = VK_LOGIC_OP_NO_OP;
+ m_Map[LOGIC_OP_INVERT] = VK_LOGIC_OP_INVERT;
+ m_Map[LOGIC_OP_AND] = VK_LOGIC_OP_AND;
+ m_Map[LOGIC_OP_NAND] = VK_LOGIC_OP_NAND;
+ m_Map[LOGIC_OP_OR] = VK_LOGIC_OP_OR;
+ m_Map[LOGIC_OP_NOR] = VK_LOGIC_OP_NOR;
+ m_Map[LOGIC_OP_XOR] = VK_LOGIC_OP_XOR;
+ m_Map[LOGIC_OP_EQUIV] = VK_LOGIC_OP_EQUIVALENT;
+ m_Map[LOGIC_OP_AND_REVERSE] = VK_LOGIC_OP_AND_REVERSE;
+ m_Map[LOGIC_OP_AND_INVERTED] = VK_LOGIC_OP_AND_INVERTED;
+ m_Map[LOGIC_OP_OR_REVERSE] = VK_LOGIC_OP_OR_REVERSE;
+ m_Map[LOGIC_OP_OR_INVERTED] = VK_LOGIC_OP_OR_INVERTED;
}
- VkLogicOp operator[](LOGIC_OPERATION op)const
+ VkLogicOp operator[](LOGIC_OPERATION op) const
{
VERIFY_EXPR(op >= LOGIC_OP_CLEAR && op < LOGIC_OP_NUM_OPERATIONS);
return m_Map[static_cast<int>(op)];
@@ -849,14 +863,14 @@ public:
BlendOperationToVkBlendOp()
{
// 26.1.3
- m_Map[ BLEND_OPERATION_ADD ] = VK_BLEND_OP_ADD;
- m_Map[ BLEND_OPERATION_SUBTRACT ] = VK_BLEND_OP_SUBTRACT;
- m_Map[ BLEND_OPERATION_REV_SUBTRACT ] = VK_BLEND_OP_REVERSE_SUBTRACT;
- m_Map[ BLEND_OPERATION_MIN ] = VK_BLEND_OP_MIN;
- m_Map[ BLEND_OPERATION_MAX ] = VK_BLEND_OP_MAX;
+ m_Map[BLEND_OPERATION_ADD] = VK_BLEND_OP_ADD;
+ m_Map[BLEND_OPERATION_SUBTRACT] = VK_BLEND_OP_SUBTRACT;
+ m_Map[BLEND_OPERATION_REV_SUBTRACT] = VK_BLEND_OP_REVERSE_SUBTRACT;
+ m_Map[BLEND_OPERATION_MIN] = VK_BLEND_OP_MIN;
+ m_Map[BLEND_OPERATION_MAX] = VK_BLEND_OP_MAX;
}
- VkBlendOp operator[](BLEND_OPERATION op)const
+ VkBlendOp operator[](BLEND_OPERATION op) const
{
VERIFY_EXPR(op > BLEND_OPERATION_UNDEFINED && op < BLEND_OPERATION_NUM_OPERATIONS);
return m_Map[static_cast<int>(op)];
@@ -866,11 +880,12 @@ private:
std::array<VkBlendOp, BLEND_OPERATION_NUM_OPERATIONS> m_Map = {};
};
-VkPipelineColorBlendAttachmentState RenderTargetBlendDescToVkColorBlendAttachmentState(const RenderTargetBlendDesc &RTBlendDesc)
+VkPipelineColorBlendAttachmentState RenderTargetBlendDescToVkColorBlendAttachmentState(const RenderTargetBlendDesc& RTBlendDesc)
{
static const BlendFactorToVkBlendFactorMapper BFtoVKBF;
- static const BlendOperationToVkBlendOp BOtoVKBO;
- VkPipelineColorBlendAttachmentState AttachmentBlendState = {};
+ static const BlendOperationToVkBlendOp BOtoVKBO;
+ VkPipelineColorBlendAttachmentState AttachmentBlendState = {};
+
AttachmentBlendState.blendEnable = RTBlendDesc.BlendEnable;
AttachmentBlendState.srcColorBlendFactor = BFtoVKBF[RTBlendDesc.SrcBlend];
AttachmentBlendState.dstColorBlendFactor = BFtoVKBF[RTBlendDesc.DestBlend];
@@ -878,47 +893,47 @@ VkPipelineColorBlendAttachmentState RenderTargetBlendDescToVkColorBlendAttachmen
AttachmentBlendState.srcAlphaBlendFactor = BFtoVKBF[RTBlendDesc.SrcBlendAlpha];
AttachmentBlendState.dstAlphaBlendFactor = BFtoVKBF[RTBlendDesc.DestBlendAlpha];
AttachmentBlendState.alphaBlendOp = BOtoVKBO[RTBlendDesc.BlendOpAlpha];
- AttachmentBlendState.colorWriteMask =
- ((RTBlendDesc.RenderTargetWriteMask & COLOR_MASK_RED) ? VK_COLOR_COMPONENT_R_BIT : 0) |
+ AttachmentBlendState.colorWriteMask =
+ ((RTBlendDesc.RenderTargetWriteMask & COLOR_MASK_RED) ? VK_COLOR_COMPONENT_R_BIT : 0) |
((RTBlendDesc.RenderTargetWriteMask & COLOR_MASK_GREEN) ? VK_COLOR_COMPONENT_G_BIT : 0) |
- ((RTBlendDesc.RenderTargetWriteMask & COLOR_MASK_BLUE) ? VK_COLOR_COMPONENT_B_BIT : 0) |
+ ((RTBlendDesc.RenderTargetWriteMask & COLOR_MASK_BLUE) ? VK_COLOR_COMPONENT_B_BIT : 0) |
((RTBlendDesc.RenderTargetWriteMask & COLOR_MASK_ALPHA) ? VK_COLOR_COMPONENT_A_BIT : 0);
return AttachmentBlendState;
}
-void BlendStateDesc_To_VkBlendStateCI(const BlendStateDesc &BSDesc,
- VkPipelineColorBlendStateCreateInfo &ColorBlendStateCI,
- std::vector<VkPipelineColorBlendAttachmentState> &ColorBlendAttachments)
+void BlendStateDesc_To_VkBlendStateCI(const BlendStateDesc& BSDesc,
+ VkPipelineColorBlendStateCreateInfo& ColorBlendStateCI,
+ std::vector<VkPipelineColorBlendAttachmentState>& ColorBlendAttachments)
{
// Color blend state (26.1)
static const LogicOperationToVkLogicOp LogicOpToVkLogicOp;
- ColorBlendStateCI.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
- ColorBlendStateCI.pNext = nullptr;
- ColorBlendStateCI.flags = 0; // reserved for future use
- ColorBlendStateCI.logicOpEnable = BSDesc.RenderTargets[0].LogicOperationEnable; // 26.2
- ColorBlendStateCI.logicOp = LogicOpToVkLogicOp[BSDesc.RenderTargets[0].LogicOp];
+ ColorBlendStateCI.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
+ ColorBlendStateCI.pNext = nullptr;
+ ColorBlendStateCI.flags = 0; // reserved for future use
+ ColorBlendStateCI.logicOpEnable = BSDesc.RenderTargets[0].LogicOperationEnable; // 26.2
+ ColorBlendStateCI.logicOp = LogicOpToVkLogicOp[BSDesc.RenderTargets[0].LogicOp];
ColorBlendStateCI.blendConstants[0] = 0.f; // We use dynamic blend constants
ColorBlendStateCI.blendConstants[1] = 0.f;
ColorBlendStateCI.blendConstants[2] = 0.f;
ColorBlendStateCI.blendConstants[3] = 0.f;
// attachmentCount must equal the colorAttachmentCount for the subpass in which this pipeline is used.
- for(uint32_t attachment = 0; attachment < ColorBlendStateCI.attachmentCount; ++attachment)
+ for (uint32_t attachment = 0; attachment < ColorBlendStateCI.attachmentCount; ++attachment)
{
- const auto& RTBlendState = BSDesc.IndependentBlendEnable ? BSDesc.RenderTargets[attachment] : BSDesc.RenderTargets[0];
+ const auto& RTBlendState = BSDesc.IndependentBlendEnable ? BSDesc.RenderTargets[attachment] : BSDesc.RenderTargets[0];
ColorBlendAttachments[attachment] = RenderTargetBlendDescToVkColorBlendAttachmentState(RTBlendState);
}
}
VkVertexInputRate LayoutElemFrequencyToVkInputRate(LayoutElement::FREQUENCY frequency)
{
- switch(frequency)
+ switch (frequency)
{
- case LayoutElement::FREQUENCY_UNDEFINED:
+ case LayoutElement::FREQUENCY_UNDEFINED:
UNEXPECTED("Undefined layout element frequency");
return VK_VERTEX_INPUT_RATE_VERTEX;
-
- case LayoutElement::FREQUENCY_PER_VERTEX: return VK_VERTEX_INPUT_RATE_VERTEX;
+
+ case LayoutElement::FREQUENCY_PER_VERTEX: return VK_VERTEX_INPUT_RATE_VERTEX;
case LayoutElement::FREQUENCY_PER_INSTANCE: return VK_VERTEX_INPUT_RATE_INSTANCE;
default:
@@ -927,56 +942,56 @@ VkVertexInputRate LayoutElemFrequencyToVkInputRate(LayoutElement::FREQUENCY freq
}
}
-void InputLayoutDesc_To_VkVertexInputStateCI(const InputLayoutDesc& LayoutDesc,
- VkPipelineVertexInputStateCreateInfo &VertexInputStateCI,
- std::array<VkVertexInputBindingDescription, iMaxLayoutElements>& BindingDescriptions,
+void InputLayoutDesc_To_VkVertexInputStateCI(const InputLayoutDesc& LayoutDesc,
+ VkPipelineVertexInputStateCreateInfo& VertexInputStateCI,
+ std::array<VkVertexInputBindingDescription, iMaxLayoutElements>& BindingDescriptions,
std::array<VkVertexInputAttributeDescription, iMaxLayoutElements>& AttributeDescription)
{
// Vertex input description (20.2)
- VertexInputStateCI.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
- VertexInputStateCI.pNext = nullptr;
- VertexInputStateCI.flags = 0; // reserved for future use.
- VertexInputStateCI.vertexBindingDescriptionCount = 0;
- VertexInputStateCI.pVertexBindingDescriptions = BindingDescriptions.data();
+ VertexInputStateCI.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
+ VertexInputStateCI.pNext = nullptr;
+ VertexInputStateCI.flags = 0; // reserved for future use.
+ VertexInputStateCI.vertexBindingDescriptionCount = 0;
+ VertexInputStateCI.pVertexBindingDescriptions = BindingDescriptions.data();
VertexInputStateCI.vertexAttributeDescriptionCount = LayoutDesc.NumElements;
- VertexInputStateCI.pVertexAttributeDescriptions = AttributeDescription.data();
+ VertexInputStateCI.pVertexAttributeDescriptions = AttributeDescription.data();
std::array<Int32, iMaxLayoutElements> BufferSlot2BindingDescInd;
BufferSlot2BindingDescInd.fill(-1);
- for(Uint32 elem=0; elem < LayoutDesc.NumElements; ++elem)
+ for (Uint32 elem = 0; elem < LayoutDesc.NumElements; ++elem)
{
- auto &LayoutElem = LayoutDesc.LayoutElements[elem];
- auto &BindingDescInd = BufferSlot2BindingDescInd[LayoutElem.BufferSlot];
- if(BindingDescInd < 0)
+ auto& LayoutElem = LayoutDesc.LayoutElements[elem];
+ auto& BindingDescInd = BufferSlot2BindingDescInd[LayoutElem.BufferSlot];
+ if (BindingDescInd < 0)
{
- BindingDescInd = VertexInputStateCI.vertexBindingDescriptionCount++;
- auto &BindingDesc = BindingDescriptions[BindingDescInd];
- BindingDesc.binding = LayoutElem.BufferSlot;
- BindingDesc.stride = LayoutElem.Stride;
+ BindingDescInd = VertexInputStateCI.vertexBindingDescriptionCount++;
+ auto& BindingDesc = BindingDescriptions[BindingDescInd];
+ BindingDesc.binding = LayoutElem.BufferSlot;
+ BindingDesc.stride = LayoutElem.Stride;
BindingDesc.inputRate = LayoutElemFrequencyToVkInputRate(LayoutElem.Frequency);
}
- const auto &BindingDesc = BindingDescriptions[BindingDescInd];
+ const auto& BindingDesc = BindingDescriptions[BindingDescInd];
VERIFY(BindingDesc.binding == LayoutElem.BufferSlot, "Inconsistent buffer slot");
VERIFY(BindingDesc.stride == LayoutElem.Stride, "Inconsistent strides");
VERIFY(BindingDesc.inputRate == LayoutElemFrequencyToVkInputRate(LayoutElem.Frequency), "Incosistent layout element frequency");
- auto &AttribDesc = AttributeDescription[elem];
- AttribDesc.binding = BindingDesc.binding;
+ auto& AttribDesc = AttributeDescription[elem];
+ AttribDesc.binding = BindingDesc.binding;
AttribDesc.location = LayoutElem.InputIndex;
- AttribDesc.format = TypeToVkFormat(LayoutElem.ValueType, LayoutElem.NumComponents, LayoutElem.IsNormalized);
- AttribDesc.offset = LayoutElem.RelativeOffset;
+ AttribDesc.format = TypeToVkFormat(LayoutElem.ValueType, LayoutElem.NumComponents, LayoutElem.IsNormalized);
+ AttribDesc.offset = LayoutElem.RelativeOffset;
}
}
-void PrimitiveTopology_To_VkPrimitiveTopologyAndPatchCPCount(PRIMITIVE_TOPOLOGY PrimTopology,
- VkPrimitiveTopology &VkPrimTopology,
- uint32_t &PatchControlPoints)
+void PrimitiveTopology_To_VkPrimitiveTopologyAndPatchCPCount(PRIMITIVE_TOPOLOGY PrimTopology,
+ VkPrimitiveTopology& VkPrimTopology,
+ uint32_t& PatchControlPoints)
{
PatchControlPoints = 0;
- switch(PrimTopology)
+ switch (PrimTopology)
{
- case PRIMITIVE_TOPOLOGY_UNDEFINED:
- UNEXPECTED("Undefined primitive topology");
+ case PRIMITIVE_TOPOLOGY_UNDEFINED:
+ UNEXPECTED("Undefined primitive topology");
VkPrimTopology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
return;
@@ -998,7 +1013,7 @@ void PrimitiveTopology_To_VkPrimitiveTopologyAndPatchCPCount(PRIMITIVE_TOPOLOGY
default:
VERIFY_EXPR(PrimTopology >= PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST && PrimTopology < PRIMITIVE_TOPOLOGY_NUM_TOPOLOGIES);
- VkPrimTopology = VK_PRIMITIVE_TOPOLOGY_PATCH_LIST;
+ VkPrimTopology = VK_PRIMITIVE_TOPOLOGY_PATCH_LIST;
PatchControlPoints = static_cast<uint32_t>(PrimTopology) - static_cast<uint32_t>(PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST) + 1;
return;
}
@@ -1006,9 +1021,9 @@ void PrimitiveTopology_To_VkPrimitiveTopologyAndPatchCPCount(PRIMITIVE_TOPOLOGY
VkFilter FilterTypeToVkFilter(FILTER_TYPE FilterType)
{
- switch(FilterType)
+ switch (FilterType)
{
- case FILTER_TYPE_UNKNOWN:
+ case FILTER_TYPE_UNKNOWN:
UNEXPECTED("Unknown filter type");
return VK_FILTER_NEAREST;
@@ -1024,7 +1039,7 @@ VkFilter FilterTypeToVkFilter(FILTER_TYPE FilterType)
case FILTER_TYPE_COMPARISON_ANISOTROPIC:
case FILTER_TYPE_MINIMUM_LINEAR:
case FILTER_TYPE_MINIMUM_ANISOTROPIC:
- case FILTER_TYPE_MAXIMUM_LINEAR:
+ case FILTER_TYPE_MAXIMUM_LINEAR:
case FILTER_TYPE_MAXIMUM_ANISOTROPIC:
return VK_FILTER_LINEAR;
@@ -1066,17 +1081,19 @@ VkSamplerMipmapMode FilterTypeToVkMipmapMode(FILTER_TYPE FilterType)
VkSamplerAddressMode AddressModeToVkAddressMode(TEXTURE_ADDRESS_MODE AddressMode)
{
- switch(AddressMode)
+ switch (AddressMode)
{
case TEXTURE_ADDRESS_UNKNOWN:
UNEXPECTED("Unknown address mode");
return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
+ // clang-format off
case TEXTURE_ADDRESS_WRAP: return VK_SAMPLER_ADDRESS_MODE_REPEAT;
case TEXTURE_ADDRESS_MIRROR: return VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT;
case TEXTURE_ADDRESS_CLAMP: return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
case TEXTURE_ADDRESS_BORDER: return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
case TEXTURE_ADDRESS_MIRROR_ONCE: return VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE;
+ // clang-format on
default:
UNEXPECTED("Unexpected address mode");
@@ -1121,9 +1138,10 @@ static VkAccessFlags ResourceStateFlagToVkAccessFlags(RESOURCE_STATE StateFlag)
//VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_NVX
static_assert(RESOURCE_STATE_MAX_BIT == 0x8000, "This function must be updated to handle new resource state flag");
- VERIFY((StateFlag & (StateFlag-1)) == 0, "Only single bit must be set");
- switch(StateFlag)
+ VERIFY((StateFlag & (StateFlag - 1)) == 0, "Only single bit must be set");
+ switch (StateFlag)
{
+ // clang-format off
case RESOURCE_STATE_UNDEFINED: return 0;
case RESOURCE_STATE_VERTEX_BUFFER: return VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT;
case RESOURCE_STATE_CONSTANT_BUFFER: return VK_ACCESS_UNIFORM_READ_BIT;
@@ -1140,6 +1158,7 @@ static VkAccessFlags ResourceStateFlagToVkAccessFlags(RESOURCE_STATE StateFlag)
case RESOURCE_STATE_RESOLVE_DEST: return VK_ACCESS_MEMORY_READ_BIT;
case RESOURCE_STATE_RESOLVE_SOURCE: return VK_ACCESS_MEMORY_WRITE_BIT;
case RESOURCE_STATE_PRESENT: return VK_ACCESS_MEMORY_READ_BIT;
+ // clang-format on
default:
UNEXPECTED("Unexpected resource state flag");
@@ -1152,46 +1171,48 @@ class StateFlagBitPosToVkAccessFlags
public:
StateFlagBitPosToVkAccessFlags()
{
- static_assert( (1 << MaxFlagBitPos) == RESOURCE_STATE_MAX_BIT, "This function must be updated to handle new resource state flag");
- for (Uint32 bit=0; bit < MaxFlagBitPos; ++bit)
+ static_assert((1 << MaxFlagBitPos) == RESOURCE_STATE_MAX_BIT, "This function must be updated to handle new resource state flag");
+ for (Uint32 bit = 0; bit < MaxFlagBitPos; ++bit)
{
- FlagBitPosToVkAccessFlagsMap[bit] = ResourceStateFlagToVkAccessFlags(static_cast<RESOURCE_STATE>(1<<bit));
+ FlagBitPosToVkAccessFlagsMap[bit] = ResourceStateFlagToVkAccessFlags(static_cast<RESOURCE_STATE>(1 << bit));
}
}
- VkAccessFlags operator()(Uint32 BitPos)const
+ VkAccessFlags operator()(Uint32 BitPos) const
{
VERIFY(BitPos <= MaxFlagBitPos, "Resource state flag bit position (", BitPos, ") exceeds max bit position (", Uint32{MaxFlagBitPos}, ")");
return FlagBitPosToVkAccessFlagsMap[BitPos];
}
private:
- static constexpr const Uint32 MaxFlagBitPos = 15;
+ static constexpr const Uint32 MaxFlagBitPos = 15;
std::array<VkAccessFlags, MaxFlagBitPos + 1> FlagBitPosToVkAccessFlagsMap;
};
VkAccessFlags ResourceStateFlagsToVkAccessFlags(RESOURCE_STATE StateFlags)
{
- VERIFY(Uint32{StateFlags} < (RESOURCE_STATE_MAX_BIT<<1), "Resource state flags are out of range");
+ VERIFY(Uint32{StateFlags} < (RESOURCE_STATE_MAX_BIT << 1), "Resource state flags are out of range");
static const StateFlagBitPosToVkAccessFlags BitPosToAccessFlags;
+
VkAccessFlags AccessFlags = 0;
- Uint32 Bits = StateFlags;
- while(Bits != 0)
+ Uint32 Bits = StateFlags;
+ while (Bits != 0)
{
auto lsb = PlatformMisc::GetLSB(Bits);
AccessFlags |= BitPosToAccessFlags(lsb);
- Bits &= ~(1<<lsb);
+ Bits &= ~(1 << lsb);
}
return AccessFlags;
}
RESOURCE_STATE VkAccessFlagsToResourceStates(VkAccessFlagBits AccessFlagBit)
{
- VERIFY((AccessFlagBit & (AccessFlagBit-1)) == 0, "Single access flag bit is expected");
+ VERIFY((AccessFlagBit & (AccessFlagBit - 1)) == 0, "Single access flag bit is expected");
- switch(AccessFlagBit)
+ switch (AccessFlagBit)
{
+ // clang-format off
case VK_ACCESS_INDIRECT_COMMAND_READ_BIT: return RESOURCE_STATE_INDIRECT_ARGUMENT;
case VK_ACCESS_INDEX_READ_BIT: return RESOURCE_STATE_INDEX_BUFFER;
case VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT: return RESOURCE_STATE_VERTEX_BUFFER;
@@ -1219,7 +1240,8 @@ RESOURCE_STATE VkAccessFlagsToResourceStates(VkAccessFlagBits AccessFlagBit)
case VK_ACCESS_SHADING_RATE_IMAGE_READ_BIT_NV: return RESOURCE_STATE_UNKNOWN;
case VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_NVX: return RESOURCE_STATE_UNKNOWN;
case VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_NVX: return RESOURCE_STATE_UNKNOWN;
- default:
+ // clang-format on
+ default:
UNEXPECTED("Unknown access flag");
return RESOURCE_STATE_UNKNOWN;
}
@@ -1231,20 +1253,20 @@ class VkAccessFlagBitPosToResourceState
public:
VkAccessFlagBitPosToResourceState()
{
- for (Uint32 bit=0; bit < MaxFlagBitPos; ++bit)
+ for (Uint32 bit = 0; bit < MaxFlagBitPos; ++bit)
{
- FlagBitPosToResourceState[bit] = VkAccessFlagsToResourceStates(static_cast<VkAccessFlagBits>(1<<bit));
+ FlagBitPosToResourceState[bit] = VkAccessFlagsToResourceStates(static_cast<VkAccessFlagBits>(1 << bit));
}
}
- RESOURCE_STATE operator()(Uint32 BitPos)const
+ RESOURCE_STATE operator()(Uint32 BitPos) const
{
VERIFY(BitPos <= MaxFlagBitPos, "Resource state flag bit position (", BitPos, ") exceeds max bit position (", Uint32{MaxFlagBitPos}, ")");
return FlagBitPosToResourceState[BitPos];
}
private:
- static constexpr const Uint32 MaxFlagBitPos = 20;
+ static constexpr const Uint32 MaxFlagBitPos = 20;
std::array<RESOURCE_STATE, MaxFlagBitPos + 1> FlagBitPosToResourceState;
};
@@ -1252,12 +1274,12 @@ private:
RESOURCE_STATE VkAccessFlagsToResourceStates(VkAccessFlags AccessFlags)
{
static const VkAccessFlagBitPosToResourceState BitPosToState;
- Uint32 State = 0;
+ Uint32 State = 0;
while (AccessFlags != 0)
{
auto lsb = PlatformMisc::GetLSB(AccessFlags);
State |= BitPosToState(lsb);
- AccessFlags &= ~(1<<lsb);
+ AccessFlags &= ~(1 << lsb);
}
return static_cast<RESOURCE_STATE>(State);
}
@@ -1266,7 +1288,7 @@ RESOURCE_STATE VkAccessFlagsToResourceStates(VkAccessFlags AccessFlags)
VkImageLayout ResourceStateToVkImageLayout(RESOURCE_STATE StateFlag)
{
- if(StateFlag == RESOURCE_STATE_UNKNOWN)
+ if (StateFlag == RESOURCE_STATE_UNKNOWN)
{
return VK_IMAGE_LAYOUT_UNDEFINED;
}
@@ -1278,9 +1300,10 @@ VkImageLayout ResourceStateToVkImageLayout(RESOURCE_STATE StateFlag)
//VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL_KHR = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL,
static_assert(RESOURCE_STATE_MAX_BIT == 0x8000, "This function must be updated to handle new resource state flag");
- VERIFY((StateFlag & (StateFlag-1)) == 0, "Only single bit must be set");
- switch(StateFlag)
+ VERIFY((StateFlag & (StateFlag - 1)) == 0, "Only single bit must be set");
+ switch (StateFlag)
{
+ // clang-format off
case RESOURCE_STATE_UNDEFINED: return VK_IMAGE_LAYOUT_UNDEFINED;
case RESOURCE_STATE_VERTEX_BUFFER: UNEXPECTED("Invalid resource state"); return VK_IMAGE_LAYOUT_UNDEFINED;
case RESOURCE_STATE_CONSTANT_BUFFER: UNEXPECTED("Invalid resource state"); return VK_IMAGE_LAYOUT_UNDEFINED;
@@ -1297,6 +1320,7 @@ VkImageLayout ResourceStateToVkImageLayout(RESOURCE_STATE StateFlag)
case RESOURCE_STATE_RESOLVE_DEST: return VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
case RESOURCE_STATE_RESOLVE_SOURCE: return VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
case RESOURCE_STATE_PRESENT: return VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
+ // clang-format on
default:
UNEXPECTED("Unexpected resource state flag (", StateFlag, ")");
@@ -1307,8 +1331,9 @@ VkImageLayout ResourceStateToVkImageLayout(RESOURCE_STATE StateFlag)
RESOURCE_STATE VkImageLayoutToResourceState(VkImageLayout Layout)
{
static_assert(RESOURCE_STATE_MAX_BIT == 0x8000, "This function must be updated to handle new resource state flag");
- switch(Layout)
+ switch (Layout)
{
+ // clang-format off
case VK_IMAGE_LAYOUT_UNDEFINED: return RESOURCE_STATE_UNDEFINED;
case VK_IMAGE_LAYOUT_GENERAL: return RESOURCE_STATE_UNORDERED_ACCESS;
case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: return RESOURCE_STATE_RENDER_TARGET;
@@ -1326,7 +1351,8 @@ RESOURCE_STATE VkImageLayoutToResourceState(VkImageLayout Layout)
default:
UNEXPECTED("Unknown image layout (", Layout, ")");
return RESOURCE_STATE_UNDEFINED;
+ // clang-format on
}
}
-}
+} // namespace Diligent
diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUploadHeap.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUploadHeap.cpp
index b1858405..0316ec05 100644
--- a/Graphics/GraphicsEngineVulkan/src/VulkanUploadHeap.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/VulkanUploadHeap.cpp
@@ -31,9 +31,11 @@ namespace Diligent
VulkanUploadHeap::VulkanUploadHeap(RenderDeviceVkImpl& RenderDevice,
std::string HeapName,
VkDeviceSize PageSize) :
+ // clang-format off
m_RenderDevice {RenderDevice },
m_HeapName {std::move(HeapName)},
m_PageSize {PageSize }
+// clang-format on
{
}
@@ -41,13 +43,15 @@ VulkanUploadHeap::~VulkanUploadHeap()
{
DEV_CHECK_ERR(m_Pages.empty(), "Upload heap '", m_HeapName, "' not all pages are released");
auto PeakAllocatedPages = m_PeakAllocatedSize / m_PageSize;
- LOG_INFO_MESSAGE(m_HeapName, " peak used/allocated frame size: ", FormatMemorySize(m_PeakFrameSize, 2, m_PeakAllocatedSize), " / ", FormatMemorySize(m_PeakAllocatedSize, 2),
- " (", PeakAllocatedPages, (PeakAllocatedPages == 1 ? " page)" : " pages)") );
+ LOG_INFO_MESSAGE(m_HeapName, " peak used/allocated frame size: ", FormatMemorySize(m_PeakFrameSize, 2, m_PeakAllocatedSize),
+ " / ", FormatMemorySize(m_PeakAllocatedSize, 2),
+ " (", PeakAllocatedPages, (PeakAllocatedPages == 1 ? " page)" : " pages)"));
}
-VulkanUploadHeap::UploadPageInfo VulkanUploadHeap::CreateNewPage(VkDeviceSize SizeInBytes)const
+VulkanUploadHeap::UploadPageInfo VulkanUploadHeap::CreateNewPage(VkDeviceSize SizeInBytes) const
{
VkBufferCreateInfo StagingBufferCI = {};
+
StagingBufferCI.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
StagingBufferCI.pNext = nullptr;
StagingBufferCI.flags = 0; // VK_BUFFER_CREATE_SPARSE_BINDING_BIT, VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT, VK_BUFFER_CREATE_SPARSE_ALIASED_BIT
@@ -57,25 +61,26 @@ VulkanUploadHeap::UploadPageInfo VulkanUploadHeap::CreateNewPage(VkDeviceSize Si
StagingBufferCI.queueFamilyIndexCount = 0;
StagingBufferCI.pQueueFamilyIndices = nullptr;
- const auto& LogicalDevice = m_RenderDevice.GetLogicalDevice();
- const auto& PhysicalDevice = m_RenderDevice.GetPhysicalDevice();
- auto& GlobalMemoryMgr = m_RenderDevice.GetGlobalMemoryManager();
+ const auto& LogicalDevice = m_RenderDevice.GetLogicalDevice();
+ const auto& PhysicalDevice = m_RenderDevice.GetPhysicalDevice();
+ auto& GlobalMemoryMgr = m_RenderDevice.GetGlobalMemoryManager();
- auto NewBuffer = LogicalDevice.CreateBuffer(StagingBufferCI, "Upload buffer");
- auto MemReqs = LogicalDevice.GetBufferMemoryRequirements(NewBuffer);
+ auto NewBuffer = LogicalDevice.CreateBuffer(StagingBufferCI, "Upload buffer");
+ auto MemReqs = LogicalDevice.GetBufferMemoryRequirements(NewBuffer);
auto MemoryTypeIndex = PhysicalDevice.GetMemoryTypeIndex(MemReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
DEV_CHECK_ERR(MemoryTypeIndex != VulkanUtilities::VulkanPhysicalDevice::InvalidMemoryTypeIndex,
- "Vulkan spec requires that for a VkBuffer not created with the VK_BUFFER_CREATE_SPARSE_BINDING_BIT "
- "bit set, or for a VkImage that was created with a VK_IMAGE_TILING_LINEAR value in the tiling member "
- "of the VkImageCreateInfo structure passed to vkCreateImage, the memoryTypeBits member always contains "
- "at least one bit set corresponding to a VkMemoryType with a propertyFlags that has both the "
- "VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT bit AND the VK_MEMORY_PROPERTY_HOST_COHERENT_BIT bit set. (11.6)");
+ "Vulkan spec requires that for a VkBuffer not created with the VK_BUFFER_CREATE_SPARSE_BINDING_BIT "
+ "bit set, or for a VkImage that was created with a VK_IMAGE_TILING_LINEAR value in the tiling member "
+ "of the VkImageCreateInfo structure passed to vkCreateImage, the memoryTypeBits member always contains "
+ "at least one bit set corresponding to a VkMemoryType with a propertyFlags that has both the "
+ "VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT bit AND the VK_MEMORY_PROPERTY_HOST_COHERENT_BIT bit set. (11.6)");
auto MemAllocation = GlobalMemoryMgr.Allocate(MemReqs.size, MemReqs.alignment, MemoryTypeIndex, true);
- auto AlignedOffset = (MemAllocation.UnalignedOffset + (MemReqs.alignment-1)) & ~(MemReqs.alignment-1);
- auto err = LogicalDevice.BindBufferMemory(NewBuffer, MemAllocation.Page->GetVkMemory(), AlignedOffset);
- DEV_CHECK_ERR(err == VK_SUCCESS, "Failed to bind buffer memory"); (void)err;
+ auto AlignedOffset = (MemAllocation.UnalignedOffset + (MemReqs.alignment - 1)) & ~(MemReqs.alignment - 1);
+ auto err = LogicalDevice.BindBufferMemory(NewBuffer, MemAllocation.Page->GetVkMemory(), AlignedOffset);
+ DEV_CHECK_ERR(err == VK_SUCCESS, "Failed to bind buffer memory");
+ (void)err;
auto CPUAddress = reinterpret_cast<Uint8*>(MemAllocation.Page->GetCPUMemory()) + AlignedOffset;
return UploadPageInfo{std::move(MemAllocation), std::move(NewBuffer), CPUAddress};
@@ -86,34 +91,34 @@ VulkanUploadAllocation VulkanUploadHeap::Allocate(size_t SizeInBytes, size_t Ali
VERIFY(IsPowerOfTwo(Alignment), "Alignment (", Alignment, ") must be power of two");
VulkanUploadAllocation Allocation;
- if(SizeInBytes >= m_PageSize/2)
+ if (SizeInBytes >= m_PageSize / 2)
{
// Allocate large chunk directly from the memory manager
- auto NewPage = CreateNewPage(SizeInBytes);
+ auto NewPage = CreateNewPage(SizeInBytes);
Allocation.vkBuffer = NewPage.Buffer;
Allocation.CPUAddress = NewPage.CPUAddress;
Allocation.Size = SizeInBytes;
VERIFY(Alignment < SizeInBytes, "Alignment must be smaller than the page size");
Allocation.AlignedOffset = 0;
- m_CurrAllocatedSize += NewPage.MemAllocation.Size;
+ m_CurrAllocatedSize += NewPage.MemAllocation.Size;
m_Pages.emplace_back(std::move(NewPage));
}
else
{
auto AlignmentOffset = Align(m_CurrPage.CurrOffset, Alignment) - m_CurrPage.CurrOffset;
- if(m_CurrPage.AvailableSize < SizeInBytes + AlignmentOffset)
+ if (m_CurrPage.AvailableSize < SizeInBytes + AlignmentOffset)
{
// Allocate new page
auto NewPage = CreateNewPage(m_PageSize);
m_CurrPage.Reset(NewPage, m_PageSize);
m_CurrAllocatedSize += NewPage.MemAllocation.Size;
m_Pages.emplace_back(std::move(NewPage));
- VERIFY_EXPR((m_CurrPage.CurrOffset & (Alignment-1)) == 0);
+ VERIFY_EXPR((m_CurrPage.CurrOffset & (Alignment - 1)) == 0);
AlignmentOffset = 0;
}
m_CurrPage.Advance(AlignmentOffset);
- VERIFY_EXPR((m_CurrPage.CurrOffset & (Alignment-1)) == 0);
+ VERIFY_EXPR((m_CurrPage.CurrOffset & (Alignment - 1)) == 0);
Allocation.vkBuffer = m_CurrPage.vkBuffer;
Allocation.CPUAddress = m_CurrPage.CurrCPUAddress;
Allocation.Size = SizeInBytes;
@@ -124,7 +129,7 @@ VulkanUploadAllocation VulkanUploadHeap::Allocate(size_t SizeInBytes, size_t Ali
m_PeakFrameSize = std::max(m_CurrFrameSize, m_PeakFrameSize);
m_PeakAllocatedSize = std::max(m_CurrAllocatedSize, m_PeakAllocatedSize);
- VERIFY_EXPR((Allocation.AlignedOffset & (Alignment-1)) == 0);
+ VERIFY_EXPR((Allocation.AlignedOffset & (Alignment - 1)) == 0);
return Allocation;
}
@@ -135,14 +140,14 @@ void VulkanUploadHeap::ReleaseAllocatedPages(Uint64 CmdQueueMask)
for (auto& Page : m_Pages)
{
m_RenderDevice.SafeReleaseDeviceObject(std::move(Page.MemAllocation), CmdQueueMask);
- m_RenderDevice.SafeReleaseDeviceObject(std::move(Page.Buffer), CmdQueueMask);
+ m_RenderDevice.SafeReleaseDeviceObject(std::move(Page.Buffer), CmdQueueMask);
}
m_Pages.clear();
- m_CurrPage = CurrPageInfo{};
+ m_CurrPage = CurrPageInfo{};
m_CurrFrameSize = 0;
m_CurrAllocatedSize = 0;
}
-}
+} // namespace Diligent
diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanCommandBuffer.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanCommandBuffer.cpp
index 7e842c7a..49602446 100644
--- a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanCommandBuffer.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanCommandBuffer.cpp
@@ -27,7 +27,7 @@
namespace VulkanUtilities
{
-static VkPipelineStageFlags PipelineStageFromAccessFlags( VkAccessFlags AccessFlags,
+static VkPipelineStageFlags PipelineStageFromAccessFlags(VkAccessFlags AccessFlags,
const VkPipelineStageFlags EnabledGraphicsShaderStages)
{
// 6.1.3
@@ -35,11 +35,11 @@ static VkPipelineStageFlags PipelineStageFromAccessFlags( VkAccessFlags
while (AccessFlags != 0)
{
- VkAccessFlagBits AccessFlag = static_cast<VkAccessFlagBits>( AccessFlags & (~(AccessFlags-1)));
- VERIFY_EXPR( AccessFlag != 0 && (AccessFlag & (AccessFlag-1)) == 0 );
+ VkAccessFlagBits AccessFlag = static_cast<VkAccessFlagBits>(AccessFlags & (~(AccessFlags - 1)));
+ VERIFY_EXPR(AccessFlag != 0 && (AccessFlag & (AccessFlag - 1)) == 0);
AccessFlags &= ~AccessFlag;
- // An application MUST NOT specify an access flag in a synchronization command if it does not include a
+ // An application MUST NOT specify an access flag in a synchronization command if it does not include a
// pipeline stage in the corresponding stage mask that is able to perform accesses of that type.
// A table that lists, for each access flag, which pipeline stages can perform that type of access is given in 6.1.3.
switch (AccessFlag)
@@ -47,88 +47,88 @@ static VkPipelineStageFlags PipelineStageFromAccessFlags( VkAccessFlags
// Read access to an indirect command structure read as part of an indirect drawing or dispatch command
case VK_ACCESS_INDIRECT_COMMAND_READ_BIT:
Stages |= VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT;
- break;
+ break;
// Read access to an index buffer as part of an indexed drawing command, bound by vkCmdBindIndexBuffer
case VK_ACCESS_INDEX_READ_BIT:
Stages |= VK_PIPELINE_STAGE_VERTEX_INPUT_BIT;
- break;
+ break;
// Read access to a vertex buffer as part of a drawing command, bound by vkCmdBindVertexBuffers
case VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT:
Stages |= VK_PIPELINE_STAGE_VERTEX_INPUT_BIT;
- break;
+ break;
// Read access to a uniform buffer
case VK_ACCESS_UNIFORM_READ_BIT:
Stages |= EnabledGraphicsShaderStages | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
- break;
+ break;
// Read access to an input attachment within a render pass during fragment shading
case VK_ACCESS_INPUT_ATTACHMENT_READ_BIT:
Stages |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
- break;
+ break;
// Read access to a storage buffer, uniform texel buffer, storage texel buffer, sampled image, or storage image
case VK_ACCESS_SHADER_READ_BIT:
Stages |= EnabledGraphicsShaderStages | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
- break;
+ break;
// Write access to a storage buffer, storage texel buffer, or storage image
case VK_ACCESS_SHADER_WRITE_BIT:
Stages |= EnabledGraphicsShaderStages | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
- break;
+ break;
// Read access to a color attachment, such as via blending, logic operations, or via certain subpass load operations
case VK_ACCESS_COLOR_ATTACHMENT_READ_BIT:
Stages |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
- break;
+ break;
// Write access to a color or resolve attachment during a render pass or via certain subpass load and store operations
case VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT:
Stages |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
- break;
+ break;
// Read access to a depth/stencil attachment, via depth or stencil operations or via certain subpass load operations
case VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT:
Stages |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
- break;
+ break;
// Write access to a depth/stencil attachment, via depth or stencil operations or via certain subpass load and store operations
case VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT:
Stages |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
- break;
+ break;
// Read access to an image or buffer in a copy operation
case VK_ACCESS_TRANSFER_READ_BIT:
Stages |= VK_PIPELINE_STAGE_TRANSFER_BIT;
- break;
+ break;
// Write access to an image or buffer in a clear or copy operation
case VK_ACCESS_TRANSFER_WRITE_BIT:
Stages |= VK_PIPELINE_STAGE_TRANSFER_BIT;
- break;
+ break;
// Read access by a host operation. Accesses of this type are not performed through a resource, but directly on memory
case VK_ACCESS_HOST_READ_BIT:
Stages |= VK_PIPELINE_STAGE_HOST_BIT;
- break;
+ break;
// Write access by a host operation. Accesses of this type are not performed through a resource, but directly on memory
case VK_ACCESS_HOST_WRITE_BIT:
Stages |= VK_PIPELINE_STAGE_HOST_BIT;
- break;
+ break;
- // Read access via non-specific entities. When included in a destination access mask, makes all available writes
+ // Read access via non-specific entities. When included in a destination access mask, makes all available writes
// visible to all future read accesses on entities known to the Vulkan device
case VK_ACCESS_MEMORY_READ_BIT:
- break;
+ break;
- // Write access via non-specific entities. hen included in a source access mask, all writes that are performed
- // by entities known to the Vulkan device are made available. When included in a destination access mask, makes
+ // Write access via non-specific entities. hen included in a source access mask, all writes that are performed
+ // by entities known to the Vulkan device are made available. When included in a destination access mask, makes
// all available writes visible to all future write accesses on entities known to the Vulkan device.
case VK_ACCESS_MEMORY_WRITE_BIT:
- break;
+ break;
default:
UNEXPECTED("Unknown memory access flag");
@@ -141,59 +141,59 @@ static VkPipelineStageFlags PipelineStageFromAccessFlags( VkAccessFlags
static VkPipelineStageFlags AccessMaskFromImageLayout(VkImageLayout Layout,
bool IsDstMask // false - source mask
// true - destination mask
- )
+)
{
VkPipelineStageFlags AccessMask = 0;
- switch (Layout)
+ switch (Layout)
{
- // does not support device access. This layout must only be used as the initialLayout member
- // of VkImageCreateInfo or VkAttachmentDescription, or as the oldLayout in an image transition.
+ // does not support device access. This layout must only be used as the initialLayout member
+ // of VkImageCreateInfo or VkAttachmentDescription, or as the oldLayout in an image transition.
// When transitioning out of this layout, the contents of the memory are not guaranteed to be preserved (11.4)
case VK_IMAGE_LAYOUT_UNDEFINED:
if (IsDstMask)
{
UNEXPECTED("The new layout used in a transition must not be VK_IMAGE_LAYOUT_UNDEFINED. "
- "This layout must only be used as the initialLayout member of VkImageCreateInfo "
+ "This layout must only be used as the initialLayout member of VkImageCreateInfo "
"or VkAttachmentDescription, or as the oldLayout in an image transition. (11.4)");
}
- break;
+ break;
// supports all types of device access
case VK_IMAGE_LAYOUT_GENERAL:
// VK_IMAGE_LAYOUT_GENERAL must be used for image load/store operations (13.1.1, 13.2.4)
AccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
- break;
+ break;
// must only be used as a color or resolve attachment in a VkFramebuffer (11.4)
case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
AccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
- break;
+ break;
// must only be used as a depth/stencil attachment in a VkFramebuffer (11.4)
case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
AccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
- break;
+ break;
// must only be used as a read-only depth/stencil attachment in a VkFramebuffer and/or as a read-only image in a shader (11.4)
case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL:
AccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
- break;
+ break;
- // must only be used as a read-only image in a shader (which can be read as a sampled image,
+ // must only be used as a read-only image in a shader (which can be read as a sampled image,
// combined image/sampler and/or input attachment) (11.4)
case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
AccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
- break;
+ break;
// must only be used as a source image of a transfer command (11.4)
case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
AccessMask = VK_ACCESS_TRANSFER_READ_BIT;
- break;
+ break;
// must only be used as a destination image of a transfer command (11.4)
case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
AccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
- break;
+ break;
// does not support device access. This layout must only be used as the initialLayout member
// of VkImageCreateInfo or VkAttachmentDescription, or as the oldLayout in an image transition.
@@ -205,27 +205,27 @@ static VkPipelineStageFlags AccessMaskFromImageLayout(VkImageLayout Layout,
}
else
{
- UNEXPECTED("The new layout used in a transition must not be VK_IMAGE_LAYOUT_PREINITIALIZED. "
- "This layout must only be used as the initialLayout member of VkImageCreateInfo "
+ UNEXPECTED("The new layout used in a transition must not be VK_IMAGE_LAYOUT_PREINITIALIZED. "
+ "This layout must only be used as the initialLayout member of VkImageCreateInfo "
"or VkAttachmentDescription, or as the oldLayout in an image transition. (11.4)");
}
- break;
+ break;
case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL:
AccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
- break;
+ break;
case VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL:
AccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
- break;
+ break;
case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR:
AccessMask = VK_ACCESS_MEMORY_READ_BIT;
- break;
+ break;
default:
UNEXPECTED("Unexpected image layout");
- break;
+ break;
}
return AccessMask;
@@ -237,24 +237,24 @@ void VulkanCommandBuffer::TransitionImageLayout(VkCommandBuffer C
VkImageLayout NewLayout,
const VkImageSubresourceRange& SubresRange,
VkPipelineStageFlags EnabledGraphicsShaderStages,
- VkPipelineStageFlags SrcStages,
+ VkPipelineStageFlags SrcStages,
VkPipelineStageFlags DestStages)
{
VERIFY_EXPR(CmdBuffer != VK_NULL_HANDLE);
VkImageMemoryBarrier ImgBarrier = {};
- ImgBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
- ImgBarrier.pNext = nullptr;
- ImgBarrier.srcAccessMask = 0;
- ImgBarrier.dstAccessMask = 0;
- ImgBarrier.oldLayout = OldLayout;
- ImgBarrier.newLayout = NewLayout;
- ImgBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; // source queue family for a queue family ownership transfer.
- ImgBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; // destination queue family for a queue family ownership transfer.
- ImgBarrier.image = Image;
- ImgBarrier.subresourceRange = SubresRange;
- ImgBarrier.srcAccessMask = AccessMaskFromImageLayout(OldLayout, false);
- ImgBarrier.dstAccessMask = AccessMaskFromImageLayout(NewLayout, true);
+ ImgBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
+ ImgBarrier.pNext = nullptr;
+ ImgBarrier.srcAccessMask = 0;
+ ImgBarrier.dstAccessMask = 0;
+ ImgBarrier.oldLayout = OldLayout;
+ ImgBarrier.newLayout = NewLayout;
+ ImgBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; // source queue family for a queue family ownership transfer.
+ ImgBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; // destination queue family for a queue family ownership transfer.
+ ImgBarrier.image = Image;
+ ImgBarrier.subresourceRange = SubresRange;
+ ImgBarrier.srcAccessMask = AccessMaskFromImageLayout(OldLayout, false);
+ ImgBarrier.dstAccessMask = AccessMaskFromImageLayout(NewLayout, true);
if (SrcStages == 0)
{
@@ -264,11 +264,11 @@ void VulkanCommandBuffer::TransitionImageLayout(VkCommandBuffer C
}
else if (ImgBarrier.srcAccessMask != 0)
{
- SrcStages = PipelineStageFromAccessFlags(ImgBarrier.srcAccessMask, EnabledGraphicsShaderStages);
+ SrcStages = PipelineStageFromAccessFlags(ImgBarrier.srcAccessMask, EnabledGraphicsShaderStages);
}
else
{
- // An execution dependency with only VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT in the source stage
+ // An execution dependency with only VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT in the source stage
// mask will effectively not wait for any prior commands to complete. (6.1.2)
SrcStages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
}
@@ -286,64 +286,64 @@ void VulkanCommandBuffer::TransitionImageLayout(VkCommandBuffer C
}
else
{
- // An execution dependency with only VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT in the destination
- // stage mask will only prevent that stage from executing in subsequently submitted commands.
- // As this stage does not perform any actual execution, this is not observable - in effect,
+ // An execution dependency with only VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT in the destination
+ // stage mask will only prevent that stage from executing in subsequently submitted commands.
+ // As this stage does not perform any actual execution, this is not observable - in effect,
// it does not delay processing of subsequent commands. (6.1.2)
DestStages = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
}
}
- // Including a particular pipeline stage in the first synchronization scope of a command implicitly
- // includes logically earlier pipeline stages in the synchronization scope. Similarly, the second
+ // Including a particular pipeline stage in the first synchronization scope of a command implicitly
+ // includes logically earlier pipeline stages in the synchronization scope. Similarly, the second
// synchronization scope includes logically later pipeline stages.
- // However, note that access scopes are not affected in this way - only the precise stages specified
+ // However, note that access scopes are not affected in this way - only the precise stages specified
// are considered part of each access scope. (6.1.2)
vkCmdPipelineBarrier(CmdBuffer,
- SrcStages, // must not be 0
- DestStages, // must not be 0
- 0, // a bitmask specifying how execution and memory dependencies are formed
- 0, // memoryBarrierCount
- nullptr, // pMemoryBarriers
- 0, // bufferMemoryBarrierCount
- nullptr, // pBufferMemoryBarriers
- 1,
- &ImgBarrier);
- // Each element of pMemoryBarriers, pBufferMemoryBarriers and pImageMemoryBarriers must not
- // have any access flag included in its srcAccessMask member if that bit is not supported by
+ SrcStages, // must not be 0
+ DestStages, // must not be 0
+ 0, // a bitmask specifying how execution and memory dependencies are formed
+ 0, // memoryBarrierCount
+ nullptr, // pMemoryBarriers
+ 0, // bufferMemoryBarrierCount
+ nullptr, // pBufferMemoryBarriers
+ 1,
+ &ImgBarrier);
+ // Each element of pMemoryBarriers, pBufferMemoryBarriers and pImageMemoryBarriers must not
+ // have any access flag included in its srcAccessMask member if that bit is not supported by
// any of the pipeline stages in srcStageMask.
- // Each element of pMemoryBarriers, pBufferMemoryBarriers and pImageMemoryBarriers must not
- // have any access flag included in its dstAccessMask member if that bit is not supported by any
+ // Each element of pMemoryBarriers, pBufferMemoryBarriers and pImageMemoryBarriers must not
+ // have any access flag included in its dstAccessMask member if that bit is not supported by any
// of the pipeline stages in dstStageMask (6.6)
}
void VulkanCommandBuffer::BufferMemoryBarrier(VkCommandBuffer CmdBuffer,
- VkBuffer Buffer,
+ VkBuffer Buffer,
VkAccessFlags srcAccessMask,
VkAccessFlags dstAccessMask,
VkPipelineStageFlags EnabledGraphicsShaderStages,
- VkPipelineStageFlags SrcStages,
+ VkPipelineStageFlags SrcStages,
VkPipelineStageFlags DestStages)
{
VkBufferMemoryBarrier BuffBarrier = {};
- BuffBarrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
- BuffBarrier.pNext = nullptr;
- BuffBarrier.srcAccessMask = srcAccessMask;
- BuffBarrier.dstAccessMask = dstAccessMask;
- BuffBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
- BuffBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
- BuffBarrier.buffer = Buffer;
- BuffBarrier.offset = 0;
- BuffBarrier.size = VK_WHOLE_SIZE;
+ BuffBarrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
+ BuffBarrier.pNext = nullptr;
+ BuffBarrier.srcAccessMask = srcAccessMask;
+ BuffBarrier.dstAccessMask = dstAccessMask;
+ BuffBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ BuffBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ BuffBarrier.buffer = Buffer;
+ BuffBarrier.offset = 0;
+ BuffBarrier.size = VK_WHOLE_SIZE;
if (SrcStages == 0)
{
if (BuffBarrier.srcAccessMask != 0)
SrcStages = PipelineStageFromAccessFlags(BuffBarrier.srcAccessMask, EnabledGraphicsShaderStages);
else
{
- // An execution dependency with only VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT in the source stage
+ // An execution dependency with only VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT in the source stage
// mask will effectively not wait for any prior commands to complete. (6.1.2)
SrcStages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
}
@@ -356,20 +356,19 @@ void VulkanCommandBuffer::BufferMemoryBarrier(VkCommandBuffer CmdBuffer,
}
vkCmdPipelineBarrier(CmdBuffer,
- SrcStages, // must not be 0
- DestStages, // must not be 0
- 0, // a bitmask specifying how execution and memory dependencies are formed
- 0, // memoryBarrierCount
- nullptr, // pMemoryBarriers
- 1, // bufferMemoryBarrierCount
- &BuffBarrier, // pBufferMemoryBarriers
- 0,
- nullptr);
+ SrcStages, // must not be 0
+ DestStages, // must not be 0
+ 0, // a bitmask specifying how execution and memory dependencies are formed
+ 0, // memoryBarrierCount
+ nullptr, // pMemoryBarriers
+ 1, // bufferMemoryBarrierCount
+ &BuffBarrier, // pBufferMemoryBarriers
+ 0,
+ nullptr);
}
void VulkanCommandBuffer::FlushBarriers()
{
-
}
-}
+} // namespace VulkanUtilities
diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanCommandBufferPool.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanCommandBufferPool.cpp
index df90bd6e..5b19da72 100644
--- a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanCommandBufferPool.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanCommandBufferPool.cpp
@@ -30,91 +30,101 @@
namespace VulkanUtilities
{
- VulkanCommandBufferPool::VulkanCommandBufferPool(std::shared_ptr<const VulkanLogicalDevice> LogicalDevice,
- uint32_t queueFamilyIndex,
- VkCommandPoolCreateFlags flags) :
- m_LogicalDevice{std::move(LogicalDevice)}
- {
- VkCommandPoolCreateInfo CmdPoolCI = {};
- CmdPoolCI.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
- CmdPoolCI.pNext = nullptr;
- CmdPoolCI.queueFamilyIndex = queueFamilyIndex;
- CmdPoolCI.flags = flags;
- m_CmdPool = m_LogicalDevice->CreateCommandPool(CmdPoolCI);
- DEV_CHECK_ERR(m_CmdPool != VK_NULL_HANDLE, "Failed to create vulkan command pool");
+
+VulkanCommandBufferPool::VulkanCommandBufferPool(std::shared_ptr<const VulkanLogicalDevice> LogicalDevice,
+ uint32_t queueFamilyIndex,
+ VkCommandPoolCreateFlags flags) :
+ m_LogicalDevice{std::move(LogicalDevice)}
+{
+ VkCommandPoolCreateInfo CmdPoolCI = {};
+
+ CmdPoolCI.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
+ CmdPoolCI.pNext = nullptr;
+ CmdPoolCI.queueFamilyIndex = queueFamilyIndex;
+ CmdPoolCI.flags = flags;
+
+ m_CmdPool = m_LogicalDevice->CreateCommandPool(CmdPoolCI);
+ DEV_CHECK_ERR(m_CmdPool != VK_NULL_HANDLE, "Failed to create vulkan command pool");
#ifdef DEVELOPMENT
- m_BuffCounter = 0;
+ m_BuffCounter = 0;
#endif
- }
+}
- VulkanCommandBufferPool::~VulkanCommandBufferPool()
- {
- m_CmdPool.Release();
- DEV_CHECK_ERR(m_BuffCounter == 0, m_BuffCounter, " command buffer(s) have not been returned to the pool. If there are outstanding references to these buffers in release queues, FreeCommandBuffer() will crash when attempting to return a buffer to the pool.");
- }
+VulkanCommandBufferPool::~VulkanCommandBufferPool()
+{
+ m_CmdPool.Release();
+ DEV_CHECK_ERR(m_BuffCounter == 0, m_BuffCounter, " command buffer(s) have not been returned to the pool. If there are outstanding references to these buffers in release queues, FreeCommandBuffer() will crash when attempting to return a buffer to the pool.");
+}
+
+VkCommandBuffer VulkanCommandBufferPool::GetCommandBuffer(const char* DebugName)
+{
+ VkCommandBuffer CmdBuffer = VK_NULL_HANDLE;
- VkCommandBuffer VulkanCommandBufferPool::GetCommandBuffer(const char* DebugName)
{
- VkCommandBuffer CmdBuffer = VK_NULL_HANDLE;
+ std::lock_guard<std::mutex> Lock{m_Mutex};
+ if (!m_CmdBuffers.empty())
{
- std::lock_guard<std::mutex> Lock{m_Mutex};
-
- if (!m_CmdBuffers.empty())
- {
- CmdBuffer = m_CmdBuffers.front();
- auto err = vkResetCommandBuffer(CmdBuffer,
- 0 // VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT - specifies that most or all memory resources currently
- // owned by the command buffer should be returned to the parent command pool.
- );
- DEV_CHECK_ERR(err == VK_SUCCESS, "Failed to reset command buffer"); (void)err;
- m_CmdBuffers.pop_front();
- }
+ CmdBuffer = m_CmdBuffers.front();
+ auto err = vkResetCommandBuffer(
+ CmdBuffer,
+ 0 // VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT - specifies that most or all memory resources currently
+ // owned by the command buffer should be returned to the parent command pool.
+ );
+ DEV_CHECK_ERR(err == VK_SUCCESS, "Failed to reset command buffer");
+ (void)err;
+ m_CmdBuffers.pop_front();
}
+ }
- // If no cmd buffers were ready to be reused, create a new one
- if (CmdBuffer == VK_NULL_HANDLE)
- {
- VkCommandBufferAllocateInfo BuffAllocInfo = {};
- BuffAllocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
- BuffAllocInfo.pNext = nullptr;
- BuffAllocInfo.commandPool = m_CmdPool;
- BuffAllocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
- BuffAllocInfo.commandBufferCount = 1;
-
- CmdBuffer = m_LogicalDevice->AllocateVkCommandBuffer(BuffAllocInfo);
- DEV_CHECK_ERR(CmdBuffer != VK_NULL_HANDLE, "Failed to allocate vulkan command buffer");
- }
+ // If no cmd buffers were ready to be reused, create a new one
+ if (CmdBuffer == VK_NULL_HANDLE)
+ {
+ VkCommandBufferAllocateInfo BuffAllocInfo = {};
+
+ BuffAllocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
+ BuffAllocInfo.pNext = nullptr;
+ BuffAllocInfo.commandPool = m_CmdPool;
+ BuffAllocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
+ BuffAllocInfo.commandBufferCount = 1;
+
+ CmdBuffer = m_LogicalDevice->AllocateVkCommandBuffer(BuffAllocInfo);
+ DEV_CHECK_ERR(CmdBuffer != VK_NULL_HANDLE, "Failed to allocate vulkan command buffer");
+ }
+
+ VkCommandBufferBeginInfo CmdBuffBeginInfo = {};
- VkCommandBufferBeginInfo CmdBuffBeginInfo = {};
- CmdBuffBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
- CmdBuffBeginInfo.pNext = nullptr;
- CmdBuffBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; // Each recording of the command buffer will only be
- // submitted once, and the command buffer will be reset
- // and recorded again between each submission.
- CmdBuffBeginInfo.pInheritanceInfo = nullptr; // Ignored for a primary command buffer
- auto err = vkBeginCommandBuffer(CmdBuffer, &CmdBuffBeginInfo);
- DEV_CHECK_ERR(err == VK_SUCCESS, "Failed to begin command buffer"); (void)err;
+ CmdBuffBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
+ CmdBuffBeginInfo.pNext = nullptr;
+ CmdBuffBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; // Each recording of the command buffer will only be
+ // submitted once, and the command buffer will be reset
+ // and recorded again between each submission.
+ CmdBuffBeginInfo.pInheritanceInfo = nullptr; // Ignored for a primary command buffer
+
+ auto err = vkBeginCommandBuffer(CmdBuffer, &CmdBuffBeginInfo);
+ DEV_CHECK_ERR(err == VK_SUCCESS, "Failed to begin command buffer");
+ (void)err;
#ifdef DEVELOPMENT
- ++m_BuffCounter;
+ ++m_BuffCounter;
#endif
- return CmdBuffer;
- }
+ return CmdBuffer;
+}
- void VulkanCommandBufferPool::FreeCommandBuffer(VkCommandBuffer&& CmdBuffer)
- {
- std::lock_guard<std::mutex> Lock{m_Mutex};
- m_CmdBuffers.emplace_back(CmdBuffer);
- CmdBuffer = VK_NULL_HANDLE;
+void VulkanCommandBufferPool::FreeCommandBuffer(VkCommandBuffer&& CmdBuffer)
+{
+ std::lock_guard<std::mutex> Lock{m_Mutex};
+ m_CmdBuffers.emplace_back(CmdBuffer);
+ CmdBuffer = VK_NULL_HANDLE;
#ifdef DEVELOPMENT
- --m_BuffCounter;
+ --m_BuffCounter;
#endif
- }
+}
- CommandPoolWrapper&& VulkanCommandBufferPool::Release()
- {
- m_LogicalDevice.reset();
- m_CmdBuffers.clear();
- return std::move(m_CmdPool);
- }
+CommandPoolWrapper&& VulkanCommandBufferPool::Release()
+{
+ m_LogicalDevice.reset();
+ m_CmdBuffers.clear();
+ return std::move(m_CmdPool);
}
+
+} // namespace VulkanUtilities
diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanDebug.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanDebug.cpp
index a5a71d01..c4781196 100644
--- a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanDebug.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanDebug.cpp
@@ -17,615 +17,639 @@
namespace VulkanUtilities
{
- static PFN_vkCreateDebugUtilsMessengerEXT CreateDebugUtilsMessengerEXT = nullptr;
- static PFN_vkDestroyDebugUtilsMessengerEXT DestroyDebugUtilsMessengerEXT = nullptr;
- static PFN_vkSetDebugUtilsObjectNameEXT SetDebugUtilsObjectNameEXT = nullptr;
- static PFN_vkSetDebugUtilsObjectTagEXT SetDebugUtilsObjectTagEXT = nullptr;
- static PFN_vkQueueBeginDebugUtilsLabelEXT QueueBeginDebugUtilsLabelEXT = nullptr;
- static PFN_vkQueueEndDebugUtilsLabelEXT QueueEndDebugUtilsLabelEXT = nullptr;
- static PFN_vkQueueInsertDebugUtilsLabelEXT QueueInsertDebugUtilsLabelEXT = nullptr;
- static PFN_vkCmdBeginDebugUtilsLabelEXT CmdBeginDebugUtilsLabelEXT = nullptr;
- static PFN_vkCmdEndDebugUtilsLabelEXT CmdEndDebugUtilsLabelEXT = nullptr;
- static PFN_vkCmdInsertDebugUtilsLabelEXT CmdInsertDebugUtilsLabelEXT = nullptr;
-
- static VkDebugUtilsMessengerEXT DbgMessenger = VK_NULL_HANDLE;
-
- VKAPI_ATTR VkBool32 VKAPI_CALL DebugMessengerCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
- VkDebugUtilsMessageTypeFlagsEXT messageType,
- const VkDebugUtilsMessengerCallbackDataEXT* callbackData,
- void* userData)
- {
- std::stringstream debugMessage;
- // Ignore some validation messages
- if ((messageType & VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT))
- {
- {
- // UNASSIGNED-CoreValidation-DrawState-ClearCmdBeforeDraw:
- // vkCmdClearAttachments() issued on command buffer object 0x... prior to any Draw Cmds. It is recommended you use RenderPass LOAD_OP_CLEAR on Attachments prior to any Draw.
- static const char* ClearCmdBeforeDrawIdName = "UNASSIGNED-CoreValidation-DrawState-ClearCmdBeforeDraw";
- constexpr int32_t DeprecatedClearCmdBeforeDrawIdNumber = 64; // Starting with sdk version 1.1.85, messageIdNumber is 0 for all messages
- if ((callbackData->pMessageIdName != nullptr && strcmp(callbackData->pMessageIdName, ClearCmdBeforeDrawIdName) == 0) || callbackData->messageIdNumber == DeprecatedClearCmdBeforeDrawIdNumber)
- return VK_FALSE;
- }
- }
-
- Diligent::DebugMessageSeverity MsgSeverity = Diligent::DebugMessageSeverity::Info;
- if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT)
- {
- MsgSeverity = Diligent::DebugMessageSeverity::Info;
- }
- else if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT)
- {
- MsgSeverity = Diligent::DebugMessageSeverity::Info;
- }
- else if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT)
- {
- MsgSeverity = Diligent::DebugMessageSeverity::Warning;
- }
- else if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT)
- {
- MsgSeverity = Diligent::DebugMessageSeverity::Error;
- }
- else
- {
- MsgSeverity = Diligent::DebugMessageSeverity::Info;
- }
-
- debugMessage << "Vulkan debug message (";
- if (messageType & VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT)
- {
- debugMessage << "general";
- if (messageType & (VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT))
- debugMessage << ", ";
- }
- if (messageType & VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT)
- {
- debugMessage << "validation";
- if (messageType & VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT)
- debugMessage << ", ";
- }
- if (messageType & VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT)
- debugMessage << "performance";
- debugMessage << "): ";
-
- // callbackData->messageIdNumber is deprecated and starting with version 1.1.85 it is always 0
- debugMessage << (callbackData->pMessageIdName != nullptr ? callbackData->pMessageIdName : "<Unknown name>");
- if (callbackData->pMessage != nullptr)
- {
- debugMessage << std::endl << " " << callbackData->pMessage;
- }
-
- if (callbackData->objectCount > 0)
- {
- for (uint32_t obj = 0; obj < callbackData->objectCount; ++obj)
- {
- const auto& Object = callbackData->pObjects[obj];
- debugMessage << std::endl << " Object[" << obj << "] (" << VkObjectTypeToString(Object.objectType)
- << "): Handle " << std::hex << "0x" << Object.objectHandle;
- if (Object.pObjectName != nullptr)
- {
- debugMessage << ", Name: '" << Object.pObjectName << '\'';
- }
- }
- }
+static PFN_vkCreateDebugUtilsMessengerEXT CreateDebugUtilsMessengerEXT = nullptr;
+static PFN_vkDestroyDebugUtilsMessengerEXT DestroyDebugUtilsMessengerEXT = nullptr;
+static PFN_vkSetDebugUtilsObjectNameEXT SetDebugUtilsObjectNameEXT = nullptr;
+static PFN_vkSetDebugUtilsObjectTagEXT SetDebugUtilsObjectTagEXT = nullptr;
+static PFN_vkQueueBeginDebugUtilsLabelEXT QueueBeginDebugUtilsLabelEXT = nullptr;
+static PFN_vkQueueEndDebugUtilsLabelEXT QueueEndDebugUtilsLabelEXT = nullptr;
+static PFN_vkQueueInsertDebugUtilsLabelEXT QueueInsertDebugUtilsLabelEXT = nullptr;
+static PFN_vkCmdBeginDebugUtilsLabelEXT CmdBeginDebugUtilsLabelEXT = nullptr;
+static PFN_vkCmdEndDebugUtilsLabelEXT CmdEndDebugUtilsLabelEXT = nullptr;
+static PFN_vkCmdInsertDebugUtilsLabelEXT CmdInsertDebugUtilsLabelEXT = nullptr;
+
+static VkDebugUtilsMessengerEXT DbgMessenger = VK_NULL_HANDLE;
+
+VKAPI_ATTR VkBool32 VKAPI_CALL DebugMessengerCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
+ VkDebugUtilsMessageTypeFlagsEXT messageType,
+ const VkDebugUtilsMessengerCallbackDataEXT* callbackData,
+ void* userData)
+{
+ std::stringstream debugMessage;
- if (callbackData->cmdBufLabelCount > 0)
+ // Ignore some validation messages
+ if ((messageType & VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT))
+ {
{
- for (uint32_t l = 0; l < callbackData->cmdBufLabelCount; ++l)
- {
- const auto& Label = callbackData->pCmdBufLabels[l];
- debugMessage << std::endl << " Label[" << l << "]";
- if (Label.pLabelName != nullptr)
- {
- debugMessage << " - " << Label.pLabelName;
- }
- debugMessage << " {";
- debugMessage << std::fixed << std::setw(4) << Label.color[0] << ", "
- << std::fixed << std::setw(4) << Label.color[1] << ", "
- << std::fixed << std::setw(4) << Label.color[2] << ", "
- << std::fixed << std::setw(4) << Label.color[3] << "}";
- }
+ // UNASSIGNED-CoreValidation-DrawState-ClearCmdBeforeDraw:
+ // vkCmdClearAttachments() issued on command buffer object 0x... prior to any Draw Cmds. It is recommended you use RenderPass LOAD_OP_CLEAR on Attachments prior to any Draw.
+ static const char* ClearCmdBeforeDrawIdName = "UNASSIGNED-CoreValidation-DrawState-ClearCmdBeforeDraw";
+ constexpr int32_t DeprecatedClearCmdBeforeDrawIdNumber = 64; // Starting with sdk version 1.1.85, messageIdNumber is 0 for all messages
+ if ((callbackData->pMessageIdName != nullptr && strcmp(callbackData->pMessageIdName, ClearCmdBeforeDrawIdName) == 0) || callbackData->messageIdNumber == DeprecatedClearCmdBeforeDrawIdNumber)
+ return VK_FALSE;
}
-
- LOG_DEBUG_MESSAGE(MsgSeverity, debugMessage.str().c_str());
-
- // The return value of this callback controls wether the Vulkan call that caused
- // the validation message will be aborted or not
- // We return VK_FALSE as we DON'T want Vulkan calls that cause a validation message
- // (and return a VkResult) to abort
- return VK_FALSE;
}
-
- void SetupDebugging(VkInstance instance,
- VkDebugUtilsMessageSeverityFlagsEXT messageSeverity,
- VkDebugUtilsMessageTypeFlagsEXT messageType,
- void* pUserData)
+ Diligent::DebugMessageSeverity MsgSeverity = Diligent::DebugMessageSeverity::Info;
+ if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT)
{
- CreateDebugUtilsMessengerEXT = reinterpret_cast<PFN_vkCreateDebugUtilsMessengerEXT>(vkGetInstanceProcAddr(instance, "vkCreateDebugUtilsMessengerEXT"));
- DestroyDebugUtilsMessengerEXT = reinterpret_cast<PFN_vkDestroyDebugUtilsMessengerEXT>(vkGetInstanceProcAddr(instance, "vkDestroyDebugUtilsMessengerEXT"));
- VERIFY_EXPR(CreateDebugUtilsMessengerEXT != nullptr && DestroyDebugUtilsMessengerEXT != nullptr);
-
- VkDebugUtilsMessengerCreateInfoEXT DbgMessenger_CI = {};
- DbgMessenger_CI.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
- DbgMessenger_CI.pNext = NULL;
- DbgMessenger_CI.flags = 0;
- DbgMessenger_CI.messageSeverity = messageSeverity;
- DbgMessenger_CI.messageType = messageType;
- DbgMessenger_CI.pfnUserCallback = DebugMessengerCallback;
- DbgMessenger_CI.pUserData = pUserData;
- VkResult err = CreateDebugUtilsMessengerEXT(instance, &DbgMessenger_CI, nullptr, &DbgMessenger);
- VERIFY(err == VK_SUCCESS, "Failed to create debug utils messenger"); (void)err;
-
- // Load function pointers
- SetDebugUtilsObjectNameEXT = reinterpret_cast<PFN_vkSetDebugUtilsObjectNameEXT>(vkGetInstanceProcAddr(instance, "vkSetDebugUtilsObjectNameEXT"));
- VERIFY_EXPR(SetDebugUtilsObjectNameEXT != nullptr);
- SetDebugUtilsObjectTagEXT = reinterpret_cast<PFN_vkSetDebugUtilsObjectTagEXT>(vkGetInstanceProcAddr(instance, "vkSetDebugUtilsObjectTagEXT"));
- VERIFY_EXPR(SetDebugUtilsObjectTagEXT != nullptr);
-
- QueueBeginDebugUtilsLabelEXT = reinterpret_cast<PFN_vkQueueBeginDebugUtilsLabelEXT>(vkGetInstanceProcAddr(instance, "vkQueueBeginDebugUtilsLabelEXT"));
- VERIFY_EXPR(QueueBeginDebugUtilsLabelEXT != nullptr);
- QueueEndDebugUtilsLabelEXT = reinterpret_cast<PFN_vkQueueEndDebugUtilsLabelEXT>(vkGetInstanceProcAddr(instance, "vkQueueEndDebugUtilsLabelEXT"));
- VERIFY_EXPR(QueueEndDebugUtilsLabelEXT != nullptr);
- QueueInsertDebugUtilsLabelEXT = reinterpret_cast<PFN_vkQueueInsertDebugUtilsLabelEXT>(vkGetInstanceProcAddr(instance, "vkQueueInsertDebugUtilsLabelEXT"));
- VERIFY_EXPR(QueueInsertDebugUtilsLabelEXT != nullptr);
-
- CmdBeginDebugUtilsLabelEXT = reinterpret_cast<PFN_vkCmdBeginDebugUtilsLabelEXT>(vkGetInstanceProcAddr(instance, "vkCmdBeginDebugUtilsLabelEXT"));
- VERIFY_EXPR(CmdBeginDebugUtilsLabelEXT != nullptr);
- CmdEndDebugUtilsLabelEXT = reinterpret_cast<PFN_vkCmdEndDebugUtilsLabelEXT>(vkGetInstanceProcAddr(instance, "vkCmdEndDebugUtilsLabelEXT"));
- VERIFY_EXPR(CmdEndDebugUtilsLabelEXT != nullptr);
- CmdInsertDebugUtilsLabelEXT = reinterpret_cast<PFN_vkCmdInsertDebugUtilsLabelEXT>(vkGetInstanceProcAddr(instance, "vkCmdInsertDebugUtilsLabelEXT"));
- VERIFY_EXPR(CmdInsertDebugUtilsLabelEXT != nullptr);
+ MsgSeverity = Diligent::DebugMessageSeverity::Info;
}
-
- void FreeDebugging(VkInstance instance)
+ else if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT)
{
- if (DbgMessenger != VK_NULL_HANDLE)
- {
- DestroyDebugUtilsMessengerEXT(instance, DbgMessenger, nullptr);
- }
+ MsgSeverity = Diligent::DebugMessageSeverity::Info;
}
-
- void BeginCmdQueueLabelRegion(VkQueue cmdQueue, const char* pLabelName, const float* color)
+ else if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT)
{
- VkDebugUtilsLabelEXT Label = {};
- Label.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;
- Label.pNext = nullptr;
- Label.pLabelName = pLabelName;
- for(int i=0; i < 4; ++i)
- Label.color[i] = color[i];
- QueueBeginDebugUtilsLabelEXT(cmdQueue, &Label);
+ MsgSeverity = Diligent::DebugMessageSeverity::Warning;
}
-
- void InsertCmdQueueLabel(VkQueue cmdQueue, const char* pLabelName, const float* color)
+ else if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT)
{
- VkDebugUtilsLabelEXT Label = {};
- Label.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;
- Label.pNext = nullptr;
- Label.pLabelName = pLabelName;
- for(int i=0; i < 4; ++i)
- Label.color[i] = color[i];
- QueueInsertDebugUtilsLabelEXT(cmdQueue, &Label);
+ MsgSeverity = Diligent::DebugMessageSeverity::Error;
}
-
- void EndCmdQueueLabelRegion(VkQueue cmdQueue)
+ else
{
- QueueEndDebugUtilsLabelEXT(cmdQueue);
+ MsgSeverity = Diligent::DebugMessageSeverity::Info;
}
-
- // Start a new label region
- void BeginCmdBufferLabelRegion(VkCommandBuffer cmdBuffer, const char* pLabelName, const float* color)
+ debugMessage << "Vulkan debug message (";
+ if (messageType & VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT)
{
- VkDebugUtilsLabelEXT Label = {};
- Label.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;
- Label.pNext = nullptr;
- Label.pLabelName = pLabelName;
- for(int i=0; i < 4; ++i)
- Label.color[i] = color[i];
- CmdBeginDebugUtilsLabelEXT(cmdBuffer, &Label);
+ debugMessage << "general";
+ if (messageType & (VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT))
+ debugMessage << ", ";
}
-
- // End the label region
- void EndCmdBufferLabelRegion(VkCommandBuffer cmdBuffer)
+ if (messageType & VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT)
{
- CmdEndDebugUtilsLabelEXT(cmdBuffer);
+ debugMessage << "validation";
+ if (messageType & VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT)
+ debugMessage << ", ";
}
+ if (messageType & VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT)
+ debugMessage << "performance";
+ debugMessage << "): ";
- // Start a single label
- void InsertCmdBufferLabel(VkCommandBuffer cmdBuffer, const char* pLabelName, const float* color)
+ // callbackData->messageIdNumber is deprecated and starting with version 1.1.85 it is always 0
+ debugMessage << (callbackData->pMessageIdName != nullptr ? callbackData->pMessageIdName : "<Unknown name>");
+ if (callbackData->pMessage != nullptr)
{
- VkDebugUtilsLabelEXT Label = {};
- Label.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;
- Label.pNext = nullptr;
- Label.pLabelName = pLabelName;
- for(int i=0; i < 4; ++i)
- Label.color[i] = color[i];
- CmdInsertDebugUtilsLabelEXT(cmdBuffer, &Label);
+ debugMessage << std::endl
+ << " " << callbackData->pMessage;
}
-
- void SetObjectName(VkDevice device, uint64_t objectHandle, VkObjectType objectType, const char *name)
+ if (callbackData->objectCount > 0)
{
- // Check for valid function pointer (may not be present if not running in a debugging application)
- if (SetDebugUtilsObjectNameEXT != nullptr && name != nullptr && *name != 0)
+ for (uint32_t obj = 0; obj < callbackData->objectCount; ++obj)
{
- VkDebugUtilsObjectNameInfoEXT ObjectNameInfo = {};
- ObjectNameInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
- ObjectNameInfo.pNext = nullptr;
- ObjectNameInfo.objectType = objectType;
- ObjectNameInfo.objectHandle = objectHandle;
- ObjectNameInfo.pObjectName = name;
- VkResult res = SetDebugUtilsObjectNameEXT(device, &ObjectNameInfo);
- VERIFY_EXPR(res == VK_SUCCESS); (void)res;
+ const auto& Object = callbackData->pObjects[obj];
+ debugMessage << std::endl
+ << " Object[" << obj << "] (" << VkObjectTypeToString(Object.objectType)
+ << "): Handle " << std::hex << "0x" << Object.objectHandle;
+ if (Object.pObjectName != nullptr)
+ {
+ debugMessage << ", Name: '" << Object.pObjectName << '\'';
+ }
}
}
- void SetObjectTag(VkDevice device, uint64_t objectHandle, VkObjectType objectType, uint64_t name, size_t tagSize, const void* tag)
+ if (callbackData->cmdBufLabelCount > 0)
{
- // Check for valid function pointer (may not be present if not running in a debugging application)
- if (SetDebugUtilsObjectTagEXT)
+ for (uint32_t l = 0; l < callbackData->cmdBufLabelCount; ++l)
{
- VkDebugUtilsObjectTagInfoEXT tagInfo = {};
- tagInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_TAG_INFO_EXT;
- tagInfo.pNext = nullptr;
- tagInfo.objectType = objectType;
- tagInfo.objectHandle = objectHandle;
- tagInfo.tagName = name;
- tagInfo.tagSize = tagSize;
- tagInfo.pTag = tag;
- SetDebugUtilsObjectTagEXT(device, &tagInfo);
+ const auto& Label = callbackData->pCmdBufLabels[l];
+ debugMessage << std::endl
+ << " Label[" << l << "]";
+ if (Label.pLabelName != nullptr)
+ {
+ debugMessage << " - " << Label.pLabelName;
+ }
+ debugMessage << " {";
+ debugMessage << std::fixed << std::setw(4) << Label.color[0] << ", "
+ << std::fixed << std::setw(4) << Label.color[1] << ", "
+ << std::fixed << std::setw(4) << Label.color[2] << ", "
+ << std::fixed << std::setw(4) << Label.color[3] << "}";
}
}
- void SetCommandPoolName(VkDevice device, VkCommandPool cmdPool, const char * name)
- {
- SetObjectName(device, (uint64_t)cmdPool, VK_OBJECT_TYPE_COMMAND_POOL, name);
- }
+ LOG_DEBUG_MESSAGE(MsgSeverity, debugMessage.str().c_str());
- void SetCommandBufferName(VkDevice device, VkCommandBuffer cmdBuffer, const char * name)
- {
- SetObjectName(device, (uint64_t)cmdBuffer, VK_OBJECT_TYPE_COMMAND_BUFFER, name);
- }
+ // The return value of this callback controls wether the Vulkan call that caused
+ // the validation message will be aborted or not
+ // We return VK_FALSE as we DON'T want Vulkan calls that cause a validation message
+ // (and return a VkResult) to abort
+ return VK_FALSE;
+}
- void SetQueueName(VkDevice device, VkQueue queue, const char * name)
- {
- SetObjectName(device, (uint64_t)queue, VK_OBJECT_TYPE_QUEUE, name);
- }
- void SetImageName(VkDevice device, VkImage image, const char * name)
- {
- SetObjectName(device, (uint64_t)image, VK_OBJECT_TYPE_IMAGE, name);
- }
+void SetupDebugging(VkInstance instance,
+ VkDebugUtilsMessageSeverityFlagsEXT messageSeverity,
+ VkDebugUtilsMessageTypeFlagsEXT messageType,
+ void* pUserData)
+{
+ CreateDebugUtilsMessengerEXT = reinterpret_cast<PFN_vkCreateDebugUtilsMessengerEXT>(vkGetInstanceProcAddr(instance, "vkCreateDebugUtilsMessengerEXT"));
+ DestroyDebugUtilsMessengerEXT = reinterpret_cast<PFN_vkDestroyDebugUtilsMessengerEXT>(vkGetInstanceProcAddr(instance, "vkDestroyDebugUtilsMessengerEXT"));
+ VERIFY_EXPR(CreateDebugUtilsMessengerEXT != nullptr && DestroyDebugUtilsMessengerEXT != nullptr);
+
+ VkDebugUtilsMessengerCreateInfoEXT DbgMessenger_CI = {};
+
+ DbgMessenger_CI.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
+ DbgMessenger_CI.pNext = NULL;
+ DbgMessenger_CI.flags = 0;
+ DbgMessenger_CI.messageSeverity = messageSeverity;
+ DbgMessenger_CI.messageType = messageType;
+ DbgMessenger_CI.pfnUserCallback = DebugMessengerCallback;
+ DbgMessenger_CI.pUserData = pUserData;
+
+ VkResult err = CreateDebugUtilsMessengerEXT(instance, &DbgMessenger_CI, nullptr, &DbgMessenger);
+ VERIFY(err == VK_SUCCESS, "Failed to create debug utils messenger");
+ (void)err;
+
+ // Load function pointers
+ SetDebugUtilsObjectNameEXT = reinterpret_cast<PFN_vkSetDebugUtilsObjectNameEXT>(vkGetInstanceProcAddr(instance, "vkSetDebugUtilsObjectNameEXT"));
+ VERIFY_EXPR(SetDebugUtilsObjectNameEXT != nullptr);
+ SetDebugUtilsObjectTagEXT = reinterpret_cast<PFN_vkSetDebugUtilsObjectTagEXT>(vkGetInstanceProcAddr(instance, "vkSetDebugUtilsObjectTagEXT"));
+ VERIFY_EXPR(SetDebugUtilsObjectTagEXT != nullptr);
+
+ QueueBeginDebugUtilsLabelEXT = reinterpret_cast<PFN_vkQueueBeginDebugUtilsLabelEXT>(vkGetInstanceProcAddr(instance, "vkQueueBeginDebugUtilsLabelEXT"));
+ VERIFY_EXPR(QueueBeginDebugUtilsLabelEXT != nullptr);
+ QueueEndDebugUtilsLabelEXT = reinterpret_cast<PFN_vkQueueEndDebugUtilsLabelEXT>(vkGetInstanceProcAddr(instance, "vkQueueEndDebugUtilsLabelEXT"));
+ VERIFY_EXPR(QueueEndDebugUtilsLabelEXT != nullptr);
+ QueueInsertDebugUtilsLabelEXT = reinterpret_cast<PFN_vkQueueInsertDebugUtilsLabelEXT>(vkGetInstanceProcAddr(instance, "vkQueueInsertDebugUtilsLabelEXT"));
+ VERIFY_EXPR(QueueInsertDebugUtilsLabelEXT != nullptr);
+
+ CmdBeginDebugUtilsLabelEXT = reinterpret_cast<PFN_vkCmdBeginDebugUtilsLabelEXT>(vkGetInstanceProcAddr(instance, "vkCmdBeginDebugUtilsLabelEXT"));
+ VERIFY_EXPR(CmdBeginDebugUtilsLabelEXT != nullptr);
+ CmdEndDebugUtilsLabelEXT = reinterpret_cast<PFN_vkCmdEndDebugUtilsLabelEXT>(vkGetInstanceProcAddr(instance, "vkCmdEndDebugUtilsLabelEXT"));
+ VERIFY_EXPR(CmdEndDebugUtilsLabelEXT != nullptr);
+ CmdInsertDebugUtilsLabelEXT = reinterpret_cast<PFN_vkCmdInsertDebugUtilsLabelEXT>(vkGetInstanceProcAddr(instance, "vkCmdInsertDebugUtilsLabelEXT"));
+ VERIFY_EXPR(CmdInsertDebugUtilsLabelEXT != nullptr);
+}
- void SetImageViewName(VkDevice device, VkImageView imageView, const char * name)
+void FreeDebugging(VkInstance instance)
+{
+ if (DbgMessenger != VK_NULL_HANDLE)
{
- SetObjectName(device, (uint64_t)imageView, VK_OBJECT_TYPE_IMAGE_VIEW, name);
+ DestroyDebugUtilsMessengerEXT(instance, DbgMessenger, nullptr);
}
+}
- void SetSamplerName(VkDevice device, VkSampler sampler, const char * name)
- {
- SetObjectName(device, (uint64_t)sampler, VK_OBJECT_TYPE_SAMPLER, name);
- }
+void BeginCmdQueueLabelRegion(VkQueue cmdQueue, const char* pLabelName, const float* color)
+{
+ VkDebugUtilsLabelEXT Label = {};
+
+ Label.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;
+ Label.pNext = nullptr;
+ Label.pLabelName = pLabelName;
+ for (int i = 0; i < 4; ++i)
+ Label.color[i] = color[i];
+ QueueBeginDebugUtilsLabelEXT(cmdQueue, &Label);
+}
- void SetBufferName(VkDevice device, VkBuffer buffer, const char * name)
- {
- SetObjectName(device, (uint64_t)buffer, VK_OBJECT_TYPE_BUFFER, name);
- }
+void InsertCmdQueueLabel(VkQueue cmdQueue, const char* pLabelName, const float* color)
+{
+ VkDebugUtilsLabelEXT Label = {};
+
+ Label.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;
+ Label.pNext = nullptr;
+ Label.pLabelName = pLabelName;
+ for (int i = 0; i < 4; ++i)
+ Label.color[i] = color[i];
+ QueueInsertDebugUtilsLabelEXT(cmdQueue, &Label);
+}
- void SetBufferViewName(VkDevice device, VkBufferView bufferView, const char * name)
- {
- SetObjectName(device, (uint64_t)bufferView, VK_OBJECT_TYPE_BUFFER_VIEW, name);
- }
+void EndCmdQueueLabelRegion(VkQueue cmdQueue)
+{
+ QueueEndDebugUtilsLabelEXT(cmdQueue);
+}
- void SetDeviceMemoryName(VkDevice device, VkDeviceMemory memory, const char * name)
- {
- SetObjectName(device, (uint64_t)memory, VK_OBJECT_TYPE_DEVICE_MEMORY, name);
- }
- void SetShaderModuleName(VkDevice device, VkShaderModule shaderModule, const char * name)
- {
- SetObjectName(device, (uint64_t)shaderModule, VK_OBJECT_TYPE_SHADER_MODULE, name);
- }
+// Start a new label region
+void BeginCmdBufferLabelRegion(VkCommandBuffer cmdBuffer, const char* pLabelName, const float* color)
+{
+ VkDebugUtilsLabelEXT Label = {};
+
+ Label.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;
+ Label.pNext = nullptr;
+ Label.pLabelName = pLabelName;
+ for (int i = 0; i < 4; ++i)
+ Label.color[i] = color[i];
+ CmdBeginDebugUtilsLabelEXT(cmdBuffer, &Label);
+}
- void SetPipelineName(VkDevice device, VkPipeline pipeline, const char * name)
- {
- SetObjectName(device, (uint64_t)pipeline, VK_OBJECT_TYPE_PIPELINE, name);
- }
+// End the label region
+void EndCmdBufferLabelRegion(VkCommandBuffer cmdBuffer)
+{
+ CmdEndDebugUtilsLabelEXT(cmdBuffer);
+}
- void SetPipelineLayoutName(VkDevice device, VkPipelineLayout pipelineLayout, const char * name)
- {
- SetObjectName(device, (uint64_t)pipelineLayout, VK_OBJECT_TYPE_PIPELINE_LAYOUT, name);
- }
+// Start a single label
+void InsertCmdBufferLabel(VkCommandBuffer cmdBuffer, const char* pLabelName, const float* color)
+{
+ VkDebugUtilsLabelEXT Label = {};
+
+ Label.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;
+ Label.pNext = nullptr;
+ Label.pLabelName = pLabelName;
+ for (int i = 0; i < 4; ++i)
+ Label.color[i] = color[i];
+ CmdInsertDebugUtilsLabelEXT(cmdBuffer, &Label);
+}
- void SetRenderPassName(VkDevice device, VkRenderPass renderPass, const char * name)
- {
- SetObjectName(device, (uint64_t)renderPass, VK_OBJECT_TYPE_RENDER_PASS, name);
- }
- void SetFramebufferName(VkDevice device, VkFramebuffer framebuffer, const char * name)
+void SetObjectName(VkDevice device, uint64_t objectHandle, VkObjectType objectType, const char* name)
+{
+ // Check for valid function pointer (may not be present if not running in a debugging application)
+ if (SetDebugUtilsObjectNameEXT != nullptr && name != nullptr && *name != 0)
{
- SetObjectName(device, (uint64_t)framebuffer, VK_OBJECT_TYPE_FRAMEBUFFER, name);
- }
+ VkDebugUtilsObjectNameInfoEXT ObjectNameInfo = {};
- void SetDescriptorSetLayoutName(VkDevice device, VkDescriptorSetLayout descriptorSetLayout, const char * name)
- {
- SetObjectName(device, (uint64_t)descriptorSetLayout, VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT, name);
- }
+ ObjectNameInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
+ ObjectNameInfo.pNext = nullptr;
+ ObjectNameInfo.objectType = objectType;
+ ObjectNameInfo.objectHandle = objectHandle;
+ ObjectNameInfo.pObjectName = name;
- void SetDescriptorSetName(VkDevice device, VkDescriptorSet descriptorSet, const char * name)
- {
- SetObjectName(device, (uint64_t)descriptorSet, VK_OBJECT_TYPE_DESCRIPTOR_SET, name);
+ VkResult res = SetDebugUtilsObjectNameEXT(device, &ObjectNameInfo);
+ VERIFY_EXPR(res == VK_SUCCESS);
+ (void)res;
}
+}
- void SetDescriptorPoolName(VkDevice device, VkDescriptorPool descriptorPool, const char * name)
+void SetObjectTag(VkDevice device, uint64_t objectHandle, VkObjectType objectType, uint64_t name, size_t tagSize, const void* tag)
+{
+ // Check for valid function pointer (may not be present if not running in a debugging application)
+ if (SetDebugUtilsObjectTagEXT)
{
- SetObjectName(device, (uint64_t)descriptorPool, VK_OBJECT_TYPE_DESCRIPTOR_POOL, name);
- }
+ VkDebugUtilsObjectTagInfoEXT tagInfo = {};
- void SetSemaphoreName(VkDevice device, VkSemaphore semaphore, const char * name)
- {
- SetObjectName(device, (uint64_t)semaphore, VK_OBJECT_TYPE_SEMAPHORE, name);
+ tagInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_TAG_INFO_EXT;
+ tagInfo.pNext = nullptr;
+ tagInfo.objectType = objectType;
+ tagInfo.objectHandle = objectHandle;
+ tagInfo.tagName = name;
+ tagInfo.tagSize = tagSize;
+ tagInfo.pTag = tag;
+ SetDebugUtilsObjectTagEXT(device, &tagInfo);
}
+}
- void SetFenceName(VkDevice device, VkFence fence, const char * name)
- {
- SetObjectName(device, (uint64_t)fence, VK_OBJECT_TYPE_FENCE, name);
- }
+void SetCommandPoolName(VkDevice device, VkCommandPool cmdPool, const char* name)
+{
+ SetObjectName(device, (uint64_t)cmdPool, VK_OBJECT_TYPE_COMMAND_POOL, name);
+}
- void SetEventName(VkDevice device, VkEvent _event, const char * name)
- {
- SetObjectName(device, (uint64_t)_event, VK_OBJECT_TYPE_EVENT, name);
- }
+void SetCommandBufferName(VkDevice device, VkCommandBuffer cmdBuffer, const char* name)
+{
+ SetObjectName(device, (uint64_t)cmdBuffer, VK_OBJECT_TYPE_COMMAND_BUFFER, name);
+}
+void SetQueueName(VkDevice device, VkQueue queue, const char* name)
+{
+ SetObjectName(device, (uint64_t)queue, VK_OBJECT_TYPE_QUEUE, name);
+}
+void SetImageName(VkDevice device, VkImage image, const char* name)
+{
+ SetObjectName(device, (uint64_t)image, VK_OBJECT_TYPE_IMAGE, name);
+}
+void SetImageViewName(VkDevice device, VkImageView imageView, const char* name)
+{
+ SetObjectName(device, (uint64_t)imageView, VK_OBJECT_TYPE_IMAGE_VIEW, name);
+}
- void SetVulkanObjectName(VkDevice device, VkCommandPool cmdPool, const char * name)
- {
- SetCommandPoolName(device, cmdPool, name);
- }
+void SetSamplerName(VkDevice device, VkSampler sampler, const char* name)
+{
+ SetObjectName(device, (uint64_t)sampler, VK_OBJECT_TYPE_SAMPLER, name);
+}
- void SetVulkanObjectName(VkDevice device, VkCommandBuffer cmdBuffer, const char * name)
- {
- SetCommandBufferName(device, cmdBuffer, name);
- }
+void SetBufferName(VkDevice device, VkBuffer buffer, const char* name)
+{
+ SetObjectName(device, (uint64_t)buffer, VK_OBJECT_TYPE_BUFFER, name);
+}
- void SetVulkanObjectName(VkDevice device, VkQueue queue, const char * name)
- {
- SetQueueName(device, queue, name);
- }
+void SetBufferViewName(VkDevice device, VkBufferView bufferView, const char* name)
+{
+ SetObjectName(device, (uint64_t)bufferView, VK_OBJECT_TYPE_BUFFER_VIEW, name);
+}
- void SetVulkanObjectName(VkDevice device, VkImage image, const char * name)
- {
- SetImageName(device, image, name);
- }
+void SetDeviceMemoryName(VkDevice device, VkDeviceMemory memory, const char* name)
+{
+ SetObjectName(device, (uint64_t)memory, VK_OBJECT_TYPE_DEVICE_MEMORY, name);
+}
- void SetVulkanObjectName(VkDevice device, VkImageView imageView, const char * name)
- {
- SetImageViewName(device, imageView, name);
- }
+void SetShaderModuleName(VkDevice device, VkShaderModule shaderModule, const char* name)
+{
+ SetObjectName(device, (uint64_t)shaderModule, VK_OBJECT_TYPE_SHADER_MODULE, name);
+}
- void SetVulkanObjectName(VkDevice device, VkSampler sampler, const char * name)
- {
- SetSamplerName(device, sampler, name);
- }
+void SetPipelineName(VkDevice device, VkPipeline pipeline, const char* name)
+{
+ SetObjectName(device, (uint64_t)pipeline, VK_OBJECT_TYPE_PIPELINE, name);
+}
- void SetVulkanObjectName(VkDevice device, VkBuffer buffer, const char * name)
- {
- SetBufferName(device, buffer, name);
- }
+void SetPipelineLayoutName(VkDevice device, VkPipelineLayout pipelineLayout, const char* name)
+{
+ SetObjectName(device, (uint64_t)pipelineLayout, VK_OBJECT_TYPE_PIPELINE_LAYOUT, name);
+}
- void SetVulkanObjectName(VkDevice device, VkBufferView bufferView, const char * name)
- {
- SetBufferViewName(device, bufferView, name);
- }
+void SetRenderPassName(VkDevice device, VkRenderPass renderPass, const char* name)
+{
+ SetObjectName(device, (uint64_t)renderPass, VK_OBJECT_TYPE_RENDER_PASS, name);
+}
- void SetVulkanObjectName(VkDevice device, VkDeviceMemory memory, const char * name)
- {
- SetDeviceMemoryName(device, memory, name);
- }
+void SetFramebufferName(VkDevice device, VkFramebuffer framebuffer, const char* name)
+{
+ SetObjectName(device, (uint64_t)framebuffer, VK_OBJECT_TYPE_FRAMEBUFFER, name);
+}
- void SetVulkanObjectName(VkDevice device, VkShaderModule shaderModule, const char * name)
- {
- SetShaderModuleName(device, shaderModule, name);
- }
+void SetDescriptorSetLayoutName(VkDevice device, VkDescriptorSetLayout descriptorSetLayout, const char* name)
+{
+ SetObjectName(device, (uint64_t)descriptorSetLayout, VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT, name);
+}
- void SetVulkanObjectName(VkDevice device, VkPipeline pipeline, const char * name)
- {
- SetPipelineName(device, pipeline, name);
- }
+void SetDescriptorSetName(VkDevice device, VkDescriptorSet descriptorSet, const char* name)
+{
+ SetObjectName(device, (uint64_t)descriptorSet, VK_OBJECT_TYPE_DESCRIPTOR_SET, name);
+}
- void SetVulkanObjectName(VkDevice device, VkPipelineLayout pipelineLayout, const char * name)
- {
- SetPipelineLayoutName(device, pipelineLayout, name);
- }
+void SetDescriptorPoolName(VkDevice device, VkDescriptorPool descriptorPool, const char* name)
+{
+ SetObjectName(device, (uint64_t)descriptorPool, VK_OBJECT_TYPE_DESCRIPTOR_POOL, name);
+}
- void SetVulkanObjectName(VkDevice device, VkRenderPass renderPass, const char * name)
- {
- SetRenderPassName(device, renderPass, name);
- }
+void SetSemaphoreName(VkDevice device, VkSemaphore semaphore, const char* name)
+{
+ SetObjectName(device, (uint64_t)semaphore, VK_OBJECT_TYPE_SEMAPHORE, name);
+}
- void SetVulkanObjectName(VkDevice device, VkFramebuffer framebuffer, const char * name)
- {
- SetFramebufferName(device, framebuffer, name);
- }
+void SetFenceName(VkDevice device, VkFence fence, const char* name)
+{
+ SetObjectName(device, (uint64_t)fence, VK_OBJECT_TYPE_FENCE, name);
+}
- void SetVulkanObjectName(VkDevice device, VkDescriptorSetLayout descriptorSetLayout, const char * name)
- {
- SetDescriptorSetLayoutName(device, descriptorSetLayout, name);
- }
+void SetEventName(VkDevice device, VkEvent _event, const char* name)
+{
+ SetObjectName(device, (uint64_t)_event, VK_OBJECT_TYPE_EVENT, name);
+}
- void SetVulkanObjectName(VkDevice device, VkDescriptorSet descriptorSet, const char * name)
- {
- SetDescriptorSetName(device, descriptorSet, name);
- }
- void SetVulkanObjectName(VkDevice device, VkDescriptorPool descriptorPool, const char * name)
- {
- SetDescriptorPoolName(device, descriptorPool, name);
- }
- void SetVulkanObjectName(VkDevice device, VkSemaphore semaphore, const char * name)
- {
- SetSemaphoreName(device, semaphore, name);
- }
- void SetVulkanObjectName(VkDevice device, VkFence fence, const char * name)
- {
- SetFenceName(device, fence, name);
- }
+void SetVulkanObjectName(VkDevice device, VkCommandPool cmdPool, const char* name)
+{
+ SetCommandPoolName(device, cmdPool, name);
+}
- void SetVulkanObjectName(VkDevice device, VkEvent _event, const char * name)
- {
- SetEventName(device, _event, name);
- }
-
+void SetVulkanObjectName(VkDevice device, VkCommandBuffer cmdBuffer, const char* name)
+{
+ SetCommandBufferName(device, cmdBuffer, name);
+}
+
+void SetVulkanObjectName(VkDevice device, VkQueue queue, const char* name)
+{
+ SetQueueName(device, queue, name);
+}
+
+void SetVulkanObjectName(VkDevice device, VkImage image, const char* name)
+{
+ SetImageName(device, image, name);
+}
+
+void SetVulkanObjectName(VkDevice device, VkImageView imageView, const char* name)
+{
+ SetImageViewName(device, imageView, name);
+}
+
+void SetVulkanObjectName(VkDevice device, VkSampler sampler, const char* name)
+{
+ SetSamplerName(device, sampler, name);
+}
+
+void SetVulkanObjectName(VkDevice device, VkBuffer buffer, const char* name)
+{
+ SetBufferName(device, buffer, name);
+}
+
+void SetVulkanObjectName(VkDevice device, VkBufferView bufferView, const char* name)
+{
+ SetBufferViewName(device, bufferView, name);
+}
+
+void SetVulkanObjectName(VkDevice device, VkDeviceMemory memory, const char* name)
+{
+ SetDeviceMemoryName(device, memory, name);
+}
+
+void SetVulkanObjectName(VkDevice device, VkShaderModule shaderModule, const char* name)
+{
+ SetShaderModuleName(device, shaderModule, name);
+}
+
+void SetVulkanObjectName(VkDevice device, VkPipeline pipeline, const char* name)
+{
+ SetPipelineName(device, pipeline, name);
+}
+
+void SetVulkanObjectName(VkDevice device, VkPipelineLayout pipelineLayout, const char* name)
+{
+ SetPipelineLayoutName(device, pipelineLayout, name);
+}
+
+void SetVulkanObjectName(VkDevice device, VkRenderPass renderPass, const char* name)
+{
+ SetRenderPassName(device, renderPass, name);
+}
+
+void SetVulkanObjectName(VkDevice device, VkFramebuffer framebuffer, const char* name)
+{
+ SetFramebufferName(device, framebuffer, name);
+}
+
+void SetVulkanObjectName(VkDevice device, VkDescriptorSetLayout descriptorSetLayout, const char* name)
+{
+ SetDescriptorSetLayoutName(device, descriptorSetLayout, name);
+}
+
+void SetVulkanObjectName(VkDevice device, VkDescriptorSet descriptorSet, const char* name)
+{
+ SetDescriptorSetName(device, descriptorSet, name);
+}
+
+void SetVulkanObjectName(VkDevice device, VkDescriptorPool descriptorPool, const char* name)
+{
+ SetDescriptorPoolName(device, descriptorPool, name);
+}
+void SetVulkanObjectName(VkDevice device, VkSemaphore semaphore, const char* name)
+{
+ SetSemaphoreName(device, semaphore, name);
+}
- const char* VkResultToString(VkResult errorCode)
+void SetVulkanObjectName(VkDevice device, VkFence fence, const char* name)
+{
+ SetFenceName(device, fence, name);
+}
+
+void SetVulkanObjectName(VkDevice device, VkEvent _event, const char* name)
+{
+ SetEventName(device, _event, name);
+}
+
+
+
+const char* VkResultToString(VkResult errorCode)
+{
+ switch (errorCode)
{
- switch (errorCode)
- {
+ // clang-format off
#define STR(r) case VK_ ##r: return #r
- STR(NOT_READY);
- STR(TIMEOUT);
- STR(EVENT_SET);
- STR(EVENT_RESET);
- STR(INCOMPLETE);
- STR(ERROR_OUT_OF_HOST_MEMORY);
- STR(ERROR_OUT_OF_DEVICE_MEMORY);
- STR(ERROR_INITIALIZATION_FAILED);
- STR(ERROR_DEVICE_LOST);
- STR(ERROR_MEMORY_MAP_FAILED);
- STR(ERROR_LAYER_NOT_PRESENT);
- STR(ERROR_EXTENSION_NOT_PRESENT);
- STR(ERROR_FEATURE_NOT_PRESENT);
- STR(ERROR_INCOMPATIBLE_DRIVER);
- STR(ERROR_TOO_MANY_OBJECTS);
- STR(ERROR_FORMAT_NOT_SUPPORTED);
- STR(ERROR_SURFACE_LOST_KHR);
- STR(ERROR_NATIVE_WINDOW_IN_USE_KHR);
- STR(SUBOPTIMAL_KHR);
- STR(ERROR_OUT_OF_DATE_KHR);
- STR(ERROR_INCOMPATIBLE_DISPLAY_KHR);
- STR(ERROR_VALIDATION_FAILED_EXT);
- STR(ERROR_INVALID_SHADER_NV);
+ STR(NOT_READY);
+ STR(TIMEOUT);
+ STR(EVENT_SET);
+ STR(EVENT_RESET);
+ STR(INCOMPLETE);
+ STR(ERROR_OUT_OF_HOST_MEMORY);
+ STR(ERROR_OUT_OF_DEVICE_MEMORY);
+ STR(ERROR_INITIALIZATION_FAILED);
+ STR(ERROR_DEVICE_LOST);
+ STR(ERROR_MEMORY_MAP_FAILED);
+ STR(ERROR_LAYER_NOT_PRESENT);
+ STR(ERROR_EXTENSION_NOT_PRESENT);
+ STR(ERROR_FEATURE_NOT_PRESENT);
+ STR(ERROR_INCOMPATIBLE_DRIVER);
+ STR(ERROR_TOO_MANY_OBJECTS);
+ STR(ERROR_FORMAT_NOT_SUPPORTED);
+ STR(ERROR_SURFACE_LOST_KHR);
+ STR(ERROR_NATIVE_WINDOW_IN_USE_KHR);
+ STR(SUBOPTIMAL_KHR);
+ STR(ERROR_OUT_OF_DATE_KHR);
+ STR(ERROR_INCOMPATIBLE_DISPLAY_KHR);
+ STR(ERROR_VALIDATION_FAILED_EXT);
+ STR(ERROR_INVALID_SHADER_NV);
#undef STR
+ // clang-format on
default:
return "UNKNOWN_ERROR";
- }
}
+}
- const char* VkAccessFlagBitToString(VkAccessFlagBits Bit)
+const char* VkAccessFlagBitToString(VkAccessFlagBits Bit)
+{
+ VERIFY(Bit != 0 && (Bit & (Bit - 1)) == 0, "Single bit is expected");
+ switch (Bit)
{
- VERIFY(Bit != 0 && (Bit & (Bit-1)) == 0, "Single bit is expected");
- switch(Bit)
- {
+ // clang-format off
#define ACCESS_FLAG_BIT_TO_STRING(ACCESS_FLAG_BIT)case ACCESS_FLAG_BIT: return #ACCESS_FLAG_BIT;
- ACCESS_FLAG_BIT_TO_STRING(VK_ACCESS_INDIRECT_COMMAND_READ_BIT)
- ACCESS_FLAG_BIT_TO_STRING(VK_ACCESS_INDEX_READ_BIT)
- ACCESS_FLAG_BIT_TO_STRING(VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT)
- ACCESS_FLAG_BIT_TO_STRING(VK_ACCESS_UNIFORM_READ_BIT)
- ACCESS_FLAG_BIT_TO_STRING(VK_ACCESS_INPUT_ATTACHMENT_READ_BIT)
- ACCESS_FLAG_BIT_TO_STRING(VK_ACCESS_SHADER_READ_BIT)
- ACCESS_FLAG_BIT_TO_STRING(VK_ACCESS_SHADER_WRITE_BIT)
- ACCESS_FLAG_BIT_TO_STRING(VK_ACCESS_COLOR_ATTACHMENT_READ_BIT)
- ACCESS_FLAG_BIT_TO_STRING(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT)
- ACCESS_FLAG_BIT_TO_STRING(VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT)
- ACCESS_FLAG_BIT_TO_STRING(VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT)
- ACCESS_FLAG_BIT_TO_STRING(VK_ACCESS_TRANSFER_READ_BIT)
- ACCESS_FLAG_BIT_TO_STRING(VK_ACCESS_TRANSFER_WRITE_BIT)
- ACCESS_FLAG_BIT_TO_STRING(VK_ACCESS_HOST_READ_BIT)
- ACCESS_FLAG_BIT_TO_STRING(VK_ACCESS_HOST_WRITE_BIT)
- ACCESS_FLAG_BIT_TO_STRING(VK_ACCESS_MEMORY_READ_BIT)
- ACCESS_FLAG_BIT_TO_STRING(VK_ACCESS_MEMORY_WRITE_BIT)
+ ACCESS_FLAG_BIT_TO_STRING(VK_ACCESS_INDIRECT_COMMAND_READ_BIT)
+ ACCESS_FLAG_BIT_TO_STRING(VK_ACCESS_INDEX_READ_BIT)
+ ACCESS_FLAG_BIT_TO_STRING(VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT)
+ ACCESS_FLAG_BIT_TO_STRING(VK_ACCESS_UNIFORM_READ_BIT)
+ ACCESS_FLAG_BIT_TO_STRING(VK_ACCESS_INPUT_ATTACHMENT_READ_BIT)
+ ACCESS_FLAG_BIT_TO_STRING(VK_ACCESS_SHADER_READ_BIT)
+ ACCESS_FLAG_BIT_TO_STRING(VK_ACCESS_SHADER_WRITE_BIT)
+ ACCESS_FLAG_BIT_TO_STRING(VK_ACCESS_COLOR_ATTACHMENT_READ_BIT)
+ ACCESS_FLAG_BIT_TO_STRING(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT)
+ ACCESS_FLAG_BIT_TO_STRING(VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT)
+ ACCESS_FLAG_BIT_TO_STRING(VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT)
+ ACCESS_FLAG_BIT_TO_STRING(VK_ACCESS_TRANSFER_READ_BIT)
+ ACCESS_FLAG_BIT_TO_STRING(VK_ACCESS_TRANSFER_WRITE_BIT)
+ ACCESS_FLAG_BIT_TO_STRING(VK_ACCESS_HOST_READ_BIT)
+ ACCESS_FLAG_BIT_TO_STRING(VK_ACCESS_HOST_WRITE_BIT)
+ ACCESS_FLAG_BIT_TO_STRING(VK_ACCESS_MEMORY_READ_BIT)
+ ACCESS_FLAG_BIT_TO_STRING(VK_ACCESS_MEMORY_WRITE_BIT)
#undef ACCESS_FLAG_BIT_TO_STRING
- default: UNEXPECTED("Unexpected bit"); return "";
- }
+ default: UNEXPECTED("Unexpected bit"); return "";
+ // clang-format on
}
+}
- const char* VkImageLayoutToString(VkImageLayout Layout)
+const char* VkImageLayoutToString(VkImageLayout Layout)
+{
+ switch (Layout)
{
- switch(Layout)
- {
+ // clang-format off
#define IMAGE_LAYOUT_TO_STRING(LAYOUT)case LAYOUT: return #LAYOUT;
- IMAGE_LAYOUT_TO_STRING(VK_IMAGE_LAYOUT_UNDEFINED)
- IMAGE_LAYOUT_TO_STRING(VK_IMAGE_LAYOUT_GENERAL)
- IMAGE_LAYOUT_TO_STRING(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)
- IMAGE_LAYOUT_TO_STRING(VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)
- IMAGE_LAYOUT_TO_STRING(VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL)
- IMAGE_LAYOUT_TO_STRING(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
- IMAGE_LAYOUT_TO_STRING(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL)
- IMAGE_LAYOUT_TO_STRING(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL)
- IMAGE_LAYOUT_TO_STRING(VK_IMAGE_LAYOUT_PREINITIALIZED)
- IMAGE_LAYOUT_TO_STRING(VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL)
- IMAGE_LAYOUT_TO_STRING(VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL)
- IMAGE_LAYOUT_TO_STRING(VK_IMAGE_LAYOUT_PRESENT_SRC_KHR)
- IMAGE_LAYOUT_TO_STRING(VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR)
+ IMAGE_LAYOUT_TO_STRING(VK_IMAGE_LAYOUT_UNDEFINED)
+ IMAGE_LAYOUT_TO_STRING(VK_IMAGE_LAYOUT_GENERAL)
+ IMAGE_LAYOUT_TO_STRING(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)
+ IMAGE_LAYOUT_TO_STRING(VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)
+ IMAGE_LAYOUT_TO_STRING(VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL)
+ IMAGE_LAYOUT_TO_STRING(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
+ IMAGE_LAYOUT_TO_STRING(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL)
+ IMAGE_LAYOUT_TO_STRING(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL)
+ IMAGE_LAYOUT_TO_STRING(VK_IMAGE_LAYOUT_PREINITIALIZED)
+ IMAGE_LAYOUT_TO_STRING(VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL)
+ IMAGE_LAYOUT_TO_STRING(VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL)
+ IMAGE_LAYOUT_TO_STRING(VK_IMAGE_LAYOUT_PRESENT_SRC_KHR)
+ IMAGE_LAYOUT_TO_STRING(VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR)
#undef IMAGE_LAYOUT_TO_STRING
- default: UNEXPECTED("Unknown layout"); return "";
- }
+ default: UNEXPECTED("Unknown layout"); return "";
+ // clang-format on
}
+}
- std::string VkAccessFlagsToString(VkAccessFlags Flags)
+std::string VkAccessFlagsToString(VkAccessFlags Flags)
+{
+ std::string FlagsString;
+ while (Flags != 0)
{
- std::string FlagsString;
- while(Flags != 0)
- {
- auto Bit = Flags & ~(Flags - 1);
- if (!FlagsString.empty())
- FlagsString += ", ";
- FlagsString += VkAccessFlagBitToString( static_cast<VkAccessFlagBits>(Bit) );
- Flags = Flags & (Flags - 1);
- }
- return std::move(FlagsString);
+ auto Bit = Flags & ~(Flags - 1);
+ if (!FlagsString.empty())
+ FlagsString += ", ";
+ FlagsString += VkAccessFlagBitToString(static_cast<VkAccessFlagBits>(Bit));
+ Flags = Flags & (Flags - 1);
}
+ return std::move(FlagsString);
+}
- const char* VkObjectTypeToString(VkObjectType ObjectType)
- {
- switch(ObjectType)
- {
- case VK_OBJECT_TYPE_UNKNOWN: return "unknown";
- case VK_OBJECT_TYPE_INSTANCE: return "instance";
- case VK_OBJECT_TYPE_PHYSICAL_DEVICE: return "physical device";
- case VK_OBJECT_TYPE_DEVICE: return "device";
- case VK_OBJECT_TYPE_QUEUE: return "queue";
- case VK_OBJECT_TYPE_SEMAPHORE: return "semaphore";
- case VK_OBJECT_TYPE_COMMAND_BUFFER: return "cmd buffer";
- case VK_OBJECT_TYPE_FENCE: return "fence";
- case VK_OBJECT_TYPE_DEVICE_MEMORY: return "memory";
- case VK_OBJECT_TYPE_BUFFER: return "buffer";
- case VK_OBJECT_TYPE_IMAGE: return "image";
- case VK_OBJECT_TYPE_EVENT: return "event";
- case VK_OBJECT_TYPE_QUERY_POOL: return "query pool";
- case VK_OBJECT_TYPE_BUFFER_VIEW: return "buffer view";
- case VK_OBJECT_TYPE_IMAGE_VIEW: return "image view";
- case VK_OBJECT_TYPE_SHADER_MODULE: return "shader module";
- case VK_OBJECT_TYPE_PIPELINE_CACHE: return "pipeline cache";
- case VK_OBJECT_TYPE_PIPELINE_LAYOUT: return "pipeline layout";
- case VK_OBJECT_TYPE_RENDER_PASS: return "render pass";
- case VK_OBJECT_TYPE_PIPELINE: return "pipeline";
- case VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT: return "descriptor set layout";
- case VK_OBJECT_TYPE_SAMPLER: return "sampler";
- case VK_OBJECT_TYPE_DESCRIPTOR_POOL: return "descriptor pool";
- case VK_OBJECT_TYPE_DESCRIPTOR_SET: return "descriptor set";
- case VK_OBJECT_TYPE_FRAMEBUFFER: return "framebuffer";
- case VK_OBJECT_TYPE_COMMAND_POOL: return "command pool";
- case VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION: return "sampler ycbcr conversion";
- case VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE: return "descriptor update template";
- case VK_OBJECT_TYPE_SURFACE_KHR: return "surface KHR";
- case VK_OBJECT_TYPE_SWAPCHAIN_KHR: return "swapchain KHR";
- case VK_OBJECT_TYPE_DISPLAY_KHR: return "display KHR";
- case VK_OBJECT_TYPE_DISPLAY_MODE_KHR: return "display mode KHR";
- case VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT: return "debug report callback";
- case VK_OBJECT_TYPE_OBJECT_TABLE_NVX: return "object tabke NVX";
- case VK_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX: return "indirect cmd layout NVX";
- case VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT: return "debug utils messenger";
- case VK_OBJECT_TYPE_VALIDATION_CACHE_EXT: return "validation cache";
- case VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_NVX: return "acceleration structure NVX";
- default: return "unknown";
- }
+const char* VkObjectTypeToString(VkObjectType ObjectType)
+{
+ switch (ObjectType)
+ {
+ // clang-format off
+ case VK_OBJECT_TYPE_UNKNOWN: return "unknown";
+ case VK_OBJECT_TYPE_INSTANCE: return "instance";
+ case VK_OBJECT_TYPE_PHYSICAL_DEVICE: return "physical device";
+ case VK_OBJECT_TYPE_DEVICE: return "device";
+ case VK_OBJECT_TYPE_QUEUE: return "queue";
+ case VK_OBJECT_TYPE_SEMAPHORE: return "semaphore";
+ case VK_OBJECT_TYPE_COMMAND_BUFFER: return "cmd buffer";
+ case VK_OBJECT_TYPE_FENCE: return "fence";
+ case VK_OBJECT_TYPE_DEVICE_MEMORY: return "memory";
+ case VK_OBJECT_TYPE_BUFFER: return "buffer";
+ case VK_OBJECT_TYPE_IMAGE: return "image";
+ case VK_OBJECT_TYPE_EVENT: return "event";
+ case VK_OBJECT_TYPE_QUERY_POOL: return "query pool";
+ case VK_OBJECT_TYPE_BUFFER_VIEW: return "buffer view";
+ case VK_OBJECT_TYPE_IMAGE_VIEW: return "image view";
+ case VK_OBJECT_TYPE_SHADER_MODULE: return "shader module";
+ case VK_OBJECT_TYPE_PIPELINE_CACHE: return "pipeline cache";
+ case VK_OBJECT_TYPE_PIPELINE_LAYOUT: return "pipeline layout";
+ case VK_OBJECT_TYPE_RENDER_PASS: return "render pass";
+ case VK_OBJECT_TYPE_PIPELINE: return "pipeline";
+ case VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT: return "descriptor set layout";
+ case VK_OBJECT_TYPE_SAMPLER: return "sampler";
+ case VK_OBJECT_TYPE_DESCRIPTOR_POOL: return "descriptor pool";
+ case VK_OBJECT_TYPE_DESCRIPTOR_SET: return "descriptor set";
+ case VK_OBJECT_TYPE_FRAMEBUFFER: return "framebuffer";
+ case VK_OBJECT_TYPE_COMMAND_POOL: return "command pool";
+ case VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION: return "sampler ycbcr conversion";
+ case VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE: return "descriptor update template";
+ case VK_OBJECT_TYPE_SURFACE_KHR: return "surface KHR";
+ case VK_OBJECT_TYPE_SWAPCHAIN_KHR: return "swapchain KHR";
+ case VK_OBJECT_TYPE_DISPLAY_KHR: return "display KHR";
+ case VK_OBJECT_TYPE_DISPLAY_MODE_KHR: return "display mode KHR";
+ case VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT: return "debug report callback";
+ case VK_OBJECT_TYPE_OBJECT_TABLE_NVX: return "object tabke NVX";
+ case VK_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX: return "indirect cmd layout NVX";
+ case VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT: return "debug utils messenger";
+ case VK_OBJECT_TYPE_VALIDATION_CACHE_EXT: return "validation cache";
+ case VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_NVX: return "acceleration structure NVX";
+ default: return "unknown";
+ // clang-format on
}
}
+
+} // namespace VulkanUtilities
diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanFencePool.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanFencePool.cpp
index 6d153fd7..c527d497 100644
--- a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanFencePool.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanFencePool.cpp
@@ -28,44 +28,48 @@
namespace VulkanUtilities
{
- VulkanFencePool::VulkanFencePool(std::shared_ptr<const VulkanLogicalDevice> LogicalDevice)noexcept :
- m_LogicalDevice{std::move(LogicalDevice)}
- {}
- VulkanFencePool::~VulkanFencePool()
- {
+VulkanFencePool::VulkanFencePool(std::shared_ptr<const VulkanLogicalDevice> LogicalDevice) noexcept :
+ m_LogicalDevice{std::move(LogicalDevice)}
+{}
+
+VulkanFencePool::~VulkanFencePool()
+{
#ifdef DEVELOPMENT
- for (const auto& fence : m_Fences)
- {
- DEV_CHECK_ERR(m_LogicalDevice->GetFenceStatus(fence) == VK_SUCCESS, "Destroying a fence that has not been signaled");
- }
-#endif
- m_Fences.clear();
+ for (const auto& fence : m_Fences)
+ {
+ DEV_CHECK_ERR(m_LogicalDevice->GetFenceStatus(fence) == VK_SUCCESS, "Destroying a fence that has not been signaled");
}
+#endif
+ m_Fences.clear();
+}
- FenceWrapper VulkanFencePool::GetFence()
+FenceWrapper VulkanFencePool::GetFence()
+{
+ FenceWrapper Fence;
+ if (!m_Fences.empty())
{
- FenceWrapper Fence;
- if(!m_Fences.empty())
- {
- Fence = std::move(m_Fences.back());
- m_LogicalDevice->ResetFence(Fence);
- m_Fences.pop_back();
- }
- else
- {
- VkFenceCreateInfo FenceCI = {};
- FenceCI.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
- FenceCI.pNext = nullptr;
- FenceCI.flags = 0; // Available flag: VK_FENCE_CREATE_SIGNALED_BIT
- Fence = m_LogicalDevice->CreateFence(FenceCI);
- }
- return Fence;
+ Fence = std::move(m_Fences.back());
+ m_LogicalDevice->ResetFence(Fence);
+ m_Fences.pop_back();
}
-
- void VulkanFencePool::DisposeFence(FenceWrapper&& Fence)
+ else
{
- DEV_CHECK_ERR(m_LogicalDevice->GetFenceStatus(Fence) == VK_SUCCESS, "Disposing a fence that has not been signaled");
- m_Fences.emplace_back(std::move(Fence));
+ VkFenceCreateInfo FenceCI = {};
+
+ FenceCI.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
+ FenceCI.pNext = nullptr;
+ FenceCI.flags = 0; // Available flag: VK_FENCE_CREATE_SIGNALED_BIT
+
+ Fence = m_LogicalDevice->CreateFence(FenceCI);
}
+ return Fence;
}
+
+void VulkanFencePool::DisposeFence(FenceWrapper&& Fence)
+{
+ DEV_CHECK_ERR(m_LogicalDevice->GetFenceStatus(Fence) == VK_SUCCESS, "Disposing a fence that has not been signaled");
+ m_Fences.emplace_back(std::move(Fence));
+}
+
+} // namespace VulkanUtilities
diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanInstance.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanInstance.cpp
index 03baf0fa..ebad66bf 100644
--- a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanInstance.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanInstance.cpp
@@ -28,252 +28,260 @@
#include "VulkanUtilities/VulkanDebug.h"
#if !NO_GLSLANG
-#include "SPIRVUtils.h"
+# include "SPIRVUtils.h"
#endif
#include "PlatformDefinitions.h"
namespace VulkanUtilities
{
- bool VulkanInstance::IsLayerAvailable(const char* LayerName)const
- {
- for (const auto& Layer : m_Layers)
- if (strcmp(Layer.layerName, LayerName) == 0)
- return true;
- return false;
- }
+bool VulkanInstance::IsLayerAvailable(const char* LayerName) const
+{
+ for (const auto& Layer : m_Layers)
+ if (strcmp(Layer.layerName, LayerName) == 0)
+ return true;
- bool VulkanInstance::IsExtensionAvailable(const char* ExtensionName)const
- {
- for (const auto& Extension : m_Extensions)
- if (strcmp(Extension.extensionName, ExtensionName) == 0)
- return true;
+ return false;
+}
- return false;
- }
+bool VulkanInstance::IsExtensionAvailable(const char* ExtensionName) const
+{
+ for (const auto& Extension : m_Extensions)
+ if (strcmp(Extension.extensionName, ExtensionName) == 0)
+ return true;
+
+ return false;
+}
+
+std::shared_ptr<VulkanInstance> VulkanInstance::Create(bool EnableValidation,
+ uint32_t GlobalExtensionCount,
+ const char* const* ppGlobalExtensionNames,
+ VkAllocationCallbacks* pVkAllocator)
+{
+ auto Instance = new VulkanInstance{EnableValidation, GlobalExtensionCount, ppGlobalExtensionNames, pVkAllocator};
+ return std::shared_ptr<VulkanInstance>{Instance};
+}
- std::shared_ptr<VulkanInstance> VulkanInstance::Create(bool EnableValidation,
- uint32_t GlobalExtensionCount,
- const char* const* ppGlobalExtensionNames,
- VkAllocationCallbacks* pVkAllocator)
+VulkanInstance::VulkanInstance(bool EnableValidation,
+ uint32_t GlobalExtensionCount,
+ const char* const* ppGlobalExtensionNames,
+ VkAllocationCallbacks* pVkAllocator) :
+ m_pVkAllocator{pVkAllocator}
+{
{
- auto Instance = new VulkanInstance{EnableValidation, GlobalExtensionCount, ppGlobalExtensionNames, pVkAllocator};
- return std::shared_ptr<VulkanInstance>{Instance};
+ // Enumerate available layers
+ uint32_t LayerCount = 0;
+
+ auto res = vkEnumerateInstanceLayerProperties(&LayerCount, nullptr);
+ CHECK_VK_ERROR_AND_THROW(res, "Failed to query layer count");
+ m_Layers.resize(LayerCount);
+ vkEnumerateInstanceLayerProperties(&LayerCount, m_Layers.data());
+ CHECK_VK_ERROR_AND_THROW(res, "Failed to enumerate extensions");
+ VERIFY_EXPR(LayerCount == m_Layers.size());
}
- VulkanInstance::VulkanInstance(bool EnableValidation,
- uint32_t GlobalExtensionCount,
- const char* const* ppGlobalExtensionNames,
- VkAllocationCallbacks* pVkAllocator) :
- m_pVkAllocator{pVkAllocator}
{
- {
- // Enumerate available layers
- uint32_t LayerCount = 0;
- auto res = vkEnumerateInstanceLayerProperties(&LayerCount, nullptr);
- CHECK_VK_ERROR_AND_THROW(res, "Failed to query layer count");
- m_Layers.resize(LayerCount);
- vkEnumerateInstanceLayerProperties(&LayerCount, m_Layers.data());
- CHECK_VK_ERROR_AND_THROW(res, "Failed to enumerate extensions");
- VERIFY_EXPR(LayerCount == m_Layers.size());
- }
+ // Enumerate available extensions
+ uint32_t ExtensionCount = 0;
- {
- // Enumerate available extensions
- uint32_t ExtensionCount = 0;
- auto res = vkEnumerateInstanceExtensionProperties(nullptr, &ExtensionCount, nullptr);
- CHECK_VK_ERROR_AND_THROW(res, "Failed to query extension count");
- m_Extensions.resize(ExtensionCount);
- vkEnumerateInstanceExtensionProperties(nullptr, &ExtensionCount, m_Extensions.data());
- CHECK_VK_ERROR_AND_THROW(res, "Failed to enumerate extensions");
- VERIFY_EXPR(ExtensionCount == m_Extensions.size());
- }
+ auto res = vkEnumerateInstanceExtensionProperties(nullptr, &ExtensionCount, nullptr);
+ CHECK_VK_ERROR_AND_THROW(res, "Failed to query extension count");
+ m_Extensions.resize(ExtensionCount);
+ vkEnumerateInstanceExtensionProperties(nullptr, &ExtensionCount, m_Extensions.data());
+ CHECK_VK_ERROR_AND_THROW(res, "Failed to enumerate extensions");
+ VERIFY_EXPR(ExtensionCount == m_Extensions.size());
+ }
- std::vector<const char*> GlobalExtensions =
- {
- VK_KHR_SURFACE_EXTENSION_NAME,
+ std::vector<const char*> GlobalExtensions =
+ {
+ VK_KHR_SURFACE_EXTENSION_NAME,
- // Enable surface extensions depending on OS
+ // Enable surface extensions depending on OS
#if defined(VK_USE_PLATFORM_WIN32_KHR)
- VK_KHR_WIN32_SURFACE_EXTENSION_NAME
+ VK_KHR_WIN32_SURFACE_EXTENSION_NAME
#elif defined(VK_USE_PLATFORM_ANDROID_KHR)
- VK_KHR_ANDROID_SURFACE_EXTENSION_NAME
+ VK_KHR_ANDROID_SURFACE_EXTENSION_NAME
#elif defined(VK_USE_PLATFORM_WAYLAND_KHR)
- VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME
+ VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME
#elif defined(VK_USE_PLATFORM_XCB_KHR)
- VK_KHR_XCB_SURFACE_EXTENSION_NAME
+ VK_KHR_XCB_SURFACE_EXTENSION_NAME
#elif defined(VK_USE_PLATFORM_IOS_MVK)
- VK_MVK_IOS_SURFACE_EXTENSION_NAME
+ VK_MVK_IOS_SURFACE_EXTENSION_NAME
#elif defined(VK_USE_PLATFORM_MACOS_MVK)
- VK_MVK_MACOS_SURFACE_EXTENSION_NAME
+ VK_MVK_MACOS_SURFACE_EXTENSION_NAME
#endif
- };
+ };
- if (ppGlobalExtensionNames != nullptr)
+ if (ppGlobalExtensionNames != nullptr)
+ {
+ for (uint32_t ext = 0; ext < GlobalExtensionCount; ++ext)
+ GlobalExtensions.push_back(ppGlobalExtensionNames[ext]);
+ }
+ else
+ {
+ if (GlobalExtensionCount != 0)
+ LOG_ERROR_MESSAGE("Global extensions pointer is null while extensions count is ", GlobalExtensionCount,
+ ". Please initialize 'ppGlobalExtensionNames' member of EngineVkCreateInfo struct.");
+ }
+
+ for (const auto* ExtName : GlobalExtensions)
+ {
+ if (!IsExtensionAvailable(ExtName))
+ LOG_ERROR_AND_THROW("Required extension ", ExtName, " is not available");
+ }
+
+ if (EnableValidation)
+ {
+ m_DebugUtilsEnabled = IsExtensionAvailable(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
+ if (m_DebugUtilsEnabled)
{
- for (uint32_t ext = 0; ext < GlobalExtensionCount; ++ext)
- GlobalExtensions.push_back(ppGlobalExtensionNames[ext]);
+ GlobalExtensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
}
else
{
- if (GlobalExtensionCount != 0)
- LOG_ERROR_MESSAGE("Global extensions pointer is null while extensions count is ", GlobalExtensionCount, ". "
- "Please initialize 'ppGlobalExtensionNames' member of EngineVkCreateInfo struct.");
+ LOG_WARNING_MESSAGE("Extension ", VK_EXT_DEBUG_UTILS_EXTENSION_NAME, " is not available.");
}
+ }
- for(const auto* ExtName : GlobalExtensions)
- {
- if (!IsExtensionAvailable(ExtName))
- LOG_ERROR_AND_THROW("Required extension ", ExtName, " is not available");
- }
+ VkApplicationInfo appInfo = {};
- if (EnableValidation)
- {
- m_DebugUtilsEnabled = IsExtensionAvailable(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
- if (m_DebugUtilsEnabled)
- {
- GlobalExtensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
- }
- else
- {
- LOG_WARNING_MESSAGE("Extension ", VK_EXT_DEBUG_UTILS_EXTENSION_NAME, " is not available.");
- }
- }
+ appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
+ appInfo.pNext = nullptr; // Pointer to an extension-specific structure.
+ appInfo.pApplicationName = nullptr;
+ appInfo.applicationVersion = 0; // Developer-supplied version number of the application
+ appInfo.pEngineName = "Diligent Engine";
+ appInfo.engineVersion = 0; // Developer-supplied version number of the engine used to create the application.
+ appInfo.apiVersion = VK_API_VERSION_1_0;
+
+ VkInstanceCreateInfo InstanceCreateInfo = {};
- VkApplicationInfo appInfo = {};
- appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
- appInfo.pNext = nullptr; // Pointer to an extension-specific structure.
- appInfo.pApplicationName = nullptr;
- appInfo.applicationVersion = 0; // Developer-supplied version number of the application
- appInfo.pEngineName = "Diligent Engine";
- appInfo.engineVersion = 0;// Developer-supplied version number of the engine used to create the application.
- appInfo.apiVersion = VK_API_VERSION_1_0;
-
- VkInstanceCreateInfo InstanceCreateInfo = {};
- InstanceCreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
- InstanceCreateInfo.pNext = nullptr; // Pointer to an extension-specific structure.
- InstanceCreateInfo.flags = 0; // Reserved for future use.
- InstanceCreateInfo.pApplicationInfo = &appInfo;
- InstanceCreateInfo.enabledExtensionCount = static_cast<uint32_t>(GlobalExtensions.size());
- InstanceCreateInfo.ppEnabledExtensionNames = GlobalExtensions.empty() ? nullptr : GlobalExtensions.data();
-
- if (EnableValidation)
+ InstanceCreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
+ InstanceCreateInfo.pNext = nullptr; // Pointer to an extension-specific structure.
+ InstanceCreateInfo.flags = 0; // Reserved for future use.
+ InstanceCreateInfo.pApplicationInfo = &appInfo;
+ InstanceCreateInfo.enabledExtensionCount = static_cast<uint32_t>(GlobalExtensions.size());
+ InstanceCreateInfo.ppEnabledExtensionNames = GlobalExtensions.empty() ? nullptr : GlobalExtensions.data();
+
+ if (EnableValidation)
+ {
+ bool ValidationLayersPresent = true;
+ for (size_t l = 0; l < _countof(VulkanUtilities::ValidationLayerNames); ++l)
{
- bool ValidationLayersPresent = true;
- for (size_t l = 0; l < _countof(VulkanUtilities::ValidationLayerNames); ++l)
+ auto* pLayerName = VulkanUtilities::ValidationLayerNames[l];
+ if (!IsLayerAvailable(pLayerName))
{
- auto* pLayerName = VulkanUtilities::ValidationLayerNames[l];
- if (!IsLayerAvailable(pLayerName))
- {
- ValidationLayersPresent = false;
- LOG_ERROR_MESSAGE("Failed to find ", pLayerName, " layer. Validation will be disabled");
- }
- }
- if (ValidationLayersPresent)
- {
- InstanceCreateInfo.enabledLayerCount = static_cast<uint32_t>(_countof(VulkanUtilities::ValidationLayerNames));
- InstanceCreateInfo.ppEnabledLayerNames = VulkanUtilities::ValidationLayerNames;
+ ValidationLayersPresent = false;
+ LOG_ERROR_MESSAGE("Failed to find ", pLayerName, " layer. Validation will be disabled");
}
}
- auto res = vkCreateInstance(&InstanceCreateInfo, m_pVkAllocator, &m_VkInstance);
- CHECK_VK_ERROR_AND_THROW(res, "Failed to create Vulkan instance");
-
- // If requested, we enable the default validation layers for debugging
- if (m_DebugUtilsEnabled)
+ if (ValidationLayersPresent)
{
- VkDebugUtilsMessageSeverityFlagsEXT messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT |
- VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
- VkDebugUtilsMessageTypeFlagsEXT messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |
- VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT |
- VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
- VulkanUtilities::SetupDebugging(m_VkInstance, messageSeverity, messageType, nullptr);
+ InstanceCreateInfo.enabledLayerCount = static_cast<uint32_t>(_countof(VulkanUtilities::ValidationLayerNames));
+ InstanceCreateInfo.ppEnabledLayerNames = VulkanUtilities::ValidationLayerNames;
}
+ }
+ auto res = vkCreateInstance(&InstanceCreateInfo, m_pVkAllocator, &m_VkInstance);
+ CHECK_VK_ERROR_AND_THROW(res, "Failed to create Vulkan instance");
- // Enumerate physical devices
- {
- // Physical device
- uint32_t PhysicalDeviceCount = 0;
- // Get the number of available physical devices
- auto err = vkEnumeratePhysicalDevices(m_VkInstance, &PhysicalDeviceCount, nullptr);
- CHECK_VK_ERROR(err, "Failed to get physical device count");
- if (PhysicalDeviceCount == 0)
- LOG_ERROR_AND_THROW("No physical devices found on the system");
-
- // Enumerate devices
- m_PhysicalDevices.resize(PhysicalDeviceCount);
- err = vkEnumeratePhysicalDevices(m_VkInstance, &PhysicalDeviceCount, m_PhysicalDevices.data());
- CHECK_VK_ERROR(err, "Failed to enumerate physical devices");
- VERIFY_EXPR(m_PhysicalDevices.size() == PhysicalDeviceCount);
- }
-#if !NO_GLSLANG
- Diligent::InitializeGlslang();
-#endif
+ // If requested, we enable the default validation layers for debugging
+ if (m_DebugUtilsEnabled)
+ {
+ VkDebugUtilsMessageSeverityFlagsEXT messageSeverity =
+ VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT |
+ VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
+ VkDebugUtilsMessageTypeFlagsEXT messageType =
+ VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |
+ VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT |
+ VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
+ VulkanUtilities::SetupDebugging(m_VkInstance, messageSeverity, messageType, nullptr);
}
- VulkanInstance::~VulkanInstance()
+ // Enumerate physical devices
{
- if (m_DebugUtilsEnabled)
- {
- VulkanUtilities::FreeDebugging(m_VkInstance);
- }
- vkDestroyInstance(m_VkInstance, m_pVkAllocator);
+ // Physical device
+ uint32_t PhysicalDeviceCount = 0;
+ // Get the number of available physical devices
+ auto err = vkEnumeratePhysicalDevices(m_VkInstance, &PhysicalDeviceCount, nullptr);
+ CHECK_VK_ERROR(err, "Failed to get physical device count");
+ if (PhysicalDeviceCount == 0)
+ LOG_ERROR_AND_THROW("No physical devices found on the system");
+ // Enumerate devices
+ m_PhysicalDevices.resize(PhysicalDeviceCount);
+ err = vkEnumeratePhysicalDevices(m_VkInstance, &PhysicalDeviceCount, m_PhysicalDevices.data());
+ CHECK_VK_ERROR(err, "Failed to enumerate physical devices");
+ VERIFY_EXPR(m_PhysicalDevices.size() == PhysicalDeviceCount);
+ }
#if !NO_GLSLANG
- Diligent::FinalizeGlslang();
+ Diligent::InitializeGlslang();
#endif
+}
+
+VulkanInstance::~VulkanInstance()
+{
+ if (m_DebugUtilsEnabled)
+ {
+ VulkanUtilities::FreeDebugging(m_VkInstance);
}
+ vkDestroyInstance(m_VkInstance, m_pVkAllocator);
- VkPhysicalDevice VulkanInstance::SelectPhysicalDevice()const
+#if !NO_GLSLANG
+ Diligent::FinalizeGlslang();
+#endif
+}
+
+VkPhysicalDevice VulkanInstance::SelectPhysicalDevice() const
+{
+ VkPhysicalDevice SelectedPhysicalDevice = VK_NULL_HANDLE;
+
+ // Select a device that exposes a queue family that suppors both compute and graphics operations
+ // Prefer discrete GPU
+ for (auto Device : m_PhysicalDevices)
{
- VkPhysicalDevice SelectedPhysicalDevice = VK_NULL_HANDLE;
+ VkPhysicalDeviceProperties DeviceProps;
+ vkGetPhysicalDeviceProperties(Device, &DeviceProps);
+
+ uint32_t QueueFamilyCount = 0;
+ vkGetPhysicalDeviceQueueFamilyProperties(Device, &QueueFamilyCount, nullptr);
+ VERIFY_EXPR(QueueFamilyCount > 0);
+ std::vector<VkQueueFamilyProperties> QueueFamilyProperties(QueueFamilyCount);
+ vkGetPhysicalDeviceQueueFamilyProperties(Device, &QueueFamilyCount, QueueFamilyProperties.data());
+ VERIFY_EXPR(QueueFamilyCount == QueueFamilyProperties.size());
- // Select a device that exposes a queue family that suppors both compute and graphics operations
- // Prefer discrete GPU
- for (auto Device : m_PhysicalDevices)
+ // If an implementation exposes any queue family that supports graphics operations,
+ // at least one queue family of at least one physical device exposed by the implementation
+ // must support both graphics and compute operations.
+ bool GraphicsAndComputeQueueSupported = false;
+ for (const auto& QueueFamilyProps : QueueFamilyProperties)
{
- VkPhysicalDeviceProperties DeviceProps;
- vkGetPhysicalDeviceProperties(Device, &DeviceProps);
-
- uint32_t QueueFamilyCount = 0;
- vkGetPhysicalDeviceQueueFamilyProperties(Device, &QueueFamilyCount, nullptr);
- VERIFY_EXPR(QueueFamilyCount > 0);
- std::vector<VkQueueFamilyProperties> QueueFamilyProperties(QueueFamilyCount);
- vkGetPhysicalDeviceQueueFamilyProperties(Device, &QueueFamilyCount, QueueFamilyProperties.data());
- VERIFY_EXPR(QueueFamilyCount == QueueFamilyProperties.size());
-
- // If an implementation exposes any queue family that supports graphics operations,
- // at least one queue family of at least one physical device exposed by the implementation
- // must support both graphics and compute operations.
- bool GraphicsAndComputeQueueSupported = false;
- for(const auto &QueueFamilyProps : QueueFamilyProperties)
+ if ((QueueFamilyProps.queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0 &&
+ (QueueFamilyProps.queueFlags & VK_QUEUE_COMPUTE_BIT) != 0)
{
- if ((QueueFamilyProps.queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0 &&
- (QueueFamilyProps.queueFlags & VK_QUEUE_COMPUTE_BIT) != 0)
- {
- GraphicsAndComputeQueueSupported = true;
- break;
- }
- }
- if (GraphicsAndComputeQueueSupported)
- {
- SelectedPhysicalDevice = Device;
- if (DeviceProps.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)
- break;
+ GraphicsAndComputeQueueSupported = true;
+ break;
}
}
-
- if (SelectedPhysicalDevice != VK_NULL_HANDLE)
+ if (GraphicsAndComputeQueueSupported)
{
- VkPhysicalDeviceProperties SelectedDeviceProps;
- vkGetPhysicalDeviceProperties(SelectedPhysicalDevice, &SelectedDeviceProps);
- LOG_INFO_MESSAGE("Using physical device '", SelectedDeviceProps.deviceName, '\'');
- }
- else
- {
- LOG_ERROR_MESSAGE("Failed to find suitable physical device");
+ SelectedPhysicalDevice = Device;
+ if (DeviceProps.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)
+ break;
}
+ }
- return SelectedPhysicalDevice;
+ if (SelectedPhysicalDevice != VK_NULL_HANDLE)
+ {
+ VkPhysicalDeviceProperties SelectedDeviceProps;
+ vkGetPhysicalDeviceProperties(SelectedPhysicalDevice, &SelectedDeviceProps);
+ LOG_INFO_MESSAGE("Using physical device '", SelectedDeviceProps.deviceName, '\'');
}
+ else
+ {
+ LOG_ERROR_MESSAGE("Failed to find suitable physical device");
+ }
+
+ return SelectedPhysicalDevice;
}
+
+} // namespace VulkanUtilities
diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanLogicalDevice.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanLogicalDevice.cpp
index b2a8b0c9..d43ac776 100644
--- a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanLogicalDevice.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanLogicalDevice.cpp
@@ -29,443 +29,452 @@
namespace VulkanUtilities
{
- std::shared_ptr<VulkanLogicalDevice> VulkanLogicalDevice::Create(VkPhysicalDevice vkPhysicalDevice,
- const VkDeviceCreateInfo& DeviceCI,
- const VkAllocationCallbacks* vkAllocator)
- {
- auto* LogicalDevice = new VulkanLogicalDevice{vkPhysicalDevice, DeviceCI, vkAllocator};
- return std::shared_ptr<VulkanLogicalDevice>{LogicalDevice};
- }
-
- VulkanLogicalDevice::~VulkanLogicalDevice()
- {
- vkDestroyDevice(m_VkDevice, m_VkAllocator);
- }
-
- VulkanLogicalDevice::VulkanLogicalDevice(VkPhysicalDevice vkPhysicalDevice,
- const VkDeviceCreateInfo& DeviceCI,
- const VkAllocationCallbacks* vkAllocator) :
- m_VkAllocator{vkAllocator}
- {
- auto res = vkCreateDevice(vkPhysicalDevice, &DeviceCI, vkAllocator, &m_VkDevice);
- CHECK_VK_ERROR_AND_THROW(res, "Failed to create logical device");
-
- m_EnabledGraphicsShaderStages = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
- if (DeviceCI.pEnabledFeatures->geometryShader)
- m_EnabledGraphicsShaderStages = VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT;
- if (DeviceCI.pEnabledFeatures->tessellationShader)
- m_EnabledGraphicsShaderStages = VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT | VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT;
- }
-
- VkQueue VulkanLogicalDevice::GetQueue(uint32_t queueFamilyIndex, uint32_t queueIndex)
- {
- VkQueue vkQueue = VK_NULL_HANDLE;
- vkGetDeviceQueue(m_VkDevice,
- queueFamilyIndex, // Index of the queue family to which the queue belongs
- 0, // Index within this queue family of the queue to retrieve
- &vkQueue);
- VERIFY_EXPR(vkQueue != VK_NULL_HANDLE);
- return vkQueue;
- }
-
- void VulkanLogicalDevice::WaitIdle()const
- {
- auto err = vkDeviceWaitIdle(m_VkDevice);
- DEV_CHECK_ERR(err == VK_SUCCESS, "Failed to idle device"); (void)err;
- }
-
- template<typename VkObjectType, typename VkCreateObjectFuncType, typename VkObjectCreateInfoType>
- VulkanObjectWrapper<VkObjectType> VulkanLogicalDevice::CreateVulkanObject(VkCreateObjectFuncType VkCreateObject,
- const VkObjectCreateInfoType& CreateInfo,
- const char* DebugName,
- const char* ObjectType)const
- {
- if (DebugName == nullptr)
- DebugName = "";
-
- VkObjectType VkObject = VK_NULL_HANDLE;
- auto err = VkCreateObject(m_VkDevice, &CreateInfo, m_VkAllocator, &VkObject);
- CHECK_VK_ERROR_AND_THROW(err, "Failed to create Vulkan ", ObjectType, " '", DebugName, '\'');
-
- if (DebugName != nullptr && *DebugName != 0)
- SetVulkanObjectName(m_VkDevice, VkObject, DebugName);
-
- return VulkanObjectWrapper<VkObjectType>{ GetSharedPtr(), std::move(VkObject) };
- }
-
- CommandPoolWrapper VulkanLogicalDevice::CreateCommandPool(const VkCommandPoolCreateInfo &CmdPoolCI,
- const char* DebugName) const
- {
- VERIFY_EXPR(CmdPoolCI.sType == VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO);
- return CreateVulkanObject<VkCommandPool>(vkCreateCommandPool, CmdPoolCI, DebugName, "command pool");
- }
-
- BufferWrapper VulkanLogicalDevice::CreateBuffer(const VkBufferCreateInfo& BufferCI,
- const char* DebugName)const
- {
- VERIFY_EXPR(BufferCI.sType == VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO);
- return CreateVulkanObject<VkBuffer>(vkCreateBuffer, BufferCI, DebugName, "buffer");
- }
-
- BufferViewWrapper VulkanLogicalDevice::CreateBufferView(const VkBufferViewCreateInfo &BuffViewCI,
- const char* DebugName)const
- {
- VERIFY_EXPR(BuffViewCI.sType == VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO);
- return CreateVulkanObject<VkBufferView>(vkCreateBufferView, BuffViewCI, DebugName, "buffer view");
- }
-
- ImageWrapper VulkanLogicalDevice::CreateImage(const VkImageCreateInfo &ImageCI,
- const char* DebugName)const
- {
- VERIFY_EXPR(ImageCI.sType == VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO);
- return CreateVulkanObject<VkImage>(vkCreateImage, ImageCI, DebugName, "image");
- }
-
- ImageViewWrapper VulkanLogicalDevice::CreateImageView(const VkImageViewCreateInfo &ImageViewCI,
- const char* DebugName)const
- {
- VERIFY_EXPR(ImageViewCI.sType == VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO);
- return CreateVulkanObject<VkImageView>(vkCreateImageView, ImageViewCI, DebugName, "image view");
- }
-
- SamplerWrapper VulkanLogicalDevice::CreateSampler(const VkSamplerCreateInfo &SamplerCI, const char* DebugName)const
- {
- VERIFY_EXPR(SamplerCI.sType == VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO);
- return CreateVulkanObject<VkSampler>(vkCreateSampler, SamplerCI, DebugName, "sampler");
- }
-
- FenceWrapper VulkanLogicalDevice::CreateFence(const VkFenceCreateInfo &FenceCI, const char* DebugName)const
- {
- VERIFY_EXPR(FenceCI.sType == VK_STRUCTURE_TYPE_FENCE_CREATE_INFO);
- return CreateVulkanObject<VkFence>(vkCreateFence, FenceCI, DebugName, "fence");
- }
-
- RenderPassWrapper VulkanLogicalDevice::CreateRenderPass(const VkRenderPassCreateInfo &RenderPassCI, const char* DebugName)const
- {
- VERIFY_EXPR(RenderPassCI.sType == VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO);
- return CreateVulkanObject<VkRenderPass>(vkCreateRenderPass, RenderPassCI, DebugName, "render pass");
- }
-
- DeviceMemoryWrapper VulkanLogicalDevice::AllocateDeviceMemory(const VkMemoryAllocateInfo& AllocInfo,
- const char* DebugName)const
- {
- VERIFY_EXPR(AllocInfo.sType == VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO);
-
- if (DebugName == nullptr)
- DebugName = "";
-
- VkDeviceMemory vkDeviceMem = VK_NULL_HANDLE;
-
- auto err = vkAllocateMemory(m_VkDevice, &AllocInfo, m_VkAllocator, &vkDeviceMem);
- CHECK_VK_ERROR_AND_THROW(err, "Failed to allocate device memory '", DebugName, '\'');
-
- if (DebugName != nullptr && *DebugName != 0)
- SetDeviceMemoryName(m_VkDevice, vkDeviceMem, DebugName);
-
- return DeviceMemoryWrapper{ GetSharedPtr(), std::move(vkDeviceMem) };
- }
-
- PipelineWrapper VulkanLogicalDevice::CreateComputePipeline(const VkComputePipelineCreateInfo &PipelineCI,
- VkPipelineCache cache,
- const char* DebugName)const
- {
- VERIFY_EXPR(PipelineCI.sType == VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO);
-
- if (DebugName == nullptr)
- DebugName = "";
-
- VkPipeline vkPipeline = VK_NULL_HANDLE;
- auto err = vkCreateComputePipelines(m_VkDevice, cache, 1, &PipelineCI, m_VkAllocator, &vkPipeline);
- CHECK_VK_ERROR_AND_THROW(err, "Failed to create compute pipeline '", DebugName, '\'');
-
- if (DebugName != nullptr && *DebugName != 0)
- SetPipelineName(m_VkDevice, vkPipeline, DebugName);
-
- return PipelineWrapper{ GetSharedPtr(), std::move(vkPipeline) };
- }
-
- PipelineWrapper VulkanLogicalDevice::CreateGraphicsPipeline(const VkGraphicsPipelineCreateInfo& PipelineCI,
- VkPipelineCache cache,
- const char* DebugName)const
- {
- VERIFY_EXPR(PipelineCI.sType == VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO);
-
- if (DebugName == nullptr)
- DebugName = "";
-
- VkPipeline vkPipeline = VK_NULL_HANDLE;
- auto err = vkCreateGraphicsPipelines(m_VkDevice, cache, 1, &PipelineCI, m_VkAllocator, &vkPipeline);
- CHECK_VK_ERROR_AND_THROW(err, "Failed to create graphics pipeline '", DebugName, '\'');
-
- if (DebugName != nullptr && *DebugName != 0)
- SetPipelineName(m_VkDevice, vkPipeline, DebugName);
-
- return PipelineWrapper{ GetSharedPtr(), std::move(vkPipeline) };
- }
-
- ShaderModuleWrapper VulkanLogicalDevice::CreateShaderModule(const VkShaderModuleCreateInfo& ShaderModuleCI, const char* DebugName)const
- {
- VERIFY_EXPR(ShaderModuleCI.sType == VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO);
- return CreateVulkanObject<VkShaderModule>(vkCreateShaderModule, ShaderModuleCI, DebugName, "shader module");
- }
-
- PipelineLayoutWrapper VulkanLogicalDevice::CreatePipelineLayout(const VkPipelineLayoutCreateInfo &PipelineLayoutCI, const char* DebugName)const
- {
- VERIFY_EXPR(PipelineLayoutCI.sType == VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO);
- return CreateVulkanObject<VkPipelineLayout>(vkCreatePipelineLayout, PipelineLayoutCI, DebugName, "pipeline layout");
- }
-
- FramebufferWrapper VulkanLogicalDevice::CreateFramebuffer(const VkFramebufferCreateInfo &FramebufferCI, const char* DebugName)const
- {
- VERIFY_EXPR(FramebufferCI.sType == VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO);
- return CreateVulkanObject<VkFramebuffer>(vkCreateFramebuffer, FramebufferCI, DebugName, "framebuffer");
- }
-
- DescriptorPoolWrapper VulkanLogicalDevice::CreateDescriptorPool(const VkDescriptorPoolCreateInfo &DescrPoolCI, const char* DebugName)const
- {
- VERIFY_EXPR(DescrPoolCI.sType == VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO);
- return CreateVulkanObject<VkDescriptorPool>(vkCreateDescriptorPool, DescrPoolCI, DebugName, "descriptor pool");
- }
-
- DescriptorSetLayoutWrapper VulkanLogicalDevice::CreateDescriptorSetLayout(const VkDescriptorSetLayoutCreateInfo &LayoutCI, const char* DebugName)const
- {
- VERIFY_EXPR(LayoutCI.sType == VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO);
- return CreateVulkanObject<VkDescriptorSetLayout>(vkCreateDescriptorSetLayout, LayoutCI, DebugName, "descriptor set layout");
- }
-
- SemaphoreWrapper VulkanLogicalDevice::CreateSemaphore(const VkSemaphoreCreateInfo &SemaphoreCI, const char* DebugName)const
- {
- VERIFY_EXPR(SemaphoreCI.sType == VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO);
- return CreateVulkanObject<VkSemaphore>(vkCreateSemaphore, SemaphoreCI, DebugName, "semaphore");
- }
-
- VkCommandBuffer VulkanLogicalDevice::AllocateVkCommandBuffer(const VkCommandBufferAllocateInfo& AllocInfo, const char* DebugName)const
- {
- VERIFY_EXPR(AllocInfo.sType == VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO);
-
- if (DebugName == nullptr)
- DebugName = "";
-
- VkCommandBuffer CmdBuff = VK_NULL_HANDLE;
- auto err = vkAllocateCommandBuffers(m_VkDevice, &AllocInfo, &CmdBuff);
- DEV_CHECK_ERR(err == VK_SUCCESS, "Failed to allocate command buffer '", DebugName, '\''); (void)err;
-
- if (DebugName != nullptr && *DebugName != 0)
- SetCommandBufferName(m_VkDevice, CmdBuff, DebugName);
-
- return CmdBuff;
- }
-
- VkDescriptorSet VulkanLogicalDevice::AllocateVkDescriptorSet(const VkDescriptorSetAllocateInfo& AllocInfo, const char* DebugName)const
- {
- VERIFY_EXPR(AllocInfo.sType == VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO);
- VERIFY_EXPR(AllocInfo.descriptorSetCount == 1);
-
- if (DebugName == nullptr)
- DebugName = "";
-
- VkDescriptorSet DescrSet = VK_NULL_HANDLE;
- auto err = vkAllocateDescriptorSets(m_VkDevice, &AllocInfo, &DescrSet);
- if(err != VK_SUCCESS)
- return VK_NULL_HANDLE;
-
- if (DebugName != nullptr && *DebugName != 0)
- SetDescriptorSetName(m_VkDevice, DescrSet, DebugName);
-
- return DescrSet;
- }
-
- void VulkanLogicalDevice::ReleaseVulkanObject(CommandPoolWrapper &&CmdPool)const
- {
- vkDestroyCommandPool(m_VkDevice, CmdPool.m_VkObject, m_VkAllocator);
- CmdPool.m_VkObject = VK_NULL_HANDLE;
- }
-
- void VulkanLogicalDevice::ReleaseVulkanObject(BufferWrapper&& Buffer)const
- {
- vkDestroyBuffer(m_VkDevice, Buffer.m_VkObject, m_VkAllocator);
- Buffer.m_VkObject = VK_NULL_HANDLE;
- }
-
- void VulkanLogicalDevice::ReleaseVulkanObject(BufferViewWrapper&& BufferView)const
- {
- vkDestroyBufferView(m_VkDevice, BufferView.m_VkObject, m_VkAllocator);
- BufferView.m_VkObject = VK_NULL_HANDLE;
- }
-
- void VulkanLogicalDevice::ReleaseVulkanObject(ImageWrapper&& Image)const
- {
- vkDestroyImage(m_VkDevice, Image.m_VkObject, m_VkAllocator);
- Image.m_VkObject = VK_NULL_HANDLE;
- }
-
- void VulkanLogicalDevice::ReleaseVulkanObject(ImageViewWrapper&& ImageView)const
- {
- vkDestroyImageView(m_VkDevice, ImageView.m_VkObject, m_VkAllocator);
- ImageView.m_VkObject = VK_NULL_HANDLE;
- }
-
- void VulkanLogicalDevice::ReleaseVulkanObject(SamplerWrapper&& Sampler)const
- {
- vkDestroySampler(m_VkDevice, Sampler.m_VkObject, m_VkAllocator);
- Sampler.m_VkObject = VK_NULL_HANDLE;
- }
-
- void VulkanLogicalDevice::ReleaseVulkanObject(FenceWrapper&& Fence)const
- {
- vkDestroyFence(m_VkDevice, Fence.m_VkObject, m_VkAllocator);
- Fence.m_VkObject = VK_NULL_HANDLE;
- }
-
- void VulkanLogicalDevice::ReleaseVulkanObject(RenderPassWrapper&& RenderPass)const
- {
- vkDestroyRenderPass(m_VkDevice, RenderPass.m_VkObject, m_VkAllocator);
- RenderPass.m_VkObject = VK_NULL_HANDLE;
- }
-
- void VulkanLogicalDevice::ReleaseVulkanObject(DeviceMemoryWrapper&& Memory)const
- {
- vkFreeMemory(m_VkDevice, Memory.m_VkObject, m_VkAllocator);
- Memory.m_VkObject = VK_NULL_HANDLE;
- }
-
- void VulkanLogicalDevice::ReleaseVulkanObject(PipelineWrapper&& Pipeline)const
- {
- vkDestroyPipeline(m_VkDevice, Pipeline.m_VkObject, m_VkAllocator);
- Pipeline.m_VkObject = VK_NULL_HANDLE;
- }
-
- void VulkanLogicalDevice::ReleaseVulkanObject(ShaderModuleWrapper&& ShaderModule)const
- {
- vkDestroyShaderModule(m_VkDevice, ShaderModule.m_VkObject, m_VkAllocator);
- ShaderModule.m_VkObject = VK_NULL_HANDLE;
- }
-
- void VulkanLogicalDevice::ReleaseVulkanObject(PipelineLayoutWrapper&& PipelineLayout)const
- {
- vkDestroyPipelineLayout(m_VkDevice, PipelineLayout.m_VkObject, m_VkAllocator);
- PipelineLayout.m_VkObject = VK_NULL_HANDLE;
- }
-
- void VulkanLogicalDevice::ReleaseVulkanObject(FramebufferWrapper&& Framebuffer)const
- {
- vkDestroyFramebuffer(m_VkDevice, Framebuffer.m_VkObject, m_VkAllocator);
- Framebuffer.m_VkObject = VK_NULL_HANDLE;
- }
-
- void VulkanLogicalDevice::ReleaseVulkanObject(DescriptorPoolWrapper&& DescriptorPool)const
- {
- vkDestroyDescriptorPool(m_VkDevice, DescriptorPool.m_VkObject, m_VkAllocator);
- DescriptorPool.m_VkObject = VK_NULL_HANDLE;
- }
-
- void VulkanLogicalDevice::ReleaseVulkanObject(DescriptorSetLayoutWrapper&& DescriptorSetLayout)const
- {
- vkDestroyDescriptorSetLayout(m_VkDevice, DescriptorSetLayout.m_VkObject, m_VkAllocator);
- DescriptorSetLayout.m_VkObject = VK_NULL_HANDLE;
- }
-
- void VulkanLogicalDevice::ReleaseVulkanObject(SemaphoreWrapper&& Semaphore)const
- {
- vkDestroySemaphore(m_VkDevice, Semaphore.m_VkObject, m_VkAllocator);
- Semaphore.m_VkObject = VK_NULL_HANDLE;
- }
-
-
- void VulkanLogicalDevice::FreeDescriptorSet(VkDescriptorPool Pool, VkDescriptorSet Set)const
- {
- VERIFY_EXPR(Pool != VK_NULL_HANDLE && Set != VK_NULL_HANDLE);
- vkFreeDescriptorSets(m_VkDevice, Pool, 1, &Set);
- }
-
-
-
-
- VkMemoryRequirements VulkanLogicalDevice::GetBufferMemoryRequirements(VkBuffer vkBuffer)const
- {
- VkMemoryRequirements MemReqs = {};
- vkGetBufferMemoryRequirements(m_VkDevice, vkBuffer, &MemReqs);
- return MemReqs;
- }
-
- VkMemoryRequirements VulkanLogicalDevice::GetImageMemoryRequirements(VkImage vkImage)const
- {
- VkMemoryRequirements MemReqs = {};
- vkGetImageMemoryRequirements(m_VkDevice, vkImage, &MemReqs);
- return MemReqs;
- }
-
- VkResult VulkanLogicalDevice::BindBufferMemory(VkBuffer buffer, VkDeviceMemory memory, VkDeviceSize memoryOffset)const
- {
- return vkBindBufferMemory(m_VkDevice, buffer, memory, memoryOffset);
- }
-
- VkResult VulkanLogicalDevice::BindImageMemory(VkImage image, VkDeviceMemory memory, VkDeviceSize memoryOffset)const
- {
- return vkBindImageMemory(m_VkDevice, image, memory, memoryOffset);
- }
-
- VkResult VulkanLogicalDevice::MapMemory(VkDeviceMemory memory, VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags, void** ppData)const
- {
- return vkMapMemory(m_VkDevice, memory, offset, size, flags, ppData);
- }
-
- void VulkanLogicalDevice::UnmapMemory(VkDeviceMemory memory)const
- {
- vkUnmapMemory(m_VkDevice, memory);
- }
-
- VkResult VulkanLogicalDevice::InvalidateMappedMemoryRanges(uint32_t memoryRangeCount, const VkMappedMemoryRange* pMemoryRanges)const
- {
- return vkInvalidateMappedMemoryRanges(m_VkDevice, memoryRangeCount, pMemoryRanges);
- }
-
- VkResult VulkanLogicalDevice::FlushMappedMemoryRanges(uint32_t memoryRangeCount, const VkMappedMemoryRange* pMemoryRanges)const
- {
- return vkFlushMappedMemoryRanges(m_VkDevice, memoryRangeCount, pMemoryRanges);
- }
-
- VkResult VulkanLogicalDevice::GetFenceStatus(VkFence fence)const
- {
- return vkGetFenceStatus(m_VkDevice, fence);
- }
-
- VkResult VulkanLogicalDevice::ResetFence(VkFence fence)const
- {
- auto err = vkResetFences(m_VkDevice, 1, &fence);
- DEV_CHECK_ERR(err == VK_SUCCESS, "vkResetFences() failed");
- return err;
- }
-
- VkResult VulkanLogicalDevice::WaitForFences(uint32_t fenceCount,
- const VkFence* pFences,
- VkBool32 waitAll,
- uint64_t timeout) const
- {
- return vkWaitForFences(m_VkDevice, fenceCount, pFences, waitAll, timeout);
- }
-
- void VulkanLogicalDevice::UpdateDescriptorSets(uint32_t descriptorWriteCount,
- const VkWriteDescriptorSet* pDescriptorWrites,
- uint32_t descriptorCopyCount,
- const VkCopyDescriptorSet* pDescriptorCopies)const
- {
- vkUpdateDescriptorSets(m_VkDevice, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount, pDescriptorCopies);
- }
-
- VkResult VulkanLogicalDevice::ResetCommandPool(VkCommandPool vkCmdPool,
- VkCommandPoolResetFlags flags)const
- {
- auto err = vkResetCommandPool(m_VkDevice, vkCmdPool, flags);
- DEV_CHECK_ERR(err == VK_SUCCESS, "Failed to reset command pool");
- return err;
- }
-
- VkResult VulkanLogicalDevice::ResetDescriptorPool(VkDescriptorPool vkDescriptorPool,
- VkDescriptorPoolResetFlags flags)const
- {
- auto err = vkResetDescriptorPool(m_VkDevice, vkDescriptorPool, flags);
- DEV_CHECK_ERR(err == VK_SUCCESS, "Failed to reset descriptor pool");
- return err;
- }
+
+std::shared_ptr<VulkanLogicalDevice> VulkanLogicalDevice::Create(VkPhysicalDevice vkPhysicalDevice,
+ const VkDeviceCreateInfo& DeviceCI,
+ const VkAllocationCallbacks* vkAllocator)
+{
+ auto* LogicalDevice = new VulkanLogicalDevice{vkPhysicalDevice, DeviceCI, vkAllocator};
+ return std::shared_ptr<VulkanLogicalDevice>{LogicalDevice};
+}
+
+VulkanLogicalDevice::~VulkanLogicalDevice()
+{
+ vkDestroyDevice(m_VkDevice, m_VkAllocator);
+}
+
+VulkanLogicalDevice::VulkanLogicalDevice(VkPhysicalDevice vkPhysicalDevice,
+ const VkDeviceCreateInfo& DeviceCI,
+ const VkAllocationCallbacks* vkAllocator) :
+ m_VkAllocator{vkAllocator}
+{
+ auto res = vkCreateDevice(vkPhysicalDevice, &DeviceCI, vkAllocator, &m_VkDevice);
+ CHECK_VK_ERROR_AND_THROW(res, "Failed to create logical device");
+
+ m_EnabledGraphicsShaderStages = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
+ if (DeviceCI.pEnabledFeatures->geometryShader)
+ m_EnabledGraphicsShaderStages = VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT;
+ if (DeviceCI.pEnabledFeatures->tessellationShader)
+ m_EnabledGraphicsShaderStages = VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT | VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT;
+}
+
+VkQueue VulkanLogicalDevice::GetQueue(uint32_t queueFamilyIndex, uint32_t queueIndex)
+{
+ VkQueue vkQueue = VK_NULL_HANDLE;
+ vkGetDeviceQueue(m_VkDevice,
+ queueFamilyIndex, // Index of the queue family to which the queue belongs
+ 0, // Index within this queue family of the queue to retrieve
+ &vkQueue);
+ VERIFY_EXPR(vkQueue != VK_NULL_HANDLE);
+ return vkQueue;
+}
+
+void VulkanLogicalDevice::WaitIdle() const
+{
+ auto err = vkDeviceWaitIdle(m_VkDevice);
+ DEV_CHECK_ERR(err == VK_SUCCESS, "Failed to idle device");
+ (void)err;
}
+
+template <typename VkObjectType, typename VkCreateObjectFuncType, typename VkObjectCreateInfoType>
+VulkanObjectWrapper<VkObjectType> VulkanLogicalDevice::CreateVulkanObject(VkCreateObjectFuncType VkCreateObject,
+ const VkObjectCreateInfoType& CreateInfo,
+ const char* DebugName,
+ const char* ObjectType) const
+{
+ if (DebugName == nullptr)
+ DebugName = "";
+
+ VkObjectType VkObject = VK_NULL_HANDLE;
+
+ auto err = VkCreateObject(m_VkDevice, &CreateInfo, m_VkAllocator, &VkObject);
+ CHECK_VK_ERROR_AND_THROW(err, "Failed to create Vulkan ", ObjectType, " '", DebugName, '\'');
+
+ if (DebugName != nullptr && *DebugName != 0)
+ SetVulkanObjectName(m_VkDevice, VkObject, DebugName);
+
+ return VulkanObjectWrapper<VkObjectType>{GetSharedPtr(), std::move(VkObject)};
+}
+
+CommandPoolWrapper VulkanLogicalDevice::CreateCommandPool(const VkCommandPoolCreateInfo& CmdPoolCI,
+ const char* DebugName) const
+{
+ VERIFY_EXPR(CmdPoolCI.sType == VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO);
+ return CreateVulkanObject<VkCommandPool>(vkCreateCommandPool, CmdPoolCI, DebugName, "command pool");
+}
+
+BufferWrapper VulkanLogicalDevice::CreateBuffer(const VkBufferCreateInfo& BufferCI,
+ const char* DebugName) const
+{
+ VERIFY_EXPR(BufferCI.sType == VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO);
+ return CreateVulkanObject<VkBuffer>(vkCreateBuffer, BufferCI, DebugName, "buffer");
+}
+
+BufferViewWrapper VulkanLogicalDevice::CreateBufferView(const VkBufferViewCreateInfo& BuffViewCI,
+ const char* DebugName) const
+{
+ VERIFY_EXPR(BuffViewCI.sType == VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO);
+ return CreateVulkanObject<VkBufferView>(vkCreateBufferView, BuffViewCI, DebugName, "buffer view");
+}
+
+ImageWrapper VulkanLogicalDevice::CreateImage(const VkImageCreateInfo& ImageCI,
+ const char* DebugName) const
+{
+ VERIFY_EXPR(ImageCI.sType == VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO);
+ return CreateVulkanObject<VkImage>(vkCreateImage, ImageCI, DebugName, "image");
+}
+
+ImageViewWrapper VulkanLogicalDevice::CreateImageView(const VkImageViewCreateInfo& ImageViewCI,
+ const char* DebugName) const
+{
+ VERIFY_EXPR(ImageViewCI.sType == VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO);
+ return CreateVulkanObject<VkImageView>(vkCreateImageView, ImageViewCI, DebugName, "image view");
+}
+
+SamplerWrapper VulkanLogicalDevice::CreateSampler(const VkSamplerCreateInfo& SamplerCI, const char* DebugName) const
+{
+ VERIFY_EXPR(SamplerCI.sType == VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO);
+ return CreateVulkanObject<VkSampler>(vkCreateSampler, SamplerCI, DebugName, "sampler");
+}
+
+FenceWrapper VulkanLogicalDevice::CreateFence(const VkFenceCreateInfo& FenceCI, const char* DebugName) const
+{
+ VERIFY_EXPR(FenceCI.sType == VK_STRUCTURE_TYPE_FENCE_CREATE_INFO);
+ return CreateVulkanObject<VkFence>(vkCreateFence, FenceCI, DebugName, "fence");
+}
+
+RenderPassWrapper VulkanLogicalDevice::CreateRenderPass(const VkRenderPassCreateInfo& RenderPassCI, const char* DebugName) const
+{
+ VERIFY_EXPR(RenderPassCI.sType == VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO);
+ return CreateVulkanObject<VkRenderPass>(vkCreateRenderPass, RenderPassCI, DebugName, "render pass");
+}
+
+DeviceMemoryWrapper VulkanLogicalDevice::AllocateDeviceMemory(const VkMemoryAllocateInfo& AllocInfo,
+ const char* DebugName) const
+{
+ VERIFY_EXPR(AllocInfo.sType == VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO);
+
+ if (DebugName == nullptr)
+ DebugName = "";
+
+ VkDeviceMemory vkDeviceMem = VK_NULL_HANDLE;
+
+ auto err = vkAllocateMemory(m_VkDevice, &AllocInfo, m_VkAllocator, &vkDeviceMem);
+ CHECK_VK_ERROR_AND_THROW(err, "Failed to allocate device memory '", DebugName, '\'');
+
+ if (DebugName != nullptr && *DebugName != 0)
+ SetDeviceMemoryName(m_VkDevice, vkDeviceMem, DebugName);
+
+ return DeviceMemoryWrapper{GetSharedPtr(), std::move(vkDeviceMem)};
+}
+
+PipelineWrapper VulkanLogicalDevice::CreateComputePipeline(const VkComputePipelineCreateInfo& PipelineCI,
+ VkPipelineCache cache,
+ const char* DebugName) const
+{
+ VERIFY_EXPR(PipelineCI.sType == VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO);
+
+ if (DebugName == nullptr)
+ DebugName = "";
+
+ VkPipeline vkPipeline = VK_NULL_HANDLE;
+
+ auto err = vkCreateComputePipelines(m_VkDevice, cache, 1, &PipelineCI, m_VkAllocator, &vkPipeline);
+ CHECK_VK_ERROR_AND_THROW(err, "Failed to create compute pipeline '", DebugName, '\'');
+
+ if (DebugName != nullptr && *DebugName != 0)
+ SetPipelineName(m_VkDevice, vkPipeline, DebugName);
+
+ return PipelineWrapper{GetSharedPtr(), std::move(vkPipeline)};
+}
+
+PipelineWrapper VulkanLogicalDevice::CreateGraphicsPipeline(const VkGraphicsPipelineCreateInfo& PipelineCI,
+ VkPipelineCache cache,
+ const char* DebugName) const
+{
+ VERIFY_EXPR(PipelineCI.sType == VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO);
+
+ if (DebugName == nullptr)
+ DebugName = "";
+
+ VkPipeline vkPipeline = VK_NULL_HANDLE;
+
+ auto err = vkCreateGraphicsPipelines(m_VkDevice, cache, 1, &PipelineCI, m_VkAllocator, &vkPipeline);
+ CHECK_VK_ERROR_AND_THROW(err, "Failed to create graphics pipeline '", DebugName, '\'');
+
+ if (DebugName != nullptr && *DebugName != 0)
+ SetPipelineName(m_VkDevice, vkPipeline, DebugName);
+
+ return PipelineWrapper{GetSharedPtr(), std::move(vkPipeline)};
+}
+
+ShaderModuleWrapper VulkanLogicalDevice::CreateShaderModule(const VkShaderModuleCreateInfo& ShaderModuleCI, const char* DebugName) const
+{
+ VERIFY_EXPR(ShaderModuleCI.sType == VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO);
+ return CreateVulkanObject<VkShaderModule>(vkCreateShaderModule, ShaderModuleCI, DebugName, "shader module");
+}
+
+PipelineLayoutWrapper VulkanLogicalDevice::CreatePipelineLayout(const VkPipelineLayoutCreateInfo& PipelineLayoutCI, const char* DebugName) const
+{
+ VERIFY_EXPR(PipelineLayoutCI.sType == VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO);
+ return CreateVulkanObject<VkPipelineLayout>(vkCreatePipelineLayout, PipelineLayoutCI, DebugName, "pipeline layout");
+}
+
+FramebufferWrapper VulkanLogicalDevice::CreateFramebuffer(const VkFramebufferCreateInfo& FramebufferCI, const char* DebugName) const
+{
+ VERIFY_EXPR(FramebufferCI.sType == VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO);
+ return CreateVulkanObject<VkFramebuffer>(vkCreateFramebuffer, FramebufferCI, DebugName, "framebuffer");
+}
+
+DescriptorPoolWrapper VulkanLogicalDevice::CreateDescriptorPool(const VkDescriptorPoolCreateInfo& DescrPoolCI, const char* DebugName) const
+{
+ VERIFY_EXPR(DescrPoolCI.sType == VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO);
+ return CreateVulkanObject<VkDescriptorPool>(vkCreateDescriptorPool, DescrPoolCI, DebugName, "descriptor pool");
+}
+
+DescriptorSetLayoutWrapper VulkanLogicalDevice::CreateDescriptorSetLayout(const VkDescriptorSetLayoutCreateInfo& LayoutCI, const char* DebugName) const
+{
+ VERIFY_EXPR(LayoutCI.sType == VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO);
+ return CreateVulkanObject<VkDescriptorSetLayout>(vkCreateDescriptorSetLayout, LayoutCI, DebugName, "descriptor set layout");
+}
+
+SemaphoreWrapper VulkanLogicalDevice::CreateSemaphore(const VkSemaphoreCreateInfo& SemaphoreCI, const char* DebugName) const
+{
+ VERIFY_EXPR(SemaphoreCI.sType == VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO);
+ return CreateVulkanObject<VkSemaphore>(vkCreateSemaphore, SemaphoreCI, DebugName, "semaphore");
+}
+
+VkCommandBuffer VulkanLogicalDevice::AllocateVkCommandBuffer(const VkCommandBufferAllocateInfo& AllocInfo, const char* DebugName) const
+{
+ VERIFY_EXPR(AllocInfo.sType == VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO);
+
+ if (DebugName == nullptr)
+ DebugName = "";
+
+ VkCommandBuffer CmdBuff = VK_NULL_HANDLE;
+
+ auto err = vkAllocateCommandBuffers(m_VkDevice, &AllocInfo, &CmdBuff);
+ DEV_CHECK_ERR(err == VK_SUCCESS, "Failed to allocate command buffer '", DebugName, '\'');
+ (void)err;
+
+ if (DebugName != nullptr && *DebugName != 0)
+ SetCommandBufferName(m_VkDevice, CmdBuff, DebugName);
+
+ return CmdBuff;
+}
+
+VkDescriptorSet VulkanLogicalDevice::AllocateVkDescriptorSet(const VkDescriptorSetAllocateInfo& AllocInfo, const char* DebugName) const
+{
+ VERIFY_EXPR(AllocInfo.sType == VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO);
+ VERIFY_EXPR(AllocInfo.descriptorSetCount == 1);
+
+ if (DebugName == nullptr)
+ DebugName = "";
+
+ VkDescriptorSet DescrSet = VK_NULL_HANDLE;
+
+ auto err = vkAllocateDescriptorSets(m_VkDevice, &AllocInfo, &DescrSet);
+ if (err != VK_SUCCESS)
+ return VK_NULL_HANDLE;
+
+ if (DebugName != nullptr && *DebugName != 0)
+ SetDescriptorSetName(m_VkDevice, DescrSet, DebugName);
+
+ return DescrSet;
+}
+
+void VulkanLogicalDevice::ReleaseVulkanObject(CommandPoolWrapper&& CmdPool) const
+{
+ vkDestroyCommandPool(m_VkDevice, CmdPool.m_VkObject, m_VkAllocator);
+ CmdPool.m_VkObject = VK_NULL_HANDLE;
+}
+
+void VulkanLogicalDevice::ReleaseVulkanObject(BufferWrapper&& Buffer) const
+{
+ vkDestroyBuffer(m_VkDevice, Buffer.m_VkObject, m_VkAllocator);
+ Buffer.m_VkObject = VK_NULL_HANDLE;
+}
+
+void VulkanLogicalDevice::ReleaseVulkanObject(BufferViewWrapper&& BufferView) const
+{
+ vkDestroyBufferView(m_VkDevice, BufferView.m_VkObject, m_VkAllocator);
+ BufferView.m_VkObject = VK_NULL_HANDLE;
+}
+
+void VulkanLogicalDevice::ReleaseVulkanObject(ImageWrapper&& Image) const
+{
+ vkDestroyImage(m_VkDevice, Image.m_VkObject, m_VkAllocator);
+ Image.m_VkObject = VK_NULL_HANDLE;
+}
+
+void VulkanLogicalDevice::ReleaseVulkanObject(ImageViewWrapper&& ImageView) const
+{
+ vkDestroyImageView(m_VkDevice, ImageView.m_VkObject, m_VkAllocator);
+ ImageView.m_VkObject = VK_NULL_HANDLE;
+}
+
+void VulkanLogicalDevice::ReleaseVulkanObject(SamplerWrapper&& Sampler) const
+{
+ vkDestroySampler(m_VkDevice, Sampler.m_VkObject, m_VkAllocator);
+ Sampler.m_VkObject = VK_NULL_HANDLE;
+}
+
+void VulkanLogicalDevice::ReleaseVulkanObject(FenceWrapper&& Fence) const
+{
+ vkDestroyFence(m_VkDevice, Fence.m_VkObject, m_VkAllocator);
+ Fence.m_VkObject = VK_NULL_HANDLE;
+}
+
+void VulkanLogicalDevice::ReleaseVulkanObject(RenderPassWrapper&& RenderPass) const
+{
+ vkDestroyRenderPass(m_VkDevice, RenderPass.m_VkObject, m_VkAllocator);
+ RenderPass.m_VkObject = VK_NULL_HANDLE;
+}
+
+void VulkanLogicalDevice::ReleaseVulkanObject(DeviceMemoryWrapper&& Memory) const
+{
+ vkFreeMemory(m_VkDevice, Memory.m_VkObject, m_VkAllocator);
+ Memory.m_VkObject = VK_NULL_HANDLE;
+}
+
+void VulkanLogicalDevice::ReleaseVulkanObject(PipelineWrapper&& Pipeline) const
+{
+ vkDestroyPipeline(m_VkDevice, Pipeline.m_VkObject, m_VkAllocator);
+ Pipeline.m_VkObject = VK_NULL_HANDLE;
+}
+
+void VulkanLogicalDevice::ReleaseVulkanObject(ShaderModuleWrapper&& ShaderModule) const
+{
+ vkDestroyShaderModule(m_VkDevice, ShaderModule.m_VkObject, m_VkAllocator);
+ ShaderModule.m_VkObject = VK_NULL_HANDLE;
+}
+
+void VulkanLogicalDevice::ReleaseVulkanObject(PipelineLayoutWrapper&& PipelineLayout) const
+{
+ vkDestroyPipelineLayout(m_VkDevice, PipelineLayout.m_VkObject, m_VkAllocator);
+ PipelineLayout.m_VkObject = VK_NULL_HANDLE;
+}
+
+void VulkanLogicalDevice::ReleaseVulkanObject(FramebufferWrapper&& Framebuffer) const
+{
+ vkDestroyFramebuffer(m_VkDevice, Framebuffer.m_VkObject, m_VkAllocator);
+ Framebuffer.m_VkObject = VK_NULL_HANDLE;
+}
+
+void VulkanLogicalDevice::ReleaseVulkanObject(DescriptorPoolWrapper&& DescriptorPool) const
+{
+ vkDestroyDescriptorPool(m_VkDevice, DescriptorPool.m_VkObject, m_VkAllocator);
+ DescriptorPool.m_VkObject = VK_NULL_HANDLE;
+}
+
+void VulkanLogicalDevice::ReleaseVulkanObject(DescriptorSetLayoutWrapper&& DescriptorSetLayout) const
+{
+ vkDestroyDescriptorSetLayout(m_VkDevice, DescriptorSetLayout.m_VkObject, m_VkAllocator);
+ DescriptorSetLayout.m_VkObject = VK_NULL_HANDLE;
+}
+
+void VulkanLogicalDevice::ReleaseVulkanObject(SemaphoreWrapper&& Semaphore) const
+{
+ vkDestroySemaphore(m_VkDevice, Semaphore.m_VkObject, m_VkAllocator);
+ Semaphore.m_VkObject = VK_NULL_HANDLE;
+}
+
+
+void VulkanLogicalDevice::FreeDescriptorSet(VkDescriptorPool Pool, VkDescriptorSet Set) const
+{
+ VERIFY_EXPR(Pool != VK_NULL_HANDLE && Set != VK_NULL_HANDLE);
+ vkFreeDescriptorSets(m_VkDevice, Pool, 1, &Set);
+}
+
+
+
+
+VkMemoryRequirements VulkanLogicalDevice::GetBufferMemoryRequirements(VkBuffer vkBuffer) const
+{
+ VkMemoryRequirements MemReqs = {};
+ vkGetBufferMemoryRequirements(m_VkDevice, vkBuffer, &MemReqs);
+ return MemReqs;
+}
+
+VkMemoryRequirements VulkanLogicalDevice::GetImageMemoryRequirements(VkImage vkImage) const
+{
+ VkMemoryRequirements MemReqs = {};
+ vkGetImageMemoryRequirements(m_VkDevice, vkImage, &MemReqs);
+ return MemReqs;
+}
+
+VkResult VulkanLogicalDevice::BindBufferMemory(VkBuffer buffer, VkDeviceMemory memory, VkDeviceSize memoryOffset) const
+{
+ return vkBindBufferMemory(m_VkDevice, buffer, memory, memoryOffset);
+}
+
+VkResult VulkanLogicalDevice::BindImageMemory(VkImage image, VkDeviceMemory memory, VkDeviceSize memoryOffset) const
+{
+ return vkBindImageMemory(m_VkDevice, image, memory, memoryOffset);
+}
+
+VkResult VulkanLogicalDevice::MapMemory(VkDeviceMemory memory, VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags, void** ppData) const
+{
+ return vkMapMemory(m_VkDevice, memory, offset, size, flags, ppData);
+}
+
+void VulkanLogicalDevice::UnmapMemory(VkDeviceMemory memory) const
+{
+ vkUnmapMemory(m_VkDevice, memory);
+}
+
+VkResult VulkanLogicalDevice::InvalidateMappedMemoryRanges(uint32_t memoryRangeCount, const VkMappedMemoryRange* pMemoryRanges) const
+{
+ return vkInvalidateMappedMemoryRanges(m_VkDevice, memoryRangeCount, pMemoryRanges);
+}
+
+VkResult VulkanLogicalDevice::FlushMappedMemoryRanges(uint32_t memoryRangeCount, const VkMappedMemoryRange* pMemoryRanges) const
+{
+ return vkFlushMappedMemoryRanges(m_VkDevice, memoryRangeCount, pMemoryRanges);
+}
+
+VkResult VulkanLogicalDevice::GetFenceStatus(VkFence fence) const
+{
+ return vkGetFenceStatus(m_VkDevice, fence);
+}
+
+VkResult VulkanLogicalDevice::ResetFence(VkFence fence) const
+{
+ auto err = vkResetFences(m_VkDevice, 1, &fence);
+ DEV_CHECK_ERR(err == VK_SUCCESS, "vkResetFences() failed");
+ return err;
+}
+
+VkResult VulkanLogicalDevice::WaitForFences(uint32_t fenceCount,
+ const VkFence* pFences,
+ VkBool32 waitAll,
+ uint64_t timeout) const
+{
+ return vkWaitForFences(m_VkDevice, fenceCount, pFences, waitAll, timeout);
+}
+
+void VulkanLogicalDevice::UpdateDescriptorSets(uint32_t descriptorWriteCount,
+ const VkWriteDescriptorSet* pDescriptorWrites,
+ uint32_t descriptorCopyCount,
+ const VkCopyDescriptorSet* pDescriptorCopies) const
+{
+ vkUpdateDescriptorSets(m_VkDevice, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount, pDescriptorCopies);
+}
+
+VkResult VulkanLogicalDevice::ResetCommandPool(VkCommandPool vkCmdPool,
+ VkCommandPoolResetFlags flags) const
+{
+ auto err = vkResetCommandPool(m_VkDevice, vkCmdPool, flags);
+ DEV_CHECK_ERR(err == VK_SUCCESS, "Failed to reset command pool");
+ return err;
+}
+
+VkResult VulkanLogicalDevice::ResetDescriptorPool(VkDescriptorPool vkDescriptorPool,
+ VkDescriptorPoolResetFlags flags) const
+{
+ auto err = vkResetDescriptorPool(m_VkDevice, vkDescriptorPool, flags);
+ DEV_CHECK_ERR(err == VK_SUCCESS, "Failed to reset descriptor pool");
+ return err;
+}
+
+} // namespace VulkanUtilities
diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanMemoryManager.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanMemoryManager.cpp
index ac79e6d0..cc36ed99 100644
--- a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanMemoryManager.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanMemoryManager.cpp
@@ -27,7 +27,7 @@
namespace VulkanUtilities
{
-
+
VulkanMemoryAllocation::~VulkanMemoryAllocation()
{
if (Page != nullptr)
@@ -37,24 +37,28 @@ VulkanMemoryAllocation::~VulkanMemoryAllocation()
}
VulkanMemoryPage::VulkanMemoryPage(VulkanMemoryManager& ParentMemoryMgr,
- VkDeviceSize PageSize,
+ VkDeviceSize PageSize,
uint32_t MemoryTypeIndex,
- bool IsHostVisible)noexcept :
+ bool IsHostVisible) noexcept :
+ // clang-format off
m_ParentMemoryMgr{ParentMemoryMgr},
m_AllocationMgr {PageSize, ParentMemoryMgr.m_Allocator}
+// clang-format on
{
VkMemoryAllocateInfo MemAlloc = {};
- MemAlloc.pNext = nullptr;
- MemAlloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
- MemAlloc.allocationSize = PageSize;
+
+ MemAlloc.pNext = nullptr;
+ MemAlloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
+ MemAlloc.allocationSize = PageSize;
MemAlloc.memoryTypeIndex = MemoryTypeIndex;
auto MemoryName = Diligent::FormatString("Device memory page. Size: ", Diligent::FormatMemorySize(PageSize, 2), ", type: ", MemoryTypeIndex);
- m_VkMemory = ParentMemoryMgr.m_LogicalDevice.AllocateDeviceMemory(MemAlloc, MemoryName.c_str());
+ m_VkMemory = ParentMemoryMgr.m_LogicalDevice.AllocateDeviceMemory(MemAlloc, MemoryName.c_str());
if (IsHostVisible)
{
- auto err = ParentMemoryMgr.m_LogicalDevice.MapMemory(m_VkMemory,
+ auto err = ParentMemoryMgr.m_LogicalDevice.MapMemory(
+ m_VkMemory,
0, // offset
PageSize,
0, // flags, reserved for future use
@@ -77,12 +81,12 @@ VulkanMemoryPage::~VulkanMemoryPage()
VulkanMemoryAllocation VulkanMemoryPage::Allocate(VkDeviceSize size, VkDeviceSize alignment)
{
std::lock_guard<std::mutex> Lock{m_Mutex};
- auto Allocation = m_AllocationMgr.Allocate(size, alignment);
+ auto Allocation = m_AllocationMgr.Allocate(size, alignment);
if (Allocation.IsValid())
{
// Offset may not necessarily be aligned, but the allocation is guaranteed to be large enough
// to accomodate requested alignment
- VERIFY_EXPR( Diligent::Align(VkDeviceSize{Allocation.UnalignedOffset}, alignment) - Allocation.UnalignedOffset + size <= Allocation.Size );
+ VERIFY_EXPR(Diligent::Align(VkDeviceSize{Allocation.UnalignedOffset}, alignment) - Allocation.UnalignedOffset + size <= Allocation.Size);
return VulkanMemoryAllocation{this, Allocation.UnalignedOffset, Allocation.Size};
}
else
@@ -101,8 +105,8 @@ void VulkanMemoryPage::Free(VulkanMemoryAllocation&& Allocation)
VulkanMemoryAllocation VulkanMemoryManager::Allocate(const VkMemoryRequirements& MemReqs, VkMemoryPropertyFlags MemoryProps)
{
- // memoryTypeBits is a bitmask and contains one bit set for every supported memory type for the resource.
- // Bit i is set if and only if the memory type i in the VkPhysicalDeviceMemoryProperties structure for the
+ // memoryTypeBits is a bitmask and contains one bit set for every supported memory type for the resource.
+ // Bit i is set if and only if the memory type i in the VkPhysicalDeviceMemoryProperties structure for the
// physical device is supported for the resource.
auto MemoryTypeIndex = m_PhysicalDevice.GetMemoryTypeIndex(MemReqs.memoryTypeBits, MemoryProps);
if (MemoryProps == VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)
@@ -113,7 +117,7 @@ VulkanMemoryAllocation VulkanMemoryManager::Allocate(const VkMemoryRequirements&
"at least one bit set corresponding to a VkMemoryType with a propertyFlags that has the "
"VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT bit set (11.6)");
}
- else if ( (MemoryProps & (VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) == (VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT))
+ else if ((MemoryProps & (VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) == (VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT))
{
DEV_CHECK_ERR(MemoryTypeIndex != VulkanUtilities::VulkanPhysicalDevice::InvalidMemoryTypeIndex,
"Vulkan spec requires that for a VkBuffer not created with the VK_BUFFER_CREATE_SPARSE_BINDING_BIT "
@@ -136,16 +140,17 @@ VulkanMemoryAllocation VulkanMemoryManager::Allocate(VkDeviceSize Size, VkDevice
VulkanMemoryAllocation Allocation;
// On integrated GPUs, there is no difference between host-visible and GPU-only
- // memory, so MemoryTypeIndex is the same. As GPU-only pages do not have CPU address,
+ // memory, so MemoryTypeIndex is the same. As GPU-only pages do not have CPU address,
// we need to use HostVisible flag to differentiate the two.
- // It is likely a good idea to always keep staging pages separate to reduce fragmenation
- // even though on integrated GPUs same pages can be used for both GPU-only and staging
- // allocations. Staging allocations are short-living and will be released when upload is
+ // It is likely a good idea to always keep staging pages separate to reduce fragmenation
+ // even though on integrated GPUs same pages can be used for both GPU-only and staging
+ // allocations. Staging allocations are short-living and will be released when upload is
// complete, while GPU-only allocations are expected to be long-living.
- MemoryPageIndex PageIdx{MemoryTypeIndex, HostVisible};
+ MemoryPageIndex PageIdx{MemoryTypeIndex, HostVisible};
std::lock_guard<std::mutex> Lock{m_PagesMtx};
+
auto range = m_Pages.equal_range(PageIdx);
- for(auto page_it = range.first; page_it != range.second; ++page_it)
+ for (auto page_it = range.first; page_it != range.second; ++page_it)
{
Allocation = page_it->second.Allocate(Size, Alignment);
if (Allocation.Page != nullptr)
@@ -163,8 +168,8 @@ VulkanMemoryAllocation VulkanMemoryManager::Allocate(VkDeviceSize Size, VkDevice
m_PeakAllocatedSize[stat_ind] = std::max(m_PeakAllocatedSize[stat_ind], m_CurrAllocatedSize[stat_ind]);
auto it = m_Pages.emplace(PageIdx, VulkanMemoryPage{*this, PageSize, MemoryTypeIndex, HostVisible});
- LOG_INFO_MESSAGE("VulkanMemoryManager '", m_MgrName, "': created new ", (HostVisible ? "host-visible" : "device-local"),
- " page. (", Diligent::FormatMemorySize(PageSize, 2), ", type idx: ", MemoryTypeIndex,
+ LOG_INFO_MESSAGE("VulkanMemoryManager '", m_MgrName, "': created new ", (HostVisible ? "host-visible" : "device-local"),
+ " page. (", Diligent::FormatMemorySize(PageSize, 2), ", type idx: ", MemoryTypeIndex,
"). Current allocated size: ", Diligent::FormatMemorySize(m_CurrAllocatedSize[stat_ind], 2));
OnNewPageCreated(it->second);
Allocation = it->second.Allocate(Size, Alignment);
@@ -193,16 +198,17 @@ void VulkanMemoryManager::ShrinkMemory()
{
auto curr_it = it;
++it;
- auto& Page = curr_it->second;
- bool IsHostVisible = Page.GetCPUMemory() != nullptr;
- auto ReserveSize = IsHostVisible ? m_HostVisibleReserveSize : m_DeviceLocalReserveSize;
+ auto& Page = curr_it->second;
+ bool IsHostVisible = Page.GetCPUMemory() != nullptr;
+ auto ReserveSize = IsHostVisible ? m_HostVisibleReserveSize : m_DeviceLocalReserveSize;
if (Page.IsEmpty() && m_CurrAllocatedSize[IsHostVisible ? 1 : 0] > ReserveSize)
{
auto PageSize = Page.GetPageSize();
m_CurrAllocatedSize[IsHostVisible ? 1 : 0] -= PageSize;
- LOG_INFO_MESSAGE("VulkanMemoryManager '", m_MgrName, "': destroying ", (IsHostVisible ? "host-visible" : "device-local"),
- " page (", Diligent::FormatMemorySize(PageSize, 2), ")."
- " Current allocated size: ", Diligent::FormatMemorySize(m_CurrAllocatedSize[IsHostVisible ? 1 : 0], 2));
+ LOG_INFO_MESSAGE("VulkanMemoryManager '", m_MgrName, "': destroying ", (IsHostVisible ? "host-visible" : "device-local"),
+ " page (", Diligent::FormatMemorySize(PageSize, 2),
+ "). Current allocated size: ",
+ Diligent::FormatMemorySize(m_CurrAllocatedSize[IsHostVisible ? 1 : 0], 2));
OnPageDestroy(Page);
m_Pages.erase(curr_it);
}
@@ -211,7 +217,7 @@ void VulkanMemoryManager::ShrinkMemory()
void VulkanMemoryManager::OnFreeAllocation(VkDeviceSize Size, bool IsHostVisble)
{
- m_CurrUsedSize[IsHostVisble ? 1 : 0].fetch_add( -static_cast<int64_t>(Size) );
+ m_CurrUsedSize[IsHostVisble ? 1 : 0].fetch_add(-static_cast<int64_t>(Size));
}
VulkanMemoryManager::~VulkanMemoryManager()
@@ -219,19 +225,18 @@ VulkanMemoryManager::~VulkanMemoryManager()
auto PeakDeviceLocalPages = m_PeakAllocatedSize[0] / m_DeviceLocalPageSize;
auto PeakHostVisisblePages = m_PeakAllocatedSize[1] / m_HostVisiblePageSize;
LOG_INFO_MESSAGE("VulkanMemoryManager '", m_MgrName, "' stats:\n"
- " Peak used/allocated device-local memory size: ",
- Diligent::FormatMemorySize(m_PeakUsedSize[0], 2, m_PeakAllocatedSize[0]), " / ",
+ " Peak used/allocated device-local memory size: ",
+ Diligent::FormatMemorySize(m_PeakUsedSize[0], 2, m_PeakAllocatedSize[0]), " / ",
Diligent::FormatMemorySize(m_PeakAllocatedSize[0], 2, m_PeakAllocatedSize[0]),
" (", PeakDeviceLocalPages, (PeakDeviceLocalPages == 1 ? " page)" : " pages)"),
- "\n Peak used/allocated host-visible memory size: ",
- Diligent::FormatMemorySize(m_PeakUsedSize[1], 2, m_PeakAllocatedSize[1]), " / ",
+ "\n Peak used/allocated host-visible memory size: ",
+ Diligent::FormatMemorySize(m_PeakUsedSize[1], 2, m_PeakAllocatedSize[1]), " / ",
Diligent::FormatMemorySize(m_PeakAllocatedSize[1], 2, m_PeakAllocatedSize[1]),
- " (", PeakHostVisisblePages, (PeakHostVisisblePages == 1 ? " page)" : " pages)")
- );
-
- for(auto it=m_Pages.begin(); it != m_Pages.end(); ++it )
+ " (", PeakHostVisisblePages, (PeakHostVisisblePages == 1 ? " page)" : " pages)"));
+
+ for (auto it = m_Pages.begin(); it != m_Pages.end(); ++it)
VERIFY(it->second.IsEmpty(), "The page contains outstanding allocations");
VERIFY(m_CurrUsedSize[0] == 0 && m_CurrUsedSize[1] == 0, "Not all allocations have been released");
}
-}
+} // namespace VulkanUtilities
diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp
index ba2e0dda..9a0677bd 100644
--- a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp
@@ -28,174 +28,177 @@
namespace VulkanUtilities
{
- std::unique_ptr<VulkanPhysicalDevice> VulkanPhysicalDevice::Create(VkPhysicalDevice vkDevice)
+
+std::unique_ptr<VulkanPhysicalDevice> VulkanPhysicalDevice::Create(VkPhysicalDevice vkDevice)
+{
+ auto* PhysicalDevice = new VulkanPhysicalDevice{vkDevice};
+ return std::unique_ptr<VulkanPhysicalDevice>{PhysicalDevice};
+}
+
+VulkanPhysicalDevice::VulkanPhysicalDevice(VkPhysicalDevice vkDevice) :
+ m_VkDevice{vkDevice}
+{
+ VERIFY_EXPR(m_VkDevice != VK_NULL_HANDLE);
+
+ vkGetPhysicalDeviceProperties(m_VkDevice, &m_Properties);
+ vkGetPhysicalDeviceFeatures(m_VkDevice, &m_Features);
+ vkGetPhysicalDeviceMemoryProperties(m_VkDevice, &m_MemoryProperties);
+ uint32_t QueueFamilyCount = 0;
+ vkGetPhysicalDeviceQueueFamilyProperties(m_VkDevice, &QueueFamilyCount, nullptr);
+ VERIFY_EXPR(QueueFamilyCount > 0);
+ m_QueueFamilyProperties.resize(QueueFamilyCount);
+ vkGetPhysicalDeviceQueueFamilyProperties(m_VkDevice, &QueueFamilyCount, m_QueueFamilyProperties.data());
+ VERIFY_EXPR(QueueFamilyCount == m_QueueFamilyProperties.size());
+
+ // Get list of supported extensions
+ uint32_t ExtensionCount = 0;
+ vkEnumerateDeviceExtensionProperties(m_VkDevice, nullptr, &ExtensionCount, nullptr);
+ if (ExtensionCount > 0)
{
- auto* PhysicalDevice = new VulkanPhysicalDevice{vkDevice};
- return std::unique_ptr<VulkanPhysicalDevice>{PhysicalDevice};
+ m_SupportedExtensions.resize(ExtensionCount);
+ auto res = vkEnumerateDeviceExtensionProperties(m_VkDevice, nullptr, &ExtensionCount, m_SupportedExtensions.data());
+ VERIFY_EXPR(res == VK_SUCCESS);
+ (void)res;
+ VERIFY_EXPR(ExtensionCount == m_SupportedExtensions.size());
}
+}
- VulkanPhysicalDevice::VulkanPhysicalDevice(VkPhysicalDevice vkDevice) :
- m_VkDevice{vkDevice}
+uint32_t VulkanPhysicalDevice::FindQueueFamily(VkQueueFlags QueueFlags) const
+{
+ // All commands that are allowed on a queue that supports transfer operations are also allowed on
+ // a queue that supports either graphics or compute operations. Thus, if the capabilities of a queue
+ // family include VK_QUEUE_GRAPHICS_BIT or VK_QUEUE_COMPUTE_BIT, then reporting the VK_QUEUE_TRANSFER_BIT
+ // capability separately for that queue family is optional (4.1).
+ VkQueueFlags QueueFlagsOpt = QueueFlags;
+ if (QueueFlags & (VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT))
{
- VERIFY_EXPR(m_VkDevice != VK_NULL_HANDLE);
-
- vkGetPhysicalDeviceProperties(m_VkDevice, &m_Properties);
- vkGetPhysicalDeviceFeatures(m_VkDevice, &m_Features);
- vkGetPhysicalDeviceMemoryProperties(m_VkDevice, &m_MemoryProperties);
- uint32_t QueueFamilyCount = 0;
- vkGetPhysicalDeviceQueueFamilyProperties(m_VkDevice, &QueueFamilyCount, nullptr);
- VERIFY_EXPR(QueueFamilyCount> 0);
- m_QueueFamilyProperties.resize(QueueFamilyCount);
- vkGetPhysicalDeviceQueueFamilyProperties(m_VkDevice, &QueueFamilyCount, m_QueueFamilyProperties.data());
- VERIFY_EXPR(QueueFamilyCount == m_QueueFamilyProperties.size());
-
- // Get list of supported extensions
- uint32_t ExtensionCount = 0;
- vkEnumerateDeviceExtensionProperties(m_VkDevice, nullptr, &ExtensionCount, nullptr);
- if (ExtensionCount > 0)
- {
- m_SupportedExtensions.resize(ExtensionCount);
- auto res = vkEnumerateDeviceExtensionProperties(m_VkDevice, nullptr, &ExtensionCount, m_SupportedExtensions.data());
- VERIFY_EXPR(res == VK_SUCCESS); (void)res;
- VERIFY_EXPR(ExtensionCount == m_SupportedExtensions.size());
- }
+ QueueFlags &= ~VK_QUEUE_TRANSFER_BIT;
+ QueueFlagsOpt = QueueFlags | VK_QUEUE_TRANSFER_BIT;
}
- uint32_t VulkanPhysicalDevice::FindQueueFamily(VkQueueFlags QueueFlags)const
+ static constexpr uint32_t InvalidFamilyInd = std::numeric_limits<uint32_t>::max();
+ uint32_t FamilyInd = InvalidFamilyInd;
+
+ for (uint32_t i = 0; i < m_QueueFamilyProperties.size(); ++i)
{
- // All commands that are allowed on a queue that supports transfer operations are also allowed on
- // a queue that supports either graphics or compute operations. Thus, if the capabilities of a queue
- // family include VK_QUEUE_GRAPHICS_BIT or VK_QUEUE_COMPUTE_BIT, then reporting the VK_QUEUE_TRANSFER_BIT
- // capability separately for that queue family is optional (4.1).
- VkQueueFlags QueueFlagsOpt = QueueFlags;
- if (QueueFlags & (VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT))
+ // First try to find a queue, for which the flags match exactly
+ // (i.e. dedicated compute or transfer queue)
+ const auto& Props = m_QueueFamilyProperties[i];
+ if (Props.queueFlags == QueueFlags ||
+ Props.queueFlags == QueueFlagsOpt)
{
- QueueFlags &= ~VK_QUEUE_TRANSFER_BIT;
- QueueFlagsOpt = QueueFlags | VK_QUEUE_TRANSFER_BIT;
+ FamilyInd = i;
+ break;
}
+ }
- static constexpr uint32_t InvalidFamilyInd = std::numeric_limits<uint32_t>::max();
- uint32_t FamilyInd = InvalidFamilyInd;
-
- for(uint32_t i=0; i < m_QueueFamilyProperties.size(); ++i)
+ if (FamilyInd == InvalidFamilyInd)
+ {
+ for (uint32_t i = 0; i < m_QueueFamilyProperties.size(); ++i)
{
- // First try to find a queue, for which the flags match exactly
- // (i.e. dedicated compute or transfer queue)
- const auto &Props = m_QueueFamilyProperties[i];
- if( Props.queueFlags == QueueFlags ||
- Props.queueFlags == QueueFlagsOpt)
+ // Try to find a queue for which all requested flags are set
+ const auto& Props = m_QueueFamilyProperties[i];
+ // Check only QueueFlags as VK_QUEUE_TRANSFER_BIT is
+ // optional for graphics and/or compute queues
+ if ((Props.queueFlags & QueueFlags) == QueueFlags)
{
FamilyInd = i;
break;
}
}
+ }
- if(FamilyInd == InvalidFamilyInd)
- {
- for (uint32_t i = 0; i < m_QueueFamilyProperties.size(); ++i)
- {
- // Try to find a queue for which all requested flags are set
- const auto &Props = m_QueueFamilyProperties[i];
- // Check only QueueFlags as VK_QUEUE_TRANSFER_BIT is
- // optional for graphics and/or compute queues
- if ((Props.queueFlags & QueueFlags) == QueueFlags)
- {
- FamilyInd = i;
- break;
- }
- }
- }
-
- if (FamilyInd != InvalidFamilyInd)
+ if (FamilyInd != InvalidFamilyInd)
+ {
+ if (QueueFlags & (VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT))
{
- if (QueueFlags & (VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT))
- {
#ifdef _DEBUG
- const auto& Props = m_QueueFamilyProperties[FamilyInd];
- // Queues supporting graphics and/or compute operations must report (1,1,1)
- // in minImageTransferGranularity, meaning that there are no additional restrictions
- // on the granularity of image transfer operations for these queues (4.1).
- VERIFY_EXPR(Props.minImageTransferGranularity.width == 1 &&
- Props.minImageTransferGranularity.height == 1 &&
- Props.minImageTransferGranularity.depth == 1);
+ const auto& Props = m_QueueFamilyProperties[FamilyInd];
+ // Queues supporting graphics and/or compute operations must report (1,1,1)
+ // in minImageTransferGranularity, meaning that there are no additional restrictions
+ // on the granularity of image transfer operations for these queues (4.1).
+ VERIFY_EXPR(Props.minImageTransferGranularity.width == 1 &&
+ Props.minImageTransferGranularity.height == 1 &&
+ Props.minImageTransferGranularity.depth == 1);
#endif
- }
}
- else
- {
- LOG_ERROR_AND_THROW("Failed to find suitable queue family");
- }
-
- return FamilyInd;
}
-
- bool VulkanPhysicalDevice::IsExtensionSupported(const char *ExtensionName)const
+ else
{
- for(const auto& Extension : m_SupportedExtensions)
- if(strcmp(Extension.extensionName, ExtensionName) == 0)
- return true;
-
- return false;
+ LOG_ERROR_AND_THROW("Failed to find suitable queue family");
}
- bool VulkanPhysicalDevice::CheckPresentSupport(uint32_t queueFamilyIndex, VkSurfaceKHR VkSurface)const
- {
- VkBool32 PresentSupport = VK_FALSE;
- vkGetPhysicalDeviceSurfaceSupportKHR(m_VkDevice, queueFamilyIndex, VkSurface, &PresentSupport);
- return PresentSupport == VK_TRUE;
- }
+ return FamilyInd;
+}
+bool VulkanPhysicalDevice::IsExtensionSupported(const char* ExtensionName) const
+{
+ for (const auto& Extension : m_SupportedExtensions)
+ if (strcmp(Extension.extensionName, ExtensionName) == 0)
+ return true;
- // This function is used to find a device memory type that supports all the property flags we request
- // Params:
- // * memoryTypeBitsRequirement - a bitmask that contains one bit set for every supported memory type for
- // the resource. Bit i is set if and only if the memory type i in the
- // VkPhysicalDeviceMemoryProperties structure for the physical device is
- // supported for the resource.
- // * requiredProperties - required memory properties (device local, host visible, etc.)
- uint32_t VulkanPhysicalDevice::GetMemoryTypeIndex(uint32_t memoryTypeBitsRequirement,
- VkMemoryPropertyFlags requiredProperties)const
- {
- // Iterate over all memory types available for the device
- // For each pair of elements X and Y returned in memoryTypes, X must be placed at a lower index position than Y if:
- // * either the set of bit flags of X is a strict subset of the set of bit flags of Y.
- // * or the propertyFlags members of X and Y are equal, and X belongs to a memory heap with greater performance
+ return false;
+}
+
+bool VulkanPhysicalDevice::CheckPresentSupport(uint32_t queueFamilyIndex, VkSurfaceKHR VkSurface) const
+{
+ VkBool32 PresentSupport = VK_FALSE;
+ vkGetPhysicalDeviceSurfaceSupportKHR(m_VkDevice, queueFamilyIndex, VkSurface, &PresentSupport);
+ return PresentSupport == VK_TRUE;
+}
+
+
+// This function is used to find a device memory type that supports all the property flags we request
+// Params:
+// * memoryTypeBitsRequirement - a bitmask that contains one bit set for every supported memory type for
+// the resource. Bit i is set if and only if the memory type i in the
+// VkPhysicalDeviceMemoryProperties structure for the physical device is
+// supported for the resource.
+// * requiredProperties - required memory properties (device local, host visible, etc.)
+uint32_t VulkanPhysicalDevice::GetMemoryTypeIndex(uint32_t memoryTypeBitsRequirement,
+ VkMemoryPropertyFlags requiredProperties) const
+{
+ // Iterate over all memory types available for the device
+ // For each pair of elements X and Y returned in memoryTypes, X must be placed at a lower index position than Y if:
+ // * either the set of bit flags of X is a strict subset of the set of bit flags of Y.
+ // * or the propertyFlags members of X and Y are equal, and X belongs to a memory heap with greater performance
- for (uint32_t memoryIndex = 0; memoryIndex < m_MemoryProperties.memoryTypeCount; memoryIndex++)
+ for (uint32_t memoryIndex = 0; memoryIndex < m_MemoryProperties.memoryTypeCount; memoryIndex++)
+ {
+ // Each memory type returned by vkGetPhysicalDeviceMemoryProperties must have its propertyFlags set
+ // to one of the following values:
+ // * 0
+ // * HOST_VISIBLE_BIT | HOST_COHERENT_BIT
+ // * HOST_VISIBLE_BIT | HOST_CACHED_BIT
+ // * HOST_VISIBLE_BIT | HOST_CACHED_BIT | HOST_COHERENT_BIT
+ // * DEVICE_LOCAL_BIT
+ // * DEVICE_LOCAL_BIT | HOST_VISIBLE_BIT | HOST_COHERENT_BIT
+ // * DEVICE_LOCAL_BIT | HOST_VISIBLE_BIT | HOST_CACHED_BIT
+ // * DEVICE_LOCAL_BIT | HOST_VISIBLE_BIT | HOST_CACHED_BIT | HOST_COHERENT_BIT
+ // * DEVICE_LOCAL_BIT | LAZILY_ALLOCATED_BIT
+ //
+ // There must be at least one memory type with both the HOST_VISIBLE_BIT and HOST_COHERENT_BIT bits set
+ // There must be at least one memory type with the DEVICE_LOCAL_BIT bit set
+
+ const uint32_t memoryTypeBit = (1 << memoryIndex);
+ const bool isRequiredMemoryType = (memoryTypeBitsRequirement & memoryTypeBit) != 0;
+ if (isRequiredMemoryType)
{
- // Each memory type returned by vkGetPhysicalDeviceMemoryProperties must have its propertyFlags set
- // to one of the following values:
- // * 0
- // * HOST_VISIBLE_BIT | HOST_COHERENT_BIT
- // * HOST_VISIBLE_BIT | HOST_CACHED_BIT
- // * HOST_VISIBLE_BIT | HOST_CACHED_BIT | HOST_COHERENT_BIT
- // * DEVICE_LOCAL_BIT
- // * DEVICE_LOCAL_BIT | HOST_VISIBLE_BIT | HOST_COHERENT_BIT
- // * DEVICE_LOCAL_BIT | HOST_VISIBLE_BIT | HOST_CACHED_BIT
- // * DEVICE_LOCAL_BIT | HOST_VISIBLE_BIT | HOST_CACHED_BIT | HOST_COHERENT_BIT
- // * DEVICE_LOCAL_BIT | LAZILY_ALLOCATED_BIT
- //
- // There must be at least one memory type with both the HOST_VISIBLE_BIT and HOST_COHERENT_BIT bits set
- // There must be at least one memory type with the DEVICE_LOCAL_BIT bit set
-
- const uint32_t memoryTypeBit = (1 << memoryIndex);
- const bool isRequiredMemoryType = (memoryTypeBitsRequirement & memoryTypeBit) != 0;
- if(isRequiredMemoryType)
- {
- const VkMemoryPropertyFlags properties = m_MemoryProperties.memoryTypes[memoryIndex].propertyFlags;
- const bool hasRequiredProperties = (properties & requiredProperties) == requiredProperties;
+ const VkMemoryPropertyFlags properties = m_MemoryProperties.memoryTypes[memoryIndex].propertyFlags;
+ const bool hasRequiredProperties = (properties & requiredProperties) == requiredProperties;
- if (hasRequiredProperties)
- return memoryIndex;
- }
+ if (hasRequiredProperties)
+ return memoryIndex;
}
- return InvalidMemoryTypeIndex;
}
+ return InvalidMemoryTypeIndex;
+}
- VkFormatProperties VulkanPhysicalDevice::GetPhysicalDeviceFormatProperties(VkFormat imageFormat)const
- {
- VkFormatProperties formatProperties;
- vkGetPhysicalDeviceFormatProperties(m_VkDevice, imageFormat, &formatProperties);
- return formatProperties;
- }
+VkFormatProperties VulkanPhysicalDevice::GetPhysicalDeviceFormatProperties(VkFormat imageFormat) const
+{
+ VkFormatProperties formatProperties;
+ vkGetPhysicalDeviceFormatProperties(m_VkDevice, imageFormat, &formatProperties);
+ return formatProperties;
}
+
+} // namespace VulkanUtilities