mirror of
https://github.com/doitsujin/dxvk.git
synced 2024-12-05 01:24:14 +01:00
[dxvk] Introduce tryInvalidateDeviceLocalBuffer
This commit is contained in:
parent
6a3de28f94
commit
5e763853e5
@ -2133,35 +2133,20 @@ namespace dxvk {
|
||||
VkDeviceSize offset,
|
||||
VkDeviceSize size,
|
||||
const void* data) {
|
||||
bool isHostVisible = buffer->memFlags() & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
|
||||
bool replaceBuffer = size == buffer->info().size && !isHostVisible;
|
||||
|
||||
DxvkBufferSliceHandle bufferSlice;
|
||||
DxvkCmdBuffer cmdBuffer;
|
||||
bool replaceBuffer = this->tryInvalidateDeviceLocalBuffer(buffer, size);
|
||||
auto bufferSlice = buffer->getSliceHandle(offset, size);
|
||||
|
||||
if (replaceBuffer) {
|
||||
// Suspend render pass so that we don't mess with the
|
||||
// currently bound transform feedback counter buffers
|
||||
if (m_flags.test(DxvkContextFlag::GpXfbActive))
|
||||
this->spillRenderPass(true);
|
||||
|
||||
// As an optimization, allocate a free slice and perform
|
||||
// the copy in the initialization command buffer instead
|
||||
// interrupting the render pass and stalling the pipeline.
|
||||
bufferSlice = buffer->allocSlice();
|
||||
cmdBuffer = DxvkCmdBuffer::InitBuffer;
|
||||
|
||||
this->invalidateBuffer(buffer, bufferSlice);
|
||||
} else {
|
||||
if (!replaceBuffer) {
|
||||
this->spillRenderPass(true);
|
||||
|
||||
bufferSlice = buffer->getSliceHandle(offset, size);
|
||||
cmdBuffer = DxvkCmdBuffer::ExecBuffer;
|
||||
|
||||
if (m_execBarriers.isBufferDirty(bufferSlice, DxvkAccess::Write))
|
||||
m_execBarriers.recordCommands(m_cmd);
|
||||
}
|
||||
|
||||
DxvkCmdBuffer cmdBuffer = replaceBuffer
|
||||
? DxvkCmdBuffer::InitBuffer
|
||||
: DxvkCmdBuffer::ExecBuffer;
|
||||
|
||||
m_cmd->cmdUpdateBuffer(cmdBuffer,
|
||||
bufferSlice.handle,
|
||||
bufferSlice.offset,
|
||||
@ -2172,8 +2157,7 @@ namespace dxvk {
|
||||
? m_initBarriers
|
||||
: m_execBarriers;
|
||||
|
||||
barriers.accessBuffer(
|
||||
bufferSlice,
|
||||
barriers.accessBuffer(bufferSlice,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||
buffer->info().stages,
|
||||
@ -5300,6 +5284,29 @@ namespace dxvk {
|
||||
m_cmd->trackResource<DxvkAccess::Read>(m_state.id.cntBuffer.buffer());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool DxvkContext::tryInvalidateDeviceLocalBuffer(
|
||||
const Rc<DxvkBuffer>& buffer,
|
||||
VkDeviceSize copySize) {
|
||||
// We can only discard if the full buffer gets written, and we will only discard
|
||||
// small buffers in order to not waste significant amounts of memory.
|
||||
if (copySize != buffer->info().size || copySize > 0x40000)
|
||||
return false;
|
||||
|
||||
// Don't discard host-visible buffers since that may interfere with the frontend
|
||||
if (buffer->memFlags() & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
|
||||
return false;
|
||||
|
||||
// Suspend the current render pass if transform feedback is active prior to
|
||||
// invalidating the buffer, since otherwise we may invalidate a bound buffer.
|
||||
if ((buffer->info().usage & VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT)
|
||||
&& (m_flags.test(DxvkContextFlag::GpXfbActive)))
|
||||
this->spillRenderPass(true);
|
||||
|
||||
this->invalidateBuffer(buffer, buffer->allocSlice());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
DxvkGraphicsPipeline* DxvkContext::lookupGraphicsPipeline(
|
||||
|
@ -1362,6 +1362,10 @@ namespace dxvk {
|
||||
|
||||
void trackDrawBuffer();
|
||||
|
||||
bool tryInvalidateDeviceLocalBuffer(
|
||||
const Rc<DxvkBuffer>& buffer,
|
||||
VkDeviceSize copySize);
|
||||
|
||||
DxvkGraphicsPipeline* lookupGraphicsPipeline(
|
||||
const DxvkGraphicsPipelineShaders& shaders);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user