1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-01-17 17:52:11 +01:00

[d3d11] Implemented image mapping for reads

This commit is contained in:
Philip Rebohle 2018-01-19 18:09:49 +01:00
parent 0bb98eb03e
commit 2a364c557b
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
4 changed files with 127 additions and 21 deletions

View File

@ -254,29 +254,9 @@ namespace dxvk {
return E_INVALIDARG;
}
// FIXME copy current image contents into the
// buffer unless D3D11_MAP_DISCARD is used.
if (MapType == D3D11_MAP_READ || MapType == D3D11_MAP_READ_WRITE) {
Logger::err("D3D11DeviceContext: Read-only and Read-Write mapping of images currently not supported");
return E_INVALIDARG;
}
if (pMappedResource == nullptr)
return S_FALSE;
if (textureInfo->imageBuffer->isInUse()) {
// Don't wait if the application tells us not to
if (MapFlags & D3D11_MAP_FLAG_DO_NOT_WAIT)
return DXGI_ERROR_WAS_STILL_DRAWING;
if (MapType == D3D11_MAP_WRITE_DISCARD) {
m_context->invalidateBuffer(textureInfo->imageBuffer);
} else if (MapType != D3D11_MAP_WRITE_NO_OVERWRITE) {
this->Flush();
this->Synchronize();
}
}
// Query format and subresource in order to compute
// the row pitch and layer pitch properly.
const DxvkImageCreateInfo& imageInfo = textureInfo->image->info();
@ -294,6 +274,29 @@ namespace dxvk {
levelExtent.height / formatInfo->blockSize.height,
levelExtent.depth / formatInfo->blockSize.depth };
// When using any map mode which requires the image contents
// to be preserved, copy image contents into the buffer.
if (MapType != D3D11_MAP_WRITE_DISCARD) {
const VkImageSubresourceLayers subresourceLayers = {
textureInfo->mappedSubresource.aspectMask,
textureInfo->mappedSubresource.mipLevel,
textureInfo->mappedSubresource.arrayLayer, 1 };
m_context->copyImageToBuffer(
textureInfo->imageBuffer, 0, { 0u, 0u },
textureInfo->image, subresourceLayers,
VkOffset3D { 0, 0, 0 }, levelExtent);
}
if (textureInfo->imageBuffer->isInUse()) {
if (MapType == D3D11_MAP_WRITE_DISCARD) {
m_context->invalidateBuffer(textureInfo->imageBuffer);
} else {
this->Flush();
this->Synchronize();
}
}
// Set up map pointer. Data is tightly packed within the mapped buffer.
pMappedResource->pData = textureInfo->imageBuffer->mapPtr(0);
pMappedResource->RowPitch = formatInfo->elementSize * blockCount.width;

View File

@ -213,6 +213,18 @@ namespace dxvk {
}
void cmdCopyImageToBuffer(
VkImage srcImage,
VkImageLayout srcImageLayout,
VkBuffer dstBuffer,
uint32_t regionCount,
const VkBufferImageCopy* pRegions) {
m_vkd->vkCmdCopyImageToBuffer(m_buffer,
srcImage, srcImageLayout, dstBuffer,
regionCount, pRegions);
}
void cmdDispatch(
uint32_t x,
uint32_t y,

View File

@ -354,6 +354,13 @@ namespace dxvk {
dstImage->info().layout,
dstImage->info().stages,
dstImage->info().access);
m_barriers.accessBuffer(srcSlice,
VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_ACCESS_TRANSFER_READ_BIT,
srcBuffer->info().stages,
srcBuffer->info().access);
m_barriers.recordCommands(m_cmd);
m_cmd->trackResource(dstImage);
@ -442,6 +449,70 @@ namespace dxvk {
}
void DxvkContext::copyImageToBuffer(
const Rc<DxvkBuffer>& dstBuffer,
VkDeviceSize dstOffset,
VkExtent2D dstExtent,
const Rc<DxvkImage>& srcImage,
VkImageSubresourceLayers srcSubresource,
VkOffset3D srcOffset,
VkExtent3D srcExtent) {
this->renderPassEnd();
auto dstSlice = dstBuffer->subSlice(dstOffset, 0);
const VkImageSubresourceRange srcSubresourceRange = {
srcSubresource.aspectMask,
srcSubresource.mipLevel, 1,
srcSubresource.baseArrayLayer,
srcSubresource.layerCount };
m_barriers.accessImage(
srcImage, srcSubresourceRange,
srcImage->info().layout,
srcImage->info().stages,
srcImage->info().access,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_ACCESS_TRANSFER_READ_BIT);
m_barriers.recordCommands(m_cmd);
VkBufferImageCopy copyRegion;
copyRegion.bufferOffset = dstSlice.offset();
copyRegion.bufferRowLength = dstExtent.width;
copyRegion.bufferImageHeight = dstExtent.height;
copyRegion.imageSubresource = srcSubresource;
copyRegion.imageOffset = srcOffset;
copyRegion.imageExtent = srcExtent;
m_cmd->cmdCopyImageToBuffer(
srcImage->handle(),
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
dstSlice.handle(),
1, &copyRegion);
m_barriers.accessImage(
srcImage, srcSubresourceRange,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_ACCESS_TRANSFER_READ_BIT,
srcImage->info().layout,
srcImage->info().stages,
srcImage->info().access);
m_barriers.accessBuffer(dstSlice,
VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_ACCESS_TRANSFER_WRITE_BIT,
dstBuffer->info().stages,
dstBuffer->info().access);
m_barriers.recordCommands(m_cmd);
m_cmd->trackResource(srcImage);
m_cmd->trackResource(dstSlice.resource());
}
void DxvkContext::dispatch(
uint32_t x,
uint32_t y,

View File

@ -224,7 +224,27 @@ namespace dxvk {
VkImageSubresourceLayers srcSubresource,
VkOffset3D srcOffset,
VkExtent3D extent);
/**
* \brief Copies data from an image into a buffer
*
* \param [in] dstBuffer Destination buffer
* \param [in] dstOffset Destination offset, in bytes
* \param [in] dstExtent Destination data extent
* \param [in] srcImage Source image
* \param [in] srcSubresource Source subresource
* \param [in] srcOffset Source area offset
* \param [in] srcExtent Source area size
*/
void copyImageToBuffer(
const Rc<DxvkBuffer>& dstBuffer,
VkDeviceSize dstOffset,
VkExtent2D dstExtent,
const Rc<DxvkImage>& srcImage,
VkImageSubresourceLayers srcSubresource,
VkOffset3D srcOffset,
VkExtent3D srcExtent);
/**
* \brief Starts compute jobs
*