diff --git a/src/dxvk/dxvk_barrier.cpp b/src/dxvk/dxvk_barrier.cpp index acda4f15b..a00a80c98 100644 --- a/src/dxvk/dxvk_barrier.cpp +++ b/src/dxvk/dxvk_barrier.cpp @@ -117,50 +117,6 @@ namespace dxvk { } - void DxvkBarrierSet::releaseBuffer( - DxvkBarrierSet& acquire, - const DxvkBufferSliceHandle& bufSlice, - uint32_t srcQueue, - VkPipelineStageFlags srcStages, - VkAccessFlags srcAccess, - uint32_t dstQueue, - VkPipelineStageFlags dstStages, - VkAccessFlags dstAccess) { - auto& release = *this; - - m_allBarrierSrcStages |= srcStages; - - VkBufferMemoryBarrier2 barrier = { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2 }; - barrier.srcStageMask = srcStages & vk::StageDeviceMask; - barrier.srcAccessMask = srcAccess & vk::AccessWriteMask; - barrier.dstStageMask = VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT; - barrier.dstAccessMask = 0; - barrier.srcQueueFamilyIndex = srcQueue; - barrier.dstQueueFamilyIndex = dstQueue; - barrier.buffer = bufSlice.handle; - barrier.offset = bufSlice.offset; - barrier.size = bufSlice.length; - release.m_bufBarriers.push_back(barrier); - - barrier.srcStageMask = VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT; - barrier.srcAccessMask = 0; - barrier.dstStageMask = dstStages; - barrier.dstAccessMask = dstAccess; - acquire.m_bufBarriers.push_back(barrier); - - if (dstAccess & vk::AccessHostMask) { - acquire.m_hostBarrierSrcStages |= srcStages & vk::StageDeviceMask; - acquire.m_hostBarrierDstAccess |= dstAccess & vk::AccessHostMask; - } - - DxvkAccessFlags access(DxvkAccess::Read, DxvkAccess::Write); - release.m_bufSlices.insert(bufSlice.handle, - DxvkBarrierBufferSlice(bufSlice.offset, bufSlice.length, access)); - acquire.m_bufSlices.insert(bufSlice.handle, - DxvkBarrierBufferSlice(bufSlice.offset, bufSlice.length, access)); - } - - void DxvkBarrierSet::releaseImage( DxvkBarrierSet& acquire, const Rc& image, diff --git a/src/dxvk/dxvk_barrier.h b/src/dxvk/dxvk_barrier.h index 4e9484386..38c7666d9 100644 --- a/src/dxvk/dxvk_barrier.h +++ b/src/dxvk/dxvk_barrier.h @@ -533,16 +533,6 @@ namespace dxvk { VkPipelineStageFlags dstStages, VkAccessFlags dstAccess); - void releaseBuffer( - DxvkBarrierSet& acquire, - const DxvkBufferSliceHandle& bufSlice, - uint32_t srcQueue, - VkPipelineStageFlags srcStages, - VkAccessFlags srcAccess, - uint32_t dstQueue, - VkPipelineStageFlags dstStages, - VkAccessFlags dstAccess); - void releaseImage( DxvkBarrierSet& acquire, const Rc& image, diff --git a/src/dxvk/dxvk_buffer.cpp b/src/dxvk/dxvk_buffer.cpp index 0c3f291c6..192a12d94 100644 --- a/src/dxvk/dxvk_buffer.cpp +++ b/src/dxvk/dxvk_buffer.cpp @@ -15,6 +15,7 @@ namespace dxvk { m_allocator (&allocator), m_properties (memFlags), m_shaderStages (util::shaderStages(createInfo.stages)), + m_sharingMode (device->getSharingMode()), m_info (createInfo) { // Create and assign actual buffer resource assignSlice(allocateSlice()); @@ -31,12 +32,13 @@ namespace dxvk { m_allocator (&allocator), m_properties (memFlags), m_shaderStages (util::shaderStages(createInfo.stages)), + m_sharingMode (device->getSharingMode()), m_info (createInfo) { VkBufferCreateInfo info = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; info.flags = m_info.flags; info.usage = m_info.usage; info.size = m_info.size; - info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + m_sharingMode.fill(info); assignSlice(allocator.importBufferResource(info, importInfo)); } diff --git a/src/dxvk/dxvk_buffer.h b/src/dxvk/dxvk_buffer.h index eeae1ffed..db0c7d0aa 100644 --- a/src/dxvk/dxvk_buffer.h +++ b/src/dxvk/dxvk_buffer.h @@ -317,7 +317,7 @@ namespace dxvk { info.flags = m_info.flags; info.usage = m_info.usage; info.size = m_info.size; - info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + m_sharingMode.fill(info); return m_allocator->createBufferResource(info, m_properties, cache); } @@ -391,6 +391,7 @@ namespace dxvk { DxvkMemoryAllocator* m_allocator = nullptr; VkMemoryPropertyFlags m_properties = 0u; VkShaderStageFlags m_shaderStages = 0u; + DxvkSharingModeInfo m_sharingMode = { }; DxvkBufferCreateInfo m_info = { }; diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp index 021375c24..ce7343c4d 100644 --- a/src/dxvk/dxvk_context.cpp +++ b/src/dxvk/dxvk_context.cpp @@ -1435,11 +1435,9 @@ namespace dxvk { slice.handle, slice.offset, dxvk::align(slice.length, 4), 0); - m_initBarriers.accessBuffer(slice, - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_ACCESS_TRANSFER_WRITE_BIT, - buffer->info().stages, - buffer->info().access); + m_initBarriers.accessMemory( + VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, + buffer->info().stages, buffer->info().access); m_cmd->trackResource(buffer); } @@ -2556,15 +2554,23 @@ namespace dxvk { m_cmd->cmdCopyBuffer(DxvkCmdBuffer::SdmaBuffer, ©Info); - m_sdmaBarriers.releaseBuffer( - m_initBarriers, bufferSlice, - m_device->queues().transfer.queueFamily, - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_ACCESS_TRANSFER_WRITE_BIT, - m_device->queues().graphics.queueFamily, - buffer->info().stages, - buffer->info().access); - + if (m_device->hasDedicatedTransferQueue()) { + // Buffers use SHARING_MODE_CONCURRENT, so no explicit queue + // family ownership transfer is required. Access is serialized + // via a semaphore. + m_sdmaBarriers.accessMemory( + VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, + VK_PIPELINE_STAGE_NONE, VK_ACCESS_NONE); + + m_initBarriers.accessMemory( + VK_PIPELINE_STAGE_NONE, VK_ACCESS_NONE, + buffer->info().stages, buffer->info().access); + } else { + m_sdmaBarriers.accessMemory( + VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, + buffer->info().stages, buffer->info().access); + } + m_cmd->trackResource(stagingSlice.buffer()); m_cmd->trackResource(buffer); } diff --git a/src/dxvk/dxvk_device.cpp b/src/dxvk/dxvk_device.cpp index 27a211aa8..303e15000 100644 --- a/src/dxvk/dxvk_device.cpp +++ b/src/dxvk/dxvk_device.cpp @@ -14,11 +14,11 @@ namespace dxvk { m_instance (instance), m_adapter (adapter), m_vkd (vkd), + m_queues (queues), m_features (features), m_properties (adapter->devicePropertiesExt()), m_perfHints (getPerfHints()), m_objects (this), - m_queues (queues), m_submissionQueue (this, queueCallback) { } diff --git a/src/dxvk/dxvk_device.h b/src/dxvk/dxvk_device.h index 9876aafb5..0b0c48c69 100644 --- a/src/dxvk/dxvk_device.h +++ b/src/dxvk/dxvk_device.h @@ -134,7 +134,18 @@ namespace dxvk { return m_queues.transfer.queueHandle != m_queues.graphics.queueHandle; } - + + /** + * \brief Queries sharing mode info + * \returns Sharing mode info + */ + DxvkSharingModeInfo getSharingMode() const { + DxvkSharingModeInfo result = { }; + result.queueFamilies[0] = m_queues.graphics.queueFamily; + result.queueFamilies[1] = m_queues.transfer.queueFamily; + return result; + } + /** * \brief The instance * @@ -539,6 +550,8 @@ namespace dxvk { Rc m_adapter; Rc m_vkd; + DxvkDeviceQueueSet m_queues; + DxvkDeviceFeatures m_features; DxvkDeviceInfo m_properties; @@ -548,8 +561,6 @@ namespace dxvk { sync::Spinlock m_statLock; DxvkStatCounters m_statCounters; - DxvkDeviceQueueSet m_queues; - DxvkRecycler m_recycledCommandLists; DxvkSubmissionQueue m_submissionQueue; diff --git a/src/dxvk/dxvk_memory.cpp b/src/dxvk/dxvk_memory.cpp index 28b4b3659..8c0a158b2 100644 --- a/src/dxvk/dxvk_memory.cpp +++ b/src/dxvk/dxvk_memory.cpp @@ -434,7 +434,7 @@ namespace dxvk { DxvkMemoryAllocator::DxvkMemoryAllocator(DxvkDevice* device) - : m_device(device) { + : m_device(device), m_sharingModeInfo(m_device->getSharingMode()) { VkPhysicalDeviceMemoryProperties memInfo = m_device->adapter()->memoryProperties(); m_memTypeCount = memInfo.memoryTypeCount; @@ -616,7 +616,7 @@ namespace dxvk { DxvkLocalAllocationCache* allocationCache) { Rc allocation; - if (likely(!createInfo.flags && createInfo.sharingMode == VK_SHARING_MODE_EXCLUSIVE)) { + if (likely(!createInfo.flags)) { VkMemoryRequirements memoryRequirements = { }; memoryRequirements.size = createInfo.size; memoryRequirements.alignment = GlobalBufferAlignment; @@ -998,7 +998,7 @@ namespace dxvk { VkBufferCreateInfo bufferInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; bufferInfo.size = size; bufferInfo.usage = type.bufferUsage; - bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + m_sharingModeInfo.fill(bufferInfo); VkResult status = vk->vkCreateBuffer(vk->device(), &bufferInfo, nullptr, &buffer); @@ -1499,7 +1499,7 @@ namespace dxvk { | VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT; - bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + m_sharingModeInfo.fill(bufferInfo); if (getBufferMemoryRequirements(bufferInfo, requirements)) typeMask &= requirements.memoryRequirements.memoryTypeBits; @@ -1561,7 +1561,7 @@ namespace dxvk { // to be supported, but we need to be robust around buffer creation anyway. VkBufferCreateInfo bufferInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; bufferInfo.size = 65536; - bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + m_sharingModeInfo.fill(bufferInfo); VkMemoryRequirements2 requirements = { VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2 }; diff --git a/src/dxvk/dxvk_memory.h b/src/dxvk/dxvk_memory.h index e56efcdb5..3345ddf31 100644 --- a/src/dxvk/dxvk_memory.h +++ b/src/dxvk/dxvk_memory.h @@ -213,6 +213,33 @@ namespace dxvk { }; + /** + * \brief Sharing mode info + * + * Stores available queue families and provides methods + * to fill in sharing mode infos for resource creation. + */ + struct DxvkSharingModeInfo { + std::array queueFamilies = { }; + + VkSharingMode sharingMode() const { + return queueFamilies[0] != queueFamilies[1] + ? VK_SHARING_MODE_CONCURRENT + : VK_SHARING_MODE_EXCLUSIVE; + } + + template + void fill(CreateInfo& info) const { + info.sharingMode = sharingMode(); + + if (info.sharingMode == VK_SHARING_MODE_CONCURRENT) { + info.queueFamilyIndexCount = queueFamilies.size(); + info.pQueueFamilyIndices = queueFamilies.data(); + } + } + }; + + /** * \brief Buffer view key * @@ -1121,6 +1148,8 @@ namespace dxvk { DxvkDevice* m_device; + DxvkSharingModeInfo m_sharingModeInfo; + dxvk::mutex m_mutex; dxvk::condition_variable m_cond;