mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-02-02 11:52:10 +01:00
[dxvk] Add helper for out-of-order resource transfers
This commit is contained in:
parent
06280a2ce5
commit
76db753024
@ -7140,6 +7140,81 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool DxvkContext::prepareOutOfOrderTransfer(
|
||||||
|
const Rc<DxvkBuffer>& buffer,
|
||||||
|
VkDeviceSize offset,
|
||||||
|
VkDeviceSize size,
|
||||||
|
DxvkAccess access) {
|
||||||
|
// If the resource hasn't been used yet or both uses are reads,
|
||||||
|
// we can use this buffer in the init command buffer
|
||||||
|
if (!buffer->isTracked(m_trackingId, access))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// Otherwise, our only option is to discard. We can only do that if
|
||||||
|
// we're writing the full buffer. Therefore, the resource being read
|
||||||
|
// should always be checked first to avoid unnecessary discards.
|
||||||
|
if (access != DxvkAccess::Write || size < buffer->info().size || offset)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Check if the buffer can actually be discarded at all.
|
||||||
|
if (!buffer->canRelocate())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Ignore large buffers to keep memory overhead in check. Use a higher
|
||||||
|
// threshold when a render pass is active to avoid interrupting it.
|
||||||
|
VkDeviceSize threshold = !m_flags.test(DxvkContextFlag::GpRenderPassBound)
|
||||||
|
? MaxDiscardSizeInRp
|
||||||
|
: MaxDiscardSize;
|
||||||
|
|
||||||
|
if (size > threshold)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// If the buffer is used for transform feedback in any way, we have to stop
|
||||||
|
// the render pass anyway, but we can at least avoid an extra barrier.
|
||||||
|
if (unlikely(m_flags.test(DxvkContextFlag::GpXfbActive))) {
|
||||||
|
VkBufferUsageFlags xfbUsage = VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT
|
||||||
|
| VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT;
|
||||||
|
|
||||||
|
if (buffer->info().usage & xfbUsage)
|
||||||
|
this->spillRenderPass(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Actually allocate and assign new backing storage
|
||||||
|
this->invalidateBuffer(buffer, buffer->allocateStorage());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool DxvkContext::prepareOutOfOrderTransfer(
|
||||||
|
const Rc<DxvkBufferView>& bufferView,
|
||||||
|
VkDeviceSize offset,
|
||||||
|
VkDeviceSize size,
|
||||||
|
DxvkAccess access) {
|
||||||
|
if (bufferView->info().format) {
|
||||||
|
offset *= bufferView->formatInfo()->elementSize;
|
||||||
|
size *= bufferView->formatInfo()->elementSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
return prepareOutOfOrderTransfer(bufferView->buffer(),
|
||||||
|
offset + bufferView->info().offset, size, access);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool DxvkContext::prepareOutOfOrderTransfer(
|
||||||
|
const Rc<DxvkImage>& image,
|
||||||
|
DxvkAccess access) {
|
||||||
|
// If the image can be used for rendering, some or all subresources
|
||||||
|
// might be in a non-default layout, and copies to or from render
|
||||||
|
// targets typically depend on rendering operations anyway. Skip.
|
||||||
|
if (image->info().usage & (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// If the image hasn't been used yet or all uses are
|
||||||
|
// reads, we can use it in the init command buffer
|
||||||
|
return !image->isTracked(m_trackingId, access);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool DxvkContext::formatsAreCopyCompatible(
|
bool DxvkContext::formatsAreCopyCompatible(
|
||||||
VkFormat imageFormat,
|
VkFormat imageFormat,
|
||||||
VkFormat bufferFormat) {
|
VkFormat bufferFormat) {
|
||||||
|
@ -29,7 +29,8 @@ namespace dxvk {
|
|||||||
* recorded.
|
* recorded.
|
||||||
*/
|
*/
|
||||||
class DxvkContext : public RcObject {
|
class DxvkContext : public RcObject {
|
||||||
|
constexpr static VkDeviceSize MaxDiscardSizeInRp = 256u << 10u;
|
||||||
|
constexpr static VkDeviceSize MaxDiscardSize = 16u << 10u;
|
||||||
public:
|
public:
|
||||||
|
|
||||||
DxvkContext(const Rc<DxvkDevice>& device);
|
DxvkContext(const Rc<DxvkDevice>& device);
|
||||||
@ -1903,6 +1904,22 @@ namespace dxvk {
|
|||||||
DxvkBarrierBatch& getBarrierBatch(
|
DxvkBarrierBatch& getBarrierBatch(
|
||||||
DxvkCmdBuffer cmdBuffer);
|
DxvkCmdBuffer cmdBuffer);
|
||||||
|
|
||||||
|
bool prepareOutOfOrderTransfer(
|
||||||
|
const Rc<DxvkBuffer>& buffer,
|
||||||
|
VkDeviceSize offset,
|
||||||
|
VkDeviceSize size,
|
||||||
|
DxvkAccess access);
|
||||||
|
|
||||||
|
bool prepareOutOfOrderTransfer(
|
||||||
|
const Rc<DxvkBufferView>& bufferView,
|
||||||
|
VkDeviceSize offset,
|
||||||
|
VkDeviceSize size,
|
||||||
|
DxvkAccess access);
|
||||||
|
|
||||||
|
bool prepareOutOfOrderTransfer(
|
||||||
|
const Rc<DxvkImage>& image,
|
||||||
|
DxvkAccess access);
|
||||||
|
|
||||||
template<typename Pred>
|
template<typename Pred>
|
||||||
bool checkResourceBarrier(
|
bool checkResourceBarrier(
|
||||||
const Pred& pred,
|
const Pred& pred,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user