diff --git a/src/renderer_d3d11.cpp b/src/renderer_d3d11.cpp index 6d11c9ac3..154146f4a 100644 --- a/src/renderer_d3d11.cpp +++ b/src/renderer_d3d11.cpp @@ -1923,13 +1923,16 @@ namespace bgfx { namespace d3d11 uint8_t* src = (uint8_t*)mapped.pData; uint32_t srcPitch = mapped.RowPitch; - const uint8_t bpp = bimg::getBitsPerPixel(bimg::TextureFormat::Enum(texture.m_textureFormat) ); + const bimg::ImageBlockInfo& blockInfo = bimg::getBlockInfo(bimg::TextureFormat::Enum(texture.m_textureFormat) ); + const uint32_t blockWidth = bx::max(1, blockInfo.blockWidth); + const uint32_t blockHeight = bx::max(1, blockInfo.blockHeight); uint8_t* dst = (uint8_t*)_data; - uint32_t dstPitch = srcWidth*bpp/8; + uint32_t dstPitch = ( (srcWidth + blockWidth - 1)/blockWidth)*blockInfo.blockSize; + uint32_t numRows = (srcHeight + blockHeight - 1)/blockHeight; uint32_t pitch = bx::min(srcPitch, dstPitch); - bx::memCopy(dst, dstPitch, src, srcPitch, pitch, srcHeight); + bx::memCopy(dst, dstPitch, src, srcPitch, pitch, numRows); m_deviceCtx->Unmap(texture.m_ptr, subresource); } @@ -4451,8 +4454,8 @@ namespace bgfx { namespace d3d11 } else if (compressed) { - srd[kk].SysMemPitch = (mip.m_width /blockInfo.blockWidth )*mip.m_blockSize; - srd[kk].SysMemSlicePitch = (mip.m_height/blockInfo.blockHeight)*srd[kk].SysMemPitch; + const uint32_t numBlocksX = (mip.m_width + blockInfo.blockWidth - 1) / blockInfo.blockWidth; + srd[kk].SysMemPitch = numBlocksX * mip.m_blockSize; } else { @@ -4478,7 +4481,7 @@ namespace bgfx { namespace d3d11 } } - srd[kk].SysMemSlicePitch = mip.m_height*srd[kk].SysMemPitch; + srd[kk].SysMemSlicePitch = ( (mip.m_height + blockInfo.blockHeight - 1) / blockInfo.blockHeight) * srd[kk].SysMemPitch; ++kk; } } @@ -4885,7 +4888,13 @@ namespace bgfx { namespace d3d11 uint32_t rectPitch = _rect.m_width*bpp/8; if (bimg::isCompressed(bimg::TextureFormat::Enum(m_textureFormat) ) ) { - rectPitch = (_rect.m_width / blockInfo.blockWidth)*blockInfo.blockSize; + const uint32_t blockW = blockInfo.blockWidth; + const uint32_t blockH = blockInfo.blockHeight; + const uint32_t alignedW = bx::max(blockW, bx::alignUp(_rect.m_width, blockW) ); + const uint32_t alignedH = bx::max(blockH, bx::alignUp(_rect.m_height, blockH) ); + box.right = box.left + alignedW; + box.bottom = box.top + alignedH; + rectPitch = (alignedW / blockW) * blockInfo.blockSize; } const uint32_t srcPitch = UINT16_MAX == _pitch ? rectPitch : _pitch; diff --git a/src/renderer_d3d12.cpp b/src/renderer_d3d12.cpp index b0de16695..8fa73d446 100644 --- a/src/renderer_d3d12.cpp +++ b/src/renderer_d3d12.cpp @@ -2279,16 +2279,19 @@ namespace bgfx { namespace d3d12 finish(); m_commandList = m_cmd.alloc(); - const uint8_t bpp = bimg::getBitsPerPixel(bimg::TextureFormat::Enum(texture.m_textureFormat) ); + const bimg::ImageBlockInfo& blockInfo = bimg::getBlockInfo(bimg::TextureFormat::Enum(texture.m_textureFormat) ); + const uint32_t blockWidth = bx::max(1, blockInfo.blockWidth); + const uint32_t blockHeight = bx::max(1, blockInfo.blockHeight); uint8_t* dst = (uint8_t*)_data; - uint32_t dstPitch = srcWidth*bpp/8; + uint32_t dstPitch = ( (srcWidth + blockWidth - 1)/blockWidth)*blockInfo.blockSize; + uint32_t numBlockRows = (srcHeight + blockHeight - 1)/blockHeight; uint32_t pitch = bx::min(srcPitch, dstPitch); uint8_t* src; readback->Map(0, NULL, (void**)&src); - bx::memCopy(dst, dstPitch, src, srcPitch, pitch, srcHeight); + bx::memCopy(dst, dstPitch, src, srcPitch, pitch, numBlockRows); D3D12_RANGE writeRange = { 0, 0 }; readback->Unmap(0, &writeRange); @@ -5952,14 +5955,16 @@ namespace bgfx { namespace d3d12 } else if (compressed) { - const uint32_t pitch = bx::strideAlign( (mip.m_width /blockInfo.blockWidth )*mip.m_blockSize, D3D12_TEXTURE_DATA_PITCH_ALIGNMENT); - const uint32_t slice = bx::strideAlign( (mip.m_height/blockInfo.blockHeight)*pitch, D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT); + const uint32_t numBlocksX = (mip.m_width + blockInfo.blockWidth - 1) / blockInfo.blockWidth; + const uint32_t numBlocksY = (mip.m_height + blockInfo.blockHeight - 1) / blockInfo.blockHeight; + const uint32_t pitch = bx::strideAlign(numBlocksX*mip.m_blockSize, D3D12_TEXTURE_DATA_PITCH_ALIGNMENT); + const uint32_t slice = bx::strideAlign(numBlocksY*pitch, D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT); const uint32_t size = slice*mip.m_depth; uint8_t* temp = (uint8_t*)bx::alloc(g_allocator, size); bimg::imageCopy(temp - , mip.m_height/blockInfo.blockHeight - , (mip.m_width /blockInfo.blockWidth )*mip.m_blockSize + , numBlocksY + , numBlocksX*mip.m_blockSize , mip.m_depth , mip.m_data , pitch @@ -6394,10 +6399,16 @@ namespace bgfx { namespace d3d12 const uint32_t bpp = bimg::getBitsPerPixel(bimg::TextureFormat::Enum(m_textureFormat) ); uint32_t rectPitch = _rect.m_width*bpp/8; + uint32_t boxWidth = _rect.m_width; + uint32_t boxHeight = _rect.m_height; 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; + const uint32_t blockW = blockInfo.blockWidth; + const uint32_t blockH = blockInfo.blockHeight; + boxWidth = bx::max(blockW, bx::alignUp(_rect.m_width, blockW) ); + boxHeight = bx::max(blockH, bx::alignUp(_rect.m_height, blockH) ); + rectPitch = (boxWidth / blockW) * blockInfo.blockSize; } const uint32_t srcPitch = UINT16_MAX == _pitch ? rectPitch : _pitch; @@ -6408,8 +6419,8 @@ namespace bgfx { namespace d3d12 D3D12_BOX box; box.left = 0; box.top = 0; - box.right = box.left + _rect.m_width; - box.bottom = box.top + _rect.m_height; + box.right = box.left + boxWidth; + box.bottom = box.top + boxHeight; box.front = 0; box.back = _depth; @@ -6446,8 +6457,8 @@ namespace bgfx { namespace d3d12 D3D12_RESOURCE_DESC desc = getResourceDesc(m_ptr); - desc.Width = _rect.m_width; - desc.Height = _rect.m_height; + desc.Width = boxWidth; + desc.Height = boxHeight; if (TextureD3D12::Texture3D == m_type) { diff --git a/src/renderer_mtl.cpp b/src/renderer_mtl.cpp index 08e83b04b..61f082ead 100644 --- a/src/renderer_mtl.cpp +++ b/src/renderer_mtl.cpp @@ -1374,9 +1374,17 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames const uint32_t srcHeight = bx::max(1, texture.m_ptr->height() >> _mip); const uint8_t bpp = bimg::getBitsPerPixel(bimg::TextureFormat::Enum(texture.m_textureFormat) ); + const bimg::ImageBlockInfo& blockInfo = bimg::getBlockInfo(bimg::TextureFormat::Enum(texture.m_textureFormat) ); + const uint32_t numBlocksX = (srcWidth + blockInfo.blockWidth - 1) / blockInfo.blockWidth; + const uint32_t bytesPerRow = bimg::isCompressed(bimg::TextureFormat::Enum(texture.m_textureFormat) ) + ? numBlocksX * blockInfo.blockSize + : srcWidth * bpp / 8 + ; + BX_UNUSED(bpp); + MTL::Region region(0, 0, 0, srcWidth, srcHeight, 1); - texture.m_ptr->getBytes(_data, srcWidth*bpp/8, 0, region, _mip, _layer); + texture.m_ptr->getBytes(_data, bytesPerRow, 0, region, _mip, _layer); } void resizeTexture(TextureHandle _handle, uint16_t _width, uint16_t _height, uint8_t _numMips, uint16_t _numLayers) override @@ -3820,9 +3828,11 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames } else { - bytesPerRow = (mip.m_width / blockInfo.blockWidth)*mip.m_blockSize; + const uint32_t numBlocksX = (mip.m_width + blockInfo.blockWidth - 1) / blockInfo.blockWidth; + const uint32_t numBlocksY = (mip.m_height + blockInfo.blockHeight - 1) / blockInfo.blockHeight; + bytesPerRow = numBlocksX * mip.m_blockSize; bytesPerImage = desc->textureType() == MTL::TextureType3D - ? (mip.m_height/blockInfo.blockHeight)*bytesPerRow + ? numBlocksY * bytesPerRow : 0 ; } @@ -3920,7 +3930,9 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames else { const bimg::ImageBlockInfo& blockInfo = bimg::getBlockInfo(bimg::TextureFormat::Enum(m_textureFormat) ); - rectpitch = (_rect.m_width / blockInfo.blockWidth)*blockInfo.blockSize; + const uint32_t blockW = blockInfo.blockWidth; + const uint32_t alignedW = bx::max(blockW, bx::alignUp(_rect.m_width, blockW) ); + rectpitch = (alignedW / blockW)*blockInfo.blockSize; } } const uint32_t srcpitch = UINT16_MAX == _pitch ? rectpitch : _pitch; diff --git a/src/renderer_vk.cpp b/src/renderer_vk.cpp index aa4bdbb4b..bcfb777c0 100644 --- a/src/renderer_vk.cpp +++ b/src/renderer_vk.cpp @@ -6358,9 +6358,10 @@ VK_DESTROY uint32_t ReadbackVK::pitch(uint8_t _mip) const { - uint32_t mipWidth = bx::max(1, m_width >> _mip); - uint8_t bpp = bimg::getBitsPerPixel(bimg::TextureFormat::Enum(m_format) ); - return mipWidth * bpp / 8; + const uint32_t mipWidth = bx::max(1, m_width >> _mip); + const bimg::ImageBlockInfo& blockInfo = bimg::getBlockInfo(bimg::TextureFormat::Enum(m_format) ); + const uint32_t numBlocksX = (mipWidth + blockInfo.blockWidth - 1) / blockInfo.blockWidth; + return numBlocksX * blockInfo.blockSize; } void ReadbackVK::copyImageToBuffer(VkCommandBuffer _commandBuffer, VkBuffer _buffer, VkImageLayout _layout, VkImageAspectFlags _aspect, uint16_t _layer, uint8_t _mip) const @@ -6370,6 +6371,10 @@ VK_DESTROY uint32_t mipWidth = bx::max(1, m_width >> _mip); uint32_t mipHeight = bx::max(1, m_height >> _mip); + const bimg::ImageBlockInfo& blockInfo = bimg::getBlockInfo(bimg::TextureFormat::Enum(m_format) ); + const uint32_t numBlocksX = (mipWidth + blockInfo.blockWidth - 1) / blockInfo.blockWidth; + const uint32_t numBlocksY = (mipHeight + blockInfo.blockHeight - 1) / blockInfo.blockHeight; + setImageMemoryBarrier( _commandBuffer , m_image @@ -6384,8 +6389,8 @@ VK_DESTROY VkBufferImageCopy bic; bic.bufferOffset = 0; - bic.bufferRowLength = mipWidth; - bic.bufferImageHeight = mipHeight; + bic.bufferRowLength = numBlocksX * blockInfo.blockWidth; + bic.bufferImageHeight = numBlocksY * blockInfo.blockHeight; bic.imageSubresource.aspectMask = _aspect; bic.imageSubresource.mipLevel = _mip; bic.imageSubresource.baseArrayLayer = _layer; @@ -6434,11 +6439,14 @@ VK_DESTROY const uint32_t mipHeight = bx::max(1, m_height >> _mip); const uint32_t rowPitch = pitch(_mip); + const bimg::ImageBlockInfo& blockInfo = bimg::getBlockInfo(bimg::TextureFormat::Enum(m_format) ); + const uint32_t numRows = (mipHeight + blockInfo.blockHeight - 1) / blockInfo.blockHeight; + const uint8_t* src; VK_CHECK(vkMapMemory(s_renderVK->m_device, _memory, 0, VK_WHOLE_SIZE, 0, (void**)&src) ); src += _offset; - bx::gather(_data, src, rowPitch, rowPitch, mipHeight); + bx::gather(_data, src, rowPitch, rowPitch, numRows); vkUnmapMemory(s_renderVK->m_device, _memory); } @@ -6810,15 +6818,17 @@ VK_DESTROY } else if (compressed) { - const uint32_t pitch = bx::strideAlign( (mip.m_width / blockInfo.blockWidth) * mip.m_blockSize, alignment); - const uint32_t slice = bx::strideAlign( (mip.m_height / blockInfo.blockHeight) * pitch, alignment); + const uint32_t numBlocksX = (mip.m_width + blockInfo.blockWidth - 1) / blockInfo.blockWidth; + const uint32_t numBlocksY = (mip.m_height + blockInfo.blockHeight - 1) / blockInfo.blockHeight; + const uint32_t pitch = bx::strideAlign(numBlocksX * mip.m_blockSize, alignment); + const uint32_t slice = bx::strideAlign(numBlocksY * pitch, alignment); const uint32_t size = slice * mip.m_depth; uint8_t* temp = (uint8_t*)bx::alloc(g_allocator, size); bimg::imageCopy( temp - , mip.m_height / blockInfo.blockHeight - , (mip.m_width / blockInfo.blockWidth) * mip.m_blockSize + , numBlocksY + , numBlocksX * mip.m_blockSize , mip.m_depth , mip.m_data , pitch @@ -7032,8 +7042,14 @@ VK_DESTROY numRows = numBlocksY; } - const uint32_t srcPitch = UINT16_MAX == _pitch ? rectPitch : _pitch; - const uint32_t size = convert || UINT16_MAX == _pitch + const bool repackPitch = true + && !convert + && UINT16_MAX != _pitch + && _pitch != rectPitch + ; + + const uint32_t srcPitch = (UINT16_MAX == _pitch || repackPitch) ? rectPitch : _pitch; + const uint32_t size = convert || UINT16_MAX == _pitch || repackPitch ? slicePitch * _depth : numRows * srcPitch * _depth ; @@ -7042,7 +7058,8 @@ VK_DESTROY // formats, must be a multiple of the block width. uint32_t bufferRowLength = 0; if (!convert - && UINT16_MAX != _pitch) + && UINT16_MAX != _pitch + && !repackPitch) { bufferRowLength = compressed ? (srcPitch / blockInfo.blockSize) * blockInfo.blockWidth @@ -7073,6 +7090,12 @@ VK_DESTROY region.imageExtent.width = bx::clamp(region.imageExtent.width, 0u, bx::max(1u, m_width >> _mip) - _rect.m_x); region.imageExtent.height = bx::clamp(region.imageExtent.height, 0u, bx::max(1u, m_height >> _mip) - _rect.m_y); } + else if (repackPitch) + { + temp = (uint8_t*)bx::alloc(g_allocator, slicePitch * _depth); + bimg::imageCopy(temp, numRows, _pitch, _depth, data, rectPitch); + data = temp; + } StagingBufferVK stagingBuffer = s_renderVK->allocFromScratchStagingBuffer(size, align, data); region.bufferOffset += stagingBuffer.m_offset;