mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-02-20 19:54:19 +01:00
[dxvk] Support format conversion in copyImageToBuffer
This commit is contained in:
parent
f67c8dd1da
commit
ad1f70beea
@ -4007,6 +4007,7 @@ namespace dxvk {
|
||||
|
||||
EmitCs([
|
||||
cSrcImage = pSrcTexture->GetImage(),
|
||||
cSrcFormat = pSrcTexture->GetPackedFormat(),
|
||||
cSrcLayers = srcLayer,
|
||||
cSrcOffset = SrcOffset,
|
||||
cSrcExtent = SrcExtent,
|
||||
@ -4014,21 +4015,10 @@ namespace dxvk {
|
||||
cDstLayout = pDstTexture->GetSubresourceLayout(dstAspectMask, dstSubresource),
|
||||
cDstOffset = pDstTexture->ComputeMappedOffset(dstSubresource, j, DstOffset),
|
||||
cDstCoord = DstOffset,
|
||||
cDstExtent = dstMipExtent,
|
||||
cDstFormat = pDstTexture->GetPackedFormat()
|
||||
cDstExtent = dstMipExtent
|
||||
] (DxvkContext* ctx) {
|
||||
if (cSrcLayers.aspectMask != (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
|
||||
ctx->copyImageToBuffer(cDstBuffer, cDstOffset, cDstLayout.RowPitch,
|
||||
cDstLayout.DepthPitch, cSrcImage, cSrcLayers, cSrcOffset, cSrcExtent);
|
||||
} else {
|
||||
ctx->copyDepthStencilImageToPackedBuffer(cDstBuffer, cDstLayout.Offset,
|
||||
VkOffset2D { cDstCoord.x, cDstCoord.y },
|
||||
VkExtent2D { cDstExtent.width, cDstExtent.height },
|
||||
cSrcImage, cSrcLayers,
|
||||
VkOffset2D { cSrcOffset.x, cSrcOffset.y },
|
||||
VkExtent2D { cSrcExtent.width, cSrcExtent.height },
|
||||
cDstFormat);
|
||||
}
|
||||
ctx->copyImageToBuffer(cDstBuffer, cDstOffset, cDstLayout.RowPitch,
|
||||
cDstLayout.DepthPitch, cSrcFormat, cSrcImage, cSrcLayers, cSrcOffset, cSrcExtent);
|
||||
});
|
||||
} else {
|
||||
// The backend is not aware of image metadata in this case,
|
||||
|
@ -617,18 +617,8 @@ namespace dxvk {
|
||||
VkOffset3D offset = { 0, 0, 0 };
|
||||
VkExtent3D extent = cSrcImage->mipLevelExtent(cSrcSubresource.mipLevel);
|
||||
|
||||
if (cSrcSubresource.aspectMask != (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
|
||||
ctx->copyImageToBuffer(cDstBuffer, 0, 0, 0,
|
||||
cSrcImage, cSrcSubresource, offset, extent);
|
||||
} else {
|
||||
ctx->copyDepthStencilImageToPackedBuffer(cDstBuffer, 0,
|
||||
VkOffset2D { 0, 0 },
|
||||
VkExtent2D { extent.width, extent.height },
|
||||
cSrcImage, cSrcSubresource,
|
||||
VkOffset2D { 0, 0 },
|
||||
VkExtent2D { extent.width, extent.height },
|
||||
cPackedFormat);
|
||||
}
|
||||
ctx->copyImageToBuffer(cDstBuffer, 0, 0, 0, cPackedFormat,
|
||||
cSrcImage, cSrcSubresource, offset, extent);
|
||||
});
|
||||
|
||||
if (pResource->HasSequenceNumber())
|
||||
|
@ -1139,9 +1139,9 @@ namespace dxvk {
|
||||
cSubresources = srcSubresourceLayers,
|
||||
cLevelExtent = srcTexExtent
|
||||
] (DxvkContext* ctx) {
|
||||
ctx->copyImageToBuffer(cBufferSlice.buffer(), cBufferSlice.offset(), 4, 0,
|
||||
cImage, cSubresources, VkOffset3D { 0, 0, 0 },
|
||||
cLevelExtent);
|
||||
ctx->copyImageToBuffer(cBufferSlice.buffer(), cBufferSlice.offset(),
|
||||
4, 0, VK_FORMAT_UNDEFINED, cImage, cSubresources,
|
||||
VkOffset3D { 0, 0, 0 }, cLevelExtent);
|
||||
});
|
||||
|
||||
dstTexInfo->SetNeedsReadback(dst->GetSubresource(), true);
|
||||
@ -4839,23 +4839,10 @@ namespace dxvk {
|
||||
cLevelExtent = levelExtent,
|
||||
cPackedFormat = packedFormat
|
||||
] (DxvkContext* ctx) {
|
||||
if (cSubresources.aspectMask != (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
|
||||
ctx->copyImageToBuffer(cImageBufferSlice.buffer(),
|
||||
cImageBufferSlice.offset(), 4, 0, cImage,
|
||||
cSubresources, VkOffset3D { 0, 0, 0 },
|
||||
cLevelExtent);
|
||||
} else {
|
||||
// Copying DS to a packed buffer is only supported for D24S8 and D32S8
|
||||
// right now so the 4 byte row alignment is guaranteed by the format size
|
||||
ctx->copyDepthStencilImageToPackedBuffer(
|
||||
cImageBufferSlice.buffer(), cImageBufferSlice.offset(),
|
||||
VkOffset2D { 0, 0 },
|
||||
VkExtent2D { cLevelExtent.width, cLevelExtent.height },
|
||||
cImage, cSubresources,
|
||||
VkOffset2D { 0, 0 },
|
||||
VkExtent2D { cLevelExtent.width, cLevelExtent.height },
|
||||
cPackedFormat);
|
||||
}
|
||||
ctx->copyImageToBuffer(cImageBufferSlice.buffer(),
|
||||
cImageBufferSlice.offset(), 4, 0, cPackedFormat,
|
||||
cImage, cSubresources, VkOffset3D { 0, 0, 0 },
|
||||
cLevelExtent);
|
||||
});
|
||||
TrackTextureMappingBufferSequenceNumber(pResource, Subresource);
|
||||
}
|
||||
|
@ -464,8 +464,8 @@ namespace dxvk {
|
||||
cLevelExtent = srcExtent
|
||||
] (DxvkContext* ctx) {
|
||||
ctx->copyImageToBuffer(cBufferSlice.buffer(),
|
||||
cBufferSlice.offset(), 4, 0, cImage,
|
||||
cSubresources, VkOffset3D { 0, 0, 0 },
|
||||
cBufferSlice.offset(), 4, 0, VK_FORMAT_UNDEFINED,
|
||||
cImage, cSubresources, VkOffset3D { 0, 0, 0 },
|
||||
cLevelExtent);
|
||||
});
|
||||
|
||||
|
@ -625,59 +625,22 @@ namespace dxvk {
|
||||
VkDeviceSize dstOffset,
|
||||
VkDeviceSize rowAlignment,
|
||||
VkDeviceSize sliceAlignment,
|
||||
VkFormat dstFormat,
|
||||
const Rc<DxvkImage>& srcImage,
|
||||
VkImageSubresourceLayers srcSubresource,
|
||||
VkOffset3D srcOffset,
|
||||
VkExtent3D srcExtent) {
|
||||
this->spillRenderPass(true);
|
||||
this->prepareImage(srcImage, vk::makeSubresourceRange(srcSubresource));
|
||||
bool useFb = (dstFormat && dstFormat != srcImage->info().format) ||
|
||||
(srcImage->formatInfo()->aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT));
|
||||
|
||||
auto dstSlice = dstBuffer->getSliceHandle(dstOffset, 0);
|
||||
|
||||
// We may copy to only one aspect of a depth-stencil image,
|
||||
// but pipeline barriers need to have all aspect bits set
|
||||
auto srcFormatInfo = srcImage->formatInfo();
|
||||
|
||||
auto srcSubresourceRange = vk::makeSubresourceRange(srcSubresource);
|
||||
srcSubresourceRange.aspectMask = srcFormatInfo->aspectMask;
|
||||
|
||||
if (m_execBarriers.isImageDirty(srcImage, srcSubresourceRange, DxvkAccess::Write)
|
||||
|| m_execBarriers.isBufferDirty(dstSlice, DxvkAccess::Write))
|
||||
m_execBarriers.recordCommands(m_cmd);
|
||||
|
||||
// Select a suitable image layout for the transfer op
|
||||
VkImageLayout srcImageLayoutTransfer = srcImage->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
|
||||
|
||||
m_execAcquires.accessImage(
|
||||
srcImage, srcSubresourceRange,
|
||||
srcImage->info().layout,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT, 0,
|
||||
srcImageLayoutTransfer,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
VK_ACCESS_TRANSFER_READ_BIT);
|
||||
|
||||
m_execAcquires.recordCommands(m_cmd);
|
||||
|
||||
this->copyImageBufferData<false>(DxvkCmdBuffer::ExecBuffer, srcImage, srcSubresource,
|
||||
srcOffset, srcExtent, srcImageLayoutTransfer, dstSlice, rowAlignment, sliceAlignment);
|
||||
|
||||
m_execBarriers.accessImage(
|
||||
srcImage, srcSubresourceRange,
|
||||
srcImageLayoutTransfer,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
VK_ACCESS_TRANSFER_READ_BIT,
|
||||
srcImage->info().layout,
|
||||
srcImage->info().stages,
|
||||
srcImage->info().access);
|
||||
|
||||
m_execBarriers.accessBuffer(dstSlice,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||
dstBuffer->info().stages,
|
||||
dstBuffer->info().access);
|
||||
|
||||
m_cmd->trackResource<DxvkAccess::Write>(dstBuffer);
|
||||
m_cmd->trackResource<DxvkAccess::Read>(srcImage);
|
||||
if (useFb) {
|
||||
copyImageToBufferFb(dstBuffer, dstOffset, rowAlignment, sliceAlignment,
|
||||
dstFormat ? dstFormat : srcImage->info().format,
|
||||
srcImage, srcSubresource, srcOffset, srcExtent);
|
||||
} else {
|
||||
copyImageToBufferHw(dstBuffer, dstOffset, rowAlignment, sliceAlignment,
|
||||
srcImage, srcSubresource, srcOffset, srcExtent);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -3633,6 +3596,258 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
void DxvkContext::copyImageToBufferHw(
|
||||
const Rc<DxvkBuffer>& buffer,
|
||||
VkDeviceSize bufferOffset,
|
||||
VkDeviceSize bufferRowAlignment,
|
||||
VkDeviceSize bufferSliceAlignment,
|
||||
const Rc<DxvkImage>& image,
|
||||
VkImageSubresourceLayers imageSubresource,
|
||||
VkOffset3D imageOffset,
|
||||
VkExtent3D imageExtent) {
|
||||
this->spillRenderPass(true);
|
||||
this->prepareImage(image, vk::makeSubresourceRange(imageSubresource));
|
||||
|
||||
VkDeviceSize dataSize = imageSubresource.layerCount * util::computeImageDataSize(
|
||||
image->info().format, imageExtent, imageSubresource.aspectMask);
|
||||
|
||||
auto bufferSlice = buffer->getSliceHandle(bufferOffset, dataSize);
|
||||
|
||||
// We may copy to only one aspect of a depth-stencil image,
|
||||
// but pipeline barriers need to have all aspect bits set
|
||||
auto srcFormatInfo = image->formatInfo();
|
||||
|
||||
auto srcSubresourceRange = vk::makeSubresourceRange(imageSubresource);
|
||||
srcSubresourceRange.aspectMask = srcFormatInfo->aspectMask;
|
||||
|
||||
if (m_execBarriers.isImageDirty(image, srcSubresourceRange, DxvkAccess::Write)
|
||||
|| m_execBarriers.isBufferDirty(bufferSlice, DxvkAccess::Write))
|
||||
m_execBarriers.recordCommands(m_cmd);
|
||||
|
||||
// Select a suitable image layout for the transfer op
|
||||
VkImageLayout srcImageLayoutTransfer = image->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
|
||||
|
||||
m_execAcquires.accessImage(
|
||||
image, srcSubresourceRange,
|
||||
image->info().layout,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT, 0,
|
||||
srcImageLayoutTransfer,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
VK_ACCESS_TRANSFER_READ_BIT);
|
||||
|
||||
m_execAcquires.recordCommands(m_cmd);
|
||||
|
||||
this->copyImageBufferData<false>(DxvkCmdBuffer::ExecBuffer,
|
||||
image, imageSubresource, imageOffset, imageExtent, srcImageLayoutTransfer,
|
||||
bufferSlice, bufferRowAlignment, bufferSliceAlignment);
|
||||
|
||||
m_execBarriers.accessImage(
|
||||
image, srcSubresourceRange,
|
||||
srcImageLayoutTransfer,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
VK_ACCESS_TRANSFER_READ_BIT,
|
||||
image->info().layout,
|
||||
image->info().stages,
|
||||
image->info().access);
|
||||
|
||||
m_execBarriers.accessBuffer(bufferSlice,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||
buffer->info().stages,
|
||||
buffer->info().access);
|
||||
|
||||
m_cmd->trackResource<DxvkAccess::Write>(buffer);
|
||||
m_cmd->trackResource<DxvkAccess::Read>(image);
|
||||
}
|
||||
|
||||
|
||||
void DxvkContext::copyImageToBufferFb(
|
||||
const Rc<DxvkBuffer>& buffer,
|
||||
VkDeviceSize bufferOffset,
|
||||
VkDeviceSize bufferRowAlignment,
|
||||
VkDeviceSize bufferSliceAlignment,
|
||||
VkFormat bufferFormat,
|
||||
const Rc<DxvkImage>& image,
|
||||
VkImageSubresourceLayers imageSubresource,
|
||||
VkOffset3D imageOffset,
|
||||
VkExtent3D imageExtent) {
|
||||
this->spillRenderPass(true);
|
||||
this->invalidateState();
|
||||
|
||||
this->prepareImage(image, vk::makeSubresourceRange(imageSubresource));
|
||||
|
||||
// Ensure we can read the source image
|
||||
DxvkImageUsageInfo imageUsage = { };
|
||||
imageUsage.usage = VK_IMAGE_USAGE_SAMPLED_BIT;
|
||||
|
||||
ensureImageCompatibility(image, imageUsage);
|
||||
|
||||
if (m_execBarriers.isImageDirty(image, vk::makeSubresourceRange(imageSubresource), DxvkAccess::Write))
|
||||
m_execBarriers.recordCommands(m_cmd);
|
||||
|
||||
auto formatInfo = lookupFormatInfo(bufferFormat);
|
||||
|
||||
if (formatInfo->flags.test(DxvkFormatFlag::MultiPlane)) {
|
||||
Logger::err(str::format("DxvkContext: Planar formats not supported for shader-based image to buffer copies"));
|
||||
return;
|
||||
}
|
||||
|
||||
VkDeviceSize rowPitch = imageExtent.width * formatInfo->elementSize;
|
||||
|
||||
if (bufferRowAlignment > formatInfo->elementSize)
|
||||
rowPitch = bufferRowAlignment >= rowPitch ? bufferRowAlignment : align(rowPitch, bufferRowAlignment);
|
||||
|
||||
VkDeviceSize slicePitch = imageExtent.height * rowPitch;
|
||||
|
||||
if (bufferSliceAlignment > formatInfo->elementSize)
|
||||
slicePitch = bufferSliceAlignment >= slicePitch ? bufferSliceAlignment : align(slicePitch, bufferSliceAlignment);
|
||||
|
||||
if ((rowPitch % formatInfo->elementSize) || (slicePitch % formatInfo->elementSize)) {
|
||||
Logger::err(str::format("DxvkContext: Pitches ", rowPitch, ",", slicePitch, " not a multiple of element size ", formatInfo->elementSize, " for format ", bufferFormat));
|
||||
return;
|
||||
}
|
||||
|
||||
// Create texel buffer view to write to
|
||||
DxvkBufferViewKey bufferViewInfo = { };
|
||||
bufferViewInfo.format = sanitizeTexelBufferFormat(bufferFormat);
|
||||
bufferViewInfo.usage = VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT;
|
||||
bufferViewInfo.offset = bufferOffset;
|
||||
bufferViewInfo.size = slicePitch * imageExtent.depth * imageSubresource.layerCount;
|
||||
|
||||
Rc<DxvkBufferView> bufferView = buffer->createView(bufferViewInfo);
|
||||
VkBufferView bufferViewHandle = bufferView->handle();
|
||||
|
||||
DxvkBufferSliceHandle bufferSlice = buffer->getSliceHandle(
|
||||
bufferViewInfo.offset, bufferViewInfo.size);
|
||||
|
||||
if (m_execBarriers.isBufferDirty(bufferSlice, DxvkAccess::Read))
|
||||
m_execBarriers.recordCommands(m_cmd);
|
||||
|
||||
// Transition image to a layout we can use for reading as necessary
|
||||
VkImageLayout imageLayout = (image->formatInfo()->aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT))
|
||||
? image->pickLayout(VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL)
|
||||
: image->pickLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||
|
||||
if (imageLayout != image->info().layout) {
|
||||
m_execAcquires.accessImage(image,
|
||||
vk::makeSubresourceRange(imageSubresource),
|
||||
image->info().layout,
|
||||
image->info().stages,
|
||||
image->info().access,
|
||||
imageLayout,
|
||||
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
||||
VK_ACCESS_SHADER_READ_BIT);
|
||||
|
||||
m_execAcquires.recordCommands(m_cmd);
|
||||
}
|
||||
|
||||
// Retrieve pipeline
|
||||
VkImageViewType viewType = image->info().type == VK_IMAGE_TYPE_1D
|
||||
? VK_IMAGE_VIEW_TYPE_1D_ARRAY
|
||||
: VK_IMAGE_VIEW_TYPE_2D_ARRAY;
|
||||
|
||||
if (image->info().type == VK_IMAGE_TYPE_3D)
|
||||
viewType = VK_IMAGE_VIEW_TYPE_3D;
|
||||
|
||||
DxvkMetaCopyPipeline pipeline = m_common->metaCopy().getCopyImageToBufferPipeline(viewType, bufferFormat);
|
||||
|
||||
m_cmd->cmdBindPipeline(DxvkCmdBuffer::ExecBuffer,
|
||||
VK_PIPELINE_BIND_POINT_COMPUTE, pipeline.pipeHandle);
|
||||
|
||||
// Create image views for the main and stencil aspects
|
||||
VkDescriptorImageInfo imageDescriptor = { };
|
||||
VkDescriptorImageInfo stencilDescriptor = { };
|
||||
|
||||
Rc<DxvkImageView> imageView;
|
||||
Rc<DxvkImageView> stencilView;
|
||||
|
||||
DxvkImageViewKey imageViewInfo;
|
||||
imageViewInfo.viewType = viewType;
|
||||
imageViewInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT;
|
||||
imageViewInfo.format = image->info().format;
|
||||
imageViewInfo.aspects = imageSubresource.aspectMask & (VK_IMAGE_ASPECT_COLOR_BIT | VK_IMAGE_ASPECT_DEPTH_BIT);
|
||||
imageViewInfo.mipIndex = imageSubresource.mipLevel;
|
||||
imageViewInfo.mipCount = 1;
|
||||
imageViewInfo.layerIndex = imageSubresource.baseArrayLayer;
|
||||
imageViewInfo.layerCount = imageSubresource.layerCount;
|
||||
|
||||
if (imageViewInfo.aspects) {
|
||||
imageView = image->createView(imageViewInfo);
|
||||
|
||||
imageDescriptor.imageView = imageView->handle();
|
||||
imageDescriptor.imageLayout = imageLayout;
|
||||
}
|
||||
|
||||
imageViewInfo.aspects = imageSubresource.aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||
|
||||
if (imageViewInfo.aspects) {
|
||||
stencilView = image->createView(imageViewInfo);
|
||||
|
||||
stencilDescriptor.imageView = stencilView->handle();
|
||||
stencilDescriptor.imageLayout = imageLayout;
|
||||
}
|
||||
|
||||
VkDescriptorSet set = m_descriptorPool->alloc(pipeline.dsetLayout);
|
||||
|
||||
std::array<VkWriteDescriptorSet, 3> descriptorWrites = {{
|
||||
{ VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, nullptr,
|
||||
set, 0, 0, 1, VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, nullptr, nullptr, &bufferViewHandle },
|
||||
{ VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, nullptr,
|
||||
set, 1, 0, 1, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, &imageDescriptor },
|
||||
{ VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, nullptr,
|
||||
set, 2, 0, 1, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, &stencilDescriptor },
|
||||
}};
|
||||
|
||||
m_cmd->updateDescriptorSets(
|
||||
descriptorWrites.size(),
|
||||
descriptorWrites.data());
|
||||
|
||||
m_cmd->cmdBindDescriptorSet(DxvkCmdBuffer::ExecBuffer,
|
||||
VK_PIPELINE_BIND_POINT_COMPUTE, pipeline.pipeLayout,
|
||||
set, 0, nullptr);
|
||||
|
||||
// Set up shader arguments
|
||||
DxvkBufferImageCopyArgs pushConst = { };
|
||||
pushConst.imageOffset = imageOffset;
|
||||
pushConst.bufferOffset = 0u;
|
||||
pushConst.imageExtent = imageExtent;
|
||||
pushConst.bufferImageWidth = rowPitch / formatInfo->elementSize;
|
||||
pushConst.bufferImageHeight = slicePitch / rowPitch;
|
||||
|
||||
m_cmd->cmdPushConstants(DxvkCmdBuffer::ExecBuffer,
|
||||
pipeline.pipeLayout, VK_SHADER_STAGE_COMPUTE_BIT,
|
||||
0, sizeof(pushConst), &pushConst);
|
||||
|
||||
// Compute number of workgroups and dispatch shader
|
||||
VkExtent3D workgroupCount = imageExtent;
|
||||
workgroupCount.depth *= imageSubresource.layerCount;
|
||||
workgroupCount = util::computeBlockCount(workgroupCount, { 16, 16, 1 });
|
||||
|
||||
m_cmd->cmdDispatch(DxvkCmdBuffer::ExecBuffer,
|
||||
workgroupCount.width,
|
||||
workgroupCount.height,
|
||||
workgroupCount.depth);
|
||||
|
||||
m_execBarriers.accessBuffer(bufferSlice,
|
||||
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
||||
VK_ACCESS_SHADER_WRITE_BIT,
|
||||
buffer->info().stages,
|
||||
buffer->info().access);
|
||||
|
||||
m_execBarriers.accessImage(image,
|
||||
vk::makeSubresourceRange(imageSubresource),
|
||||
imageLayout,
|
||||
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
||||
VK_ACCESS_SHADER_READ_BIT,
|
||||
image->info().layout,
|
||||
image->info().stages,
|
||||
image->info().access);
|
||||
|
||||
m_cmd->trackResource<DxvkAccess::Write>(buffer);
|
||||
m_cmd->trackResource<DxvkAccess::Read>(image);
|
||||
}
|
||||
|
||||
|
||||
void DxvkContext::clearImageViewFb(
|
||||
const Rc<DxvkImageView>& imageView,
|
||||
VkOffset3D offset,
|
||||
|
@ -605,6 +605,7 @@ namespace dxvk {
|
||||
* \param [in] dstExtent Destination data extent
|
||||
* \param [in] rowAlignment Row alignment, in bytes
|
||||
* \param [in] sliceAlignment Slice alignment, in bytes
|
||||
* \param [in] dstFormat Buffer format
|
||||
* \param [in] srcImage Source image
|
||||
* \param [in] srcSubresource Source subresource
|
||||
* \param [in] srcOffset Source area offset
|
||||
@ -615,6 +616,7 @@ namespace dxvk {
|
||||
VkDeviceSize dstOffset,
|
||||
VkDeviceSize rowAlignment,
|
||||
VkDeviceSize sliceAlignment,
|
||||
VkFormat dstFormat,
|
||||
const Rc<DxvkImage>& srcImage,
|
||||
VkImageSubresourceLayers srcSubresource,
|
||||
VkOffset3D srcOffset,
|
||||
@ -1532,6 +1534,27 @@ namespace dxvk {
|
||||
VkDeviceSize bufferSliceAlignment,
|
||||
VkFormat bufferFormat);
|
||||
|
||||
void copyImageToBufferHw(
|
||||
const Rc<DxvkBuffer>& buffer,
|
||||
VkDeviceSize bufferOffset,
|
||||
VkDeviceSize bufferRowAlignment,
|
||||
VkDeviceSize bufferSliceAlignment,
|
||||
const Rc<DxvkImage>& image,
|
||||
VkImageSubresourceLayers imageSubresource,
|
||||
VkOffset3D imageOffset,
|
||||
VkExtent3D imageExtent);
|
||||
|
||||
void copyImageToBufferFb(
|
||||
const Rc<DxvkBuffer>& buffer,
|
||||
VkDeviceSize bufferOffset,
|
||||
VkDeviceSize bufferRowAlignment,
|
||||
VkDeviceSize bufferSliceAlignment,
|
||||
VkFormat bufferFormat,
|
||||
const Rc<DxvkImage>& image,
|
||||
VkImageSubresourceLayers imageSubresource,
|
||||
VkOffset3D imageOffset,
|
||||
VkExtent3D imageExtent);
|
||||
|
||||
void clearImageViewFb(
|
||||
const Rc<DxvkImageView>& imageView,
|
||||
VkOffset3D offset,
|
||||
|
Loading…
x
Reference in New Issue
Block a user