diff --git a/examples/08-update/update.cpp b/examples/08-update/update.cpp index 7df60411a..cb1dd74e1 100644 --- a/examples/08-update/update.cpp +++ b/examples/08-update/update.cpp @@ -185,6 +185,15 @@ bgfx::TextureHandle loadTextureWithUpdate(const char* _filePath, uint64_t _flags width = bx::max(blockWidth, width); height = bx::max(blockHeight, height); + // Compute source row pitch and pass it to updateTexture2D to + // exercise the explicit-pitch upload path. + const uint32_t numBlocksX = (width + blockWidth - 1) / blockWidth; + + const uint32_t srcPitch = bimg::isCompressed(imageContainer->m_format) + ? numBlocksX * blockInfo.blockSize + : width * blockInfo.bitsPerPixel / 8 + ; + bimg::ImageMip mip; if (bimg::imageGetRawData(*imageContainer, 0, lod, imageContainer->m_data, imageContainer->m_size, mip)) @@ -201,6 +210,7 @@ bgfx::TextureHandle loadTextureWithUpdate(const char* _filePath, uint64_t _flags , uint16_t(width) , uint16_t(height) , bgfx::copy(mipData, mipDataSize) + , uint16_t(srcPitch) ); } diff --git a/src/renderer_gl.cpp b/src/renderer_gl.cpp index b182ceca1..d98bdf9d5 100644 --- a/src/renderer_gl.cpp +++ b/src/renderer_gl.cpp @@ -6003,8 +6003,11 @@ namespace bgfx { namespace gl void TextureGL::update(uint8_t _side, uint8_t _mip, const Rect& _rect, uint16_t _z, uint16_t _depth, uint16_t _pitch, const Memory* _mem) { + const bimg::ImageBlockInfo& blockInfo = bimg::getBlockInfo(bimg::TextureFormat::Enum(m_requestedFormat) ); + const bool compressed = bimg::isCompressed(bimg::TextureFormat::Enum(m_requestedFormat) ); const uint32_t bpp = bimg::getBitsPerPixel(bimg::TextureFormat::Enum(m_textureFormat) ); - const uint32_t rectpitch = _rect.m_width*bpp/8; + + uint32_t rectpitch = _rect.m_width*bpp/8; uint32_t srcpitch = UINT16_MAX == _pitch ? rectpitch : _pitch; GL_CHECK(glBindTexture(m_target, m_id) ); @@ -6021,7 +6024,6 @@ namespace bgfx { namespace gl && !s_renderGL->m_textureSwizzleSupport ; const bool unpackRowLength = !!BGFX_CONFIG_RENDERER_OPENGL || s_extension[Extension::EXT_unpack_subimage].m_supported; - const bool compressed = bimg::isCompressed(bimg::TextureFormat::Enum(m_requestedFormat) ); const bool convert = false || (compressed && m_textureFormat != m_requestedFormat) || swizzle @@ -6038,13 +6040,23 @@ namespace bgfx { namespace gl uint32_t width = rect.m_width; uint32_t height = rect.m_height; + if (compressed + && !convert) + { + const uint32_t numBlocksX = (width + blockInfo.blockWidth - 1) / blockInfo.blockWidth; + rectpitch = numBlocksX * blockInfo.blockSize; + srcpitch = UINT16_MAX == _pitch ? rectpitch : _pitch; + } + uint8_t* temp = NULL; if (convert - || !unpackRowLength) + || !unpackRowLength + || (compressed && UINT16_MAX != _pitch && srcpitch != rectpitch) ) { temp = (uint8_t*)bx::alloc(g_allocator, rectpitch*height); } - else if (unpackRowLength) + else if (unpackRowLength + && !compressed) { GL_CHECK(glPixelStorei(GL_UNPACK_ROW_LENGTH, srcpitch*8/bpp) ); } @@ -6054,9 +6066,11 @@ namespace bgfx { namespace gl { const uint8_t* data = _mem->data; - if (!unpackRowLength) + const uint32_t numBlocksY = (height + blockInfo.blockHeight - 1) / blockInfo.blockHeight; + + if (NULL != temp) { - bimg::imageCopy(temp, width, height, 1, bpp, srcpitch, data); + bimg::imageCopy(temp, numBlocksY, srcpitch, 1, data, rectpitch); data = temp; } const GLenum internalFmt = (0 != (m_flags & BGFX_TEXTURE_SRGB) ) @@ -6072,7 +6086,7 @@ namespace bgfx { namespace gl , rect.m_height , _depth , internalFmt - , _mem->size + , rectpitch*numBlocksY , data ) ); } diff --git a/src/renderer_vk.cpp b/src/renderer_vk.cpp index f9c9e8df5..bf7b33697 100644 --- a/src/renderer_vk.cpp +++ b/src/renderer_vk.cpp @@ -6933,21 +6933,43 @@ retry: const uint32_t bpp = bimg::getBitsPerPixel(bimg::TextureFormat::Enum(m_textureFormat) ); const bimg::ImageBlockInfo& blockInfo = bimg::getBlockInfo(bimg::TextureFormat::Enum(m_textureFormat) ); - uint32_t rectpitch = _rect.m_width * bpp / 8; + 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 align = blockInfo.blockSize; - if (bimg::isCompressed(bimg::TextureFormat::Enum(m_textureFormat) ) ) + uint32_t numRows = _rect.m_height; + uint32_t align = blockInfo.blockSize; + if (compressed) { - rectpitch = (_rect.m_width / blockInfo.blockWidth ) * blockInfo.blockSize; - slicepitch = (_rect.m_height / blockInfo.blockHeight) * rectpitch; + 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; + numRows = numBlocksY; } + const uint32_t srcpitch = UINT16_MAX == _pitch ? rectpitch : _pitch; - const uint32_t size = UINT16_MAX == _pitch ? slicepitch * _depth: _rect.m_height * _pitch * _depth; - const bool convert = m_textureFormat != m_requestedFormat; + const uint32_t size = convert || UINT16_MAX == _pitch + ? slicepitch * _depth + : numRows * srcpitch * _depth + ; + + // bufferRowLength is expressed in texels and, for block-compressed + // formats, must be a multiple of the block width. + uint32_t bufferRowLength = 0; + if (!convert + && UINT16_MAX != _pitch) + { + bufferRowLength = compressed + ? (srcpitch / blockInfo.blockSize) * blockInfo.blockWidth + : srcpitch * 8 / bpp + ; + } VkBufferImageCopy region; region.bufferOffset = 0; - region.bufferRowLength = (_pitch == UINT16_MAX ? 0 : _pitch * 8 / bpp); + region.bufferRowLength = bufferRowLength; region.bufferImageHeight = 0; region.imageSubresource.aspectMask = m_aspectFlags; region.imageSubresource.mipLevel = _mip;