summaryrefslogtreecommitdiffstats
path: root/Graphics/GraphicsEngineVulkan
diff options
context:
space:
mode:
authorEgor Yusov <egor.yusov@gmail.com>2019-04-18 05:11:22 +0000
committerEgor Yusov <egor.yusov@gmail.com>2019-04-18 05:11:22 +0000
commitf73ae3c6a3dbb261c63f25f279b354edf282f5aa (patch)
tree8fc8f4199a7abf8c744e4ed5e0c11f8268e0960d /Graphics/GraphicsEngineVulkan
parentAdded validation to texture uploader dtors; updated pending operations counti... (diff)
downloadDiligentCore-f73ae3c6a3dbb261c63f25f279b354edf282f5aa.tar.gz
DiligentCore-f73ae3c6a3dbb261c63f25f279b354edf282f5aa.zip
Fixed copying compressed textures in Vulkan back-end
Diffstat (limited to 'Graphics/GraphicsEngineVulkan')
-rw-r--r--Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp43
-rw-r--r--Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp22
2 files changed, 38 insertions, 27 deletions
diff --git a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp
index d9d9b3bf..636a2598 100644
--- a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp
@@ -1339,7 +1339,8 @@ namespace Diligent
FullMipBox.MaxZ = 1;
pSrcBox = &FullMipBox;
}
- const auto& FmtAttribs = GetDevice()->GetTextureFormatInfo(DstTexDesc.Format);
+ const auto& DstFmtAttribs = GetTextureFormatAttribs(DstTexDesc.Format);
+ const auto& SrcFmtAttribs = GetTextureFormatAttribs(SrcTexDesc.Format);
if (SrcTexDesc.Usage != USAGE_STAGING && DstTexDesc.Usage != USAGE_STAGING)
{
VkImageCopy CopyRegion = {};
@@ -1351,9 +1352,9 @@ namespace Diligent
CopyRegion.extent.depth = std::max(pSrcBox->MaxZ - pSrcBox->MinZ, 1u);
VkImageAspectFlags aspectMask = 0;
- if (FmtAttribs.ComponentType == COMPONENT_TYPE_DEPTH)
+ if (DstFmtAttribs.ComponentType == COMPONENT_TYPE_DEPTH)
aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
- else if (FmtAttribs.ComponentType == COMPONENT_TYPE_DEPTH_STENCIL)
+ else if (DstFmtAttribs.ComponentType == COMPONENT_TYPE_DEPTH_STENCIL)
{
aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
}
@@ -1385,10 +1386,12 @@ namespace Diligent
auto SrcMipLevelAttribs = GetMipLevelProperties(SrcTexDesc, CopyAttribs.SrcMipLevel);
// address of (x,y,z) = region->bufferOffset + (((z * imageHeight) + y) * rowLength + x) * texelBlockSize; (18.4.1)
SrcBufferOffset +=
- (pSrcBox->MinZ * SrcMipLevelAttribs.Height + pSrcBox->MinY) * SrcMipLevelAttribs.RowSize +
- (FmtAttribs.ComponentType != COMPONENT_TYPE_COMPRESSED ?
- pSrcBox->MinX * FmtAttribs.ComponentSize * FmtAttribs.NumComponents :
- pSrcBox->MinX / FmtAttribs.BlockWidth * FmtAttribs.ComponentSize);
+ // For compressed-block formats, RowSize is the size of one compressed row.
+ // For non-compressed formats, BlockHeight is 1.
+ (pSrcBox->MinZ * SrcMipLevelAttribs.Height + pSrcBox->MinY) / SrcFmtAttribs.BlockHeight * SrcMipLevelAttribs.RowSize +
+ // For compressed-block formats, ComponentSize is the block size and NumComponents is 1.
+ // For non-compressed formats, BlockWidth is 1.
+ (pSrcBox->MinX / SrcFmtAttribs.BlockWidth) * SrcFmtAttribs.ComponentSize * SrcFmtAttribs.NumComponents;
Box DstBox;
DstBox.MinX = CopyAttribs.DstX;
@@ -1418,10 +1421,12 @@ namespace Diligent
auto DstMipLevelAttribs = GetMipLevelProperties(DstTexDesc, CopyAttribs.DstMipLevel);
// address of (x,y,z) = region->bufferOffset + (((z * imageHeight) + y) * rowLength + x) * texelBlockSize; (18.4.1)
DstBufferOffset +=
- (CopyAttribs.DstZ * DstMipLevelAttribs.Height + CopyAttribs.DstY) * DstMipLevelAttribs.RowSize *
- (FmtAttribs.ComponentType != COMPONENT_TYPE_COMPRESSED ?
- CopyAttribs.DstX * FmtAttribs.ComponentSize * FmtAttribs.NumComponents :
- CopyAttribs.DstX / FmtAttribs.BlockWidth * FmtAttribs.ComponentSize);
+ // For compressed-block formats, RowSize is the size of one compressed row.
+ // For non-compressed formats, BlockHeight is 1.
+ (CopyAttribs.DstZ * DstMipLevelAttribs.Height + CopyAttribs.DstY) / DstFmtAttribs.BlockHeight * DstMipLevelAttribs.RowSize *
+ // For compressed-block formats, ComponentSize is the block size and NumComponents is 1.
+ // For non-compressed formats, BlockWidth is 1.
+ (CopyAttribs.DstX / DstFmtAttribs.BlockWidth) * DstFmtAttribs.ComponentSize * DstFmtAttribs.NumComponents;
CopyTextureToBuffer(
*pSrcTexVk,
@@ -1763,10 +1768,12 @@ namespace Diligent
auto MipLevelAttribs = GetMipLevelProperties(TexDesc, MipLevel);
// address of (x,y,z) = region->bufferOffset + (((z * imageHeight) + y) * rowLength + x) * texelBlockSize; (18.4.1)
auto MapStartOffset = SubresourceOffset +
- (pMapRegion->MinZ * MipLevelAttribs.Height + pMapRegion->MinY) * MipLevelAttribs.RowSize +
- (FmtAttribs.ComponentType != COMPONENT_TYPE_COMPRESSED ?
- pMapRegion->MinX * FmtAttribs.ComponentSize * FmtAttribs.NumComponents :
- pMapRegion->MinX / FmtAttribs.BlockWidth * FmtAttribs.ComponentSize);
+ // For compressed-block formats, RowSize is the size of one compressed row.
+ // For non-compressed formats, BlockHeight is 1.
+ (pMapRegion->MinZ * MipLevelAttribs.Height + pMapRegion->MinY) / FmtAttribs.BlockHeight * MipLevelAttribs.RowSize +
+ // For compressed-block formats, ComponentSize is the block size and NumComponents is 1.
+ // For non-compressed formats, BlockWidth is 1.
+ pMapRegion->MinX / FmtAttribs.BlockWidth * FmtAttribs.ComponentSize * FmtAttribs.NumComponents;
MappedData.pData = TextureVk.GetStagingDataCPUAddress() + MapStartOffset;
MappedData.Stride = MipLevelAttribs.RowSize;
@@ -1779,10 +1786,8 @@ namespace Diligent
// to make device writes visible to CPU reads
VERIFY_EXPR(pMapRegion->MaxZ >= 1 && pMapRegion->MaxY >= 1);
auto MapEndOffset = SubresourceOffset +
- ((pMapRegion->MaxZ-1) * MipLevelAttribs.Height + (pMapRegion->MaxY-1)) * MipLevelAttribs.RowSize +
- (FmtAttribs.ComponentType != COMPONENT_TYPE_COMPRESSED ?
- pMapRegion->MaxX * FmtAttribs.ComponentSize * FmtAttribs.NumComponents :
- pMapRegion->MaxX / FmtAttribs.BlockWidth * FmtAttribs.ComponentSize);
+ ((pMapRegion->MaxZ-1) * MipLevelAttribs.Height + (pMapRegion->MaxY-FmtAttribs.BlockHeight)) / FmtAttribs.BlockHeight * MipLevelAttribs.RowSize +
+ (pMapRegion->MaxX / FmtAttribs.BlockWidth) * FmtAttribs.ComponentSize * FmtAttribs.NumComponents;
TextureVk.InvalidateStagingRange(MapStartOffset, MapEndOffset - MapStartOffset);
}
else if (MapType == MAP_WRITE)
diff --git a/Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp
index 8739397f..c6f336ee 100644
--- a/Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp
@@ -45,9 +45,12 @@ MipLevelProperties GetMipLevelProperties(const TextureDesc& TexDesc, Uint32 MipL
if (FmtAttribs.ComponentType == COMPONENT_TYPE_COMPRESSED)
{
VERIFY_EXPR(FmtAttribs.BlockWidth > 1 && FmtAttribs.BlockHeight > 1);
- MipProps.Width = (MipProps.Width + FmtAttribs.BlockWidth -1) / FmtAttribs.BlockWidth;
- MipProps.Height = (MipProps.Height + FmtAttribs.BlockHeight-1) / FmtAttribs.BlockHeight;
- MipProps.RowSize = MipProps.Width * Uint32{FmtAttribs.ComponentSize}; // ComponentSize is the block size
+ VERIFY((FmtAttribs.BlockWidth & (FmtAttribs.BlockWidth-1)) == 0, "Compressed block widht is expected to be power of 2");
+ VERIFY((FmtAttribs.BlockHeight & (FmtAttribs.BlockHeight-1)) == 0, "Compressed block widht is expected to be power of 2");
+ // For block-compression formats, all parameters are still specified in texels rather than compressed texel blocks (18.4.1)
+ MipProps.Width = Align(MipProps.Width, Uint32{FmtAttribs.BlockWidth});
+ MipProps.Height = Align(MipProps.Height,Uint32{FmtAttribs.BlockHeight});
+ MipProps.RowSize = MipProps.Width / Uint32{FmtAttribs.BlockWidth} * Uint32{FmtAttribs.ComponentSize}; // ComponentSize is the block size
}
else
{
@@ -274,7 +277,8 @@ TextureVkImpl :: TextureVkImpl(IReferenceCounters* pRefCounters,
CopyRegion.imageSubresource.layerCount = 1;
VERIFY(SubResData.Stride == 0 || SubResData.Stride >= MipInfo.RowSize, "Stride is too small");
- VERIFY(SubResData.DepthStride == 0 || SubResData.DepthStride >= MipInfo.RowSize * MipInfo.Height, "Depth stride is too small");
+ // For compressed-block formats, MipInfo.RowSize is the size of one row of blocks
+ VERIFY(SubResData.DepthStride == 0 || SubResData.DepthStride >= (MipInfo.Height / FmtAttribs.BlockHeight) * MipInfo.RowSize, "Depth stride is too small");
// bufferOffset must be a multiple of 4 (18.4)
// If the calling command's VkImage parameter is a compressed image, bufferOffset
@@ -330,14 +334,16 @@ TextureVkImpl :: TextureVkImpl(IReferenceCounters* pRefCounters,
VERIFY_EXPR(MipInfo.Depth == CopyRegion.imageExtent.depth);
VERIFY(SubResData.Stride == 0 || SubResData.Stride >= MipInfo.RowSize, "Stride is too small");
- VERIFY(SubResData.DepthStride == 0 || SubResData.DepthStride >= MipInfo.RowSize * MipInfo.Height, "Depth stride is too small");
+ // For compressed-block formats, MipInfo.RowSize is the size of one row of blocks
+ VERIFY(SubResData.DepthStride == 0 || SubResData.DepthStride >= (MipInfo.Height / FmtAttribs.BlockHeight) * MipInfo.RowSize, "Depth stride is too small");
for(Uint32 z=0; z < MipInfo.Depth; ++z)
{
- for(Uint32 y=0; y < MipInfo.Height; ++y)
+ for(Uint32 y=0; y < MipInfo.Height; y += FmtAttribs.BlockHeight)
{
- memcpy(StagingData + CopyRegion.bufferOffset + (y + z * MipInfo.Height) * MipInfo.RowSize,
- reinterpret_cast<const uint8_t*>(SubResData.pData) + y * SubResData.Stride + z * SubResData.DepthStride,
+ memcpy(StagingData + CopyRegion.bufferOffset + ((y + z * MipInfo.Height) / FmtAttribs.BlockHeight) * MipInfo.RowSize,
+ // SubResData.Stride must be the stride of one row of compressed blocks
+ reinterpret_cast<const uint8_t*>(SubResData.pData) + (y/FmtAttribs.BlockHeight) * SubResData.Stride + z * SubResData.DepthStride,
MipInfo.RowSize);
}
}