mirror of
https://github.com/doitsujin/dxvk.git
synced 2024-12-01 16:24:12 +01:00
[dxvk] Add copyBufferRegion and copyImageRegion methods
These new methods can support overlapped subresource copies by creating a temporary resource and effectively using two copy operations. This is required for D3D11 overlapped copies.
This commit is contained in:
parent
3f47fdab4d
commit
e3c2815782
@ -567,6 +567,36 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
void DxvkContext::copyBufferRegion(
|
||||
const Rc<DxvkBuffer>& dstBuffer,
|
||||
VkDeviceSize dstOffset,
|
||||
VkDeviceSize srcOffset,
|
||||
VkDeviceSize numBytes) {
|
||||
VkDeviceSize loOvl = std::max(dstOffset, srcOffset);
|
||||
VkDeviceSize hiOvl = std::min(dstOffset, srcOffset) + numBytes;
|
||||
|
||||
if (hiOvl > loOvl) {
|
||||
DxvkBufferCreateInfo bufInfo;
|
||||
bufInfo.size = numBytes;
|
||||
bufInfo.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT
|
||||
| VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
|
||||
bufInfo.stages = VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||
bufInfo.access = VK_ACCESS_TRANSFER_WRITE_BIT
|
||||
| VK_ACCESS_TRANSFER_READ_BIT;
|
||||
|
||||
auto tmpBuffer = m_device->createBuffer(
|
||||
bufInfo, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||
|
||||
VkDeviceSize tmpOffset = 0;
|
||||
|
||||
this->copyBuffer(tmpBuffer, tmpOffset, dstBuffer, srcOffset, numBytes);
|
||||
this->copyBuffer(dstBuffer, dstOffset, tmpBuffer, tmpOffset, numBytes);
|
||||
} else {
|
||||
this->copyBuffer(dstBuffer, dstOffset, dstBuffer, srcOffset, numBytes);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DxvkContext::copyBufferToImage(
|
||||
const Rc<DxvkImage>& dstImage,
|
||||
VkImageSubresourceLayers dstSubresource,
|
||||
@ -783,6 +813,72 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
void DxvkContext::copyImageRegion(
|
||||
const Rc<DxvkImage>& dstImage,
|
||||
VkImageSubresourceLayers dstSubresource,
|
||||
VkOffset3D dstOffset,
|
||||
VkOffset3D srcOffset,
|
||||
VkExtent3D extent) {
|
||||
VkOffset3D loOvl = {
|
||||
std::max(dstOffset.x, srcOffset.x),
|
||||
std::max(dstOffset.y, srcOffset.y),
|
||||
std::max(dstOffset.z, srcOffset.z) };
|
||||
|
||||
VkOffset3D hiOvl = {
|
||||
std::min(dstOffset.x, srcOffset.x) + int32_t(extent.width),
|
||||
std::min(dstOffset.y, srcOffset.y) + int32_t(extent.height),
|
||||
std::min(dstOffset.z, srcOffset.z) + int32_t(extent.depth) };
|
||||
|
||||
bool overlap = hiOvl.x > loOvl.x
|
||||
&& hiOvl.y > loOvl.y
|
||||
&& hiOvl.z > loOvl.z;
|
||||
|
||||
if (overlap) {
|
||||
DxvkImageCreateInfo imgInfo;
|
||||
imgInfo.type = dstImage->info().type;
|
||||
imgInfo.format = dstImage->info().format;
|
||||
imgInfo.flags = 0;
|
||||
imgInfo.sampleCount = dstImage->info().sampleCount;
|
||||
imgInfo.extent = extent;
|
||||
imgInfo.numLayers = dstSubresource.layerCount;
|
||||
imgInfo.mipLevels = 1;
|
||||
imgInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT
|
||||
| VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
|
||||
imgInfo.stages = VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||
imgInfo.access = VK_ACCESS_TRANSFER_WRITE_BIT
|
||||
| VK_ACCESS_TRANSFER_READ_BIT;
|
||||
imgInfo.tiling = dstImage->info().tiling;
|
||||
imgInfo.layout = VK_IMAGE_LAYOUT_GENERAL;
|
||||
|
||||
auto tmpImage = m_device->createImage(
|
||||
imgInfo, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||
|
||||
VkImageSubresourceLayers tmpSubresource;
|
||||
tmpSubresource.aspectMask = dstSubresource.aspectMask;
|
||||
tmpSubresource.mipLevel = 0;
|
||||
tmpSubresource.baseArrayLayer = 0;
|
||||
tmpSubresource.layerCount = dstSubresource.layerCount;
|
||||
|
||||
VkOffset3D tmpOffset = { 0, 0, 0 };
|
||||
|
||||
this->copyImage(
|
||||
tmpImage, tmpSubresource, tmpOffset,
|
||||
dstImage, dstSubresource, srcOffset,
|
||||
extent);
|
||||
|
||||
this->copyImage(
|
||||
dstImage, dstSubresource, dstOffset,
|
||||
tmpImage, tmpSubresource, tmpOffset,
|
||||
extent);
|
||||
} else {
|
||||
this->copyImage(
|
||||
dstImage, dstSubresource, dstOffset,
|
||||
dstImage, dstSubresource, srcOffset,
|
||||
extent);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DxvkContext::copyImageToBuffer(
|
||||
const Rc<DxvkBuffer>& dstBuffer,
|
||||
VkDeviceSize dstOffset,
|
||||
|
@ -263,6 +263,24 @@ namespace dxvk {
|
||||
VkDeviceSize srcOffset,
|
||||
VkDeviceSize numBytes);
|
||||
|
||||
/**
|
||||
* \brief Copies overlapping buffer region
|
||||
*
|
||||
* Can be used to copy potentially overlapping
|
||||
* buffer regions within the same buffer. If
|
||||
* the source and destination regions do not
|
||||
* overlap, it will behave as \ref copyBuffer.
|
||||
* \param [in] dstBuffer The buffer
|
||||
* \param [in] dstOffset Offset of target region
|
||||
* \param [in] srcOffset Offset of source region
|
||||
* \param [in] numBytes Number of bytes to copy
|
||||
*/
|
||||
void copyBufferRegion(
|
||||
const Rc<DxvkBuffer>& dstBuffer,
|
||||
VkDeviceSize dstOffset,
|
||||
VkDeviceSize srcOffset,
|
||||
VkDeviceSize numBytes);
|
||||
|
||||
/**
|
||||
* \brief Copies data from a buffer to an image
|
||||
*
|
||||
@ -303,6 +321,22 @@ namespace dxvk {
|
||||
VkOffset3D srcOffset,
|
||||
VkExtent3D extent);
|
||||
|
||||
/**
|
||||
* \brief Copies overlapping image region
|
||||
*
|
||||
* \param [in] dstImage The image
|
||||
* \param [in] dstSubresource The image subresource
|
||||
* \param [in] dstOffset Destination region offset
|
||||
* \param [in] srcOffset Source region offset
|
||||
* \param [in] extent Size of the copy region
|
||||
*/
|
||||
void copyImageRegion(
|
||||
const Rc<DxvkImage>& dstImage,
|
||||
VkImageSubresourceLayers dstSubresource,
|
||||
VkOffset3D dstOffset,
|
||||
VkOffset3D srcOffset,
|
||||
VkExtent3D extent);
|
||||
|
||||
/**
|
||||
* \brief Copies data from an image into a buffer
|
||||
*
|
||||
|
@ -233,6 +233,23 @@ inline bool operator != (
|
||||
}
|
||||
|
||||
|
||||
inline bool operator == (
|
||||
const VkImageSubresourceLayers& a,
|
||||
const VkImageSubresourceLayers& b) {
|
||||
return a.aspectMask == b.aspectMask
|
||||
&& a.mipLevel == b.mipLevel
|
||||
&& a.baseArrayLayer == b.baseArrayLayer
|
||||
&& a.layerCount == b.layerCount;
|
||||
}
|
||||
|
||||
|
||||
inline bool operator != (
|
||||
const VkImageSubresourceLayers& a,
|
||||
const VkImageSubresourceLayers& b) {
|
||||
return !operator == (a, b);
|
||||
}
|
||||
|
||||
|
||||
inline bool operator == (VkExtent3D a, VkExtent3D b) {
|
||||
return a.width == b.width
|
||||
&& a.height == b.height
|
||||
|
Loading…
Reference in New Issue
Block a user