mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-01-31 05:52:11 +01:00
[dxvk] Introduce copySparsePages{To,From}Buffer
This commit is contained in:
parent
d5348a0cf0
commit
fc0d952edb
@ -1168,6 +1168,30 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
void DxvkContext::copySparsePagesToBuffer(
|
||||
const Rc<DxvkBuffer>& dstBuffer,
|
||||
VkDeviceSize dstOffset,
|
||||
const Rc<DxvkPagedResource>& srcResource,
|
||||
uint32_t pageCount,
|
||||
const uint32_t* pages) {
|
||||
this->copySparsePages<true>(
|
||||
srcResource, pageCount, pages,
|
||||
dstBuffer, dstOffset);
|
||||
}
|
||||
|
||||
|
||||
void DxvkContext::copySparsePagesFromBuffer(
|
||||
const Rc<DxvkPagedResource>& dstResource,
|
||||
uint32_t pageCount,
|
||||
const uint32_t* pages,
|
||||
const Rc<DxvkBuffer>& srcBuffer,
|
||||
VkDeviceSize srcOffset) {
|
||||
this->copySparsePages<false>(
|
||||
dstResource, pageCount, pages,
|
||||
srcBuffer, srcOffset);
|
||||
}
|
||||
|
||||
|
||||
void DxvkContext::discardBuffer(
|
||||
const Rc<DxvkBuffer>& buffer) {
|
||||
if ((buffer->memFlags() & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
|
||||
@ -3723,6 +3747,188 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
template<bool ToBuffer>
|
||||
void DxvkContext::copySparsePages(
|
||||
const Rc<DxvkPagedResource>& sparse,
|
||||
uint32_t pageCount,
|
||||
const uint32_t* pages,
|
||||
const Rc<DxvkBuffer>& buffer,
|
||||
VkDeviceSize offset) {
|
||||
auto pageTable = sparse->getSparsePageTable();
|
||||
auto bufferHandle = buffer->getSliceHandle(offset, SparseMemoryPageSize * pageCount);
|
||||
|
||||
if (m_execBarriers.isBufferDirty(bufferHandle,
|
||||
ToBuffer ? DxvkAccess::Write : DxvkAccess::Read))
|
||||
m_execBarriers.recordCommands(m_cmd);
|
||||
|
||||
if (pageTable->getBufferHandle()) {
|
||||
this->copySparseBufferPages<ToBuffer>(
|
||||
static_cast<DxvkBuffer*>(sparse.ptr()),
|
||||
pageCount, pages, buffer, offset);
|
||||
} else {
|
||||
this->copySparseImagePages<ToBuffer>(
|
||||
static_cast<DxvkImage*>(sparse.ptr()),
|
||||
pageCount, pages, buffer, offset);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<bool ToBuffer>
|
||||
void DxvkContext::copySparseBufferPages(
|
||||
const Rc<DxvkBuffer>& sparse,
|
||||
uint32_t pageCount,
|
||||
const uint32_t* pages,
|
||||
const Rc<DxvkBuffer>& buffer,
|
||||
VkDeviceSize offset) {
|
||||
std::vector<VkBufferCopy2> regions;
|
||||
regions.reserve(pageCount);
|
||||
|
||||
auto pageTable = sparse->getSparsePageTable();
|
||||
|
||||
auto sparseHandle = sparse->getSliceHandle();
|
||||
auto bufferHandle = buffer->getSliceHandle(offset, SparseMemoryPageSize * pageCount);
|
||||
|
||||
if (m_execBarriers.isBufferDirty(sparseHandle,
|
||||
ToBuffer ? DxvkAccess::Read : DxvkAccess::Write))
|
||||
m_execBarriers.recordCommands(m_cmd);
|
||||
|
||||
for (uint32_t i = 0; i < pageCount; i++) {
|
||||
auto pageInfo = pageTable->getPageInfo(pages[i]);
|
||||
|
||||
if (pageInfo.type == DxvkSparsePageType::Buffer) {
|
||||
VkDeviceSize sparseOffset = pageInfo.buffer.offset;
|
||||
VkDeviceSize bufferOffset = bufferHandle.offset + SparseMemoryPageSize * i;
|
||||
|
||||
VkBufferCopy2 copy = { VK_STRUCTURE_TYPE_BUFFER_COPY_2 };
|
||||
copy.srcOffset = ToBuffer ? sparseOffset : bufferOffset;
|
||||
copy.dstOffset = ToBuffer ? bufferOffset : sparseOffset;
|
||||
copy.size = pageInfo.buffer.length;
|
||||
|
||||
regions.push_back(copy);
|
||||
}
|
||||
}
|
||||
|
||||
VkCopyBufferInfo2 info = { VK_STRUCTURE_TYPE_COPY_BUFFER_INFO_2 };
|
||||
info.srcBuffer = ToBuffer ? sparseHandle.handle : bufferHandle.handle;
|
||||
info.dstBuffer = ToBuffer ? bufferHandle.handle : sparseHandle.handle;
|
||||
info.regionCount = uint32_t(regions.size());
|
||||
info.pRegions = regions.data();
|
||||
|
||||
if (info.regionCount)
|
||||
m_cmd->cmdCopyBuffer(DxvkCmdBuffer::ExecBuffer, &info);
|
||||
|
||||
m_execBarriers.accessBuffer(sparseHandle,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
ToBuffer ? VK_ACCESS_TRANSFER_READ_BIT : VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||
sparse->info().stages,
|
||||
sparse->info().access);
|
||||
|
||||
m_execBarriers.accessBuffer(bufferHandle,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
ToBuffer ? VK_ACCESS_TRANSFER_WRITE_BIT : VK_ACCESS_TRANSFER_READ_BIT,
|
||||
buffer->info().stages,
|
||||
buffer->info().access);
|
||||
|
||||
m_cmd->trackResource<ToBuffer ? DxvkAccess::Read : DxvkAccess::Write>(sparse);
|
||||
m_cmd->trackResource<ToBuffer ? DxvkAccess::Write : DxvkAccess::Read>(buffer);
|
||||
}
|
||||
|
||||
|
||||
template<bool ToBuffer>
|
||||
void DxvkContext::copySparseImagePages(
|
||||
const Rc<DxvkImage>& sparse,
|
||||
uint32_t pageCount,
|
||||
const uint32_t* pages,
|
||||
const Rc<DxvkBuffer>& buffer,
|
||||
VkDeviceSize offset) {
|
||||
std::vector<VkBufferImageCopy2> regions;
|
||||
regions.reserve(pageCount);
|
||||
|
||||
auto pageTable = sparse->getSparsePageTable();
|
||||
auto pageExtent = pageTable->getProperties().pageRegionExtent;
|
||||
|
||||
auto bufferHandle = buffer->getSliceHandle(offset, SparseMemoryPageSize * pageCount);
|
||||
auto sparseSubresources = sparse->getAvailableSubresources();
|
||||
|
||||
if (m_execBarriers.isImageDirty(sparse, sparseSubresources, DxvkAccess::Write))
|
||||
m_execBarriers.recordCommands(m_cmd);
|
||||
|
||||
VkImageLayout transferLayout = sparse->pickLayout(ToBuffer
|
||||
? VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL
|
||||
: VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||||
|
||||
VkAccessFlags transferAccess = ToBuffer
|
||||
? VK_ACCESS_TRANSFER_READ_BIT
|
||||
: VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||
|
||||
if (sparse->info().layout != transferLayout) {
|
||||
m_execAcquires.accessImage(sparse, sparseSubresources,
|
||||
sparse->info().layout,
|
||||
sparse->info().stages, 0,
|
||||
transferLayout,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
transferAccess);
|
||||
|
||||
m_execAcquires.recordCommands(m_cmd);
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < pageCount; i++) {
|
||||
auto pageInfo = pageTable->getPageInfo(pages[i]);
|
||||
|
||||
if (pageInfo.type == DxvkSparsePageType::Image) {
|
||||
VkBufferImageCopy2 copy = { VK_STRUCTURE_TYPE_BUFFER_IMAGE_COPY_2 };
|
||||
copy.bufferOffset = bufferHandle.offset + SparseMemoryPageSize * i;
|
||||
copy.bufferRowLength = pageExtent.width;
|
||||
copy.bufferImageHeight = pageExtent.height;
|
||||
copy.imageSubresource = vk::makeSubresourceLayers(pageInfo.image.subresource);
|
||||
copy.imageOffset = pageInfo.image.offset;
|
||||
copy.imageExtent = pageInfo.image.extent;
|
||||
|
||||
regions.push_back(copy);
|
||||
}
|
||||
}
|
||||
|
||||
if (ToBuffer) {
|
||||
VkCopyImageToBufferInfo2 info = { VK_STRUCTURE_TYPE_COPY_IMAGE_TO_BUFFER_INFO_2 };
|
||||
info.srcImage = sparse->handle();
|
||||
info.srcImageLayout = transferLayout;
|
||||
info.dstBuffer = bufferHandle.handle;
|
||||
info.regionCount = regions.size();
|
||||
info.pRegions = regions.data();
|
||||
|
||||
if (info.regionCount)
|
||||
m_cmd->cmdCopyImageToBuffer(DxvkCmdBuffer::ExecBuffer, &info);
|
||||
} else {
|
||||
VkCopyBufferToImageInfo2 info = { VK_STRUCTURE_TYPE_COPY_BUFFER_TO_IMAGE_INFO_2 };
|
||||
info.srcBuffer = bufferHandle.handle;
|
||||
info.dstImage = sparse->handle();
|
||||
info.dstImageLayout = transferLayout;
|
||||
info.regionCount = regions.size();
|
||||
info.pRegions = regions.data();
|
||||
|
||||
if (info.regionCount)
|
||||
m_cmd->cmdCopyBufferToImage(DxvkCmdBuffer::ExecBuffer, &info);
|
||||
}
|
||||
|
||||
m_execAcquires.accessImage(sparse, sparseSubresources,
|
||||
transferLayout,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
transferAccess,
|
||||
sparse->info().layout,
|
||||
sparse->info().stages,
|
||||
sparse->info().access);
|
||||
|
||||
m_execBarriers.accessBuffer(bufferHandle,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
ToBuffer ? VK_ACCESS_TRANSFER_WRITE_BIT : VK_ACCESS_TRANSFER_READ_BIT,
|
||||
buffer->info().stages,
|
||||
buffer->info().access);
|
||||
|
||||
m_cmd->trackResource<ToBuffer ? DxvkAccess::Read : DxvkAccess::Write>(sparse);
|
||||
m_cmd->trackResource<ToBuffer ? DxvkAccess::Write : DxvkAccess::Read>(buffer);
|
||||
}
|
||||
|
||||
|
||||
void DxvkContext::resolveImageHw(
|
||||
const Rc<DxvkImage>& dstImage,
|
||||
const Rc<DxvkImage>& srcImage,
|
||||
|
@ -669,7 +669,39 @@ namespace dxvk {
|
||||
VkOffset2D srcOffset,
|
||||
VkExtent2D srcExtent,
|
||||
VkFormat format);
|
||||
|
||||
|
||||
/**
|
||||
* \brief Copies pages from a sparse resource to a buffer
|
||||
*
|
||||
* \param [in] dstBuffer Buffer to write to
|
||||
* \param [in] dstOffset Buffer offset
|
||||
* \param [in] srcResource Source resource
|
||||
* \param [in] pageCount Number of pages to copy
|
||||
* \param [in] pages Page indices to copy
|
||||
*/
|
||||
void copySparsePagesToBuffer(
|
||||
const Rc<DxvkBuffer>& dstBuffer,
|
||||
VkDeviceSize dstOffset,
|
||||
const Rc<DxvkPagedResource>& srcResource,
|
||||
uint32_t pageCount,
|
||||
const uint32_t* pages);
|
||||
|
||||
/**
|
||||
* \brief Copies pages from a buffer to a sparse resource
|
||||
*
|
||||
* \param [in] dstResource Resource to write to
|
||||
* \param [in] pageCount Number of pages to copy
|
||||
* \param [in] pages Page indices to copy
|
||||
* \param [in] srcBuffer Source buffer
|
||||
* \param [in] srcOffset Buffer offset
|
||||
*/
|
||||
void copySparsePagesFromBuffer(
|
||||
const Rc<DxvkPagedResource>& dstResource,
|
||||
uint32_t pageCount,
|
||||
const uint32_t* pages,
|
||||
const Rc<DxvkBuffer>& srcBuffer,
|
||||
VkDeviceSize srcOffset);
|
||||
|
||||
/**
|
||||
* \brief Discards a buffer
|
||||
*
|
||||
@ -1422,6 +1454,30 @@ namespace dxvk {
|
||||
const Rc<DxvkImage>& srcImage,
|
||||
VkImageSubresourceLayers srcSubresource);
|
||||
|
||||
template<bool ToBuffer>
|
||||
void copySparsePages(
|
||||
const Rc<DxvkPagedResource>& sparse,
|
||||
uint32_t pageCount,
|
||||
const uint32_t* pages,
|
||||
const Rc<DxvkBuffer>& buffer,
|
||||
VkDeviceSize offset);
|
||||
|
||||
template<bool ToBuffer>
|
||||
void copySparseBufferPages(
|
||||
const Rc<DxvkBuffer>& sparse,
|
||||
uint32_t pageCount,
|
||||
const uint32_t* pages,
|
||||
const Rc<DxvkBuffer>& buffer,
|
||||
VkDeviceSize offset);
|
||||
|
||||
template<bool ToBuffer>
|
||||
void copySparseImagePages(
|
||||
const Rc<DxvkImage>& sparse,
|
||||
uint32_t pageCount,
|
||||
const uint32_t* pages,
|
||||
const Rc<DxvkBuffer>& buffer,
|
||||
VkDeviceSize offset);
|
||||
|
||||
void resolveImageHw(
|
||||
const Rc<DxvkImage>& dstImage,
|
||||
const Rc<DxvkImage>& srcImage,
|
||||
|
Loading…
x
Reference in New Issue
Block a user