mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-02-20 19:54:19 +01:00
[d3d11] Move internal resource update methods to D3D11CommonContext
This commit is contained in:
parent
956bad5e84
commit
7c82ed35b2
@ -984,201 +984,6 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
void D3D11DeviceContext::UpdateBuffer(
|
||||
D3D11Buffer* pDstBuffer,
|
||||
UINT Offset,
|
||||
UINT Length,
|
||||
const void* pSrcData) {
|
||||
DxvkBufferSlice bufferSlice = pDstBuffer->GetBufferSlice(Offset, Length);
|
||||
|
||||
if (Length <= 1024 && !(Offset & 0x3) && !(Length & 0x3)) {
|
||||
// The backend has special code paths for small buffer updates,
|
||||
// however both offset and size must be aligned to four bytes.
|
||||
DxvkDataSlice dataSlice = AllocUpdateBufferSlice(Length);
|
||||
std::memcpy(dataSlice.ptr(), pSrcData, Length);
|
||||
|
||||
EmitCs([
|
||||
cDataBuffer = std::move(dataSlice),
|
||||
cBufferSlice = std::move(bufferSlice)
|
||||
] (DxvkContext* ctx) {
|
||||
ctx->updateBuffer(
|
||||
cBufferSlice.buffer(),
|
||||
cBufferSlice.offset(),
|
||||
cBufferSlice.length(),
|
||||
cDataBuffer.ptr());
|
||||
});
|
||||
} else {
|
||||
// Otherwise, to avoid large data copies on the CS thread,
|
||||
// write directly to a staging buffer and dispatch a copy
|
||||
DxvkBufferSlice stagingSlice = AllocStagingBuffer(Length);
|
||||
std::memcpy(stagingSlice.mapPtr(0), pSrcData, Length);
|
||||
|
||||
EmitCs([
|
||||
cStagingSlice = std::move(stagingSlice),
|
||||
cBufferSlice = std::move(bufferSlice)
|
||||
] (DxvkContext* ctx) {
|
||||
ctx->copyBuffer(
|
||||
cBufferSlice.buffer(),
|
||||
cBufferSlice.offset(),
|
||||
cStagingSlice.buffer(),
|
||||
cStagingSlice.offset(),
|
||||
cBufferSlice.length());
|
||||
});
|
||||
}
|
||||
|
||||
if (pDstBuffer->HasSequenceNumber())
|
||||
TrackBufferSequenceNumber(pDstBuffer);
|
||||
}
|
||||
|
||||
|
||||
void D3D11DeviceContext::UpdateTexture(
|
||||
D3D11CommonTexture* pDstTexture,
|
||||
UINT DstSubresource,
|
||||
const D3D11_BOX* pDstBox,
|
||||
const void* pSrcData,
|
||||
UINT SrcRowPitch,
|
||||
UINT SrcDepthPitch) {
|
||||
if (DstSubresource >= pDstTexture->CountSubresources())
|
||||
return;
|
||||
|
||||
VkFormat packedFormat = pDstTexture->GetPackedFormat();
|
||||
|
||||
auto formatInfo = lookupFormatInfo(packedFormat);
|
||||
auto subresource = pDstTexture->GetSubresourceFromIndex(
|
||||
formatInfo->aspectMask, DstSubresource);
|
||||
|
||||
VkExtent3D mipExtent = pDstTexture->MipLevelExtent(subresource.mipLevel);
|
||||
|
||||
VkOffset3D offset = { 0, 0, 0 };
|
||||
VkExtent3D extent = mipExtent;
|
||||
|
||||
if (pDstBox != nullptr) {
|
||||
if (pDstBox->left >= pDstBox->right
|
||||
|| pDstBox->top >= pDstBox->bottom
|
||||
|| pDstBox->front >= pDstBox->back)
|
||||
return; // no-op, but legal
|
||||
|
||||
offset.x = pDstBox->left;
|
||||
offset.y = pDstBox->top;
|
||||
offset.z = pDstBox->front;
|
||||
|
||||
extent.width = pDstBox->right - pDstBox->left;
|
||||
extent.height = pDstBox->bottom - pDstBox->top;
|
||||
extent.depth = pDstBox->back - pDstBox->front;
|
||||
}
|
||||
|
||||
if (!util::isBlockAligned(offset, extent, formatInfo->blockSize, mipExtent)) {
|
||||
Logger::err("D3D11: UpdateSubresource1: Unaligned region");
|
||||
return;
|
||||
}
|
||||
|
||||
auto stagingSlice = AllocStagingBuffer(util::computeImageDataSize(packedFormat, extent));
|
||||
|
||||
util::packImageData(stagingSlice.mapPtr(0),
|
||||
pSrcData, SrcRowPitch, SrcDepthPitch, 0, 0,
|
||||
pDstTexture->GetVkImageType(), extent, 1,
|
||||
formatInfo, formatInfo->aspectMask);
|
||||
|
||||
UpdateImage(pDstTexture, &subresource,
|
||||
offset, extent, std::move(stagingSlice));
|
||||
}
|
||||
|
||||
|
||||
void D3D11DeviceContext::UpdateImage(
|
||||
D3D11CommonTexture* pDstTexture,
|
||||
const VkImageSubresource* pDstSubresource,
|
||||
VkOffset3D DstOffset,
|
||||
VkExtent3D DstExtent,
|
||||
DxvkBufferSlice StagingBuffer) {
|
||||
bool dstIsImage = pDstTexture->GetMapMode() != D3D11_COMMON_TEXTURE_MAP_MODE_STAGING;
|
||||
|
||||
uint32_t dstSubresource = D3D11CalcSubresource(pDstSubresource->mipLevel,
|
||||
pDstSubresource->arrayLayer, pDstTexture->Desc()->MipLevels);
|
||||
|
||||
if (dstIsImage) {
|
||||
EmitCs([
|
||||
cDstImage = pDstTexture->GetImage(),
|
||||
cDstLayers = vk::makeSubresourceLayers(*pDstSubresource),
|
||||
cDstOffset = DstOffset,
|
||||
cDstExtent = DstExtent,
|
||||
cStagingSlice = std::move(StagingBuffer),
|
||||
cPackedFormat = pDstTexture->GetPackedFormat()
|
||||
] (DxvkContext* ctx) {
|
||||
if (cDstLayers.aspectMask != (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
|
||||
ctx->copyBufferToImage(cDstImage,
|
||||
cDstLayers, cDstOffset, cDstExtent,
|
||||
cStagingSlice.buffer(),
|
||||
cStagingSlice.offset(), 0, 0);
|
||||
} else {
|
||||
ctx->copyPackedBufferToDepthStencilImage(cDstImage, cDstLayers,
|
||||
VkOffset2D { cDstOffset.x, cDstOffset.y },
|
||||
VkExtent2D { cDstExtent.width, cDstExtent.height },
|
||||
cStagingSlice.buffer(),
|
||||
cStagingSlice.offset(),
|
||||
VkOffset2D { 0, 0 },
|
||||
VkExtent2D { cDstExtent.width, cDstExtent.height },
|
||||
cPackedFormat);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// If the destination image is backed only by a buffer, we need to use
|
||||
// the packed buffer copy function which does not know about planes and
|
||||
// format metadata, so deal with it manually here.
|
||||
VkExtent3D dstMipExtent = pDstTexture->MipLevelExtent(pDstSubresource->mipLevel);
|
||||
|
||||
auto dstFormat = pDstTexture->GetPackedFormat();
|
||||
auto dstFormatInfo = lookupFormatInfo(dstFormat);
|
||||
|
||||
uint32_t planeCount = 1;
|
||||
|
||||
if (dstFormatInfo->flags.test(DxvkFormatFlag::MultiPlane))
|
||||
planeCount = vk::getPlaneCount(dstFormatInfo->aspectMask);
|
||||
|
||||
// The source data isn't stored in an image so we'll also need to
|
||||
// track the offset for that while iterating over the planes.
|
||||
VkDeviceSize srcPlaneOffset = 0;
|
||||
|
||||
for (uint32_t i = 0; i < planeCount; i++) {
|
||||
VkImageAspectFlags dstAspectMask = dstFormatInfo->aspectMask;
|
||||
VkDeviceSize elementSize = dstFormatInfo->elementSize;
|
||||
VkExtent3D blockSize = dstFormatInfo->blockSize;
|
||||
|
||||
if (dstFormatInfo->flags.test(DxvkFormatFlag::MultiPlane)) {
|
||||
dstAspectMask = vk::getPlaneAspect(i);
|
||||
|
||||
auto plane = &dstFormatInfo->planes[i];
|
||||
blockSize.width *= plane->blockSize.width;
|
||||
blockSize.height *= plane->blockSize.height;
|
||||
elementSize = plane->elementSize;
|
||||
}
|
||||
|
||||
VkExtent3D blockCount = util::computeBlockCount(DstExtent, blockSize);
|
||||
|
||||
EmitCs([
|
||||
cDstBuffer = pDstTexture->GetMappedBuffer(dstSubresource),
|
||||
cDstStart = pDstTexture->GetSubresourceLayout(dstAspectMask, dstSubresource).Offset,
|
||||
cDstOffset = util::computeBlockOffset(DstOffset, blockSize),
|
||||
cDstSize = util::computeBlockCount(dstMipExtent, blockSize),
|
||||
cDstExtent = blockCount,
|
||||
cSrcBuffer = StagingBuffer.buffer(),
|
||||
cSrcStart = StagingBuffer.offset() + srcPlaneOffset,
|
||||
cPixelSize = elementSize
|
||||
] (DxvkContext* ctx) {
|
||||
ctx->copyPackedBufferImage(
|
||||
cDstBuffer, cDstStart, cDstOffset, cDstSize,
|
||||
cSrcBuffer, cSrcStart, VkOffset3D(), cDstExtent,
|
||||
cDstExtent, cPixelSize);
|
||||
});
|
||||
|
||||
srcPlaneOffset += util::flattenImageExtent(blockCount) * elementSize;
|
||||
}
|
||||
}
|
||||
|
||||
if (pDstTexture->HasSequenceNumber())
|
||||
TrackTextureSequenceNumber(pDstTexture, dstSubresource);
|
||||
}
|
||||
|
||||
|
||||
void D3D11DeviceContext::SetDrawBuffers(
|
||||
ID3D11Buffer* pBufferForArgs,
|
||||
ID3D11Buffer* pBufferForCount) {
|
||||
|
@ -247,27 +247,6 @@ namespace dxvk {
|
||||
UINT CtrSlot,
|
||||
UINT Counter);
|
||||
|
||||
void UpdateBuffer(
|
||||
D3D11Buffer* pDstBuffer,
|
||||
UINT Offset,
|
||||
UINT Length,
|
||||
const void* pSrcData);
|
||||
|
||||
void UpdateTexture(
|
||||
D3D11CommonTexture* pDstTexture,
|
||||
UINT DstSubresource,
|
||||
const D3D11_BOX* pDstBox,
|
||||
const void* pSrcData,
|
||||
UINT SrcRowPitch,
|
||||
UINT SrcDepthPitch);
|
||||
|
||||
void UpdateImage(
|
||||
D3D11CommonTexture* pDstTexture,
|
||||
const VkImageSubresource* pDstSubresource,
|
||||
VkOffset3D DstOffset,
|
||||
VkExtent3D DstExtent,
|
||||
DxvkBufferSlice StagingBuffer);
|
||||
|
||||
void SetDrawBuffers(
|
||||
ID3D11Buffer* pBufferForArgs,
|
||||
ID3D11Buffer* pBufferForCount);
|
||||
|
@ -3757,6 +3757,204 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
template<typename ContextType>
|
||||
void D3D11CommonContext<ContextType>::UpdateBuffer(
|
||||
D3D11Buffer* pDstBuffer,
|
||||
UINT Offset,
|
||||
UINT Length,
|
||||
const void* pSrcData) {
|
||||
DxvkBufferSlice bufferSlice = pDstBuffer->GetBufferSlice(Offset, Length);
|
||||
|
||||
if (Length <= 1024 && !(Offset & 0x3) && !(Length & 0x3)) {
|
||||
// The backend has special code paths for small buffer updates,
|
||||
// however both offset and size must be aligned to four bytes.
|
||||
DxvkDataSlice dataSlice = AllocUpdateBufferSlice(Length);
|
||||
std::memcpy(dataSlice.ptr(), pSrcData, Length);
|
||||
|
||||
EmitCs([
|
||||
cDataBuffer = std::move(dataSlice),
|
||||
cBufferSlice = std::move(bufferSlice)
|
||||
] (DxvkContext* ctx) {
|
||||
ctx->updateBuffer(
|
||||
cBufferSlice.buffer(),
|
||||
cBufferSlice.offset(),
|
||||
cBufferSlice.length(),
|
||||
cDataBuffer.ptr());
|
||||
});
|
||||
} else {
|
||||
// Otherwise, to avoid large data copies on the CS thread,
|
||||
// write directly to a staging buffer and dispatch a copy
|
||||
DxvkBufferSlice stagingSlice = AllocStagingBuffer(Length);
|
||||
std::memcpy(stagingSlice.mapPtr(0), pSrcData, Length);
|
||||
|
||||
EmitCs([
|
||||
cStagingSlice = std::move(stagingSlice),
|
||||
cBufferSlice = std::move(bufferSlice)
|
||||
] (DxvkContext* ctx) {
|
||||
ctx->copyBuffer(
|
||||
cBufferSlice.buffer(),
|
||||
cBufferSlice.offset(),
|
||||
cStagingSlice.buffer(),
|
||||
cStagingSlice.offset(),
|
||||
cBufferSlice.length());
|
||||
});
|
||||
}
|
||||
|
||||
if (pDstBuffer->HasSequenceNumber())
|
||||
TrackBufferSequenceNumber(pDstBuffer);
|
||||
}
|
||||
|
||||
|
||||
template<typename ContextType>
|
||||
void D3D11CommonContext<ContextType>::UpdateTexture(
|
||||
D3D11CommonTexture* pDstTexture,
|
||||
UINT DstSubresource,
|
||||
const D3D11_BOX* pDstBox,
|
||||
const void* pSrcData,
|
||||
UINT SrcRowPitch,
|
||||
UINT SrcDepthPitch) {
|
||||
if (DstSubresource >= pDstTexture->CountSubresources())
|
||||
return;
|
||||
|
||||
VkFormat packedFormat = pDstTexture->GetPackedFormat();
|
||||
|
||||
auto formatInfo = lookupFormatInfo(packedFormat);
|
||||
auto subresource = pDstTexture->GetSubresourceFromIndex(
|
||||
formatInfo->aspectMask, DstSubresource);
|
||||
|
||||
VkExtent3D mipExtent = pDstTexture->MipLevelExtent(subresource.mipLevel);
|
||||
|
||||
VkOffset3D offset = { 0, 0, 0 };
|
||||
VkExtent3D extent = mipExtent;
|
||||
|
||||
if (pDstBox != nullptr) {
|
||||
if (pDstBox->left >= pDstBox->right
|
||||
|| pDstBox->top >= pDstBox->bottom
|
||||
|| pDstBox->front >= pDstBox->back)
|
||||
return; // no-op, but legal
|
||||
|
||||
offset.x = pDstBox->left;
|
||||
offset.y = pDstBox->top;
|
||||
offset.z = pDstBox->front;
|
||||
|
||||
extent.width = pDstBox->right - pDstBox->left;
|
||||
extent.height = pDstBox->bottom - pDstBox->top;
|
||||
extent.depth = pDstBox->back - pDstBox->front;
|
||||
}
|
||||
|
||||
if (!util::isBlockAligned(offset, extent, formatInfo->blockSize, mipExtent)) {
|
||||
Logger::err("D3D11: UpdateSubresource1: Unaligned region");
|
||||
return;
|
||||
}
|
||||
|
||||
auto stagingSlice = AllocStagingBuffer(util::computeImageDataSize(packedFormat, extent));
|
||||
|
||||
util::packImageData(stagingSlice.mapPtr(0),
|
||||
pSrcData, SrcRowPitch, SrcDepthPitch, 0, 0,
|
||||
pDstTexture->GetVkImageType(), extent, 1,
|
||||
formatInfo, formatInfo->aspectMask);
|
||||
|
||||
UpdateImage(pDstTexture, &subresource,
|
||||
offset, extent, std::move(stagingSlice));
|
||||
}
|
||||
|
||||
|
||||
template<typename ContextType>
|
||||
void D3D11CommonContext<ContextType>::UpdateImage(
|
||||
D3D11CommonTexture* pDstTexture,
|
||||
const VkImageSubresource* pDstSubresource,
|
||||
VkOffset3D DstOffset,
|
||||
VkExtent3D DstExtent,
|
||||
DxvkBufferSlice StagingBuffer) {
|
||||
bool dstIsImage = pDstTexture->GetMapMode() != D3D11_COMMON_TEXTURE_MAP_MODE_STAGING;
|
||||
|
||||
uint32_t dstSubresource = D3D11CalcSubresource(pDstSubresource->mipLevel,
|
||||
pDstSubresource->arrayLayer, pDstTexture->Desc()->MipLevels);
|
||||
|
||||
if (dstIsImage) {
|
||||
EmitCs([
|
||||
cDstImage = pDstTexture->GetImage(),
|
||||
cDstLayers = vk::makeSubresourceLayers(*pDstSubresource),
|
||||
cDstOffset = DstOffset,
|
||||
cDstExtent = DstExtent,
|
||||
cStagingSlice = std::move(StagingBuffer),
|
||||
cPackedFormat = pDstTexture->GetPackedFormat()
|
||||
] (DxvkContext* ctx) {
|
||||
if (cDstLayers.aspectMask != (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
|
||||
ctx->copyBufferToImage(cDstImage,
|
||||
cDstLayers, cDstOffset, cDstExtent,
|
||||
cStagingSlice.buffer(),
|
||||
cStagingSlice.offset(), 0, 0);
|
||||
} else {
|
||||
ctx->copyPackedBufferToDepthStencilImage(cDstImage, cDstLayers,
|
||||
VkOffset2D { cDstOffset.x, cDstOffset.y },
|
||||
VkExtent2D { cDstExtent.width, cDstExtent.height },
|
||||
cStagingSlice.buffer(),
|
||||
cStagingSlice.offset(),
|
||||
VkOffset2D { 0, 0 },
|
||||
VkExtent2D { cDstExtent.width, cDstExtent.height },
|
||||
cPackedFormat);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// If the destination image is backed only by a buffer, we need to use
|
||||
// the packed buffer copy function which does not know about planes and
|
||||
// format metadata, so deal with it manually here.
|
||||
VkExtent3D dstMipExtent = pDstTexture->MipLevelExtent(pDstSubresource->mipLevel);
|
||||
|
||||
auto dstFormat = pDstTexture->GetPackedFormat();
|
||||
auto dstFormatInfo = lookupFormatInfo(dstFormat);
|
||||
|
||||
uint32_t planeCount = 1;
|
||||
|
||||
if (dstFormatInfo->flags.test(DxvkFormatFlag::MultiPlane))
|
||||
planeCount = vk::getPlaneCount(dstFormatInfo->aspectMask);
|
||||
|
||||
// The source data isn't stored in an image so we'll also need to
|
||||
// track the offset for that while iterating over the planes.
|
||||
VkDeviceSize srcPlaneOffset = 0;
|
||||
|
||||
for (uint32_t i = 0; i < planeCount; i++) {
|
||||
VkImageAspectFlags dstAspectMask = dstFormatInfo->aspectMask;
|
||||
VkDeviceSize elementSize = dstFormatInfo->elementSize;
|
||||
VkExtent3D blockSize = dstFormatInfo->blockSize;
|
||||
|
||||
if (dstFormatInfo->flags.test(DxvkFormatFlag::MultiPlane)) {
|
||||
dstAspectMask = vk::getPlaneAspect(i);
|
||||
|
||||
auto plane = &dstFormatInfo->planes[i];
|
||||
blockSize.width *= plane->blockSize.width;
|
||||
blockSize.height *= plane->blockSize.height;
|
||||
elementSize = plane->elementSize;
|
||||
}
|
||||
|
||||
VkExtent3D blockCount = util::computeBlockCount(DstExtent, blockSize);
|
||||
|
||||
EmitCs([
|
||||
cDstBuffer = pDstTexture->GetMappedBuffer(dstSubresource),
|
||||
cDstStart = pDstTexture->GetSubresourceLayout(dstAspectMask, dstSubresource).Offset,
|
||||
cDstOffset = util::computeBlockOffset(DstOffset, blockSize),
|
||||
cDstSize = util::computeBlockCount(dstMipExtent, blockSize),
|
||||
cDstExtent = blockCount,
|
||||
cSrcBuffer = StagingBuffer.buffer(),
|
||||
cSrcStart = StagingBuffer.offset() + srcPlaneOffset,
|
||||
cPixelSize = elementSize
|
||||
] (DxvkContext* ctx) {
|
||||
ctx->copyPackedBufferImage(
|
||||
cDstBuffer, cDstStart, cDstOffset, cDstSize,
|
||||
cSrcBuffer, cSrcStart, VkOffset3D(), cDstExtent,
|
||||
cDstExtent, cPixelSize);
|
||||
});
|
||||
|
||||
srcPlaneOffset += util::flattenImageExtent(blockCount) * elementSize;
|
||||
}
|
||||
}
|
||||
|
||||
if (pDstTexture->HasSequenceNumber())
|
||||
TrackTextureSequenceNumber(pDstTexture, dstSubresource);
|
||||
}
|
||||
|
||||
|
||||
template<typename ContextType>
|
||||
void D3D11CommonContext<ContextType>::UpdateResource(
|
||||
ID3D11Resource* pDstResource,
|
||||
|
@ -807,6 +807,27 @@ namespace dxvk {
|
||||
bool TestSrvHazards(
|
||||
D3D11ShaderResourceView* pView);
|
||||
|
||||
void UpdateBuffer(
|
||||
D3D11Buffer* pDstBuffer,
|
||||
UINT Offset,
|
||||
UINT Length,
|
||||
const void* pSrcData);
|
||||
|
||||
void UpdateTexture(
|
||||
D3D11CommonTexture* pDstTexture,
|
||||
UINT DstSubresource,
|
||||
const D3D11_BOX* pDstBox,
|
||||
const void* pSrcData,
|
||||
UINT SrcRowPitch,
|
||||
UINT SrcDepthPitch);
|
||||
|
||||
void UpdateImage(
|
||||
D3D11CommonTexture* pDstTexture,
|
||||
const VkImageSubresource* pDstSubresource,
|
||||
VkOffset3D DstOffset,
|
||||
VkExtent3D DstExtent,
|
||||
DxvkBufferSlice StagingBuffer);
|
||||
|
||||
void UpdateResource(
|
||||
ID3D11Resource* pDstResource,
|
||||
UINT DstSubresource,
|
||||
|
Loading…
x
Reference in New Issue
Block a user