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:
parent
a278d6bf1d
commit
836e990dc5
@ -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,
|
||||||
|
@ -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,
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
|
@ -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 = { };
|
||||||
|
|
||||||
|
@ -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,14 +2554,22 @@ namespace dxvk {
|
|||||||
|
|
||||||
m_cmd->cmdCopyBuffer(DxvkCmdBuffer::SdmaBuffer, ©Info);
|
m_cmd->cmdCopyBuffer(DxvkCmdBuffer::SdmaBuffer, ©Info);
|
||||||
|
|
||||||
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);
|
||||||
|
@ -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) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -135,6 +135,17 @@ namespace dxvk {
|
|||||||
!= 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;
|
||||||
|
@ -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 };
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user