Fixed transcoded texture update using wrong decode/copy pitch with explicit source pitch. (#3747)

This commit is contained in:
Branimir Karadžić
2026-06-08 23:02:33 -07:00
committed by GitHub
parent 24c37e6eca
commit 1dac10c2ad
4 changed files with 50 additions and 44 deletions
+17 -14
View File
@@ -4807,24 +4807,27 @@ namespace bgfx { namespace d3d11
const uint16_t bpp = blockInfo.bitsPerPixel;
const uint32_t subres = _mip + ( (layer + _side) * m_numMips);
const bool depth = bimg::isDepth(bimg::TextureFormat::Enum(m_textureFormat) );
uint32_t rectpitch = _rect.m_width*bpp/8;
uint32_t rectPitch = _rect.m_width*bpp/8;
if (bimg::isCompressed(bimg::TextureFormat::Enum(m_textureFormat) ) )
{
rectpitch = (_rect.m_width / blockInfo.blockWidth)*blockInfo.blockSize;
rectPitch = (_rect.m_width / blockInfo.blockWidth)*blockInfo.blockSize;
}
const uint32_t srcpitch = UINT16_MAX == _pitch ? rectpitch : _pitch;
const uint32_t slicepitch = rectpitch*_rect.m_height;
const uint32_t srcPitch = UINT16_MAX == _pitch ? rectPitch : _pitch;
const uint32_t slicePitch = rectPitch*_rect.m_height;
const bool convert = m_textureFormat != m_requestedFormat;
uint32_t copyPitch = srcPitch;
uint8_t* data = _mem->data;
uint8_t* temp = NULL;
if (convert)
{
temp = (uint8_t*)bx::alloc(g_allocator, slicepitch);
bimg::imageDecodeToBgra8(g_allocator, temp, data, _rect.m_width, _rect.m_height, srcpitch, bimg::TextureFormat::Enum(m_requestedFormat) );
copyPitch = rectPitch;
temp = (uint8_t*)bx::alloc(g_allocator, slicePitch);
bimg::imageDecodeToBgra8(g_allocator, temp, data, _rect.m_width, _rect.m_height, copyPitch, bimg::TextureFormat::Enum(m_requestedFormat) );
data = temp;
box.right = bx::clamp<uint32_t>(box.right, box.left, bx::max(1u, m_width >> _mip) );
@@ -4835,20 +4838,20 @@ namespace bgfx { namespace d3d11
switch (m_textureFormat)
{
case TextureFormat::R5G6B5:
temp = (uint8_t*)bx::alloc(g_allocator, slicepitch);
bimg::imageConvert(temp, 16, bx::packB5G6R5, data, bx::unpackR5G6B5, slicepitch);
temp = (uint8_t*)bx::alloc(g_allocator, slicePitch);
bimg::imageConvert(temp, 16, bx::packB5G6R5, data, bx::unpackR5G6B5, slicePitch);
data = temp;
break;
case TextureFormat::RGBA4:
temp = (uint8_t*)bx::alloc(g_allocator, slicepitch);
bimg::imageConvert(temp, 16, bx::packBgra4, data, bx::unpackRgba4, slicepitch);
temp = (uint8_t*)bx::alloc(g_allocator, slicePitch);
bimg::imageConvert(temp, 16, bx::packBgra4, data, bx::unpackRgba4, slicePitch);
data = temp;
break;
case TextureFormat::RGB5A1:
temp = (uint8_t*)bx::alloc(g_allocator, slicepitch);
bimg::imageConvert(temp, 16, bx::packBgr5a1, data, bx::unpackRgb5a1, slicepitch);
temp = (uint8_t*)bx::alloc(g_allocator, slicePitch);
bimg::imageConvert(temp, 16, bx::packBgr5a1, data, bx::unpackRgb5a1, slicePitch);
data = temp;
break;
@@ -4862,8 +4865,8 @@ namespace bgfx { namespace d3d11
, subres
, depth ? NULL : &box
, data
, srcpitch
, TextureD3D11::Texture3D == m_type ? slicepitch : 0
, copyPitch
, TextureD3D11::Texture3D == m_type ? slicePitch : 0
);
if (NULL != temp)
+10 -7
View File
@@ -6004,15 +6004,15 @@ namespace bgfx { namespace d3d12
D3D12_RESOURCE_STATES state = setState(_commandList, D3D12_RESOURCE_STATE_COPY_DEST);
const uint32_t bpp = bimg::getBitsPerPixel(bimg::TextureFormat::Enum(m_textureFormat) );
uint32_t rectpitch = _rect.m_width*bpp/8;
uint32_t rectPitch = _rect.m_width*bpp/8;
if (bimg::isCompressed(bimg::TextureFormat::Enum(m_textureFormat) ) )
{
const bimg::ImageBlockInfo& blockInfo = bimg::getBlockInfo(bimg::TextureFormat::Enum(m_textureFormat) );
rectpitch = (_rect.m_width / blockInfo.blockWidth) * blockInfo.blockSize;
rectPitch = (_rect.m_width / blockInfo.blockWidth) * blockInfo.blockSize;
}
const uint32_t srcpitch = UINT16_MAX == _pitch ? rectpitch : _pitch;
const uint32_t slicepitch = rectpitch*_rect.m_height;
const uint32_t srcPitch = UINT16_MAX == _pitch ? rectPitch : _pitch;
const uint32_t slicePitch = rectPitch*_rect.m_height;
const bool convert = m_textureFormat != m_requestedFormat;
@@ -6038,13 +6038,16 @@ namespace bgfx { namespace d3d12
const uint32_t subres = _mip + ((layer + _side) * m_numMips);
uint32_t copyPitch = srcPitch;
uint8_t* srcData = _mem->data;
uint8_t* temp = NULL;
if (convert)
{
temp = (uint8_t*)bx::alloc(g_allocator, slicepitch);
bimg::imageDecodeToBgra8(g_allocator, temp, srcData, _rect.m_width, _rect.m_height, srcpitch, bimg::TextureFormat::Enum(m_requestedFormat) );
copyPitch = rectPitch;
temp = (uint8_t*)bx::alloc(g_allocator, slicePitch);
bimg::imageDecodeToBgra8(g_allocator, temp, srcData, _rect.m_width, _rect.m_height, copyPitch, bimg::TextureFormat::Enum(m_requestedFormat) );
srcData = temp;
box.right = bx::clamp<uint32_t>(box.right, box.left, bx::max(1u, m_width >> _mip) - _rect.m_x);
@@ -6077,7 +6080,7 @@ namespace bgfx { namespace d3d12
D3D12_RANGE readRange = { 0, 0 };
DX_CHECK(staging->Map(0, &readRange, (void**)&dstData) );
bx::memCopy(dstData, rowPitch, srcData, srcpitch, rectpitch, numRows);
bx::memCopy(dstData, rowPitch, srcData, copyPitch, rectPitch, numRows);
if (NULL != temp)
{
+12 -12
View File
@@ -6099,8 +6099,8 @@ namespace bgfx { namespace gl
const bool compressed = bimg::isCompressed(bimg::TextureFormat::Enum(m_requestedFormat) );
const uint32_t bpp = bimg::getBitsPerPixel(bimg::TextureFormat::Enum(m_textureFormat) );
uint32_t rectpitch = _rect.m_width*bpp/8;
uint32_t srcpitch = UINT16_MAX == _pitch ? rectpitch : _pitch;
uint32_t rectPitch = _rect.m_width*bpp/8;
uint32_t srcPitch = UINT16_MAX == _pitch ? rectPitch : _pitch;
GL_CHECK(glBindTexture(m_target, m_id) );
GL_CHECK(glPixelStorei(GL_UNPACK_ALIGNMENT, 1) );
@@ -6136,21 +6136,21 @@ namespace bgfx { namespace gl
&& !convert)
{
const uint32_t numBlocksX = (width + blockInfo.blockWidth - 1) / blockInfo.blockWidth;
rectpitch = numBlocksX * blockInfo.blockSize;
srcpitch = UINT16_MAX == _pitch ? rectpitch : _pitch;
rectPitch = numBlocksX * blockInfo.blockSize;
srcPitch = UINT16_MAX == _pitch ? rectPitch : _pitch;
}
uint8_t* temp = NULL;
if (convert
|| !unpackRowLength
|| (compressed && UINT16_MAX != _pitch && srcpitch != rectpitch) )
|| (compressed && UINT16_MAX != _pitch && srcPitch != rectPitch) )
{
temp = (uint8_t*)bx::alloc(g_allocator, rectpitch*height);
temp = (uint8_t*)bx::alloc(g_allocator, rectPitch*height);
}
else if (unpackRowLength
&& !compressed)
{
GL_CHECK(glPixelStorei(GL_UNPACK_ROW_LENGTH, srcpitch*8/bpp) );
GL_CHECK(glPixelStorei(GL_UNPACK_ROW_LENGTH, srcPitch*8/bpp) );
}
if (compressed
@@ -6162,7 +6162,7 @@ namespace bgfx { namespace gl
if (NULL != temp)
{
bimg::imageCopy(temp, numBlocksY, srcpitch, 1, data, rectpitch);
bimg::imageCopy(temp, numBlocksY, srcPitch, 1, data, rectPitch);
data = temp;
}
const GLenum internalFmt = (0 != (m_flags & BGFX_TEXTURE_SRGB) )
@@ -6178,7 +6178,7 @@ namespace bgfx { namespace gl
, rect.m_height
, _depth
, internalFmt
, rectpitch*numBlocksY
, rectPitch*numBlocksY
, data
) );
}
@@ -6188,16 +6188,16 @@ namespace bgfx { namespace gl
if (convert)
{
bimg::imageDecodeToRgba8(g_allocator, temp, data, width, height, srcpitch, bimg::TextureFormat::Enum(m_requestedFormat) );
bimg::imageDecodeToRgba8(g_allocator, temp, data, width, height, rectPitch, bimg::TextureFormat::Enum(m_requestedFormat) );
data = temp;
srcpitch = rectpitch;
srcPitch = rectPitch;
}
if (BX_IGNORE_C4127(true
&& !unpackRowLength
&& !convert) )
{
bimg::imageCopy(temp, width, height, 1, bpp, srcpitch, data);
bimg::imageCopy(temp, width, height, 1, bpp, srcPitch, data);
data = temp;
}
+11 -11
View File
@@ -6811,23 +6811,23 @@ VK_DESTROY
const bool compressed = bimg::isCompressed(bimg::TextureFormat::Enum(m_textureFormat) );
const bool convert = m_textureFormat != m_requestedFormat;
uint32_t rectpitch = _rect.m_width * bpp / 8;
uint32_t slicepitch = rectpitch * _rect.m_height;
uint32_t rectPitch = _rect.m_width * bpp / 8;
uint32_t slicePitch = rectPitch * _rect.m_height;
uint32_t numRows = _rect.m_height;
uint32_t align = blockInfo.blockSize;
if (compressed)
{
const uint32_t numBlocksX = (_rect.m_width + blockInfo.blockWidth - 1) / blockInfo.blockWidth;
const uint32_t numBlocksY = (_rect.m_height + blockInfo.blockHeight - 1) / blockInfo.blockHeight;
rectpitch = numBlocksX * blockInfo.blockSize;
slicepitch = numBlocksY * rectpitch;
rectPitch = numBlocksX * blockInfo.blockSize;
slicePitch = numBlocksY * rectPitch;
numRows = numBlocksY;
}
const uint32_t srcpitch = UINT16_MAX == _pitch ? rectpitch : _pitch;
const uint32_t srcPitch = UINT16_MAX == _pitch ? rectPitch : _pitch;
const uint32_t size = convert || UINT16_MAX == _pitch
? slicepitch * _depth
: numRows * srcpitch * _depth
? slicePitch * _depth
: numRows * srcPitch * _depth
;
// bufferRowLength is expressed in texels and, for block-compressed
@@ -6837,8 +6837,8 @@ VK_DESTROY
&& UINT16_MAX != _pitch)
{
bufferRowLength = compressed
? (srcpitch / blockInfo.blockSize) * blockInfo.blockWidth
: srcpitch * 8 / bpp
? (srcPitch / blockInfo.blockSize) * blockInfo.blockWidth
: srcPitch * 8 / bpp
;
}
@@ -6858,8 +6858,8 @@ VK_DESTROY
if (convert)
{
temp = (uint8_t*)bx::alloc(g_allocator, slicepitch);
bimg::imageDecodeToBgra8(g_allocator, temp, data, _rect.m_width, _rect.m_height, srcpitch, bimg::TextureFormat::Enum(m_requestedFormat) );
temp = (uint8_t*)bx::alloc(g_allocator, slicePitch);
bimg::imageDecodeToBgra8(g_allocator, temp, data, _rect.m_width, _rect.m_height, rectPitch, bimg::TextureFormat::Enum(m_requestedFormat) );
data = temp;
region.imageExtent.width = bx::clamp<uint32_t>(region.imageExtent.width, 0u, bx::max(1u, m_width >> _mip) - _rect.m_x);