- [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:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user