1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-01-19 14:52:10 +01:00

[dxvk] Correctly use VK_SHARING_MODE_CONCURRENT for buffers

Fixes some out-of-spec behaviour introduced with the global buffer rework.
This commit is contained in:
Philip Rebohle 2024-10-04 18:39:50 +02:00
parent a278d6bf1d
commit 836e990dc5
9 changed files with 74 additions and 79 deletions

View File

@ -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( void DxvkBarrierSet::releaseImage(
DxvkBarrierSet& acquire, DxvkBarrierSet& acquire,
const Rc<DxvkImage>& image, const Rc<DxvkImage>& image,

View File

@ -533,16 +533,6 @@ namespace dxvk {
VkPipelineStageFlags dstStages, VkPipelineStageFlags dstStages,
VkAccessFlags dstAccess); 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( void releaseImage(
DxvkBarrierSet& acquire, DxvkBarrierSet& acquire,
const Rc<DxvkImage>& image, const Rc<DxvkImage>& image,

View File

@ -15,6 +15,7 @@ namespace dxvk {
m_allocator (&allocator), m_allocator (&allocator),
m_properties (memFlags), m_properties (memFlags),
m_shaderStages (util::shaderStages(createInfo.stages)), m_shaderStages (util::shaderStages(createInfo.stages)),
m_sharingMode (device->getSharingMode()),
m_info (createInfo) { m_info (createInfo) {
// Create and assign actual buffer resource // Create and assign actual buffer resource
assignSlice(allocateSlice()); assignSlice(allocateSlice());
@ -31,12 +32,13 @@ namespace dxvk {
m_allocator (&allocator), m_allocator (&allocator),
m_properties (memFlags), m_properties (memFlags),
m_shaderStages (util::shaderStages(createInfo.stages)), m_shaderStages (util::shaderStages(createInfo.stages)),
m_sharingMode (device->getSharingMode()),
m_info (createInfo) { m_info (createInfo) {
VkBufferCreateInfo info = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; VkBufferCreateInfo info = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
info.flags = m_info.flags; info.flags = m_info.flags;
info.usage = m_info.usage; info.usage = m_info.usage;
info.size = m_info.size; info.size = m_info.size;
info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; m_sharingMode.fill(info);
assignSlice(allocator.importBufferResource(info, importInfo)); assignSlice(allocator.importBufferResource(info, importInfo));
} }

View File

@ -317,7 +317,7 @@ namespace dxvk {
info.flags = m_info.flags; info.flags = m_info.flags;
info.usage = m_info.usage; info.usage = m_info.usage;
info.size = m_info.size; info.size = m_info.size;
info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; m_sharingMode.fill(info);
return m_allocator->createBufferResource(info, m_properties, cache); return m_allocator->createBufferResource(info, m_properties, cache);
} }
@ -391,6 +391,7 @@ namespace dxvk {
DxvkMemoryAllocator* m_allocator = nullptr; DxvkMemoryAllocator* m_allocator = nullptr;
VkMemoryPropertyFlags m_properties = 0u; VkMemoryPropertyFlags m_properties = 0u;
VkShaderStageFlags m_shaderStages = 0u; VkShaderStageFlags m_shaderStages = 0u;
DxvkSharingModeInfo m_sharingMode = { };
DxvkBufferCreateInfo m_info = { }; DxvkBufferCreateInfo m_info = { };

View File

@ -1435,11 +1435,9 @@ namespace dxvk {
slice.handle, slice.offset, slice.handle, slice.offset,
dxvk::align(slice.length, 4), 0); dxvk::align(slice.length, 4), 0);
m_initBarriers.accessBuffer(slice, m_initBarriers.accessMemory(
VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_TRANSFER_WRITE_BIT,
VK_ACCESS_TRANSFER_WRITE_BIT, buffer->info().stages, buffer->info().access);
buffer->info().stages,
buffer->info().access);
m_cmd->trackResource<DxvkAccess::Write>(buffer); m_cmd->trackResource<DxvkAccess::Write>(buffer);
} }
@ -2556,15 +2554,23 @@ namespace dxvk {
m_cmd->cmdCopyBuffer(DxvkCmdBuffer::SdmaBuffer, &copyInfo); m_cmd->cmdCopyBuffer(DxvkCmdBuffer::SdmaBuffer, &copyInfo);
m_sdmaBarriers.releaseBuffer( if (m_device->hasDedicatedTransferQueue()) {
m_initBarriers, bufferSlice, // Buffers use SHARING_MODE_CONCURRENT, so no explicit queue
m_device->queues().transfer.queueFamily, // family ownership transfer is required. Access is serialized
VK_PIPELINE_STAGE_TRANSFER_BIT, // via a semaphore.
VK_ACCESS_TRANSFER_WRITE_BIT, m_sdmaBarriers.accessMemory(
m_device->queues().graphics.queueFamily, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_TRANSFER_WRITE_BIT,
buffer->info().stages, VK_PIPELINE_STAGE_NONE, VK_ACCESS_NONE);
buffer->info().access);
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<DxvkAccess::Read>(stagingSlice.buffer()); m_cmd->trackResource<DxvkAccess::Read>(stagingSlice.buffer());
m_cmd->trackResource<DxvkAccess::Write>(buffer); m_cmd->trackResource<DxvkAccess::Write>(buffer);
} }

View File

@ -14,11 +14,11 @@ namespace dxvk {
m_instance (instance), m_instance (instance),
m_adapter (adapter), m_adapter (adapter),
m_vkd (vkd), m_vkd (vkd),
m_queues (queues),
m_features (features), m_features (features),
m_properties (adapter->devicePropertiesExt()), m_properties (adapter->devicePropertiesExt()),
m_perfHints (getPerfHints()), m_perfHints (getPerfHints()),
m_objects (this), m_objects (this),
m_queues (queues),
m_submissionQueue (this, queueCallback) { m_submissionQueue (this, queueCallback) {
} }

View File

@ -134,7 +134,18 @@ namespace dxvk {
return m_queues.transfer.queueHandle return m_queues.transfer.queueHandle
!= m_queues.graphics.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 * \brief The instance
* *
@ -539,6 +550,8 @@ namespace dxvk {
Rc<DxvkAdapter> m_adapter; Rc<DxvkAdapter> m_adapter;
Rc<vk::DeviceFn> m_vkd; Rc<vk::DeviceFn> m_vkd;
DxvkDeviceQueueSet m_queues;
DxvkDeviceFeatures m_features; DxvkDeviceFeatures m_features;
DxvkDeviceInfo m_properties; DxvkDeviceInfo m_properties;
@ -548,8 +561,6 @@ namespace dxvk {
sync::Spinlock m_statLock; sync::Spinlock m_statLock;
DxvkStatCounters m_statCounters; DxvkStatCounters m_statCounters;
DxvkDeviceQueueSet m_queues;
DxvkRecycler<DxvkCommandList, 16> m_recycledCommandLists; DxvkRecycler<DxvkCommandList, 16> m_recycledCommandLists;
DxvkSubmissionQueue m_submissionQueue; DxvkSubmissionQueue m_submissionQueue;

View File

@ -434,7 +434,7 @@ namespace dxvk {
DxvkMemoryAllocator::DxvkMemoryAllocator(DxvkDevice* device) DxvkMemoryAllocator::DxvkMemoryAllocator(DxvkDevice* device)
: m_device(device) { : m_device(device), m_sharingModeInfo(m_device->getSharingMode()) {
VkPhysicalDeviceMemoryProperties memInfo = m_device->adapter()->memoryProperties(); VkPhysicalDeviceMemoryProperties memInfo = m_device->adapter()->memoryProperties();
m_memTypeCount = memInfo.memoryTypeCount; m_memTypeCount = memInfo.memoryTypeCount;
@ -616,7 +616,7 @@ namespace dxvk {
DxvkLocalAllocationCache* allocationCache) { DxvkLocalAllocationCache* allocationCache) {
Rc<DxvkResourceAllocation> allocation; Rc<DxvkResourceAllocation> allocation;
if (likely(!createInfo.flags && createInfo.sharingMode == VK_SHARING_MODE_EXCLUSIVE)) { if (likely(!createInfo.flags)) {
VkMemoryRequirements memoryRequirements = { }; VkMemoryRequirements memoryRequirements = { };
memoryRequirements.size = createInfo.size; memoryRequirements.size = createInfo.size;
memoryRequirements.alignment = GlobalBufferAlignment; memoryRequirements.alignment = GlobalBufferAlignment;
@ -998,7 +998,7 @@ namespace dxvk {
VkBufferCreateInfo bufferInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; VkBufferCreateInfo bufferInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
bufferInfo.size = size; bufferInfo.size = size;
bufferInfo.usage = type.bufferUsage; bufferInfo.usage = type.bufferUsage;
bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; m_sharingModeInfo.fill(bufferInfo);
VkResult status = vk->vkCreateBuffer(vk->device(), &bufferInfo, nullptr, &buffer); 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_UNIFORM_TEXEL_BUFFER_BIT
| VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT
| VK_BUFFER_USAGE_TRANSFER_SRC_BIT; | VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; m_sharingModeInfo.fill(bufferInfo);
if (getBufferMemoryRequirements(bufferInfo, requirements)) if (getBufferMemoryRequirements(bufferInfo, requirements))
typeMask &= requirements.memoryRequirements.memoryTypeBits; typeMask &= requirements.memoryRequirements.memoryTypeBits;
@ -1561,7 +1561,7 @@ namespace dxvk {
// to be supported, but we need to be robust around buffer creation anyway. // to be supported, but we need to be robust around buffer creation anyway.
VkBufferCreateInfo bufferInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; VkBufferCreateInfo bufferInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
bufferInfo.size = 65536; bufferInfo.size = 65536;
bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; m_sharingModeInfo.fill(bufferInfo);
VkMemoryRequirements2 requirements = { VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2 }; VkMemoryRequirements2 requirements = { VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2 };

View File

@ -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<uint32_t, 2u> queueFamilies = { };
VkSharingMode sharingMode() const {
return queueFamilies[0] != queueFamilies[1]
? VK_SHARING_MODE_CONCURRENT
: VK_SHARING_MODE_EXCLUSIVE;
}
template<typename CreateInfo>
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 * \brief Buffer view key
* *
@ -1121,6 +1148,8 @@ namespace dxvk {
DxvkDevice* m_device; DxvkDevice* m_device;
DxvkSharingModeInfo m_sharingModeInfo;
dxvk::mutex m_mutex; dxvk::mutex m_mutex;
dxvk::condition_variable m_cond; dxvk::condition_variable m_cond;