- [GPU] Rename TextureMemoryUsage to TextureExtent (and relevant functions/etc).

- [GPU] Precalculate memory byte usage for base mip (and any additional mip levels).
- [GPU] Change TextureCache::WatchCallback so that if it's fired multiple times for the same texture it does not assert.
- [GPU] Add write watches for texture memory associated with additional mipmap levels.
This commit is contained in:
gibbed
2018-05-31 19:36:25 -05:00
parent cd39bbed5c
commit e89a31006f
9 changed files with 213 additions and 152 deletions

View File

@@ -67,8 +67,7 @@ bool TextureInfo::Prepare(const xe_gpu_texture_fetch_t& fetch,
info.is_tiled = fetch.tiled;
info.has_packed_mips = fetch.packed_mips;
info.guest_address = fetch.address << 12;
info.mip_address = fetch.mip_address << 12;
info.SetupMemoryInfo(fetch.base_address << 12, fetch.mip_address << 12);
if (info.format_info()->format == TextureFormat::kUnknown) {
XELOGE("Attempting to fetch from unsupported texture format %d",
@@ -76,7 +75,7 @@ bool TextureInfo::Prepare(const xe_gpu_texture_fetch_t& fetch,
return false;
}
info.memory_usage = TextureMemoryUsage::Calculate(out_info, true);
info.extent = TextureExtent::Calculate(out_info, true);
return true;
}
@@ -92,25 +91,27 @@ bool TextureInfo::PrepareResolve(uint32_t physical_address,
auto& info = *out_info;
info.format = format;
info.endianness = endian;
info.dimension = Dimension::k2D;
info.width = width - 1;
info.height = height - 1;
info.mip_levels = 1;
info.depth = depth - 1;
info.pitch = pitch;
info.mip_levels = 1;
info.endianness = endian;
info.is_tiled = true;
info.has_packed_mips = false;
info.guest_address = physical_address;
info.mip_address = 0;
info.SetupMemoryInfo(physical_address, 0);
if (info.format_info()->format == TextureFormat::kUnknown) {
assert_true("Unsupported texture format");
return false;
}
info.memory_usage = TextureMemoryUsage::Calculate(out_info, true);
info.extent = TextureExtent::Calculate(out_info, true);
return true;
}
@@ -118,15 +119,15 @@ uint32_t TextureInfo::GetMaxMipLevels() const {
return 1 + xe::log2_floor(std::max({width + 1, height + 1, depth + 1}));
}
const TextureMemoryUsage TextureInfo::GetMipMemoryUsage(uint32_t mip,
bool is_guest) const {
const TextureExtent TextureInfo::GetMipExtent(uint32_t mip,
bool is_guest) const {
if (mip == 0) {
return memory_usage;
return extent;
}
uint32_t mip_width = xe::next_pow2(width + 1) >> mip;
uint32_t mip_height = xe::next_pow2(height + 1) >> mip;
return TextureMemoryUsage::Calculate(format_info(), mip_width, mip_height,
depth + 1, is_tiled, is_guest);
return TextureExtent::Calculate(format_info(), mip_width, mip_height,
depth + 1, is_tiled, is_guest);
}
void TextureInfo::GetMipSize(uint32_t mip, uint32_t* out_width,
@@ -154,7 +155,7 @@ uint32_t TextureInfo::GetMipLocation(uint32_t mip, uint32_t* offset_x,
} else {
GetPackedTileOffset(0, offset_x, offset_y);
}
return guest_address;
return memory.base_address;
}
uint32_t address_base, address_offset;
@@ -162,19 +163,22 @@ uint32_t TextureInfo::GetMipLocation(uint32_t mip, uint32_t* offset_x,
// If the texture is <= 16 pixels w/h, the mips are packed with the base
// texture. Otherwise, they're stored beginning from mip_address.
if (std::min(width, height) < 16) {
address_base = guest_address;
address_base = memory.base_address;
address_offset = 0;
} else if (guest_address == mip_address) {
address_base = guest_address;
address_offset = GetMipByteSize(0, is_guest);
} else if (memory.base_address == memory.mip_address) {
address_base = memory.base_address;
address_offset = memory.base_size;
} else {
address_base = mip_address;
address_base = memory.mip_address;
address_offset = 0;
}
auto bytes_per_block = format_info()->bytes_per_block();
if (!has_packed_mips) {
for (uint32_t i = 1; i < mip; i++) {
address_offset += GetMipByteSize(i, is_guest);
address_offset +=
GetMipExtent(i, is_guest).all_blocks() * bytes_per_block;
}
*offset_x = 0;
*offset_y = 0;
@@ -193,7 +197,7 @@ uint32_t TextureInfo::GetMipLocation(uint32_t mip, uint32_t* offset_x,
// We've reached the point where the mips are packed into a single tile.
break;
}
address_offset += GetMipByteSize(i, is_guest);
address_offset += GetMipExtent(i, is_guest).all_blocks() * bytes_per_block;
}
// Now, check if the mip is packed at an offset.
@@ -202,26 +206,6 @@ uint32_t TextureInfo::GetMipLocation(uint32_t mip, uint32_t* offset_x,
return address_base + address_offset;
}
uint32_t TextureInfo::GetMipByteSize(uint32_t mip, bool is_guest) const {
uint32_t bytes_per_block = format_info()->bytes_per_block();
auto mip_usage = GetMipMemoryUsage(mip, is_guest);
return mip_usage.all_blocks() * bytes_per_block;
}
uint32_t TextureInfo::GetMipVisibleByteSize(uint32_t mip, bool is_guest) const {
uint32_t bytes_per_block = format_info()->bytes_per_block();
auto mip_usage = GetMipMemoryUsage(mip, is_guest);
return mip_usage.visible_blocks() * bytes_per_block;
}
uint32_t TextureInfo::GetByteSize(bool is_guest) const {
uint32_t length = 0;
for (uint32_t mip = 0; mip < mip_levels; ++mip) {
length += GetMipByteSize(mip, is_guest);
}
return length;
}
bool TextureInfo::GetPackedTileOffset(uint32_t width, uint32_t height,
const FormatInfo* format_info,
int packed_tile, uint32_t* offset_x,
@@ -314,5 +298,57 @@ uint64_t TextureInfo::hash() const {
return XXH64(this, sizeof(TextureInfo), 0);
}
void TextureInfo::SetupMemoryInfo(uint32_t base_address, uint32_t mip_address) {
memory.base_address = base_address;
memory.base_size = 0;
memory.mip_address = 0;
memory.mip_size = 0;
uint32_t bytes_per_block = format_info()->bytes_per_block();
if (mip_levels <= 1) {
// Sort circuit. Only one mip.
memory.base_size = GetMipExtent(0, true).all_blocks() * bytes_per_block;
return;
}
if (!has_packed_mips) {
assert_true(mip_address == 0 || mip_address == base_address);
for (uint32_t mip = 0; mip < mip_levels - 1; mip++) {
memory.base_size +=
GetMipExtent(mip, true).all_blocks() * bytes_per_block;
}
memory.base_size +=
GetMipExtent(mip_levels - 1, true).visible_blocks() * bytes_per_block;
return;
}
uint32_t total_size = 0;
uint32_t width_pow2 = xe::next_pow2(width + 1);
uint32_t height_pow2 = xe::next_pow2(height + 1);
// Walk forward to find the address of the mip.
uint32_t packed_mip_base = 1;
for (uint32_t mip = packed_mip_base; mip < mip_levels - 1;
mip++, packed_mip_base++) {
uint32_t mip_width = std::max(width_pow2 >> mip, 1u);
uint32_t mip_height = std::max(height_pow2 >> mip, 1u);
if (std::min(mip_width, mip_height) <= 16) {
// We've reached the point where the mips are packed into a single tile.
break;
}
total_size += GetMipExtent(mip, true).all_blocks() * bytes_per_block;
}
if (mip_address != base_address) {
memory.mip_address = mip_address;
memory.mip_size = total_size;
} else {
memory.base_size = GetMipExtent(0, true).all_blocks() * bytes_per_block;
memory.base_size += total_size;
}
}
} // namespace gpu
} // namespace xe