mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-02-20 10:54:16 +01:00
[dxvk] Optimized barrier batching around compute shader execution
Reduces the number of unnecessary pipeline barriers after compute shader dispatches. Yields a small performance improvement in Final Fantasy XV.
This commit is contained in:
parent
f519a0f2e4
commit
79dc7d8947
@ -44,11 +44,14 @@ namespace dxvk {
|
|||||||
VkPipelineStageFlags dstStages,
|
VkPipelineStageFlags dstStages,
|
||||||
VkAccessFlags dstAccess) {
|
VkAccessFlags dstAccess) {
|
||||||
DxvkAccessFlags access = this->getAccessTypes(srcAccess);
|
DxvkAccessFlags access = this->getAccessTypes(srcAccess);
|
||||||
|
|
||||||
m_srcStages |= srcStages;
|
m_srcStages |= srcStages;
|
||||||
m_dstStages |= dstStages;
|
m_dstStages |= dstStages;
|
||||||
|
|
||||||
if ((srcLayout != dstLayout) || access.test(DxvkAccess::Write)) {
|
if (srcLayout != dstLayout)
|
||||||
|
access.set(DxvkAccess::Write);
|
||||||
|
|
||||||
|
if (access.test(DxvkAccess::Write)) {
|
||||||
VkImageMemoryBarrier barrier;
|
VkImageMemoryBarrier barrier;
|
||||||
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
||||||
barrier.pNext = nullptr;
|
barrier.pNext = nullptr;
|
||||||
@ -63,6 +66,8 @@ namespace dxvk {
|
|||||||
barrier.subresourceRange.aspectMask = image->formatInfo()->aspectMask;
|
barrier.subresourceRange.aspectMask = image->formatInfo()->aspectMask;
|
||||||
m_imgBarriers.push_back(barrier);
|
m_imgBarriers.push_back(barrier);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_imgSlices.push_back({ image.ptr(), subresources, access });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -80,6 +85,26 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool DxvkBarrierSet::isImageDirty(
|
||||||
|
const Rc<DxvkImage>& image,
|
||||||
|
const VkImageSubresourceRange& imgSubres,
|
||||||
|
DxvkAccessFlags imgAccess) {
|
||||||
|
bool result = false;
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < m_imgSlices.size() && !result; i++) {
|
||||||
|
const VkImageSubresourceRange& dstSubres = m_imgSlices[i].subres;
|
||||||
|
|
||||||
|
result = (image == m_imgSlices[i].image) && (imgAccess | m_imgSlices[i].access).test(DxvkAccess::Write)
|
||||||
|
&& imgSubres.baseArrayLayer < dstSubres.baseArrayLayer + dstSubres.layerCount
|
||||||
|
&& imgSubres.baseArrayLayer + imgSubres.layerCount > dstSubres.baseArrayLayer
|
||||||
|
&& imgSubres.baseMipLevel < dstSubres.baseMipLevel + dstSubres.levelCount
|
||||||
|
&& imgSubres.baseMipLevel + imgSubres.levelCount > dstSubres.baseMipLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void DxvkBarrierSet::recordCommands(const Rc<DxvkCommandList>& commandList) {
|
void DxvkBarrierSet::recordCommands(const Rc<DxvkCommandList>& commandList) {
|
||||||
if ((m_srcStages | m_dstStages) != 0) {
|
if ((m_srcStages | m_dstStages) != 0) {
|
||||||
VkPipelineStageFlags srcFlags = m_srcStages;
|
VkPipelineStageFlags srcFlags = m_srcStages;
|
||||||
@ -108,6 +133,7 @@ namespace dxvk {
|
|||||||
m_imgBarriers.resize(0);
|
m_imgBarriers.resize(0);
|
||||||
|
|
||||||
m_bufSlices.resize(0);
|
m_bufSlices.resize(0);
|
||||||
|
m_imgSlices.resize(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -41,6 +41,11 @@ namespace dxvk {
|
|||||||
const DxvkPhysicalBufferSlice& bufSlice,
|
const DxvkPhysicalBufferSlice& bufSlice,
|
||||||
DxvkAccessFlags bufAccess);
|
DxvkAccessFlags bufAccess);
|
||||||
|
|
||||||
|
bool isImageDirty(
|
||||||
|
const Rc<DxvkImage>& image,
|
||||||
|
const VkImageSubresourceRange& imgSubres,
|
||||||
|
DxvkAccessFlags imgAccess);
|
||||||
|
|
||||||
void recordCommands(
|
void recordCommands(
|
||||||
const Rc<DxvkCommandList>& commandList);
|
const Rc<DxvkCommandList>& commandList);
|
||||||
|
|
||||||
@ -52,6 +57,12 @@ namespace dxvk {
|
|||||||
DxvkPhysicalBufferSlice slice;
|
DxvkPhysicalBufferSlice slice;
|
||||||
DxvkAccessFlags access;
|
DxvkAccessFlags access;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ImgSlice {
|
||||||
|
DxvkImage* image;
|
||||||
|
VkImageSubresourceRange subres;
|
||||||
|
DxvkAccessFlags access;
|
||||||
|
};
|
||||||
|
|
||||||
VkPipelineStageFlags m_srcStages = 0;
|
VkPipelineStageFlags m_srcStages = 0;
|
||||||
VkPipelineStageFlags m_dstStages = 0;
|
VkPipelineStageFlags m_dstStages = 0;
|
||||||
@ -61,6 +72,7 @@ namespace dxvk {
|
|||||||
std::vector<VkImageMemoryBarrier> m_imgBarriers;
|
std::vector<VkImageMemoryBarrier> m_imgBarriers;
|
||||||
|
|
||||||
std::vector<BufSlice> m_bufSlices;
|
std::vector<BufSlice> m_bufSlices;
|
||||||
|
std::vector<ImgSlice> m_imgSlices;
|
||||||
|
|
||||||
DxvkAccessFlags getAccessTypes(VkAccessFlags flags) const;
|
DxvkAccessFlags getAccessTypes(VkAccessFlags flags) const;
|
||||||
|
|
||||||
|
@ -338,6 +338,8 @@ namespace dxvk {
|
|||||||
const VkClearColorValue& value,
|
const VkClearColorValue& value,
|
||||||
const VkImageSubresourceRange& subresources) {
|
const VkImageSubresourceRange& subresources) {
|
||||||
this->spillRenderPass();
|
this->spillRenderPass();
|
||||||
|
|
||||||
|
m_barriers.recordCommands(m_cmd);
|
||||||
|
|
||||||
m_barriers.accessImage(image, subresources,
|
m_barriers.accessImage(image, subresources,
|
||||||
VK_IMAGE_LAYOUT_UNDEFINED,
|
VK_IMAGE_LAYOUT_UNDEFINED,
|
||||||
@ -346,6 +348,7 @@ namespace dxvk {
|
|||||||
image->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL),
|
image->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL),
|
||||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
VK_ACCESS_TRANSFER_WRITE_BIT);
|
VK_ACCESS_TRANSFER_WRITE_BIT);
|
||||||
|
|
||||||
m_barriers.recordCommands(m_cmd);
|
m_barriers.recordCommands(m_cmd);
|
||||||
|
|
||||||
m_cmd->cmdClearColorImage(image->handle(),
|
m_cmd->cmdClearColorImage(image->handle(),
|
||||||
@ -359,7 +362,6 @@ namespace dxvk {
|
|||||||
image->info().layout,
|
image->info().layout,
|
||||||
image->info().stages,
|
image->info().stages,
|
||||||
image->info().access);
|
image->info().access);
|
||||||
m_barriers.recordCommands(m_cmd);
|
|
||||||
|
|
||||||
m_cmd->trackResource(image);
|
m_cmd->trackResource(image);
|
||||||
}
|
}
|
||||||
@ -371,6 +373,8 @@ namespace dxvk {
|
|||||||
const VkImageSubresourceRange& subresources) {
|
const VkImageSubresourceRange& subresources) {
|
||||||
this->spillRenderPass();
|
this->spillRenderPass();
|
||||||
|
|
||||||
|
m_barriers.recordCommands(m_cmd);
|
||||||
|
|
||||||
m_barriers.accessImage(
|
m_barriers.accessImage(
|
||||||
image, subresources,
|
image, subresources,
|
||||||
VK_IMAGE_LAYOUT_UNDEFINED,
|
VK_IMAGE_LAYOUT_UNDEFINED,
|
||||||
@ -379,6 +383,7 @@ namespace dxvk {
|
|||||||
image->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL),
|
image->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL),
|
||||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
VK_ACCESS_TRANSFER_WRITE_BIT);
|
VK_ACCESS_TRANSFER_WRITE_BIT);
|
||||||
|
|
||||||
m_barriers.recordCommands(m_cmd);
|
m_barriers.recordCommands(m_cmd);
|
||||||
|
|
||||||
m_cmd->cmdClearDepthStencilImage(image->handle(),
|
m_cmd->cmdClearDepthStencilImage(image->handle(),
|
||||||
@ -393,7 +398,6 @@ namespace dxvk {
|
|||||||
image->info().layout,
|
image->info().layout,
|
||||||
image->info().stages,
|
image->info().stages,
|
||||||
image->info().access);
|
image->info().access);
|
||||||
m_barriers.recordCommands(m_cmd);
|
|
||||||
|
|
||||||
m_cmd->trackResource(image);
|
m_cmd->trackResource(image);
|
||||||
}
|
}
|
||||||
@ -497,6 +501,8 @@ namespace dxvk {
|
|||||||
this->spillRenderPass();
|
this->spillRenderPass();
|
||||||
this->unbindComputePipeline();
|
this->unbindComputePipeline();
|
||||||
|
|
||||||
|
m_barriers.recordCommands(m_cmd);
|
||||||
|
|
||||||
// Query pipeline objects to use for this clear operation
|
// Query pipeline objects to use for this clear operation
|
||||||
DxvkMetaClearPipeline pipeInfo = m_metaClear->getClearImagePipeline(
|
DxvkMetaClearPipeline pipeInfo = m_metaClear->getClearImagePipeline(
|
||||||
imageView->type(), imageFormatInfo(imageView->info().format)->flags);
|
imageView->type(), imageFormatInfo(imageView->info().format)->flags);
|
||||||
@ -561,7 +567,6 @@ namespace dxvk {
|
|||||||
imageView->imageInfo().layout,
|
imageView->imageInfo().layout,
|
||||||
imageView->imageInfo().stages,
|
imageView->imageInfo().stages,
|
||||||
imageView->imageInfo().access);
|
imageView->imageInfo().access);
|
||||||
m_barriers.recordCommands(m_cmd);
|
|
||||||
|
|
||||||
m_cmd->trackResource(imageView);
|
m_cmd->trackResource(imageView);
|
||||||
m_cmd->trackResource(imageView->image());
|
m_cmd->trackResource(imageView->image());
|
||||||
@ -631,6 +636,8 @@ namespace dxvk {
|
|||||||
dstSubresource.baseArrayLayer,
|
dstSubresource.baseArrayLayer,
|
||||||
dstSubresource.layerCount };
|
dstSubresource.layerCount };
|
||||||
|
|
||||||
|
m_barriers.recordCommands(m_cmd);
|
||||||
|
|
||||||
m_barriers.accessImage(
|
m_barriers.accessImage(
|
||||||
dstImage, dstSubresourceRange,
|
dstImage, dstSubresourceRange,
|
||||||
dstImage->mipLevelExtent(dstSubresource.mipLevel) == dstExtent
|
dstImage->mipLevelExtent(dstSubresource.mipLevel) == dstExtent
|
||||||
@ -672,8 +679,6 @@ namespace dxvk {
|
|||||||
VK_ACCESS_TRANSFER_READ_BIT,
|
VK_ACCESS_TRANSFER_READ_BIT,
|
||||||
srcBuffer->info().stages,
|
srcBuffer->info().stages,
|
||||||
srcBuffer->info().access);
|
srcBuffer->info().access);
|
||||||
|
|
||||||
m_barriers.recordCommands(m_cmd);
|
|
||||||
|
|
||||||
m_cmd->trackResource(dstImage);
|
m_cmd->trackResource(dstImage);
|
||||||
m_cmd->trackResource(srcSlice.resource());
|
m_cmd->trackResource(srcSlice.resource());
|
||||||
@ -702,6 +707,8 @@ namespace dxvk {
|
|||||||
srcSubresource.baseArrayLayer,
|
srcSubresource.baseArrayLayer,
|
||||||
srcSubresource.layerCount };
|
srcSubresource.layerCount };
|
||||||
|
|
||||||
|
m_barriers.recordCommands(m_cmd);
|
||||||
|
|
||||||
m_barriers.accessImage(
|
m_barriers.accessImage(
|
||||||
dstImage, dstSubresourceRange,
|
dstImage, dstSubresourceRange,
|
||||||
dstImage->mipLevelExtent(dstSubresource.mipLevel) == extent
|
dstImage->mipLevelExtent(dstSubresource.mipLevel) == extent
|
||||||
@ -810,8 +817,6 @@ namespace dxvk {
|
|||||||
srcImage->info().layout,
|
srcImage->info().layout,
|
||||||
srcImage->info().stages,
|
srcImage->info().stages,
|
||||||
srcImage->info().access);
|
srcImage->info().access);
|
||||||
|
|
||||||
m_barriers.recordCommands(m_cmd);
|
|
||||||
|
|
||||||
m_cmd->trackResource(dstImage);
|
m_cmd->trackResource(dstImage);
|
||||||
m_cmd->trackResource(srcImage);
|
m_cmd->trackResource(srcImage);
|
||||||
@ -836,6 +841,8 @@ namespace dxvk {
|
|||||||
srcSubresource.baseArrayLayer,
|
srcSubresource.baseArrayLayer,
|
||||||
srcSubresource.layerCount };
|
srcSubresource.layerCount };
|
||||||
|
|
||||||
|
m_barriers.recordCommands(m_cmd);
|
||||||
|
|
||||||
m_barriers.accessImage(
|
m_barriers.accessImage(
|
||||||
srcImage, srcSubresourceRange,
|
srcImage, srcSubresourceRange,
|
||||||
srcImage->info().layout,
|
srcImage->info().layout,
|
||||||
@ -844,6 +851,7 @@ namespace dxvk {
|
|||||||
srcImage->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL),
|
srcImage->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL),
|
||||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
VK_ACCESS_TRANSFER_READ_BIT);
|
VK_ACCESS_TRANSFER_READ_BIT);
|
||||||
|
|
||||||
m_barriers.recordCommands(m_cmd);
|
m_barriers.recordCommands(m_cmd);
|
||||||
|
|
||||||
VkBufferImageCopy copyRegion;
|
VkBufferImageCopy copyRegion;
|
||||||
@ -874,8 +882,6 @@ namespace dxvk {
|
|||||||
VK_ACCESS_TRANSFER_WRITE_BIT,
|
VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||||
dstBuffer->info().stages,
|
dstBuffer->info().stages,
|
||||||
dstBuffer->info().access);
|
dstBuffer->info().access);
|
||||||
|
|
||||||
m_barriers.recordCommands(m_cmd);
|
|
||||||
|
|
||||||
m_cmd->trackResource(srcImage);
|
m_cmd->trackResource(srcImage);
|
||||||
m_cmd->trackResource(dstSlice.resource());
|
m_cmd->trackResource(dstSlice.resource());
|
||||||
@ -889,9 +895,11 @@ namespace dxvk {
|
|||||||
this->commitComputeState();
|
this->commitComputeState();
|
||||||
|
|
||||||
if (this->validateComputeState()) {
|
if (this->validateComputeState()) {
|
||||||
|
this->commitComputeInitBarriers();
|
||||||
|
|
||||||
m_cmd->cmdDispatch(x, y, z);
|
m_cmd->cmdDispatch(x, y, z);
|
||||||
|
|
||||||
this->commitComputeBarriers();
|
this->commitComputePostBarriers();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_cmd->addStatCtr(DxvkStatCounter::CmdDispatchCalls, 1);
|
m_cmd->addStatCtr(DxvkStatCounter::CmdDispatchCalls, 1);
|
||||||
@ -903,13 +911,18 @@ namespace dxvk {
|
|||||||
this->commitComputeState();
|
this->commitComputeState();
|
||||||
|
|
||||||
auto physicalSlice = buffer.physicalSlice();
|
auto physicalSlice = buffer.physicalSlice();
|
||||||
|
|
||||||
|
if (m_barriers.isBufferDirty(buffer.physicalSlice(), DxvkAccess::Read))
|
||||||
|
m_barriers.recordCommands(m_cmd);
|
||||||
|
|
||||||
if (this->validateComputeState()) {
|
if (this->validateComputeState()) {
|
||||||
|
this->commitComputeInitBarriers();
|
||||||
|
|
||||||
m_cmd->cmdDispatchIndirect(
|
m_cmd->cmdDispatchIndirect(
|
||||||
physicalSlice.handle(),
|
physicalSlice.handle(),
|
||||||
physicalSlice.offset());
|
physicalSlice.offset());
|
||||||
|
|
||||||
this->commitComputeBarriers();
|
this->commitComputePostBarriers();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_cmd->addStatCtr(DxvkStatCounter::CmdDispatchCalls, 1);
|
m_cmd->addStatCtr(DxvkStatCounter::CmdDispatchCalls, 1);
|
||||||
@ -999,7 +1012,6 @@ namespace dxvk {
|
|||||||
image->info().layout,
|
image->info().layout,
|
||||||
image->info().stages,
|
image->info().stages,
|
||||||
image->info().access);
|
image->info().access);
|
||||||
m_barriers.recordCommands(m_cmd);
|
|
||||||
|
|
||||||
m_cmd->trackResource(image);
|
m_cmd->trackResource(image);
|
||||||
}
|
}
|
||||||
@ -1012,6 +1024,8 @@ namespace dxvk {
|
|||||||
|
|
||||||
this->spillRenderPass();
|
this->spillRenderPass();
|
||||||
this->unbindGraphicsPipeline();
|
this->unbindGraphicsPipeline();
|
||||||
|
|
||||||
|
m_barriers.recordCommands(m_cmd);
|
||||||
|
|
||||||
// Create the a set of framebuffers and image views
|
// Create the a set of framebuffers and image views
|
||||||
const Rc<DxvkMetaMipGenRenderPass> mipGenerator
|
const Rc<DxvkMetaMipGenRenderPass> mipGenerator
|
||||||
@ -1139,13 +1153,13 @@ namespace dxvk {
|
|||||||
VkFormat format) {
|
VkFormat format) {
|
||||||
this->spillRenderPass();
|
this->spillRenderPass();
|
||||||
|
|
||||||
|
m_barriers.recordCommands(m_cmd);
|
||||||
|
|
||||||
if (format == VK_FORMAT_UNDEFINED)
|
if (format == VK_FORMAT_UNDEFINED)
|
||||||
format = srcImage->info().format;
|
format = srcImage->info().format;
|
||||||
|
|
||||||
if (dstImage->info().format == format
|
if (dstImage->info().format == format
|
||||||
&& srcImage->info().format == format) {
|
&& srcImage->info().format == format) {
|
||||||
// Use the built-in Vulkan resolve function if the image
|
|
||||||
// formats both match the format of the resolve operation.
|
|
||||||
VkImageSubresourceRange dstSubresourceRange = {
|
VkImageSubresourceRange dstSubresourceRange = {
|
||||||
dstSubresources.aspectMask,
|
dstSubresources.aspectMask,
|
||||||
dstSubresources.mipLevel, 1,
|
dstSubresources.mipLevel, 1,
|
||||||
@ -1168,6 +1182,7 @@ namespace dxvk {
|
|||||||
dstImage->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL),
|
dstImage->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL),
|
||||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
VK_ACCESS_TRANSFER_WRITE_BIT);
|
VK_ACCESS_TRANSFER_WRITE_BIT);
|
||||||
|
|
||||||
m_barriers.accessImage(
|
m_barriers.accessImage(
|
||||||
srcImage, srcSubresourceRange,
|
srcImage, srcSubresourceRange,
|
||||||
srcImage->info().layout,
|
srcImage->info().layout,
|
||||||
@ -1176,6 +1191,7 @@ namespace dxvk {
|
|||||||
srcImage->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL),
|
srcImage->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL),
|
||||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
VK_ACCESS_TRANSFER_READ_BIT);
|
VK_ACCESS_TRANSFER_READ_BIT);
|
||||||
|
|
||||||
m_barriers.recordCommands(m_cmd);
|
m_barriers.recordCommands(m_cmd);
|
||||||
|
|
||||||
VkImageResolve imageRegion;
|
VkImageResolve imageRegion;
|
||||||
@ -1198,6 +1214,7 @@ namespace dxvk {
|
|||||||
dstImage->info().layout,
|
dstImage->info().layout,
|
||||||
dstImage->info().stages,
|
dstImage->info().stages,
|
||||||
dstImage->info().access);
|
dstImage->info().access);
|
||||||
|
|
||||||
m_barriers.accessImage(
|
m_barriers.accessImage(
|
||||||
srcImage, srcSubresourceRange,
|
srcImage, srcSubresourceRange,
|
||||||
srcImage->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL),
|
srcImage->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL),
|
||||||
@ -1206,7 +1223,6 @@ namespace dxvk {
|
|||||||
srcImage->info().layout,
|
srcImage->info().layout,
|
||||||
srcImage->info().stages,
|
srcImage->info().stages,
|
||||||
srcImage->info().access);
|
srcImage->info().access);
|
||||||
m_barriers.recordCommands(m_cmd);
|
|
||||||
} else {
|
} else {
|
||||||
// The trick here is to submit an empty render pass which
|
// The trick here is to submit an empty render pass which
|
||||||
// performs the resolve op on properly typed image views.
|
// performs the resolve op on properly typed image views.
|
||||||
@ -1245,6 +1261,8 @@ namespace dxvk {
|
|||||||
this->spillRenderPass();
|
this->spillRenderPass();
|
||||||
|
|
||||||
if (srcLayout != dstLayout) {
|
if (srcLayout != dstLayout) {
|
||||||
|
m_barriers.recordCommands(m_cmd);
|
||||||
|
|
||||||
m_barriers.accessImage(
|
m_barriers.accessImage(
|
||||||
dstImage, dstSubresources,
|
dstImage, dstSubresources,
|
||||||
srcLayout,
|
srcLayout,
|
||||||
@ -1253,7 +1271,6 @@ namespace dxvk {
|
|||||||
dstLayout,
|
dstLayout,
|
||||||
dstImage->info().stages,
|
dstImage->info().stages,
|
||||||
dstImage->info().access);
|
dstImage->info().access);
|
||||||
m_barriers.recordCommands(m_cmd);
|
|
||||||
|
|
||||||
m_cmd->trackResource(dstImage);
|
m_cmd->trackResource(dstImage);
|
||||||
}
|
}
|
||||||
@ -1346,6 +1363,8 @@ namespace dxvk {
|
|||||||
subresourceRange.levelCount = 1;
|
subresourceRange.levelCount = 1;
|
||||||
subresourceRange.baseArrayLayer = subresources.baseArrayLayer;
|
subresourceRange.baseArrayLayer = subresources.baseArrayLayer;
|
||||||
subresourceRange.layerCount = subresources.layerCount;
|
subresourceRange.layerCount = subresources.layerCount;
|
||||||
|
|
||||||
|
m_barriers.recordCommands(m_cmd);
|
||||||
|
|
||||||
m_barriers.accessImage(
|
m_barriers.accessImage(
|
||||||
image, subresourceRange,
|
image, subresourceRange,
|
||||||
@ -1357,6 +1376,7 @@ namespace dxvk {
|
|||||||
image->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL),
|
image->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL),
|
||||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
VK_ACCESS_TRANSFER_WRITE_BIT);
|
VK_ACCESS_TRANSFER_WRITE_BIT);
|
||||||
|
|
||||||
m_barriers.recordCommands(m_cmd);
|
m_barriers.recordCommands(m_cmd);
|
||||||
|
|
||||||
// Copy contents of the staging buffer into the image.
|
// Copy contents of the staging buffer into the image.
|
||||||
@ -1383,7 +1403,6 @@ namespace dxvk {
|
|||||||
image->info().layout,
|
image->info().layout,
|
||||||
image->info().stages,
|
image->info().stages,
|
||||||
image->info().access);
|
image->info().access);
|
||||||
m_barriers.recordCommands(m_cmd);
|
|
||||||
|
|
||||||
m_cmd->trackResource(image);
|
m_cmd->trackResource(image);
|
||||||
}
|
}
|
||||||
@ -2085,50 +2104,115 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void DxvkContext::commitComputeBarriers() {
|
void DxvkContext::commitComputeInitBarriers() {
|
||||||
// TODO optimize. Each pipeline layout should
|
auto layout = m_state.cp.pipeline->layout();
|
||||||
// hold a list of resource that can be written.
|
|
||||||
// TODO generalize so that this can be used for
|
bool requiresBarrier = false;
|
||||||
// graphics pipelines as well
|
|
||||||
|
for (uint32_t i = 0; i < layout->bindingCount() && !requiresBarrier; i++) {
|
||||||
|
if (m_state.cp.state.bsBindingState.isBound(i)) {
|
||||||
|
const DxvkDescriptorSlot binding = layout->binding(i);
|
||||||
|
const DxvkShaderResourceSlot& slot = m_rc[binding.slot];
|
||||||
|
|
||||||
|
DxvkAccessFlags access = DxvkAccess::Read;
|
||||||
|
|
||||||
|
switch (binding.type) {
|
||||||
|
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
|
||||||
|
access.set(DxvkAccess::Write);
|
||||||
|
/* fall through */
|
||||||
|
|
||||||
|
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
|
||||||
|
requiresBarrier = m_barriers.isBufferDirty(
|
||||||
|
slot.bufferSlice.physicalSlice(), access);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
|
||||||
|
access.set(DxvkAccess::Write);
|
||||||
|
/* fall through */
|
||||||
|
|
||||||
|
case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
|
||||||
|
requiresBarrier = m_barriers.isBufferDirty(
|
||||||
|
slot.bufferView->physicalSlice(), access);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
|
||||||
|
access.set(DxvkAccess::Write);
|
||||||
|
/* fall through */
|
||||||
|
|
||||||
|
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
|
||||||
|
requiresBarrier = m_barriers.isImageDirty(
|
||||||
|
slot.imageView->image(),
|
||||||
|
slot.imageView->subresources(),
|
||||||
|
access);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
/* nothing to do */;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (requiresBarrier)
|
||||||
|
m_barriers.recordCommands(m_cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DxvkContext::commitComputePostBarriers() {
|
||||||
auto layout = m_state.cp.pipeline->layout();
|
auto layout = m_state.cp.pipeline->layout();
|
||||||
|
|
||||||
for (uint32_t i = 0; i < layout->bindingCount(); i++) {
|
for (uint32_t i = 0; i < layout->bindingCount(); i++) {
|
||||||
if (m_state.cp.state.bsBindingState.isBound(i)) {
|
if (m_state.cp.state.bsBindingState.isBound(i)) {
|
||||||
const DxvkDescriptorSlot binding = layout->binding(i);
|
const DxvkDescriptorSlot binding = layout->binding(i);
|
||||||
const DxvkShaderResourceSlot& slot = m_rc[binding.slot];
|
const DxvkShaderResourceSlot& slot = m_rc[binding.slot];
|
||||||
|
|
||||||
|
VkPipelineStageFlags stages = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
|
||||||
|
VkAccessFlags access = VK_ACCESS_SHADER_READ_BIT;
|
||||||
|
|
||||||
if (binding.type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER) {
|
switch (binding.type) {
|
||||||
m_barriers.accessBuffer(
|
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
|
||||||
slot.bufferSlice.physicalSlice(),
|
access |= VK_ACCESS_SHADER_WRITE_BIT;
|
||||||
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
/* fall through */
|
||||||
VK_ACCESS_SHADER_READ_BIT |
|
|
||||||
VK_ACCESS_SHADER_WRITE_BIT,
|
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
|
||||||
slot.bufferSlice.bufferInfo().stages,
|
m_barriers.accessBuffer(
|
||||||
slot.bufferSlice.bufferInfo().access);
|
slot.bufferSlice.physicalSlice(),
|
||||||
} else if (binding.type == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER) {
|
stages, access,
|
||||||
m_barriers.accessBuffer(
|
slot.bufferSlice.bufferInfo().stages,
|
||||||
slot.bufferView->physicalSlice(),
|
slot.bufferSlice.bufferInfo().access);
|
||||||
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
break;
|
||||||
VK_ACCESS_SHADER_READ_BIT |
|
|
||||||
VK_ACCESS_SHADER_WRITE_BIT,
|
case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
|
||||||
slot.bufferView->bufferInfo().stages,
|
access |= VK_ACCESS_SHADER_WRITE_BIT;
|
||||||
slot.bufferView->bufferInfo().access);
|
/* fall through */
|
||||||
} else if (binding.type == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) {
|
|
||||||
m_barriers.accessImage(
|
case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
|
||||||
slot.imageView->image(),
|
m_barriers.accessBuffer(
|
||||||
slot.imageView->subresources(),
|
slot.bufferView->physicalSlice(),
|
||||||
slot.imageView->imageInfo().layout,
|
stages, access,
|
||||||
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
slot.bufferView->bufferInfo().stages,
|
||||||
VK_ACCESS_SHADER_READ_BIT |
|
slot.bufferView->bufferInfo().access);
|
||||||
VK_ACCESS_SHADER_WRITE_BIT,
|
break;
|
||||||
slot.imageView->imageInfo().layout,
|
|
||||||
slot.imageView->imageInfo().stages,
|
case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
|
||||||
slot.imageView->imageInfo().access);
|
access |= VK_ACCESS_SHADER_WRITE_BIT;
|
||||||
|
/* fall through */
|
||||||
|
|
||||||
|
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
|
||||||
|
m_barriers.accessImage(
|
||||||
|
slot.imageView->image(),
|
||||||
|
slot.imageView->subresources(),
|
||||||
|
slot.imageView->imageInfo().layout,
|
||||||
|
stages, access,
|
||||||
|
slot.imageView->imageInfo().layout,
|
||||||
|
slot.imageView->imageInfo().stages,
|
||||||
|
slot.imageView->imageInfo().access);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
/* nothing to do */;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_barriers.recordCommands(m_cmd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -693,7 +693,8 @@ namespace dxvk {
|
|||||||
void commitComputeState();
|
void commitComputeState();
|
||||||
void commitGraphicsState();
|
void commitGraphicsState();
|
||||||
|
|
||||||
void commitComputeBarriers();
|
void commitComputeInitBarriers();
|
||||||
|
void commitComputePostBarriers();
|
||||||
|
|
||||||
DxvkQueryHandle allocQuery(
|
DxvkQueryHandle allocQuery(
|
||||||
const DxvkQueryRevision& query);
|
const DxvkQueryRevision& query);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user