mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-02-21 04:54:15 +01:00
[dxvk] Fix misaligned image uploads on transfer queue
This commit is contained in:
parent
d2155c7f8c
commit
f8b9efd11e
@ -155,8 +155,8 @@ namespace dxvk {
|
||||
VkDeviceSize dataSize = 0u;
|
||||
|
||||
for (uint32_t mip = 0; mip < image->info().mipLevels; mip++) {
|
||||
dataSize += image->info().numLayers * util::computeImageDataSize(
|
||||
packedFormat, image->mipLevelExtent(mip), formatInfo->aspectMask);
|
||||
dataSize += image->info().numLayers * align(util::computeImageDataSize(
|
||||
packedFormat, image->mipLevelExtent(mip), formatInfo->aspectMask), CACHE_LINE_SIZE);
|
||||
}
|
||||
|
||||
stagingSlice = m_stagingBuffer.alloc(dataSize);
|
||||
@ -181,7 +181,7 @@ namespace dxvk {
|
||||
pInitialData[index].pSysMem, pInitialData[index].SysMemPitch, pInitialData[index].SysMemSlicePitch,
|
||||
0, 0, pTexture->GetVkImageType(), mipLevelExtent, 1, formatInfo, formatInfo->aspectMask);
|
||||
|
||||
dataOffset += mipSizePerLayer;
|
||||
dataOffset += align(mipSizePerLayer, CACHE_LINE_SIZE);
|
||||
}
|
||||
|
||||
if (mapMode != D3D11_COMMON_TEXTURE_MAP_MODE_NONE) {
|
||||
@ -202,7 +202,7 @@ namespace dxvk {
|
||||
ctx->uploadImage(cImage,
|
||||
cStagingSlice.buffer(),
|
||||
cStagingSlice.offset(),
|
||||
cFormat);
|
||||
CACHE_LINE_SIZE, cFormat);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
|
@ -2047,6 +2047,7 @@ namespace dxvk {
|
||||
const Rc<DxvkImage>& image,
|
||||
const Rc<DxvkBuffer>& source,
|
||||
VkDeviceSize sourceOffset,
|
||||
VkDeviceSize subresourceAlignment,
|
||||
VkFormat format) {
|
||||
// Always use framebuffer path for depth-stencil images since we know
|
||||
// they are writeable and can't use Vulkan transfer queues. Stencil
|
||||
@ -2054,9 +2055,9 @@ namespace dxvk {
|
||||
bool useFb = !formatsAreCopyCompatible(image->info().format, format);
|
||||
|
||||
if (useFb)
|
||||
uploadImageFb(image, source, sourceOffset, format);
|
||||
uploadImageFb(image, source, sourceOffset, subresourceAlignment, format);
|
||||
else
|
||||
uploadImageHw(image, source, sourceOffset);
|
||||
uploadImageHw(image, source, sourceOffset, subresourceAlignment);
|
||||
}
|
||||
|
||||
|
||||
@ -4316,20 +4317,30 @@ namespace dxvk {
|
||||
const Rc<DxvkImage>& image,
|
||||
const Rc<DxvkBuffer>& source,
|
||||
VkDeviceSize sourceOffset,
|
||||
VkDeviceSize subresourceAlignment,
|
||||
VkFormat format) {
|
||||
if (!format)
|
||||
format = image->info().format;
|
||||
|
||||
for (uint32_t i = 0; i < image->info().mipLevels; i++) {
|
||||
VkExtent3D mipExtent = image->mipLevelExtent(i);
|
||||
for (uint32_t m = 0; m < image->info().mipLevels; m++) {
|
||||
VkExtent3D mipExtent = image->mipLevelExtent(m);
|
||||
|
||||
copyBufferToImageFb(image,
|
||||
vk::pickSubresourceLayers(image->getAvailableSubresources(), i),
|
||||
VkOffset3D { 0, 0, 0 }, mipExtent,
|
||||
source, sourceOffset, 0, 0, format);
|
||||
|
||||
sourceOffset += image->info().numLayers * util::computeImageDataSize(
|
||||
VkDeviceSize mipSize = util::computeImageDataSize(
|
||||
format, mipExtent, image->formatInfo()->aspectMask);
|
||||
|
||||
for (uint32_t l = 0; l < image->info().numLayers; l++) {
|
||||
VkImageSubresourceLayers layers = { };
|
||||
layers.aspectMask = image->formatInfo()->aspectMask;
|
||||
layers.mipLevel = m;
|
||||
layers.baseArrayLayer = l;
|
||||
layers.layerCount = 1;
|
||||
|
||||
copyBufferToImageFb(image, layers,
|
||||
VkOffset3D { 0, 0, 0 }, mipExtent,
|
||||
source, sourceOffset, 0, 0, format);
|
||||
|
||||
sourceOffset += align(mipSize, subresourceAlignment);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -4337,7 +4348,8 @@ namespace dxvk {
|
||||
void DxvkContext::uploadImageHw(
|
||||
const Rc<DxvkImage>& image,
|
||||
const Rc<DxvkBuffer>& source,
|
||||
VkDeviceSize sourceOffset) {
|
||||
VkDeviceSize sourceOffset,
|
||||
VkDeviceSize subresourceAlignment) {
|
||||
// Initialize all subresources of the image at once
|
||||
VkImageLayout transferLayout = image->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||||
|
||||
@ -4348,18 +4360,25 @@ namespace dxvk {
|
||||
// Copy image data, one mip at a time
|
||||
VkDeviceSize dataOffset = sourceOffset;
|
||||
|
||||
for (uint32_t i = 0; i < image->info().mipLevels; i++) {
|
||||
VkExtent3D mipExtent = image->mipLevelExtent(i);
|
||||
for (uint32_t m = 0; m < image->info().mipLevels; m++) {
|
||||
VkExtent3D mipExtent = image->mipLevelExtent(m);
|
||||
|
||||
VkDeviceSize mipSize = image->info().numLayers * util::computeImageDataSize(
|
||||
VkDeviceSize mipSize = util::computeImageDataSize(
|
||||
image->info().format, mipExtent, image->formatInfo()->aspectMask);
|
||||
|
||||
copyImageBufferData<true>(DxvkCmdBuffer::SdmaBuffer,
|
||||
image, vk::pickSubresourceLayers(image->getAvailableSubresources(), i),
|
||||
VkOffset3D { 0, 0, 0 }, mipExtent, transferLayout,
|
||||
source->getSliceHandle(dataOffset, mipSize), 0, 0);
|
||||
for (uint32_t l = 0; l < image->info().numLayers; l++) {
|
||||
VkImageSubresourceLayers layers = { };
|
||||
layers.aspectMask = image->formatInfo()->aspectMask;
|
||||
layers.mipLevel = m;
|
||||
layers.baseArrayLayer = l;
|
||||
layers.layerCount = 1;
|
||||
|
||||
dataOffset += mipSize;
|
||||
copyImageBufferData<true>(DxvkCmdBuffer::SdmaBuffer,
|
||||
image, layers, VkOffset3D { 0, 0, 0 }, mipExtent, transferLayout,
|
||||
source->getSliceHandle(dataOffset, mipSize), 0, 0);
|
||||
|
||||
dataOffset += align(mipSize, subresourceAlignment);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_device->hasDedicatedTransferQueue()) {
|
||||
|
@ -1101,20 +1101,21 @@ namespace dxvk {
|
||||
/**
|
||||
* \brief Uses transfer queue to initialize image
|
||||
*
|
||||
* Only safe to use if the image is not in use by the GPU. Data is
|
||||
* assumed to be tightly packed, with all layers of the top-level mip
|
||||
* stored first, then the next mip etc. If the given format does not
|
||||
* match the image format and is not \c VK_FORMAT_UNDEFINED, the data
|
||||
* will be converted to the image format before performing the upload.
|
||||
* Only safe to use if the image is not in use by the GPU.
|
||||
* Data for each subresource is tightly packed, but individual
|
||||
* subresources must be aligned to \c subresourceAlignment in
|
||||
* order to meet Vulkan requirements when using transfer queues.
|
||||
* \param [in] image The image to initialize
|
||||
* \param [in] source Staging buffer containing data
|
||||
* \param [in] sourceOffset Offset into staging buffer
|
||||
* \param [in] subresourceAlignment Subresource alignment
|
||||
* \param [in] format Actual data format
|
||||
*/
|
||||
void uploadImage(
|
||||
const Rc<DxvkImage>& image,
|
||||
const Rc<DxvkBuffer>& source,
|
||||
VkDeviceSize sourceOffset,
|
||||
VkDeviceSize subresourceAlignment,
|
||||
VkFormat format);
|
||||
|
||||
/**
|
||||
@ -1595,11 +1596,13 @@ namespace dxvk {
|
||||
const Rc<DxvkImage>& image,
|
||||
const Rc<DxvkBuffer>& source,
|
||||
VkDeviceSize sourceOffset,
|
||||
VkDeviceSize subresourceAlignment,
|
||||
VkFormat format);
|
||||
|
||||
void uploadImageHw(
|
||||
const Rc<DxvkImage>& image,
|
||||
const Rc<DxvkBuffer>& source,
|
||||
VkDeviceSize subresourceAlignment,
|
||||
VkDeviceSize sourceOffset);
|
||||
|
||||
void performClear(
|
||||
|
Loading…
x
Reference in New Issue
Block a user