summaryrefslogtreecommitdiffstats
path: root/Graphics
diff options
context:
space:
mode:
authorassiduous <assiduous@diligentgraphics.com>2020-10-01 01:24:40 +0000
committerassiduous <assiduous@diligentgraphics.com>2020-10-01 01:24:40 +0000
commitd8fa7f9dc4304973265461c076883053d87e52dd (patch)
tree455c568dccc24f65d7bda2303a74b53519116bea /Graphics
parentA number of updates to support Metal backend (diff)
downloadDiligentCore-d8fa7f9dc4304973265461c076883053d87e52dd.tar.gz
DiligentCore-d8fa7f9dc4304973265461c076883053d87e52dd.zip
Unified staging buffer offset processing in Vulkan and GL
Diffstat (limited to 'Graphics')
-rw-r--r--Graphics/GraphicsAccessories/interface/GraphicsAccessories.hpp62
-rw-r--r--Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp39
-rw-r--r--Graphics/GraphicsEngineOpenGL/include/TextureBaseGL.hpp2
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp36
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/TextureBaseGL.cpp34
-rw-r--r--Graphics/GraphicsEngineVulkan/include/TextureVkImpl.hpp7
-rw-r--r--Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp47
-rw-r--r--Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp2
8 files changed, 133 insertions, 96 deletions
diff --git a/Graphics/GraphicsAccessories/interface/GraphicsAccessories.hpp b/Graphics/GraphicsAccessories/interface/GraphicsAccessories.hpp
index 47ded2c1..08544b0e 100644
--- a/Graphics/GraphicsAccessories/interface/GraphicsAccessories.hpp
+++ b/Graphics/GraphicsAccessories/interface/GraphicsAccessories.hpp
@@ -458,7 +458,7 @@ static_assert(SHADER_TYPE_AMPLIFICATION == (1 << ASInd), "ASInd is not consisten
static_assert(SHADER_TYPE_MESH == (1 << MSInd), "MSInd is not consistent with SHADER_TYPE_MESH");
static_assert(SHADER_TYPE_LAST == (1 << LastShaderInd), "LastShaderInd is not consistent with SHADER_TYPE_LAST");
-// clang-format off
+// clang-format on
inline SHADER_TYPE GetShaderTypeFromIndex(Int32 Index)
{
@@ -471,9 +471,61 @@ bool IsConsistentShaderType(SHADER_TYPE ShaderType, PIPELINE_TYPE Pipelin
Int32 GetShaderTypePipelineIndex(SHADER_TYPE ShaderType, PIPELINE_TYPE PipelineType);
SHADER_TYPE GetShaderTypeFromPipelineIndex(Int32 Index, PIPELINE_TYPE PipelineType);
-Uint32 GetStagingTextureSubresOffset(const TextureDesc& TexDesc,
- Uint32 ArraySlice,
- Uint32 MipLevel,
- Uint32 Alignment);
+/// Returns an offset from the beginning of the buffer backing a staging texture
+/// to the specified location within the given subresource.
+///
+/// \param [in] TexDesc - Staging texture description.
+/// \param [in] ArraySlice - Array slice.
+/// \param [in] MipLevel - Mip level.
+/// \param [in] Alignment - Subresource alignment. The alignment is applied
+/// to whole subresources only, but not to the row/depth strides.
+/// In other words, there may be padding between subresources, but
+/// texels in every subresource are assumed to be tightly packed.
+/// \param [in] LocationX - X location within the subresoure.
+/// \param [in] LocationY - Y location within the subresoure.
+/// \param [in] LocationZ - Z location within the subresoure.
+///
+/// \return Offset from the beginning of the buffer to the given location.
+///
+/// \remarks Alignment is applied to the subresource sizes, such that the beginning of data
+/// of every subresource starts at an offset aligned by 'Alignment'. The alignment
+/// is not applied to the row/depth strides and texels in all subresources are assumed
+/// to be tightly packed.
+///
+/// Subres 0
+/// stride
+/// |<-------------->|
+/// |________________| Subres 1
+/// | | stride
+/// | | |<------->|
+// | | |_________|
+/// | Subres 0 | | |
+/// | | | Subres 1|
+/// | | | | _
+/// |________________| |_________| ... |_|
+/// A A A
+/// | | |
+/// Buffer start Subres 1 offset, Subres N offset,
+/// aligned by 'Alignment' aligned by 'Alignment'
+///
+Uint32 GetStagingTextureLocationOffset(const TextureDesc& TexDesc,
+ Uint32 ArraySlice,
+ Uint32 MipLevel,
+ Uint32 Alignment,
+ Uint32 LocationX,
+ Uint32 LocationY,
+ Uint32 LocationZ);
+
+/// Returns an offset from the beginning of the buffer backing a staging texture
+/// to the given subresource.
+/// Texels within subresources are assumed to be tightly packed. There is no padding
+/// except between whole subresources.
+inline Uint32 GetStagingTextureSubresourceOffset(const TextureDesc& TexDesc,
+ Uint32 ArraySlice,
+ Uint32 MipLevel,
+ Uint32 Alignment)
+{
+ return GetStagingTextureLocationOffset(TexDesc, ArraySlice, MipLevel, Alignment, 0, 0, 0);
+}
} // namespace Diligent
diff --git a/Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp b/Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp
index 193a4989..780562df 100644
--- a/Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp
+++ b/Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp
@@ -1396,10 +1396,13 @@ SHADER_TYPE GetShaderTypeFromPipelineIndex(Int32 Index, PIPELINE_TYPE PipelineTy
}
-Uint32 GetStagingTextureSubresOffset(const TextureDesc& TexDesc,
- Uint32 ArraySlice,
- Uint32 MipLevel,
- Uint32 Alignment)
+Uint32 GetStagingTextureLocationOffset(const TextureDesc& TexDesc,
+ Uint32 ArraySlice,
+ Uint32 MipLevel,
+ Uint32 Alignment,
+ Uint32 LocationX,
+ Uint32 LocationY,
+ Uint32 LocationZ)
{
VERIFY_EXPR(ArraySlice < TexDesc.ArraySize && MipLevel < TexDesc.MipLevels || ArraySlice == TexDesc.ArraySize && MipLevel == 0);
@@ -1427,6 +1430,34 @@ Uint32 GetStagingTextureSubresOffset(const TextureDesc& TexDesc,
Offset += Align(MipInfo.MipSize, Alignment);
}
+ if (ArraySlice == TexDesc.ArraySize)
+ {
+ VERIFY(LocationX == 0 && LocationY == 0 && LocationZ == 0,
+ "Staging buffer size is requested: location must be (0,0,0).");
+ }
+ else if (LocationX != 0 || LocationY != 0 || LocationZ != 0)
+ {
+ const auto& MipLevelAttribs = GetMipLevelProperties(TexDesc, MipLevel);
+ const auto& FmtAttribs = GetTextureFormatAttribs(TexDesc.Format);
+ VERIFY(LocationX < MipLevelAttribs.LogicalWidth && LocationY < MipLevelAttribs.LogicalHeight && LocationZ < MipLevelAttribs.Depth,
+ "Specified location is out of bounds");
+ if (FmtAttribs.ComponentType == COMPONENT_TYPE_COMPRESSED)
+ {
+ VERIFY((LocationX % FmtAttribs.BlockWidth) == 0 && (LocationY % FmtAttribs.BlockHeight) == 0,
+ "For compressed texture formats, location must be a multiple of compressed block size.");
+ }
+
+ // For compressed-block formats, RowSize is the size of one compressed row.
+ // For non-compressed formats, BlockHeight is 1.
+ Offset += (LocationZ * MipLevelAttribs.StorageHeight + LocationY) / FmtAttribs.BlockHeight * MipLevelAttribs.RowSize;
+
+ // For non-compressed formats, BlockWidth is 1.
+ Offset += (LocationX / FmtAttribs.BlockWidth) * FmtAttribs.GetElementSize();
+
+ // Note: this addressing complies with how Vulkan addresses textures when copying data to/from buffer:
+ // address of (x,y,z) = bufferOffset + (((z * imageHeight) + y) * rowLength + x) * texelBlockSize; (18.4.1)
+ }
+
return Offset;
}
diff --git a/Graphics/GraphicsEngineOpenGL/include/TextureBaseGL.hpp b/Graphics/GraphicsEngineOpenGL/include/TextureBaseGL.hpp
index 81dc8fc0..b5b0517d 100644
--- a/Graphics/GraphicsEngineOpenGL/include/TextureBaseGL.hpp
+++ b/Graphics/GraphicsEngineOpenGL/include/TextureBaseGL.hpp
@@ -114,7 +114,7 @@ public:
const Box& DstBox,
const TextureSubResData& SubresData) = 0;
- static Uint32 GetPBODataOffset(const TextureDesc& TexDesc, Uint32 ArraySlice, Uint32 MipLevel);
+ static constexpr Uint32 PBOOffsetAlignment = 4;
IBuffer* GetPBO()
{
diff --git a/Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp
index d1ef575e..f4ef1136 100644
--- a/Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp
+++ b/Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp
@@ -1500,20 +1500,15 @@ void DeviceContextGLImpl::CopyTexture(const CopyTextureAttribs& CopyAttribs)
if (SrcTexDesc.Usage == USAGE_STAGING && DstTexDesc.Usage != USAGE_STAGING)
{
TextureSubResData SubresData;
- SubresData.pData = nullptr;
- SubresData.pSrcBuffer = pSrcTexGL->GetPBO();
- SubresData.SrcOffset = TextureBaseGL::GetPBODataOffset(SrcTexDesc, CopyAttribs.SrcSlice, CopyAttribs.SrcMipLevel);
+ SubresData.pData = nullptr;
+ SubresData.pSrcBuffer = pSrcTexGL->GetPBO();
+ SubresData.SrcOffset =
+ GetStagingTextureLocationOffset(SrcTexDesc, CopyAttribs.SrcSlice, CopyAttribs.SrcMipLevel,
+ TextureBaseGL::PBOOffsetAlignment,
+ pSrcBox->MinX, pSrcBox->MinY, pSrcBox->MinZ);
SubresData.Stride = SrcMipLevelAttribs.RowSize;
SubresData.DepthStride = SrcMipLevelAttribs.DepthSliceSize;
- const auto& SrcFmtAttribs = GetTextureFormatAttribs(SrcTexDesc.Format);
- SubresData.SrcOffset +=
- // For compressed-block formats, RowSize is the size of one compressed row.
- // For non-compressed formats, BlockHeight is 1.
- (pSrcBox->MinZ * SrcMipLevelAttribs.StorageHeight + pSrcBox->MinY) / SrcFmtAttribs.BlockHeight * SrcMipLevelAttribs.RowSize +
- // For non-compressed formats, BlockWidth is 1.
- (pSrcBox->MinX / SrcFmtAttribs.BlockWidth) * SrcFmtAttribs.GetElementSize();
-
Box DstBox;
DstBox.MinX = CopyAttribs.DstX;
DstBox.MinY = CopyAttribs.DstY;
@@ -1561,17 +1556,12 @@ void DeviceContextGLImpl::CopyTexture(const CopyTextureAttribs& CopyAttribs)
auto* pDstBuffer = ValidatedCast<BufferGLImpl>(pDstTexGL->GetPBO());
VERIFY(pDstBuffer != nullptr, "Internal staging buffer must not be null");
- auto DstOffset = TextureBaseGL::GetPBODataOffset(DstTexDesc, CopyAttribs.DstSlice, CopyAttribs.DstMipLevel);
-
- auto DstMipLevelAttribs = GetMipLevelProperties(DstTexDesc, CopyAttribs.DstMipLevel);
-
- const auto& DstFmtAttribs = GetTextureFormatAttribs(DstTexDesc.Format);
- DstOffset +=
- // For compressed-block formats, RowSize is the size of one compressed row.
- // For non-compressed formats, BlockHeight is 1.
- (CopyAttribs.DstZ * DstMipLevelAttribs.StorageHeight + CopyAttribs.DstY) / DstFmtAttribs.BlockHeight * DstMipLevelAttribs.RowSize +
- // For non-compressed formats, BlockWidth is 1.
- (CopyAttribs.DstX / DstFmtAttribs.BlockWidth) * DstFmtAttribs.GetElementSize();
+ // GetStagingTextureLocationOffset assumes pixels are tightly packed in every subresource - no padding
+ // except between subresources.
+ const auto DstOffset =
+ GetStagingTextureLocationOffset(DstTexDesc, CopyAttribs.DstSlice, CopyAttribs.DstMipLevel,
+ TextureBaseGL::PBOOffsetAlignment,
+ CopyAttribs.DstX, CopyAttribs.DstY, CopyAttribs.DstZ);
m_ContextState.BindBuffer(GL_PIXEL_PACK_BUFFER, pDstBuffer->GetGLHandle(), true);
@@ -1606,7 +1596,7 @@ void DeviceContextGLImpl::MapTextureSubresource(ITexture* pTextu
const auto& TexDesc = pTexGL->GetDesc();
if (TexDesc.Usage == USAGE_STAGING)
{
- auto PBOOffset = TextureBaseGL::GetPBODataOffset(TexDesc, ArraySlice, MipLevel);
+ auto PBOOffset = GetStagingTextureSubresourceOffset(TexDesc, ArraySlice, MipLevel, TextureBaseGL::PBOOffsetAlignment);
auto MipLevelAttribs = GetMipLevelProperties(TexDesc, MipLevel);
auto pPBO = ValidatedCast<BufferGLImpl>(pTexGL->GetPBO());
pPBO->MapRange(m_ContextState, MapType, MapFlags, PBOOffset, MipLevelAttribs.MipSize, MappedData.pData);
diff --git a/Graphics/GraphicsEngineOpenGL/src/TextureBaseGL.cpp b/Graphics/GraphicsEngineOpenGL/src/TextureBaseGL.cpp
index af63e560..564d16cb 100644
--- a/Graphics/GraphicsEngineOpenGL/src/TextureBaseGL.cpp
+++ b/Graphics/GraphicsEngineOpenGL/src/TextureBaseGL.cpp
@@ -40,38 +40,6 @@
namespace Diligent
{
-
-Uint32 TextureBaseGL::GetPBODataOffset(const TextureDesc& TexDesc, Uint32 ArraySlice, Uint32 MipLevel)
-{
- VERIFY_EXPR(ArraySlice < TexDesc.ArraySize && MipLevel < TexDesc.MipLevels || ArraySlice == TexDesc.ArraySize && MipLevel == 0);
-
- Uint32 Offset = 0;
- if (ArraySlice > 0)
- {
- Uint32 ArraySliceSize = 0;
- for (Uint32 mip = 0; mip < TexDesc.MipLevels; ++mip)
- {
- auto MipInfo = GetMipLevelProperties(TexDesc, mip);
- ArraySliceSize += Align(MipInfo.MipSize, Uint32{4});
- }
-
- Offset = ArraySliceSize;
- if (TexDesc.Type == RESOURCE_DIM_TEX_1D_ARRAY ||
- TexDesc.Type == RESOURCE_DIM_TEX_2D_ARRAY ||
- TexDesc.Type == RESOURCE_DIM_TEX_CUBE ||
- TexDesc.Type == RESOURCE_DIM_TEX_CUBE_ARRAY)
- Offset *= ArraySlice;
- }
-
- for (Uint32 mip = 0; mip < MipLevel; ++mip)
- {
- auto MipInfo = GetMipLevelProperties(TexDesc, mip);
- Offset += Align(MipInfo.MipSize, Uint32{4});
- }
-
- return Offset;
-}
-
TextureBaseGL::TextureBaseGL(IReferenceCounters* pRefCounters,
FixedBlockMemoryAllocator& TexViewObjAllocator,
RenderDeviceGLImpl* pDeviceGL,
@@ -106,7 +74,7 @@ TextureBaseGL::TextureBaseGL(IReferenceCounters* pRefCounters,
StagingBuffName += '\'';
StagingBufferDesc.Name = StagingBuffName.c_str();
- StagingBufferDesc.uiSizeInBytes = GetPBODataOffset(m_Desc, m_Desc.ArraySize, 0);
+ StagingBufferDesc.uiSizeInBytes = GetStagingTextureSubresourceOffset(m_Desc, m_Desc.ArraySize, 0, PBOOffsetAlignment);
StagingBufferDesc.Usage = USAGE_STAGING;
StagingBufferDesc.CPUAccessFlags = TexDesc.CPUAccessFlags;
diff --git a/Graphics/GraphicsEngineVulkan/include/TextureVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/TextureVkImpl.hpp
index b04babec..7ca629ad 100644
--- a/Graphics/GraphicsEngineVulkan/include/TextureVkImpl.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/TextureVkImpl.hpp
@@ -99,11 +99,8 @@ public:
void InvalidateStagingRange(VkDeviceSize Offset, VkDeviceSize Size);
- // bufferOffset must be a multiple of 4 (18.4)
- // If the calling command's VkImage parameter is a compressed image, bufferOffset
- // must be a multiple of the compressed texel block size in bytes (18.4). This
- // is automatically guaranteed as MipWidth and MipHeight are rounded to block size.
- static constexpr Uint32 StagingDataAlignment = 4;
+ // Buffer offset must be a multiple of 4 (18.4)
+ static constexpr Uint32 StagingBufferOffsetAlignment = 4;
protected:
void CreateViewInternal(const struct TextureViewDesc& ViewDesc, ITextureView** ppView, bool bIsDefaultView) override;
diff --git a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp
index f14e7f9c..2d7b9591 100644
--- a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp
@@ -1590,8 +1590,7 @@ void DeviceContextVkImpl::CopyTexture(const CopyTextureAttribs& CopyAttribs)
FullMipBox.MaxZ = MipLevelAttribs.Depth;
pSrcBox = &FullMipBox;
}
- const auto& DstFmtAttribs = GetTextureFormatAttribs(DstTexDesc.Format);
- const auto& SrcFmtAttribs = GetTextureFormatAttribs(SrcTexDesc.Format);
+
if (SrcTexDesc.Usage != USAGE_STAGING && DstTexDesc.Usage != USAGE_STAGING)
{
VkImageCopy CopyRegion = {};
@@ -1603,6 +1602,8 @@ void DeviceContextVkImpl::CopyTexture(const CopyTextureAttribs& CopyAttribs)
CopyRegion.extent.height = std::max(pSrcBox->MaxY - pSrcBox->MinY, 1u);
CopyRegion.extent.depth = std::max(pSrcBox->MaxZ - pSrcBox->MinZ, 1u);
+ const auto& DstFmtAttribs = GetTextureFormatAttribs(DstTexDesc.Format);
+
VkImageAspectFlags aspectMask = 0;
if (DstFmtAttribs.ComponentType == COMPONENT_TYPE_DEPTH)
aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
@@ -1634,15 +1635,18 @@ void DeviceContextVkImpl::CopyTexture(const CopyTextureAttribs& CopyAttribs)
DEV_CHECK_ERR((SrcTexDesc.CPUAccessFlags & CPU_ACCESS_WRITE), "Attempting to copy from staging texture that was not created with CPU_ACCESS_WRITE flag");
DEV_CHECK_ERR(pSrcTexVk->GetState() == RESOURCE_STATE_COPY_SOURCE, "Source staging texture must permanently be in RESOURCE_STATE_COPY_SOURCE state");
- auto SrcBufferOffset = GetStagingTextureSubresOffset(SrcTexDesc, CopyAttribs.SrcSlice, CopyAttribs.SrcMipLevel, TextureVkImpl::StagingDataAlignment);
- auto SrcMipLevelAttribs = GetMipLevelProperties(SrcTexDesc, CopyAttribs.SrcMipLevel);
// address of (x,y,z) = region->bufferOffset + (((z * imageHeight) + y) * rowLength + x) * texelBlockSize; (18.4.1)
- SrcBufferOffset +=
- // For compressed-block formats, RowSize is the size of one compressed row.
- // For non-compressed formats, BlockHeight is 1.
- (pSrcBox->MinZ * SrcMipLevelAttribs.StorageHeight + pSrcBox->MinY) / SrcFmtAttribs.BlockHeight * SrcMipLevelAttribs.RowSize +
- // For non-compressed formats, BlockWidth is 1.
- (pSrcBox->MinX / SrcFmtAttribs.BlockWidth) * SrcFmtAttribs.GetElementSize();
+
+ // bufferOffset must be a multiple of 4 (18.4)
+ // If the calling command's VkImage parameter is a compressed image, bufferOffset
+ // must be a multiple of the compressed texel block size in bytes (18.4). This
+ // is automatically guaranteed as MipWidth and MipHeight are rounded to block size.
+
+ const auto SrcBufferOffset =
+ GetStagingTextureLocationOffset(SrcTexDesc, CopyAttribs.SrcSlice, CopyAttribs.SrcMipLevel,
+ TextureVkImpl::StagingBufferOffsetAlignment,
+ pSrcBox->MinX, pSrcBox->MinY, pSrcBox->MinZ);
+ const auto SrcMipLevelAttribs = GetMipLevelProperties(SrcTexDesc, CopyAttribs.SrcMipLevel);
Box DstBox;
DstBox.MinX = CopyAttribs.DstX;
@@ -1655,7 +1659,7 @@ void DeviceContextVkImpl::CopyTexture(const CopyTextureAttribs& CopyAttribs)
CopyBufferToTexture(
pSrcTexVk->GetVkStagingBuffer(),
SrcBufferOffset,
- SrcMipLevelAttribs.StorageWidth,
+ SrcMipLevelAttribs.StorageWidth, // GetStagingTextureLocationOffset assumes texels are tightly packed
*pDstTexVk,
DstBox,
CopyAttribs.DstMipLevel,
@@ -1667,17 +1671,12 @@ void DeviceContextVkImpl::CopyTexture(const CopyTextureAttribs& CopyAttribs)
DEV_CHECK_ERR((DstTexDesc.CPUAccessFlags & CPU_ACCESS_READ), "Attempting to copy to staging texture that was not created with CPU_ACCESS_READ flag");
DEV_CHECK_ERR(pDstTexVk->GetState() == RESOURCE_STATE_COPY_DEST, "Destination staging texture must permanently be in RESOURCE_STATE_COPY_DEST state");
- auto DstBufferOffset =
- GetStagingTextureSubresOffset(DstTexDesc, CopyAttribs.DstSlice, CopyAttribs.DstMipLevel,
- TextureVkImpl::StagingDataAlignment);
- const auto DstMipLevelAttribs = GetMipLevelProperties(DstTexDesc, CopyAttribs.DstMipLevel);
// address of (x,y,z) = region->bufferOffset + (((z * imageHeight) + y) * rowLength + x) * texelBlockSize; (18.4.1)
- DstBufferOffset +=
- // For compressed-block formats, RowSize is the size of one compressed row.
- // For non-compressed formats, BlockHeight is 1.
- (CopyAttribs.DstZ * DstMipLevelAttribs.StorageHeight + CopyAttribs.DstY) / DstFmtAttribs.BlockHeight * DstMipLevelAttribs.RowSize *
- // For non-compressed formats, BlockWidth is 1.
- (CopyAttribs.DstX / DstFmtAttribs.BlockWidth) * DstFmtAttribs.GetElementSize();
+ const auto DstBufferOffset =
+ GetStagingTextureLocationOffset(DstTexDesc, CopyAttribs.DstSlice, CopyAttribs.DstMipLevel,
+ TextureVkImpl::StagingBufferOffsetAlignment,
+ CopyAttribs.DstX, CopyAttribs.DstY, CopyAttribs.DstZ);
+ const auto DstMipLevelAttribs = GetMipLevelProperties(DstTexDesc, CopyAttribs.DstMipLevel);
CopyTextureToBuffer(
*pSrcTexVk,
@@ -1687,7 +1686,8 @@ void DeviceContextVkImpl::CopyTexture(const CopyTextureAttribs& CopyAttribs)
CopyAttribs.SrcTextureTransitionMode,
pDstTexVk->GetVkStagingBuffer(),
DstBufferOffset,
- DstMipLevelAttribs.StorageWidth);
+ DstMipLevelAttribs.StorageWidth // GetStagingTextureLocationOffset assumes texels are tightly packed
+ );
}
else
{
@@ -2010,8 +2010,7 @@ void DeviceContextVkImpl::MapTextureSubresource(ITexture* pTextu
else if (TexDesc.Usage == USAGE_STAGING)
{
auto SubresourceOffset =
- GetStagingTextureSubresOffset(TexDesc, ArraySlice, MipLevel,
- TextureVkImpl::StagingDataAlignment);
+ GetStagingTextureSubresourceOffset(TexDesc, ArraySlice, MipLevel, TextureVkImpl::StagingBufferOffsetAlignment);
const auto MipLevelAttribs = GetMipLevelProperties(TexDesc, MipLevel);
// address of (x,y,z) = region->bufferOffset + (((z * imageHeight) + y) * rowLength + x) * texelBlockSize; (18.4.1)
auto MapStartOffset = SubresourceOffset +
diff --git a/Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp
index 8a37df0c..313de089 100644
--- a/Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp
@@ -408,7 +408,7 @@ TextureVkImpl::TextureVkImpl(IReferenceCounters* pRefCounters,
VkStagingBuffCI.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
VkStagingBuffCI.pNext = nullptr;
VkStagingBuffCI.flags = 0;
- VkStagingBuffCI.size = GetStagingTextureSubresOffset(m_Desc, m_Desc.ArraySize, 0, StagingDataAlignment);
+ VkStagingBuffCI.size = GetStagingTextureSubresourceOffset(m_Desc, m_Desc.ArraySize, 0, StagingBufferOffsetAlignment);
// clang-format off
DEV_CHECK_ERR((m_Desc.CPUAccessFlags & (CPU_ACCESS_READ | CPU_ACCESS_WRITE)) == CPU_ACCESS_READ ||