[Vulkan] Handle MIPs with non-power-of-two dimensions
This commit is contained in:
parent
04748b4a0d
commit
f45cd398ef
|
@ -337,12 +337,6 @@ uint32_t TextureInfo::GetMipLocation(const TextureInfo& src, uint32_t mip,
|
|||
return src.guest_address;
|
||||
}
|
||||
|
||||
// One tile is 32x32 blocks
|
||||
const uint32_t tile_size = src.format_info()->block_width *
|
||||
src.format_info()->block_height * 32 * 32 *
|
||||
src.format_info()->bits_per_pixel / 8;
|
||||
|
||||
// Walk forward to find the address of the mip
|
||||
// If the texture is <= 16 pixels w/h, the mips are packed with the base
|
||||
// texture. Otherwise, they're stored beginning from mip_address.
|
||||
uint32_t address_base = std::min(src.width, src.height) < 16
|
||||
|
@ -350,17 +344,22 @@ uint32_t TextureInfo::GetMipLocation(const TextureInfo& src, uint32_t mip,
|
|||
: src.mip_address;
|
||||
uint32_t address_offset = 0;
|
||||
|
||||
uint32_t logical_width = std::max((src.width + 1) >> mip, 1u);
|
||||
uint32_t logical_height = std::max((src.height + 1) >> mip, 1u);
|
||||
// Walk forward to find the address of the mip.
|
||||
for (uint32_t i = 1; i < mip; i++) {
|
||||
if (std::min(logical_width, logical_height) < 16) {
|
||||
uint32_t logical_width = std::max(xe::next_pow2(src.width + 1) >> i, 1u);
|
||||
uint32_t logical_height = std::max(xe::next_pow2(src.height + 1) >> i, 1u);
|
||||
if (std::min(logical_width, logical_height) <= 16) {
|
||||
// We've reached the point where the mips are packed into a single tile.
|
||||
break;
|
||||
}
|
||||
|
||||
address_offset += std::max(src.input_length >> (i * 2), tile_size);
|
||||
address_offset += GetMipSize(src, i);
|
||||
}
|
||||
|
||||
// Now, check if the mip is packed at an offset.
|
||||
uint32_t logical_width = std::max(xe::next_pow2(src.width + 1) >> mip, 1u);
|
||||
uint32_t logical_height = std::max(xe::next_pow2(src.height + 1) >> mip, 1u);
|
||||
|
||||
*offset_x = 0;
|
||||
*offset_y = 0;
|
||||
if (std::min(logical_width, logical_height) <= 16) {
|
||||
|
@ -381,6 +380,21 @@ uint32_t TextureInfo::GetMipLocation(const TextureInfo& src, uint32_t mip,
|
|||
return address_base + address_offset;
|
||||
}
|
||||
|
||||
uint32_t TextureInfo::GetMipSize(const TextureInfo& src, uint32_t mip) {
|
||||
uint32_t size = src.format_info()->block_width *
|
||||
src.format_info()->block_height *
|
||||
(xe::next_pow2(src.width + 1) >> mip) *
|
||||
(xe::next_pow2(src.height + 1) >> mip) *
|
||||
src.format_info()->bits_per_pixel / 8;
|
||||
|
||||
// One tile is 32x32 blocks
|
||||
uint32_t tile_size = src.format_info()->block_width *
|
||||
src.format_info()->block_height * 32 * 32 *
|
||||
src.format_info()->bits_per_pixel / 8;
|
||||
|
||||
return std::max(size, tile_size);
|
||||
}
|
||||
|
||||
uint32_t TextureInfo::GetMipLinearSize(const TextureInfo& src, uint32_t mip) {
|
||||
uint32_t bytes_per_block = src.format_info()->block_width *
|
||||
src.format_info()->block_height *
|
||||
|
|
|
@ -318,6 +318,8 @@ struct TextureInfo {
|
|||
// Get the memory location of a mip. offset_x and offset_y are in blocks.
|
||||
static uint32_t GetMipLocation(const TextureInfo& src, uint32_t mip,
|
||||
uint32_t* offset_x, uint32_t* offset_y);
|
||||
static uint32_t GetMipSize(const TextureInfo& src, uint32_t mip);
|
||||
|
||||
// Get the byte size of a MIP when stored linearly.
|
||||
static uint32_t GetMipLinearSize(const TextureInfo& src, uint32_t mip);
|
||||
|
||||
|
|
|
@ -888,12 +888,11 @@ bool TextureCache::ConvertTexture2D(uint8_t* dest,
|
|||
uint32_t input_width = src.size_2d.input_width >> mip;
|
||||
uint32_t input_height = src.size_2d.input_height >> mip;
|
||||
|
||||
// All dimensions must be at least one block w/h
|
||||
// All dimensions must be a multiple of block w/h
|
||||
logical_width = std::max(logical_width, src.format_info()->block_width);
|
||||
logical_height = std::max(logical_height, src.format_info()->block_height);
|
||||
block_width = std::max(block_width, src.format_info()->block_width);
|
||||
input_width = std::max(input_width, src.format_info()->block_width);
|
||||
input_height = std::max(input_height, src.format_info()->block_height);
|
||||
input_width = xe::round_up(input_width, src.format_info()->block_width);
|
||||
input_height = xe::round_up(input_height, src.format_info()->block_height);
|
||||
|
||||
if (!src.is_tiled) {
|
||||
uint32_t offset_x, offset_y;
|
||||
|
|
Loading…
Reference in New Issue