[GPU] Ignore mipmap level count when mip data address is invalid.

This commit is contained in:
gibbed 2018-06-01 22:04:13 -05:00
parent 0d429fc7d7
commit b35fe935f9
2 changed files with 39 additions and 18 deletions

View File

@ -62,7 +62,8 @@ bool TextureInfo::Prepare(const xe_gpu_texture_fetch_t& fetch,
break; break;
} }
info.pitch = fetch.pitch << 5; info.pitch = fetch.pitch << 5;
info.mip_levels = fetch.packed_mips ? fetch.mip_max_level + 1 : 1; assert_true(fetch.mip_min_level == 0);
info.mip_levels = 1 + fetch.mip_max_level;
info.is_tiled = fetch.tiled; info.is_tiled = fetch.tiled;
info.has_packed_mips = fetch.packed_mips; info.has_packed_mips = fetch.packed_mips;
@ -77,6 +78,12 @@ bool TextureInfo::Prepare(const xe_gpu_texture_fetch_t& fetch,
info.extent = TextureExtent::Calculate(out_info, true); info.extent = TextureExtent::Calculate(out_info, true);
info.SetupMemoryInfo(fetch.base_address << 12, fetch.mip_address << 12); info.SetupMemoryInfo(fetch.base_address << 12, fetch.mip_address << 12);
if (!info.memory.mip_address) {
// No mip data? One mip level, period.
info.mip_levels = 1;
}
return true; return true;
} }
@ -149,7 +156,7 @@ void TextureInfo::GetMipSize(uint32_t mip, uint32_t* out_width,
uint32_t TextureInfo::GetMipLocation(uint32_t mip, uint32_t* offset_x, uint32_t TextureInfo::GetMipLocation(uint32_t mip, uint32_t* offset_x,
uint32_t* offset_y, bool is_guest) const { uint32_t* offset_y, bool is_guest) const {
if (mip == 0) { if (mip == 0) {
// Short-circuit. Mip 0 is always stored in guest_address. // Short-circuit. Mip 0 is always stored in base_address.
if (!has_packed_mips) { if (!has_packed_mips) {
*offset_x = 0; *offset_x = 0;
*offset_y = 0; *offset_y = 0;
@ -159,6 +166,13 @@ uint32_t TextureInfo::GetMipLocation(uint32_t mip, uint32_t* offset_x,
return memory.base_address; return memory.base_address;
} }
if (!memory.mip_address) {
// Short-circuit. There is no mip data.
*offset_x = 0;
*offset_y = 0;
return 0;
}
uint32_t address_base, address_offset; uint32_t address_base, address_offset;
address_base = memory.mip_address; address_base = memory.mip_address;
address_offset = 0; address_offset = 0;
@ -296,20 +310,21 @@ void TextureInfo::SetupMemoryInfo(uint32_t base_address, uint32_t mip_address) {
memory.mip_address = 0; memory.mip_address = 0;
memory.mip_size = 0; memory.mip_size = 0;
if (mip_levels <= 1) { if (mip_levels <= 1 || !mip_address) {
// Sort circuit. Only one mip. // Sort circuit. Only one mip.
return; return;
} }
if (!mip_address || base_address == mip_address) { if (base_address == mip_address) {
memory.mip_address = base_address; // TODO(gibbed): This doesn't actually make any sense. Force only one mip.
memory.mip_address += GetMipExtent(0, true).all_blocks() * bytes_per_block; // Offending title issues: #26, #45
} else { return;
memory.mip_address = mip_address;
} }
memory.mip_address = mip_address;
if (!has_packed_mips) { if (!has_packed_mips) {
for (uint32_t mip = 0; mip < mip_levels - 1; mip++) { for (uint32_t mip = 1; mip < mip_levels - 1; mip++) {
memory.mip_size += GetMipExtent(mip, true).all_blocks() * bytes_per_block; memory.mip_size += GetMipExtent(mip, true).all_blocks() * bytes_per_block;
} }
memory.mip_size += memory.mip_size +=

View File

@ -898,6 +898,10 @@ bool TextureCache::ConvertTexture(uint8_t* dest, VkBufferImageCopy* copy_region,
uint32_t offset_x = 0; uint32_t offset_x = 0;
uint32_t offset_y = 0; uint32_t offset_y = 0;
uint32_t address = src.GetMipLocation(mip, &offset_x, &offset_y, true); uint32_t address = src.GetMipLocation(mip, &offset_x, &offset_y, true);
if (!address) {
return false;
}
void* host_address = memory_->TranslatePhysical(address); void* host_address = memory_->TranslatePhysical(address);
auto is_cube = src.dimension == Dimension::kCube; auto is_cube = src.dimension == Dimension::kCube;
@ -1025,17 +1029,16 @@ bool TextureCache::UploadTexture(VkCommandBuffer command_buffer,
// on the CPU. // on the CPU.
std::vector<VkBufferImageCopy> copy_regions(src.mip_levels); std::vector<VkBufferImageCopy> copy_regions(src.mip_levels);
auto dest_data = reinterpret_cast<uint8_t*>(alloc->host_ptr); // Upload all mips.
auto unpack_buffer = reinterpret_cast<uint8_t*>(alloc->host_ptr);
// Upload all the mips VkDeviceSize unpack_offset = 0;
VkDeviceSize buffer_offset = 0;
for (uint32_t mip = 0; mip < src.mip_levels; mip++) { for (uint32_t mip = 0; mip < src.mip_levels; mip++) {
if (!ConvertTexture(&dest_data[buffer_offset], &copy_regions[mip], mip, if (!ConvertTexture(&unpack_buffer[unpack_offset], &copy_regions[mip], mip,
src)) { src)) {
XELOGW("Failed to convert texture mip %u!", mip); XELOGW("Failed to convert texture mip %u!", mip);
return false; return false;
} }
copy_regions[mip].bufferOffset = alloc->offset + buffer_offset; copy_regions[mip].bufferOffset = alloc->offset + unpack_offset;
copy_regions[mip].imageOffset = {0, 0, 0}; copy_regions[mip].imageOffset = {0, 0, 0};
/* /*
@ -1044,7 +1047,7 @@ bool TextureCache::UploadTexture(VkCommandBuffer command_buffer,
copy_regions[mip].imageExtent.depth, buffer_offset); copy_regions[mip].imageExtent.depth, buffer_offset);
*/ */
buffer_offset += ComputeMipStorage(src, mip); unpack_offset += ComputeMipStorage(src, mip);
} }
// Transition the texture into a transfer destination layout. // Transition the texture into a transfer destination layout.
@ -1177,8 +1180,11 @@ uint32_t TextureCache::ComputeTextureStorage(const TextureInfo& src) {
uint32_t height = src.height + 1; uint32_t height = src.height + 1;
uint32_t depth = src.depth + 1; uint32_t depth = src.depth + 1;
uint32_t length = 0; uint32_t length = 0;
for (uint32_t mip = 0; mip < src.mip_levels; mip++) { length += ComputeMipStorage(format_info, width, height, depth, 0);
length += ComputeMipStorage(format_info, width, height, depth, mip); if (src.memory.mip_address) {
for (uint32_t mip = 1; mip < src.mip_levels; mip++) {
length += ComputeMipStorage(format_info, width, height, depth, mip);
}
} }
return length; return length;
} }