summaryrefslogtreecommitdiffstats
path: root/Graphics/GraphicsEngineVulkan
diff options
context:
space:
mode:
authorassiduous <assiduous@diligentgraphics.com>2020-08-23 03:26:49 +0000
committerassiduous <assiduous@diligentgraphics.com>2020-08-23 03:26:49 +0000
commit2771c71fad9cc4311c287ad119d078662ef52c29 (patch)
treea0cf76cd433d6cba40b8a1478ed9d415a2517481 /Graphics/GraphicsEngineVulkan
parentD3D12 backend: improved command list version detection (diff)
downloadDiligentCore-2771c71fad9cc4311c287ad119d078662ef52c29.tar.gz
DiligentCore-2771c71fad9cc4311c287ad119d078662ef52c29.zip
Added USAGE_UNIFIED usage type (API 240066)
Diffstat (limited to 'Graphics/GraphicsEngineVulkan')
-rw-r--r--Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp7
-rw-r--r--Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanPhysicalDevice.hpp9
-rw-r--r--Graphics/GraphicsEngineVulkan/src/BufferVkImpl.cpp262
-rw-r--r--Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanMemoryManager.cpp2
4 files changed, 178 insertions, 102 deletions
diff --git a/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp
index 38bd4893..1adf71ee 100644
--- a/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp
@@ -163,6 +163,13 @@ public:
{
return m_MemoryMgr.Allocate(MemReqs, MemoryProperties);
}
+ VulkanUtilities::VulkanMemoryAllocation AllocateMemory(VkDeviceSize Size, VkDeviceSize Alignment, uint32_t MemoryTypeIndex)
+ {
+ const auto& MemoryProps = m_PhysicalDevice->GetMemoryProperties();
+ VERIFY_EXPR(MemoryTypeIndex < MemoryProps.memoryTypeCount);
+ const auto MemoryFlags = MemoryProps.memoryTypes[MemoryTypeIndex].propertyFlags;
+ return m_MemoryMgr.Allocate(Size, Alignment, MemoryTypeIndex, (MemoryFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0);
+ }
VulkanUtilities::VulkanMemoryManager& GetGlobalMemoryManager() { return m_MemoryMgr; }
VulkanDynamicMemoryManager& GetDynamicMemoryManager() { return m_DynamicMemoryManager; }
diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanPhysicalDevice.hpp b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanPhysicalDevice.hpp
index 24212950..c54541c6 100644
--- a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanPhysicalDevice.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanPhysicalDevice.hpp
@@ -53,13 +53,14 @@ public:
bool CheckPresentSupport (uint32_t queueFamilyIndex, VkSurfaceKHR VkSurface) const;
// clang-format on
- static constexpr uint32_t InvalidMemoryTypeIndex = static_cast<uint32_t>(-1);
+ static constexpr uint32_t InvalidMemoryTypeIndex = ~uint32_t{0};
uint32_t GetMemoryTypeIndex(uint32_t typeBits, VkMemoryPropertyFlags properties) const;
- const VkPhysicalDeviceProperties& GetProperties() const { return m_Properties; }
- const VkPhysicalDeviceFeatures& GetFeatures() const { return m_Features; }
- VkFormatProperties GetPhysicalDeviceFormatProperties(VkFormat imageFormat) const;
+ const VkPhysicalDeviceProperties& GetProperties() const { return m_Properties; }
+ const VkPhysicalDeviceFeatures& GetFeatures() const { return m_Features; }
+ const VkPhysicalDeviceMemoryProperties& GetMemoryProperties() const { return m_MemoryProperties; }
+ VkFormatProperties GetPhysicalDeviceFormatProperties(VkFormat imageFormat) const;
private:
VulkanPhysicalDevice(VkPhysicalDevice vkDevice);
diff --git a/Graphics/GraphicsEngineVulkan/src/BufferVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/BufferVkImpl.cpp
index 1e64e97b..9ff268dd 100644
--- a/Graphics/GraphicsEngineVulkan/src/BufferVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/BufferVkImpl.cpp
@@ -57,29 +57,26 @@ BufferVkImpl::BufferVkImpl(IReferenceCounters* pRefCounters,
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__)
+ ValidateBufferInitData(BuffDesc, pBuffData);
- 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_STATIC)
+ VERIFY(pBuffData != nullptr && pBuffData->pData != nullptr, "Initial data must not be null for static buffers");
+ if (m_Desc.Usage == USAGE_DYNAMIC)
+ VERIFY(pBuffData == nullptr || pBuffData->pData == nullptr, "Initial data must be null for dynamic buffers");
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");
+ VERIFY(m_Desc.CPUAccessFlags == CPU_ACCESS_WRITE || m_Desc.CPUAccessFlags == CPU_ACCESS_READ,
+ "Exactly one of the CPU_ACCESS_WRITE or CPU_ACCESS_READ flags must be specified for a staging 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");
- }
+ VERIFY(pBuffData == nullptr || pBuffData->pData == nullptr, "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& LogicalDevice = pRenderDeviceVk->GetLogicalDevice();
+ const auto& PhysicalDevice = pRenderDeviceVk->GetPhysicalDevice();
+ const auto& DeviceLimits = PhysicalDevice.GetProperties().limits;
+ m_DynamicOffsetAlignment = std::max(Uint32{4}, static_cast<Uint32>(DeviceLimits.optimalBufferCopyOffsetAlignment));
VkBufferCreateInfo VkBuffCI = {};
VkBuffCI.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
@@ -184,14 +181,56 @@ BufferVkImpl::BufferVkImpl(IReferenceCounters* pRefCounters,
VkMemoryRequirements MemReqs = LogicalDevice.GetBufferMemoryRequirements(m_VulkanBuffer);
- VkMemoryPropertyFlags BufferMemoryFlags = 0;
- if (m_Desc.Usage == USAGE_STAGING)
- BufferMemoryFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
- else
- BufferMemoryFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
+ uint32_t MemoryTypeIndex = VulkanUtilities::VulkanPhysicalDevice::InvalidMemoryTypeIndex;
+ if (m_Desc.Usage == USAGE_UNIFIED)
+ {
+ // Attempt to find device-local and CPU-visible memory type
+ // clang-format off
+ MemoryTypeIndex = PhysicalDevice.GetMemoryTypeIndex(
+ MemReqs.memoryTypeBits,
+ VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
+ VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
+ (((m_Desc.CPUAccessFlags & CPU_ACCESS_READ) != 0) ? VK_MEMORY_PROPERTY_HOST_CACHED_BIT : 0) |
+ (((m_Desc.CPUAccessFlags & CPU_ACCESS_WRITE) != 0) ? VK_MEMORY_PROPERTY_HOST_COHERENT_BIT : 0)
+ );
+ // clang-format on
+ if (MemoryTypeIndex == VulkanUtilities::VulkanPhysicalDevice::InvalidMemoryTypeIndex)
+ {
+ DecayUnifiedBuffer();
+ }
+ }
+
+ if (MemoryTypeIndex == VulkanUtilities::VulkanPhysicalDevice::InvalidMemoryTypeIndex)
+ {
+ VkMemoryPropertyFlags vkMemoryFlags = 0;
+ switch (m_Desc.Usage)
+ {
+ case USAGE_STATIC:
+ case USAGE_DEFAULT:
+ case USAGE_DYNAMIC: // Dynamic buffer with SRV or UAV bind flag
+ vkMemoryFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
+ break;
+
+ case USAGE_STAGING:
+ // clang-format off
+ vkMemoryFlags =
+ VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
+ (((m_Desc.CPUAccessFlags & CPU_ACCESS_READ) != 0) ? VK_MEMORY_PROPERTY_HOST_CACHED_BIT : 0) |
+ (((m_Desc.CPUAccessFlags & CPU_ACCESS_WRITE) != 0) ? VK_MEMORY_PROPERTY_HOST_COHERENT_BIT : 0);
+ // clang-format on
+ break;
+
+ default:
+ UNEXPECTED("Unexpected usage");
+ }
+ MemoryTypeIndex = PhysicalDevice.GetMemoryTypeIndex(MemReqs.memoryTypeBits, vkMemoryFlags);
+ }
+
+ if (MemoryTypeIndex == VulkanUtilities::VulkanPhysicalDevice::InvalidMemoryTypeIndex)
+ LOG_ERROR_AND_THROW("Failed to find suitable memory type for buffer '", m_Desc.Name, '\'');
VERIFY(IsPowerOfTwo(MemReqs.alignment), "Alignment is not power of 2!");
- m_MemoryAllocation = pRenderDeviceVk->AllocateMemory(MemReqs, BufferMemoryFlags);
+ m_MemoryAllocation = pRenderDeviceVk->AllocateMemory(MemReqs.size, MemReqs.alignment, MemoryTypeIndex);
m_BufferMemoryAlignedOffset = Align(VkDeviceSize{m_MemoryAllocation.UnalignedOffset}, MemReqs.alignment);
VERIFY(m_MemoryAllocation.Size >= MemReqs.size + (m_BufferMemoryAlignedOffset - m_MemoryAllocation.UnalignedOffset), "Size of memory allocation is too small");
@@ -203,82 +242,111 @@ BufferVkImpl::BufferVkImpl(IReferenceCounters* pRefCounters,
RESOURCE_STATE InitialState = RESOURCE_STATE_UNDEFINED;
if (bInitializeBuffer)
{
- VkBufferCreateInfo VkStaginBuffCI = VkBuffCI;
- VkStaginBuffCI.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
-
- std::string StagingBufferName = "Upload buffer for '";
- StagingBufferName += m_Desc.Name;
- StagingBufferName += '\'';
- 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
- // 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 AlignedStagingMemOffset = Align(VkDeviceSize{StagingMemoryAllocation.UnalignedOffset}, StagingBufferMemReqs.alignment);
- VERIFY_EXPR(StagingMemoryAllocation.Size >= StagingBufferMemReqs.size + (AlignedStagingMemOffset - StagingMemoryAllocation.UnalignedOffset));
-
- auto* StagingData = reinterpret_cast<uint8_t*>(StagingMemoryAllocation.Page->GetCPUMemory());
- if (StagingData == nullptr)
- LOG_BUFFER_ERROR_AND_THROW("Failed to allocate staging data");
- memcpy(StagingData + AlignedStagingMemOffset, pBuffData->pData, pBuffData->DataSize);
-
- err = LogicalDevice.BindBufferMemory(StagingBuffer, StagingBufferMemory, AlignedStagingMemOffset);
- CHECK_VK_ERROR_AND_THROW(err, "Failed to bind staging bufer memory");
-
- VulkanUtilities::CommandPoolWrapper CmdPool;
- 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;
- VkAccessFlags AccessFlags = ResourceStateFlagsToVkAccessFlags(InitialState);
- VERIFY_EXPR(AccessFlags == VK_ACCESS_TRANSFER_WRITE_BIT);
- VulkanUtilities::VulkanCommandBuffer::BufferMemoryBarrier(vkCmdBuff, m_VulkanBuffer, 0, AccessFlags, EnabledGraphicsShaderStages);
-
- // 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;
- vkCmdCopyBuffer(vkCmdBuff, StagingBuffer, m_VulkanBuffer, 1, &BuffCopy);
-
- Uint32 QueueIndex = 0;
- 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
- // first command buffer submitted through the immediate context is complete
-
- // Next Cmd Buff| Next Fence | This Thread | Immediate Context
- // | | |
- // N | F | |
- // | | |
- // | | ExecuteAndDisposeTransientCmdBuff(vkCmdBuff) |
- // | | - SubmittedCmdBuffNumber = N |
- // | | - SubmittedFenceValue = F |
- // N+1 - - | - F+1 - | |
- // | | Release(StagingBuffer) |
- // | | - {N+1, StagingBuffer} -> Stale Objects |
- // | | |
- // | | |
- // | | | ExecuteCommandBuffer()
- // | | | - SubmittedCmdBuffNumber = N+1
- // | | | - SubmittedFenceValue = F+1
- // 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(StagingMemoryAllocation), Uint64{1} << Uint64{QueueIndex});
+ const auto& MemoryProps = PhysicalDevice.GetMemoryProperties();
+ VERIFY_EXPR(MemoryTypeIndex < MemoryProps.memoryTypeCount);
+ const auto MemoryPropFlags = MemoryProps.memoryTypes[MemoryTypeIndex].propertyFlags;
+ if ((MemoryPropFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0)
+ {
+ // Memory is directly accessible by CPU
+ auto AlignedMemOffset = Align(VkDeviceSize{m_MemoryAllocation.UnalignedOffset}, MemReqs.alignment);
+ VERIFY_EXPR(m_MemoryAllocation.Size >= MemReqs.size + (AlignedMemOffset - m_MemoryAllocation.UnalignedOffset));
+
+ auto* pData = reinterpret_cast<uint8_t*>(m_MemoryAllocation.Page->GetCPUMemory());
+ VERIFY_EXPR(pData != nullptr);
+ memcpy(pData + AlignedMemOffset, pBuffData->pData, pBuffData->DataSize);
+
+ if ((MemoryPropFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) == 0)
+ {
+ // Explicit flush is required
+ VkMappedMemoryRange FlushRange = {};
+
+ FlushRange.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;
+ FlushRange.pNext = nullptr;
+ FlushRange.memory = m_MemoryAllocation.Page->GetVkMemory();
+ FlushRange.offset = AlignedMemOffset;
+ FlushRange.size = MemReqs.size;
+ LogicalDevice.FlushMappedMemoryRanges(1, &FlushRange);
+ }
+ }
+ else
+ {
+ VkBufferCreateInfo VkStaginBuffCI = VkBuffCI;
+ VkStaginBuffCI.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
+
+ std::string StagingBufferName = "Upload buffer for '";
+ StagingBufferName += m_Desc.Name;
+ StagingBufferName += '\'';
+ 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
+ // 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 AlignedStagingMemOffset = Align(VkDeviceSize{StagingMemoryAllocation.UnalignedOffset}, StagingBufferMemReqs.alignment);
+ VERIFY_EXPR(StagingMemoryAllocation.Size >= StagingBufferMemReqs.size + (AlignedStagingMemOffset - StagingMemoryAllocation.UnalignedOffset));
+
+ auto* StagingData = reinterpret_cast<uint8_t*>(StagingMemoryAllocation.Page->GetCPUMemory());
+ if (StagingData == nullptr)
+ LOG_ERROR_AND_THROW("Failed to allocate staging data for buffer '", m_Desc.Name, '\'');
+ memcpy(StagingData + AlignedStagingMemOffset, pBuffData->pData, pBuffData->DataSize);
+
+ err = LogicalDevice.BindBufferMemory(StagingBuffer, StagingBufferMemory, AlignedStagingMemOffset);
+ CHECK_VK_ERROR_AND_THROW(err, "Failed to bind staging bufer memory");
+
+ VulkanUtilities::CommandPoolWrapper CmdPool;
+ 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;
+ VkAccessFlags AccessFlags = ResourceStateFlagsToVkAccessFlags(InitialState);
+ VERIFY_EXPR(AccessFlags == VK_ACCESS_TRANSFER_WRITE_BIT);
+ VulkanUtilities::VulkanCommandBuffer::BufferMemoryBarrier(vkCmdBuff, m_VulkanBuffer, 0, AccessFlags, EnabledGraphicsShaderStages);
+
+ // 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;
+ vkCmdCopyBuffer(vkCmdBuff, StagingBuffer, m_VulkanBuffer, 1, &BuffCopy);
+
+ Uint32 QueueIndex = 0;
+ 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
+ // first command buffer submitted through the immediate context is complete
+
+ // Next Cmd Buff| Next Fence | This Thread | Immediate Context
+ // | | |
+ // N | F | |
+ // | | |
+ // | | ExecuteAndDisposeTransientCmdBuff(vkCmdBuff) |
+ // | | - SubmittedCmdBuffNumber = N |
+ // | | - SubmittedFenceValue = F |
+ // N+1 - - | - F+1 - | |
+ // | | Release(StagingBuffer) |
+ // | | - {N+1, StagingBuffer} -> Stale Objects |
+ // | | |
+ // | | |
+ // | | | ExecuteCommandBuffer()
+ // | | | - SubmittedCmdBuffNumber = N+1
+ // | | | - SubmittedFenceValue = F+1
+ // 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(StagingMemoryAllocation), Uint64{1} << Uint64{QueueIndex});
+ }
}
SetState(InitialState);
diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanMemoryManager.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanMemoryManager.cpp
index a125233f..f9cdcdea 100644
--- a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanMemoryManager.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanMemoryManager.cpp
@@ -130,7 +130,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))
{
DEV_CHECK_ERR(MemoryTypeIndex != VulkanUtilities::VulkanPhysicalDevice::InvalidMemoryTypeIndex,
"Vulkan spec requires that for a VkBuffer not created with the VK_BUFFER_CREATE_SPARSE_BINDING_BIT "