refactor gpu: consolidate texture tile layout calculations

This commit is contained in:
nmzik committed 2026-08-06 20:03:42 +02:00
1 parent a76f3ac2fe
commit 389fd1e5be
9 files changed
+802 -1147

No files matched your search

File diff suppressed because it is too large. Load diff
+60 -29
View File
@@ -39,7 +39,7 @@ enum class TileBlockFamily : uint32_t {
};
struct TileBlockLayout {
TileBlockFamily family = TileBlockFamily::Standard256B;
TileBlockFamily family = TileBlockFamily::Count;
uint32_t bytes_per_element = 0;
uint32_t block_size = 0;
uint32_t block_width = 0;
@@ -47,38 +47,69 @@ struct TileBlockLayout {
uint32_t block_depth = 0;
};
struct TileVolumeLayout {
TileBlockFamily family = TileBlockFamily::Count;
uint32_t bytes_per_element = 0;
uint32_t texel_width = 1;
uint32_t texel_height = 1;
uint32_t first_tail_level = 0;
uint32_t block_depth = 1;
uint64_t block_slice_size = 0;
uint64_t total_size = 0;
uint64_t level_offsets[16] = {};
uint64_t level_sizes[16] = {};
uint32_t tail_x[16] = {};
uint32_t tail_y[16] = {};
uint32_t level_widths[16] = {};
uint32_t level_heights[16] = {};
struct TileTextureElementLayout {
uint32_t bytes = 0;
uint32_t texel_width = 1;
uint32_t texel_height = 1;
};
struct TileTextureBlockLayout {
TileBlockLayout block;
uint32_t texel_width = 1;
uint32_t texel_height = 1;
};
enum class TileSurfaceDimension : uint32_t {
Dim2D,
Dim3D,
};
struct TileSurfaceDescription {
uint32_t format = 0;
uint32_t tile_mode = 0;
TileSurfaceDimension dimension = TileSurfaceDimension::Dim2D;
uint32_t width = 0;
uint32_t height = 0;
uint32_t depth = 1;
uint32_t levels = 1;
uint32_t layers = 1;
};
// Width/height fields are measured in addressable elements, not texture texels.
struct TileMipLayout {
uint64_t offset = 0;
uint64_t size = 0;
uint32_t width = 0;
uint32_t height = 0;
uint32_t padded_width = 0;
uint32_t padded_height = 0;
uint32_t tail_x = 0;
uint32_t tail_y = 0;
};
struct TileSurfaceLayout {
TileSurfaceDescription description;
TileTextureBlockLayout texture;
uint32_t first_tail_level = 0;
uint64_t block_slice_size = 0;
uint64_t total_size = 0;
TileMipLayout mips[16] = {};
};
bool TileGetBlockLayout(TileBlockFamily family, uint32_t bytes_per_element,
TileBlockLayout& layout);
bool TileGetTextureElementLayout(uint32_t format, TileTextureElementLayout& layout);
bool TileGetTextureBlockLayout(uint32_t format, uint32_t tile, bool volume,
TileTextureBlockLayout& layout);
bool TileGetTiledTextureLayout(const TileSurfaceDescription& description,
TileSurfaceLayout& layout);
bool TileGetBlockOffset(const TileBlockLayout& layout, uint32_t x, uint32_t y, uint32_t z,
uint32_t& byte_offset);
bool TileGetBlockXor(const TileBlockLayout& layout, uint32_t block_x, uint32_t block_y,
uint32_t& byte_offset);
bool TileGetBlockXor(const TileBlockLayout& layout, uint32_t block_x, uint32_t block_y,
uint32_t block_z, uint32_t& byte_offset);
bool TileIsStandard256BTextureSupported(uint32_t format);
bool TileIsStandard4KBTextureSupported(uint32_t format);
bool TileIsStandard64KBTextureSupported(uint32_t format);
bool TileGetTextureVolumeLayout(uint32_t format, uint32_t width, uint32_t height, uint32_t depth,
uint32_t levels, uint32_t tile, TileVolumeLayout& layout);
bool TileGetHtileSize(uint32_t width, uint32_t height, TileSizeAlign& htile_size);
bool TileGetDepthSize(uint32_t width, uint32_t height, uint32_t pitch, uint32_t z_format,
uint32_t stencil_format, bool htile, TileSizeAlign& stencil_size,
TileSizeAlign& htile_size, TileSizeAlign& depth_size,
@@ -94,13 +125,13 @@ bool TileGetRenderTargetMipLayout(uint32_t width, uint32_t height, uint32_t
uint32_t bytes_per_element, uint32_t levels,
TileSizeAlign& total_size, TileSizeOffset* level_sizes,
TilePaddedSize* padded_size);
void TileGetTextureSize(uint32_t format, uint32_t width, uint32_t height, uint32_t pitch,
uint32_t levels, uint32_t tile, TileSizeAlign* total_size,
TileSizeOffset* level_sizes, TilePaddedSize* padded_size);
void TileGetTextureTotalSize(uint32_t format, uint32_t width, uint32_t height, uint32_t depth,
uint32_t pitch, uint32_t levels, uint32_t tile, bool volume_texture,
TileSizeAlign& total_size);
uint32_t TileGetTexturePitch(uint32_t format, uint32_t width, uint32_t levels, uint32_t tile);
void TileGetTextureSize(uint32_t format, uint32_t width, uint32_t height, uint32_t levels,
uint32_t tile, TileSizeAlign* total_size, TileSizeOffset* level_sizes,
TilePaddedSize* padded_size);
void TileGetTextureTotalSize(uint32_t format, uint32_t width, uint32_t height, uint32_t depth,
uint32_t levels, uint32_t tile, bool volume_texture,
TileSizeAlign& total_size);
uint32_t TileGetTexturePitch(uint32_t format, uint32_t width, uint32_t tile);
} // namespace Libs::Graphics
+13 -24
View File
@@ -911,7 +911,6 @@ TextureCache::BuildColorTransfer(const Image& image, BindingType binding,
uint32_t format = info.guest_format;
uint32_t layers = info.TransferLayers();
bool volume = info.IsVolume();
bool layered = info.IsLayered();
bool allow_depth_tile = direction == TransferDirection::Upload;
const char* owner =
direction == TransferDirection::Upload ? "TextureCache" : "TextureCache readback";
@@ -940,7 +939,6 @@ TextureCache::BuildColorTransfer(const Image& image, BindingType binding,
format = info.guest_format;
layers = info.resources.layers;
volume = false;
layered = layers > 1;
allow_depth_tile = false;
plan.swap_bgra16 = info.bgra16;
owner = "VideoOut";
@@ -958,19 +956,14 @@ TextureCache::BuildColorTransfer(const Image& image, BindingType binding,
plan.swap_bgra16 = info.bgra16;
}
plan.layout = TextureCalcUploadLayout(format, info.extent.width, info.extent.height,
info.resources.levels, layers, info.pitch, info.tile_mode,
info.data.size, allow_depth_tile, volume, owner);
plan.regions = TextureBuildImageCopies(plan.layout, info.extent.width, info.extent.height,
layers, info.resources.levels, layered, volume);
plan.tiled = static_cast<Prospero::TileMode>(plan.layout.tile) != Prospero::TileMode::kLinear;
plan.layout = TextureCalcUploadLayout(format, info.extent.width, info.extent.height,
info.resources.levels, layers, info.tile_mode,
info.data.size, allow_depth_tile, volume, owner);
plan.regions = TextureBuildImageCopies(plan.layout);
plan.tiled = static_cast<Prospero::TileMode>(plan.layout.surface.description.tile_mode) !=
Prospero::TileMode::kLinear;
if (plan.tiled) {
// CMASK/FMASK decoding is intentionally deferred.
if (plan.layout.tile_family == TileBlockFamily::Depth64KB &&
Prospero::IsFmaskTextureFormat(format)) {
return plan;
}
if (!TextureBuildGpuTileInfos(info.data.size, plan.regions, plan.layout, format, layers,
if (!TextureBuildGpuTileInfos(info.data.size, plan.regions, plan.layout,
info.resources.levels, plan.tiles)) {
return plan;
}
@@ -1017,9 +1010,10 @@ void TextureCache::UploadImage(Image& image, const ImageDesc& desc, Buffer& sour
" size=0x%016" PRIx64 " format=%u tile=%u family=%u extent=%ux%ux%u "
"pitch=%u levels=%u layers=%u samples=%u\n",
static_cast<uint32_t>(desc.type), info.data.address, info.data.size,
info.guest_format, info.tile_mode, static_cast<uint32_t>(plan.layout.tile_family),
info.extent.width, info.extent.height, info.extent.depth, info.pitch,
info.resources.levels, info.resources.layers, info.samples);
info.guest_format, info.tile_mode,
static_cast<uint32_t>(plan.layout.surface.texture.block.family), info.extent.width,
info.extent.height, info.extent.depth, info.pitch, info.resources.levels,
info.resources.layers, info.samples);
}
TileManager::Result linear {source.Handle(), source_offset, info.data.size};
if (plan.tiled) {
@@ -1718,14 +1712,9 @@ bool BufferCache::SynchronizeBufferFromImage(Buffer& buffer, uint64_t vaddr, uin
return false;
}
if (color.tiled) {
const auto binding = m_texture_cache.UploadBinding(image);
const auto format =
binding == TextureCache::BindingType::RenderTarget
? ImageOps::RenderTargetTransferFormat(image.info.bytes_per_block)
: image.info.guest_format;
color.tiles.clear();
if (!TextureBuildGpuTileInfos(copy_size, color.regions, color.layout, format,
image.info.TransferLayers(), levels, color.tiles)) {
if (!TextureBuildGpuTileInfos(copy_size, color.regions, color.layout, levels,
color.tiles)) {
return false;
}
color.linear_size = GetLinearSize(color.tiles);
@@ -178,10 +178,10 @@ void RenderExecutor::ResolveRenderColorTarget(uint64_t submit_id, RenderCommandB
pitch = (rt.pitch.pitch_div8_minus1 + 1u) << 3u;
} else if (tile) {
if (volume) {
pitch = TileGetTexturePitch(transfer_format, width, levels, rt.attrib3.tile_mode);
pitch = TileGetTexturePitch(transfer_format, width, rt.attrib3.tile_mode);
} else if (standard64) {
pitch = TileGetTexturePitch(Prospero::GpuEnumValue(Prospero::BufferFormat::k32Float),
width, levels, rt.attrib3.tile_mode);
width, rt.attrib3.tile_mode);
} else {
pitch = TileGetRenderTargetPitch(width, bytes_per_element, rt.attrib.num_fragments);
}
@@ -192,13 +192,20 @@ void RenderExecutor::ResolveRenderColorTarget(uint64_t submit_id, RenderCommandB
pitch = width;
}
TileSizeOffset mip_sizes[16] {};
TilePaddedSize mip_padded[16] {};
TileVolumeLayout volume_layout {};
uint64_t backing_size = 0;
TileSizeOffset mip_sizes[16] {};
TilePaddedSize mip_padded[16] {};
TileSurfaceLayout volume_layout {};
uint64_t backing_size = 0;
if (volume) {
if (!tile || !TileGetTextureVolumeLayout(transfer_format, width, height, depth, levels,
rt.attrib3.tile_mode, volume_layout)) {
const TileSurfaceDescription description {transfer_format,
rt.attrib3.tile_mode,
TileSurfaceDimension::Dim3D,
width,
height,
depth,
levels,
1};
if (!tile || !TileGetTiledTextureLayout(description, volume_layout)) {
EXIT("unsupported 3D render-target layout: %ux%ux%u levels=%u tile=%u\n", width, height,
depth, levels, rt.attrib3.tile_mode);
}
@@ -209,7 +216,7 @@ void RenderExecutor::ResolveRenderColorTarget(uint64_t submit_id, RenderCommandB
bool valid_layout = false;
if (standard64) {
TileGetTextureSize(Prospero::GpuEnumValue(Prospero::BufferFormat::k32Float), width,
height, pitch, levels, rt.attrib3.tile_mode, &layout, mip_sizes,
height, levels, rt.attrib3.tile_mode, &layout, mip_sizes,
mip_padded);
valid_layout = layout.size != 0 && layout.align == 65536;
} else {
@@ -289,11 +296,12 @@ void RenderExecutor::ResolveRenderColorTarget(uint64_t submit_id, RenderCommandB
desc.info.tile_mode = rt.attrib3.tile_mode;
for (uint32_t level = 0; level < levels; level++) {
if (volume) {
const auto& mip = volume_layout.mips[level];
desc.info.mip_layout[level] = {
volume_layout.level_offsets[level],
volume_layout.level_sizes[level],
volume_layout.level_widths[level],
volume_layout.level_heights[level],
mip.offset,
mip.size,
mip.padded_width,
mip.padded_height,
};
continue;
}
@@ -168,14 +168,6 @@ RenderTargetFormatInfo TextureGetRenderTargetFormat(uint32_t raw_layout, uint32_
namespace {
static uint64_t GetLevelSrcOffset(const TileSizeOffset& level_size) {
return (level_size.src_size != 0 ? level_size.src_offset : level_size.offset);
}
static uint64_t GetLevelSrcSize(const TileSizeOffset& level_size) {
return (level_size.src_size != 0 ? level_size.src_size : level_size.size);
}
static uint32_t GetTextureLevelDepth(uint32_t depth, uint32_t level, bool volume_texture) {
return volume_texture ? std::max(depth >> level, 1u) : depth;
}
@@ -188,20 +180,6 @@ static size_t GetTextureRegionCount(uint32_t depth, uint64_t levels, bool volume
return count;
}
uint64_t TextureUploadSliceSourceOffset(const TextureUploadLayout& layout, uint32_t level,
uint32_t slice) {
if (level >= 16 || layout.level_sizes[level].size == 0) {
EXIT("invalid texture upload slice source, level=%u slice=%u\n", level, slice);
}
const auto level_offset = GetLevelSrcOffset(layout.level_sizes[level]);
const auto slice_stride =
layout.source_slice_stride != 0 ? layout.source_slice_stride : layout.slice_stride;
if (slice_stride != 0 && slice > (UINT64_MAX - level_offset) / slice_stride) {
EXIT("texture upload slice source offset overflow, level=%u slice=%u\n", level, slice);
}
return level_offset + static_cast<uint64_t>(slice) * slice_stride;
}
vk::ComponentSwizzle TextureGetComponentSwizzle(uint8_t s) {
switch (static_cast<Prospero::CompSwizzle>(s)) {
case Prospero::CompSwizzle::kZero: return vk::ComponentSwizzle::eZero;
@@ -241,12 +219,11 @@ vk::Format TextureGetFormat(uint32_t fmt) {
namespace {
uint64_t CalcTextureSliceStride(const TileSizeOffset* level_sizes, uint64_t levels,
uint64_t CalcTextureSliceStride(const TextureUploadMipLayout* mips, uint64_t levels,
uint64_t total_size, uint32_t depth) {
uint64_t stride = 0;
for (uint32_t i = 0; i < levels; i++) {
stride =
std::max(stride, static_cast<uint64_t>(level_sizes[i].offset) + level_sizes[i].size);
stride = std::max(stride, mips[i].offset + mips[i].size);
}
if (depth > 1 && total_size != 0 && total_size % depth == 0) {
@@ -259,39 +236,26 @@ uint64_t CalcTextureSliceStride(const TileSizeOffset* level_sizes, uint64_t leve
return stride;
}
uint64_t CalcLinearUploadLevelSize(uint32_t fmt, uint32_t pitch, uint32_t height) {
if (const uint32_t bytes_per_element = Prospero::NumBytesPerElement(fmt);
bytes_per_element != 0) {
return static_cast<uint64_t>(pitch) * height * bytes_per_element;
}
if (const uint32_t bytes_per_block = Prospero::BlockCompressedBytesPerBlock(fmt);
bytes_per_block != 0) {
const uint32_t blocks_w = std::max((pitch + 3u) / 4u, 1u);
const uint32_t blocks_h = std::max((height + 3u) / 4u, 1u);
return static_cast<uint64_t>(blocks_w) * blocks_h * bytes_per_block;
}
return 0;
uint64_t CalcLinearUploadLevelSize(const TileTextureElementLayout& element, uint32_t pitch,
uint32_t height) {
const uint32_t elements_w =
std::max((pitch + element.texel_width - 1u) / element.texel_width, 1u);
const uint32_t elements_h =
std::max((height + element.texel_height - 1u) / element.texel_height, 1u);
return static_cast<uint64_t>(elements_w) * elements_h * element.bytes;
}
uint64_t SetLinearUploadLevels(TileSizeOffset* level_sizes, uint32_t fmt, uint64_t height,
uint64_t SetLinearUploadLevels(TextureUploadMipLayout* mips,
const TileTextureElementLayout& element, uint64_t height,
uint64_t levels, uint32_t base_pitch) {
uint64_t offset = 0;
auto pitch = base_pitch;
auto h = static_cast<uint32_t>(height);
for (uint32_t i = 0; i < levels; i++) {
const auto size = CalcLinearUploadLevelSize(fmt, pitch, h);
EXIT_NOT_IMPLEMENTED(size > 0xffffffffull);
EXIT_NOT_IMPLEMENTED(offset > 0xffffffffull);
level_sizes[i].size = static_cast<uint32_t>(size);
level_sizes[i].offset = static_cast<uint32_t>(offset);
level_sizes[i].src_size = 0;
level_sizes[i].src_offset = 0;
level_sizes[i].x = 0;
level_sizes[i].y = 0;
const auto size = CalcLinearUploadLevelSize(element, pitch, h);
mips[i].size = size;
mips[i].offset = offset;
offset += size;
if (pitch > 1) {
@@ -307,141 +271,123 @@ uint64_t SetLinearUploadLevels(TileSizeOffset* level_sizes, uint32_t fmt, uint64
} // namespace
TextureUploadLayout TextureCalcUploadLayout(uint32_t fmt, uint64_t width, uint64_t height,
uint64_t levels, uint32_t depth, uint64_t pitch,
uint64_t tile, uint64_t upload_size,
bool allow_depth_tile, bool volume_texture,
const char* owner) {
TextureUploadLayout TextureCalcUploadLayout(uint32_t fmt, uint32_t width, uint32_t height,
uint32_t levels, uint32_t depth, uint32_t tile,
uint64_t upload_size, bool allow_depth_tile,
bool volume_texture, const char* owner) {
TextureUploadLayout layout {};
layout.tile = static_cast<uint32_t>(tile);
layout.pitch = static_cast<uint32_t>(pitch);
layout.texel_block = Prospero::BlockCompressedBytesPerBlock(fmt) != 0 ? 4u : 1u;
layout.volume_texture = volume_texture;
layout.surface.description = {
fmt,
tile,
volume_texture ? TileSurfaceDimension::Dim3D : TileSurfaceDimension::Dim2D,
width,
height,
volume_texture ? depth : 1u,
levels,
volume_texture ? 1u : depth,
};
const auto& description = layout.surface.description;
const auto tile_mode = static_cast<Prospero::TileMode>(description.tile_mode);
TileTextureElementLayout element {};
if (fmt != 0) {
if (layout.tile != 0) {
const auto tile_mode = static_cast<Prospero::TileMode>(layout.tile);
switch (tile_mode) {
case Prospero::TileMode::kStandard256B:
if (TileIsStandard256BTextureSupported(fmt)) {
layout.tile_family = TileBlockFamily::Standard256B;
}
break;
case Prospero::TileMode::kStandard4KB:
if (TileIsStandard4KBTextureSupported(fmt)) {
layout.tile_family = TileBlockFamily::Standard4KB;
}
break;
case Prospero::TileMode::kStandard64KB:
if (TileIsStandard64KBTextureSupported(fmt)) {
layout.tile_family = TileBlockFamily::Standard64KB;
}
break;
case Prospero::TileMode::kPrt:
if (TileIsStandard64KBTextureSupported(fmt)) {
layout.tile_family = TileBlockFamily::Prt64KB;
}
break;
case Prospero::TileMode::kRenderTarget:
if (Prospero::RenderTargetBytesPerElement(fmt) != 0) {
layout.tile_family = TileBlockFamily::RenderTarget64KB;
}
break;
case Prospero::TileMode::kDepth:
if (allow_depth_tile && Prospero::RenderTargetBytesPerElement(fmt) != 0) {
layout.tile_family = TileBlockFamily::Depth64KB;
}
break;
default: break;
}
if (layout.tile_family == TileBlockFamily::Count) {
EXIT("%s: unsupported typed tiled upload: fmt=%u tile=%u "
"size=%" PRIu64 " extent=%" PRIu64 "x%" PRIu64 " pitch=%" PRIu64
" levels=%" PRIu64 "\n",
owner, static_cast<uint32_t>(fmt), layout.tile, upload_size, width, height,
pitch, levels);
}
}
layout.pitch = TileGetTexturePitch(fmt, width, levels, layout.tile);
TileGetTextureSize(fmt, width, height, layout.pitch, levels, layout.tile, nullptr,
layout.level_sizes, layout.padded_sizes);
if (static_cast<Prospero::TileMode>(layout.tile) != Prospero::TileMode::kLinear) {
if (layout.volume_texture) {
layout.slice_stride = SetLinearUploadLevels(layout.level_sizes, fmt, height, levels,
static_cast<uint32_t>(width));
} else {
TileSizeOffset tiled_levels[16] {};
std::copy_n(layout.level_sizes, levels, tiled_levels);
layout.source_slice_stride =
CalcTextureSliceStride(tiled_levels, levels, upload_size, depth);
SetLinearUploadLevels(layout.level_sizes, fmt, height, levels, layout.pitch);
for (uint32_t i = 0; i < levels; ++i) {
if (tiled_levels[i].src_size > tiled_levels[i].size) {
layout.first_tail_level = std::min(layout.first_tail_level, i);
}
layout.level_sizes[i].src_offset = GetLevelSrcOffset(tiled_levels[i]);
layout.level_sizes[i].src_size = GetLevelSrcSize(tiled_levels[i]);
layout.level_sizes[i].x = tiled_levels[i].x;
layout.level_sizes[i].y = tiled_levels[i].y;
}
}
} else if (layout.volume_texture) {
layout.slice_stride =
CalcTextureSliceStride(layout.level_sizes, levels, upload_size, depth);
}
} else {
if (fmt == 0) {
EXIT("%s: legacy texture upload format unsupported: fmt=0 tile=%u size=%" PRIu64
" extent=%" PRIu64 "x%" PRIu64 " pitch=%" PRIu64 " levels=%" PRIu64 "\n",
owner, layout.tile, upload_size, width, height, pitch, levels);
" extent=%ux%u levels=%u\n",
owner, description.tile_mode, upload_size, width, height, levels);
}
if (!layout.volume_texture) {
layout.slice_stride =
CalcTextureSliceStride(layout.level_sizes, levels, upload_size, depth);
switch (tile_mode) {
case Prospero::TileMode::kLinear:
if (!TileGetTextureElementLayout(fmt, element)) {
EXIT("%s: unsupported linear texture format: fmt=%u\n", owner, fmt);
}
break;
case Prospero::TileMode::kDepth:
if (!allow_depth_tile || !TileGetTiledTextureLayout(description, layout.surface)) {
EXIT("%s: unsupported typed tiled upload: fmt=%u tile=%u "
"size=%" PRIu64 " extent=%ux%u levels=%u\n",
owner, static_cast<uint32_t>(fmt), description.tile_mode, upload_size, width,
height, levels);
}
break;
default:
if (!TileGetTiledTextureLayout(description, layout.surface)) {
EXIT("%s: unsupported typed tiled upload: fmt=%u tile=%u "
"size=%" PRIu64 " extent=%ux%u levels=%u\n",
owner, static_cast<uint32_t>(fmt), description.tile_mode, upload_size, width,
height, levels);
}
break;
}
if (tile_mode != Prospero::TileMode::kLinear) {
element = {layout.surface.texture.block.bytes_per_element,
layout.surface.texture.texel_width, layout.surface.texture.texel_height};
}
layout.pitch = TileGetTexturePitch(fmt, width, description.tile_mode);
if (tile_mode == Prospero::TileMode::kLinear) {
TileSizeOffset level_sizes[16] {};
TilePaddedSize padded_sizes[16] {};
TileGetTextureSize(fmt, width, height, levels, description.tile_mode, nullptr, level_sizes,
padded_sizes);
for (uint32_t level = 0; level < levels; ++level) {
layout.mips[level] = {level_sizes[level].offset, level_sizes[level].size,
padded_sizes[level].width, padded_sizes[level].height};
}
} else if (volume_texture) {
layout.slice_stride = SetLinearUploadLevels(layout.mips, element, height, levels, width);
} else {
layout.source_slice_stride = layout.surface.block_slice_size;
if (depth > 1 && upload_size != 0 && upload_size % depth == 0) {
layout.source_slice_stride = std::max(layout.source_slice_stride, upload_size / depth);
}
SetLinearUploadLevels(layout.mips, element, height, levels, layout.pitch);
}
if (!volume_texture || tile_mode == Prospero::TileMode::kLinear) {
layout.slice_stride = CalcTextureSliceStride(layout.mips, levels, upload_size, depth);
}
return layout;
}
std::vector<vk::BufferImageCopy> TextureBuildImageCopies(const TextureUploadLayout& layout,
uint32_t width, uint32_t height,
uint32_t depth, uint64_t levels,
bool array_texture, bool volume_texture) {
uint32_t mip_width = width;
uint32_t mip_height = height;
uint32_t mip_pitch = volume_texture && static_cast<Prospero::TileMode>(layout.tile) !=
Prospero::TileMode::kLinear
? width
: layout.pitch;
std::vector<vk::BufferImageCopy> TextureBuildImageCopies(const TextureUploadLayout& layout) {
const auto& description = layout.surface.description;
const bool volume_texture = description.dimension == TileSurfaceDimension::Dim3D;
const auto depth = volume_texture ? description.depth : description.layers;
uint32_t mip_width = description.width;
uint32_t mip_height = description.height;
uint32_t mip_pitch = volume_texture && static_cast<Prospero::TileMode>(description.tile_mode) !=
Prospero::TileMode::kLinear
? description.width
: layout.pitch;
std::vector<vk::BufferImageCopy> regions;
regions.reserve(GetTextureRegionCount(depth, levels, volume_texture));
for (uint32_t i = 0; i < levels; i++) {
EXIT_NOT_IMPLEMENTED(layout.level_sizes[i].size == 0);
regions.reserve(GetTextureRegionCount(depth, description.levels, volume_texture));
for (uint32_t i = 0; i < description.levels; i++) {
EXIT_NOT_IMPLEMENTED(layout.mips[i].size == 0);
const auto mip_depth = GetTextureLevelDepth(depth, i, volume_texture);
for (uint32_t z = 0; z < mip_depth; z++) {
const auto slice_offset = z * layout.slice_stride;
vk::BufferImageCopy region {};
region.bufferOffset = layout.level_sizes[i].offset + slice_offset;
region.imageSubresource = {vk::ImageAspectFlagBits::eColor, i, array_texture ? z : 0,
region.bufferOffset = layout.mips[i].offset + slice_offset;
region.imageSubresource = {vk::ImageAspectFlagBits::eColor, i, volume_texture ? 0u : z,
1};
region.imageOffset.z = volume_texture ? static_cast<int>(z) : 0;
region.imageExtent = {mip_width, mip_height, 1};
const bool linear =
static_cast<Prospero::TileMode>(layout.tile) == Prospero::TileMode::kLinear;
const bool linear = static_cast<Prospero::TileMode>(description.tile_mode) ==
Prospero::TileMode::kLinear;
if (linear) {
region.bufferRowLength = layout.padded_sizes[i].width;
region.bufferImageHeight = layout.padded_sizes[i].height;
region.bufferRowLength = layout.mips[i].row_length;
region.bufferImageHeight = layout.mips[i].image_height;
} else {
const auto align = [](uint32_t value, uint32_t block) {
const auto texel_width = layout.surface.texture.texel_width;
const auto align = [](uint32_t value, uint32_t block) {
return ((value + block - 1u) / block) * block;
};
const auto pitch = align(mip_pitch, layout.texel_block);
region.bufferRowLength = pitch > align(mip_width, layout.texel_block) ? pitch : 0;
const auto pitch = align(mip_pitch, texel_width);
region.bufferRowLength = pitch > align(mip_width, texel_width) ? pitch : 0;
}
regions.push_back(region);
}
@@ -460,24 +406,6 @@ std::vector<vk::BufferImageCopy> TextureBuildImageCopies(const TextureUploadLayo
return regions;
}
struct GpuTileElementLayout {
uint32_t bytes = 0;
uint32_t wide = 1;
uint32_t tall = 1;
};
static bool GetGpuTileElementLayout(uint32_t fmt, GpuTileElementLayout& out) {
if (const auto bytes = Prospero::NumBytesPerElement(fmt); bytes != 0) {
out = {bytes, 1, 1};
return true;
}
if (const auto bytes = Prospero::BlockCompressedBytesPerBlock(fmt); bytes != 0) {
out = {bytes, 4, 4};
return true;
}
return false;
}
static bool SetGpuTileSize(uint64_t offset, uint64_t length, uint64_t capacity, uint64_t& size) {
if (offset > capacity || length > capacity - offset) {
return false;
@@ -487,42 +415,32 @@ static bool SetGpuTileSize(uint64_t offset, uint64_t length, uint64_t capacity,
}
bool TextureBuildGpuTileInfos(uint64_t tiled_size, const std::vector<vk::BufferImageCopy>& regions,
const TextureUploadLayout& layout, uint32_t fmt, uint32_t depth,
uint64_t levels, std::vector<GpuTileInfo>& out_infos) {
const TextureUploadLayout& layout, uint32_t levels,
std::vector<GpuTileInfo>& out_infos) {
const auto& description = layout.surface.description;
const bool volume_texture = description.dimension == TileSurfaceDimension::Dim3D;
const auto depth = volume_texture ? description.depth : description.layers;
if (tiled_size == 0 || levels == 0 || levels > 16 || depth == 0 ||
regions.size() != GetTextureRegionCount(depth, levels, layout.volume_texture) ||
Prospero::IsFmaskTextureFormat(fmt)) {
regions.size() != GetTextureRegionCount(depth, levels, volume_texture) ||
Prospero::IsFmaskTextureFormat(description.format)) {
return false;
}
GpuTileElementLayout element {};
if (layout.tile_family == TileBlockFamily::RenderTarget64KB ||
layout.tile_family == TileBlockFamily::Depth64KB) {
element.bytes = Prospero::RenderTargetBytesPerElement(fmt);
} else if (!GetGpuTileElementLayout(fmt, element)) {
return false;
}
if (element.bytes == 0) {
const auto& surface = layout.surface;
const auto& texture = surface.texture;
const auto& block = texture.block;
if (surface.description.levels < levels || block.bytes_per_element == 0 ||
block.family == TileBlockFamily::Count) {
return false;
}
std::vector<GpuTileInfo> infos;
infos.reserve(regions.size());
if (layout.volume_texture) {
TileVolumeLayout volume {};
if (!TileGetTextureVolumeLayout(fmt, regions[0].imageExtent.width,
regions[0].imageExtent.height, depth,
static_cast<uint32_t>(levels), layout.tile, volume)) {
return false;
}
element = {volume.bytes_per_element, volume.texel_width, volume.texel_height};
TileBlockLayout block {};
if (!TileGetBlockLayout(volume.family, element.bytes, block)) return false;
if (volume_texture) {
size_t region_base = 0;
for (uint32_t level = 0; level < levels; ++level) {
const uint32_t mip_depth = GetTextureLevelDepth(depth, level, true);
const bool tail = level >= volume.first_tail_level;
const bool tail = level >= surface.first_tail_level;
const uint64_t linear_stride = layout.slice_stride;
for (uint32_t z = 0; z < mip_depth; z += block.block_depth) {
const uint32_t copy_depth = std::min(block.block_depth, mip_depth - z);
@@ -537,50 +455,43 @@ bool TextureBuildGpuTileInfos(uint64_t tiled_size, const std::vector<vk::BufferI
info.bytes_per_element = block.bytes_per_element;
info.linear_offset = region.bufferOffset;
info.tiled_offset =
static_cast<uint64_t>(z / block.block_depth) * volume.block_slice_size +
volume.level_offsets[level];
static_cast<uint64_t>(z / block.block_depth) * surface.block_slice_size +
surface.mips[level].offset;
const uint64_t linear_span =
static_cast<uint64_t>(copy_depth - 1u) * linear_stride +
layout.level_sizes[level].size;
layout.mips[level].size;
if (!SetGpuTileSize(info.linear_offset, linear_span, UINT64_MAX,
info.linear_size) ||
!SetGpuTileSize(info.tiled_offset, volume.level_sizes[level], tiled_size,
!SetGpuTileSize(info.tiled_offset, surface.mips[level].size, tiled_size,
info.tiled_size)) {
return false;
}
info.linear_slice_stride = linear_stride;
info.width =
std::max((region.imageExtent.width + element.wide - 1u) / element.wide, 1u);
info.height = std::max((logical_height + element.tall - 1u) / element.tall, 1u);
info.depth = copy_depth;
info.width = std::max((region.imageExtent.width + texture.texel_width - 1u) /
texture.texel_width,
1u);
info.height = std::max(
(logical_height + texture.texel_height - 1u) / texture.texel_height, 1u);
info.depth = copy_depth;
info.surface_z =
block.block_depth == 1 ? static_cast<uint32_t>(region.imageOffset.z) : 0;
info.pitch = std::max((pitch + element.wide - 1u) / element.wide, 1u);
info.tail_x = tail ? volume.tail_x[level] : 0;
info.tail_y = tail ? volume.tail_y[level] : 0;
info.pitch = std::max((pitch + texture.texel_width - 1u) / texture.texel_width, 1u);
info.tail_x = tail ? surface.mips[level].tail_x : 0;
info.tail_y = tail ? surface.mips[level].tail_y : 0;
info.tail = tail;
info.tiled_width = volume.level_widths[level];
info.tiled_height = volume.level_heights[level];
info.tiled_width = surface.mips[level].padded_width;
info.tiled_height = surface.mips[level].padded_height;
infos.push_back(info);
}
region_base += mip_depth;
}
} else {
const auto base_family = layout.tile_family;
if (base_family == TileBlockFamily::Count) {
return false;
}
size_t region_index = 0;
for (uint32_t level = 0; level < levels; level++) {
const auto& level_size = layout.level_sizes[level];
const bool tail = level >= layout.first_tail_level;
const auto family = base_family;
TileBlockLayout block {};
if (!TileGetBlockLayout(family, element.bytes, block)) {
return false;
}
const auto level_depth = GetTextureLevelDepth(depth, level, layout.volume_texture);
const auto& level_size = layout.mips[level];
const auto& mip = surface.mips[level];
const bool tail = level >= surface.first_tail_level;
const auto level_depth = GetTextureLevelDepth(depth, level, false);
for (uint32_t z = 0; z < level_depth; z++) {
const auto& region = regions[region_index++];
const auto pitch =
@@ -589,39 +500,36 @@ bool TextureBuildGpuTileInfos(uint64_t tiled_size, const std::vector<vk::BufferI
? region.bufferImageHeight
: region.imageExtent.height;
GpuTileInfo info {};
info.family = block.family;
info.bytes_per_element = block.bytes_per_element;
info.linear_offset = region.bufferOffset;
info.tiled_offset = TextureUploadSliceSourceOffset(layout, level, z);
if (!SetGpuTileSize(info.linear_offset, level_size.size, UINT64_MAX,
info.linear_size) ||
!SetGpuTileSize(info.tiled_offset, GetLevelSrcSize(level_size), tiled_size,
info.tiled_size)) {
info.family = block.family;
info.bytes_per_element = block.bytes_per_element;
info.linear_offset = region.bufferOffset;
const auto source_stride = layout.source_slice_stride != 0
? layout.source_slice_stride
: surface.block_slice_size;
if (z > (UINT64_MAX - mip.offset) / source_stride) {
return false;
}
info.width =
std::max((region.imageExtent.width + element.wide - 1u) / element.wide, 1u);
info.height = std::max((logical_height + element.tall - 1u) / element.tall, 1u);
info.surface_z = base_family == TileBlockFamily::RenderTarget64KB ||
base_family == TileBlockFamily::Depth64KB
info.tiled_offset = mip.offset + static_cast<uint64_t>(z) * source_stride;
if (!SetGpuTileSize(info.linear_offset, level_size.size, UINT64_MAX,
info.linear_size) ||
!SetGpuTileSize(info.tiled_offset, mip.size, tiled_size, info.tiled_size)) {
return false;
}
info.width = std::max((region.imageExtent.width + texture.texel_width - 1u) /
texture.texel_width,
1u);
info.height = std::max(
(logical_height + texture.texel_height - 1u) / texture.texel_height, 1u);
info.surface_z = block.family == TileBlockFamily::RenderTarget64KB ||
block.family == TileBlockFamily::Depth64KB
? region.imageSubresource.baseArrayLayer
: 0;
info.pitch = std::max((pitch + element.wide - 1u) / element.wide, 1u);
info.tail = tail;
info.tail_x = tail ? level_size.x : 0;
info.tail_y = tail ? level_size.y : 0;
info.tiled_width =
layout.padded_sizes[level].width != 0
? std::max((layout.padded_sizes[level].width + element.wide - 1u) /
element.wide,
1u)
: info.pitch;
info.tiled_height =
layout.padded_sizes[level].height != 0
? std::max((layout.padded_sizes[level].height + element.tall - 1u) /
element.tall,
1u)
: info.height;
info.pitch = std::max((pitch + texture.texel_width - 1u) / texture.texel_width, 1u);
info.tail = tail;
info.tail_x = tail ? mip.tail_x : 0;
info.tail_y = tail ? mip.tail_y : 0;
info.tiled_width = mip.padded_width;
info.tiled_height = mip.padded_height;
infos.push_back(info);
}
}
@@ -19,34 +19,32 @@ struct RenderTargetFormatInfo {
Prospero::ColorComponentMapping export_mapping;
};
struct TextureUploadMipLayout {
uint64_t offset = 0;
uint64_t size = 0;
uint32_t row_length = 0;
uint32_t image_height = 0;
};
struct TextureUploadLayout {
uint32_t tile = 0;
uint32_t pitch = 0;
uint32_t texel_block = 1;
uint64_t slice_stride = 0;
uint64_t source_slice_stride = 0;
uint32_t first_tail_level = 16;
TileBlockFamily tile_family = TileBlockFamily::Count;
bool volume_texture = false;
TileSizeOffset level_sizes[16] = {};
TilePaddedSize padded_sizes[16] = {};
uint32_t pitch = 0;
uint64_t slice_stride = 0;
uint64_t source_slice_stride = 0;
TileSurfaceLayout surface;
TextureUploadMipLayout mips[16] = {};
};
vk::ComponentMapping TextureGetComponentMapping(uint32_t swizzle);
vk::Format TextureGetFormat(uint32_t fmt);
RenderTargetFormatInfo TextureGetRenderTargetFormat(uint32_t layout, uint32_t type, uint32_t order);
TextureUploadLayout TextureCalcUploadLayout(uint32_t fmt, uint64_t width, uint64_t height,
uint64_t levels, uint32_t depth, uint64_t pitch,
uint64_t tile, uint64_t upload_size,
bool allow_depth_tile, bool volume_texture,
const char* owner);
std::vector<vk::BufferImageCopy> TextureBuildImageCopies(const TextureUploadLayout& layout,
uint32_t width, uint32_t height,
uint32_t depth, uint64_t levels,
bool array_texture, bool volume_texture);
TextureUploadLayout TextureCalcUploadLayout(uint32_t fmt, uint32_t width, uint32_t height,
uint32_t levels, uint32_t depth, uint32_t tile,
uint64_t upload_size, bool allow_depth_tile,
bool volume_texture, const char* owner);
std::vector<vk::BufferImageCopy> TextureBuildImageCopies(const TextureUploadLayout& layout);
bool TextureBuildGpuTileInfos(uint64_t tiled_size, const std::vector<vk::BufferImageCopy>& regions,
const TextureUploadLayout& layout, uint32_t fmt, uint32_t depth,
uint64_t levels, std::vector<GpuTileInfo>& infos);
const TextureUploadLayout& layout, uint32_t levels,
std::vector<GpuTileInfo>& infos);
} // namespace Libs::Graphics
@@ -239,7 +239,7 @@ bool IsSupportedDepthTargetDescriptor(const ShaderTextureResource& descriptor, c
const auto samples = multisampled ? 1u << descriptor.LastLevel() : 1u;
const auto pitch =
multisampled ? TileGetDepthPitch(width, image.info.bytes_per_block, descriptor.LastLevel())
: TileGetTexturePitch(descriptor.Format(), width, 1, descriptor.TileMode());
: TileGetTexturePitch(descriptor.Format(), width, descriptor.TileMode());
const bool supported_2d = type == Prospero::ImageType::kColor2D &&
image.info.resources.layers == 1 && descriptor.Depth() == 0 &&
descriptor.BaseArray5() == 0;
@@ -321,7 +321,7 @@ static void ValidateDepthTargetBinding(const ShaderRecompiler::IR::ImageResource
return;
}
const auto descriptor_pitch =
TileGetTexturePitch(descriptor.Format(), static_cast<uint32_t>(descriptor.Width5()) + 1u, 1,
TileGetTexturePitch(descriptor.Format(), static_cast<uint32_t>(descriptor.Width5()) + 1u,
descriptor.TileMode());
EXIT("unsupported sampled depth target: resource=%d descriptor=%d encoding=%d format=%d "
"kind=%u dimension=%u mip_mode=%u read=%d written=%d atomic=%d compare=%d "
@@ -373,26 +373,33 @@ static bool IsSupportedStorageTextureDescriptor(const ShaderRecompiler::IR::Imag
const bool is_3d = resource.dimension == ShaderRecompiler::Decoder::ImageDimension::Dim3D &&
descriptor.Type() == Prospero::GpuEnumValue(Prospero::ImageType::kColor3D) &&
descriptor.BaseArray5() == 0;
TileBlockLayout depth_block {};
const auto depth_bpe = Prospero::RenderTargetBytesPerElement(descriptor.Format());
const bool supported_depth_tile =
tile == Prospero::GpuEnumValue(Prospero::TileMode::kDepth) && !resource.read &&
!Prospero::IsFmaskTextureFormat(descriptor.Format()) && (is_2d || is_2d_array) &&
TileGetBlockLayout(TileBlockFamily::Depth64KB, depth_bpe, depth_block);
const bool supported_standard_256b =
(is_2d || is_2d_array) &&
tile == Prospero::GpuEnumValue(Prospero::TileMode::kStandard256B) &&
TileIsStandard256BTextureSupported(descriptor.Format());
const bool supported_standard_tile =
(tile == Prospero::GpuEnumValue(Prospero::TileMode::kStandard4KB) &&
TileIsStandard4KBTextureSupported(descriptor.Format())) ||
(tile == Prospero::GpuEnumValue(Prospero::TileMode::kStandard64KB) &&
TileIsStandard64KBTextureSupported(descriptor.Format()));
const bool supported_tile = tile == Prospero::GpuEnumValue(Prospero::TileMode::kLinear) ||
tile == Prospero::GpuEnumValue(Prospero::TileMode::kRenderTarget) ||
supported_depth_tile || supported_standard_256b ||
supported_standard_tile;
const auto swizzle = descriptor.DstSelXYZW();
TileTextureBlockLayout tile_layout {};
bool supported_tile = false;
switch (static_cast<Prospero::TileMode>(tile)) {
case Prospero::TileMode::kLinear: supported_tile = true; break;
case Prospero::TileMode::kDepth:
supported_tile =
!resource.read && !Prospero::IsFmaskTextureFormat(descriptor.Format()) &&
(is_2d || is_2d_array) &&
TileGetTextureBlockLayout(descriptor.Format(), tile, false, tile_layout);
break;
case Prospero::TileMode::kStandard256B:
supported_tile =
(is_2d || is_2d_array) &&
TileGetTextureBlockLayout(descriptor.Format(), tile, false, tile_layout);
break;
case Prospero::TileMode::kStandard4KB:
case Prospero::TileMode::kStandard64KB:
supported_tile =
TileGetTextureBlockLayout(descriptor.Format(), tile, is_3d, tile_layout);
break;
case Prospero::TileMode::kRenderTarget:
supported_tile =
TileGetTextureBlockLayout(descriptor.Format(), tile, false, tile_layout);
break;
default: break;
}
const auto swizzle = descriptor.DstSelXYZW();
const bool supported_swizzle =
IsValidImageSwizzle(swizzle) &&
(swizzle == DstSel(4, 5, 6, 7) || !resource.read || resource.atomic);
@@ -498,18 +505,20 @@ static TextureCache::ImageDesc NullTextureDesc(const ShaderRecompiler::IR::Image
static void PopulateTextureMipLayout(ImageInfo& info) {
if (info.IsVolume() && info.tile_mode != Prospero::GpuEnumValue(Prospero::TileMode::kLinear)) {
TileVolumeLayout volume {};
if (!TileGetTextureVolumeLayout(info.guest_format, info.extent.width, info.extent.height,
info.extent.depth, info.resources.levels, info.tile_mode,
volume)) {
TileSurfaceLayout surface {};
const TileSurfaceDescription description {
info.guest_format, info.tile_mode, TileSurfaceDimension::Dim3D, info.extent.width,
info.extent.height, info.extent.depth, info.resources.levels, 1};
if (!TileGetTiledTextureLayout(description, surface)) {
EXIT("unsupported normalized volume texture layout\n");
}
for (uint32_t level = 0; level < info.resources.levels; level++) {
const auto& mip = surface.mips[level];
info.mip_layout[level] = {
volume.level_offsets[level],
volume.level_sizes[level],
volume.level_widths[level],
volume.level_heights[level],
mip.offset,
mip.size,
mip.padded_width,
mip.padded_height,
};
}
return;
@@ -517,7 +526,7 @@ static void PopulateTextureMipLayout(ImageInfo& info) {
TileSizeOffset levels[16] {};
TilePaddedSize padded[16] {};
TileGetTextureSize(info.guest_format, info.extent.width, info.extent.height, info.pitch,
TileGetTextureSize(info.guest_format, info.extent.width, info.extent.height,
info.resources.levels, info.tile_mode, nullptr, levels, padded);
for (uint32_t level = 0; level < info.resources.levels; level++) {
const auto offset =
@@ -675,9 +684,9 @@ RenderExecutor::ResolveTexture(const ShaderRecompiler::IR::ImageResource& reso
}
size.size *= image_layers;
} else {
pitch = TileGetTexturePitch(format, width, levels, tile);
TileGetTextureTotalSize(format, width, height, volume ? depth : image_layers, pitch, levels,
tile, volume, size);
pitch = TileGetTexturePitch(format, width, tile);
TileGetTextureTotalSize(format, width, height, volume ? depth : image_layers, levels, tile,
volume, size);
}
EXIT_NOT_IMPLEMENTED(size.size == 0 || size.align == 0 ||
(address & (static_cast<uint64_t>(size.align) - 1u)) != 0);
+2 -2
View File
@@ -537,10 +537,10 @@ Graphics::ImageInfo BufferAttributeGroup::ImageInfo(const VideoOutBuffer& buffer
const auto tile_mode =
Graphics::Prospero::GpuEnumValue(Graphics::Prospero::TileMode::kRenderTarget);
const auto pitch =
Graphics::TileGetTexturePitch(pixel_format.guest_format, attribute.width, 1, tile_mode);
Graphics::TileGetTexturePitch(pixel_format.guest_format, attribute.width, tile_mode);
Graphics::TileSizeAlign total {};
Graphics::TileGetTextureTotalSize(pixel_format.guest_format, attribute.width, attribute.height,
1, pitch, 1, tile_mode, false, total);
1, 1, tile_mode, false, total);
if (total.size == 0 || total.align != 65536 ||
(buffer.data_address & (total.align - 1u)) != 0) {
EXIT("invalid video-out surface footprint or alignment\n");
+168 -157
View File
@@ -2970,11 +2970,11 @@ public:
constexpr uint32_t mip_height = 1;
constexpr uint32_t mip_levels = 1;
const uint32_t mip_pitch =
TileGetTexturePitch(mip_format, mip_width, mip_levels, mip_tile);
TileGetTexturePitch(mip_format, mip_width, mip_tile);
TileSizeAlign mip_total {};
std::array<TileSizeOffset, 16> mip_sizes {};
std::array<TilePaddedSize, 16> mip_padded {};
TileGetTextureSize(mip_format, mip_width, mip_height, mip_pitch, mip_levels, mip_tile,
TileGetTextureSize(mip_format, mip_width, mip_height, mip_levels, mip_tile,
&mip_total, mip_sizes.data(), mip_padded.data());
const uint64_t mip_prefix_size = mip_sizes[0].offset + mip_sizes[0].size;
const uint64_t mip_guest_size = mip_total.size + 256;
@@ -3866,11 +3866,10 @@ public:
0.625f, 0.75f, 0.875f, 1.0f, 0.0625f};
std::memset(memory + layered_offset, 0, layered_guest_size);
const auto layered_layout = TextureCalcUploadLayout(
Prospero::GpuEnumValue(Prospero::BufferFormat::k32Float), 2, 2, 2, 2, 2,
Prospero::GpuEnumValue(Prospero::BufferFormat::k32Float), 2, 2, 2, 2,
Prospero::GpuEnumValue(Prospero::TileMode::kLinear), layered_guest_size, true,
false, "UnifiedTextureCacheFlow");
const auto layered_upload_regions =
TextureBuildImageCopies(layered_layout, 2, 2, 2, 2, true, false);
const auto layered_upload_regions = TextureBuildImageCopies(layered_layout);
Require(name, "layered guest layout", layered_upload_regions.size() == 4,
"unexpected layered/mipped upload-region count");
for (const auto& region: layered_upload_regions) {
@@ -5181,11 +5180,11 @@ public:
{
GpuResourceManager resources(m_runtime_context, scheduler);
resources.MapMemory(base, allocation_size);
const uint32_t pitch = TileGetTexturePitch(format, 1, 1, tile);
const uint32_t pitch = TileGetTexturePitch(format, 1, tile);
TileSizeAlign total {};
TileSizeOffset mip {};
TilePaddedSize padded {};
TileGetTextureSize(format, 1, 1, pitch, 1, tile, &total, &mip, &padded);
TileGetTextureSize(format, 1, 1, 1, tile, &total, &mip, &padded);
Require(name, "tiled layout", total.size >= 8 && total.size <= allocation_size,
"BGRA16 tiled layout exceeds its guest allocation");
std::memset(mapped, 0x5a, total.size);
@@ -5465,9 +5464,8 @@ public:
constexpr auto stencil_format = Prospero::GpuEnumValue(Prospero::BufferFormat::k8UInt);
constexpr auto linear = Prospero::GpuEnumValue(Prospero::TileMode::kLinear);
const auto stencil_pitch = TileGetTexturePitch(stencil_format, 1, 1, linear);
TileSizeAlign stencil_layout {};
TileGetTextureTotalSize(stencil_format, 1, 1, 1, stencil_pitch, 1, linear, false,
TileGetTextureTotalSize(stencil_format, 1, 1, 1, 1, linear, false,
stencil_layout);
Require(name, "stencil footprint",
stencil_layout.size != 0 && stencil_layout.align != 0 &&
@@ -7717,7 +7715,7 @@ public:
TileSizeAlign total {};
TileSizeOffset mip[levels] {};
TilePaddedSize padded[levels] {};
TileGetTextureSize(format, 65, 33, 72, levels,
TileGetTextureSize(format, 65, 33, levels,
Prospero::GpuEnumValue(Prospero::TileMode::kStandard256B), &total,
mip, padded);
constexpr u32 offsets[levels] = {0x1a00, 0xb00, 0x500, 0x300, 0x200, 0x100, 0};
@@ -7826,18 +7824,57 @@ public:
struct StandardMode {
u32 tile;
TileBlockFamily family;
bool (*supported)(u32);
};
constexpr StandardMode standard_modes[] = {
{Prospero::GpuEnumValue(Prospero::TileMode::kStandard256B),
TileBlockFamily::Standard256B, TileIsStandard256BTextureSupported},
{Prospero::GpuEnumValue(Prospero::TileMode::kStandard4KB), TileBlockFamily::Standard4KB,
TileIsStandard4KBTextureSupported},
TileBlockFamily::Standard256B},
{Prospero::GpuEnumValue(Prospero::TileMode::kStandard4KB),
TileBlockFamily::Standard4KB},
{Prospero::GpuEnumValue(Prospero::TileMode::kStandard64KB),
TileBlockFamily::Standard64KB, TileIsStandard64KBTextureSupported},
{Prospero::GpuEnumValue(Prospero::TileMode::kPrt), TileBlockFamily::Prt64KB,
TileIsStandard64KBTextureSupported},
TileBlockFamily::Standard64KB},
{Prospero::GpuEnumValue(Prospero::TileMode::kPrt), TileBlockFamily::Prt64KB},
};
for (const auto format: {Prospero::BufferFormat::k8Srgb,
Prospero::BufferFormat::k8_8Srgb,
Prospero::BufferFormat::k9_9_9_5Float}) {
for (const auto tile: {Prospero::TileMode::kDepth,
Prospero::TileMode::kRenderTarget}) {
TileTextureBlockLayout texture {};
Require(name, "RT format policy",
!TileGetTextureBlockLayout(Prospero::GpuEnumValue(format),
Prospero::GpuEnumValue(tile), false, texture),
"non-render-target format admitted by an RT/depth tile family");
}
}
{
TileSurfaceLayout invalid {};
const TileSurfaceDescription description {
Prospero::GpuEnumValue(Prospero::BufferFormat::k32Float),
Prospero::GpuEnumValue(Prospero::TileMode::kStandard256B),
TileSurfaceDimension::Dim3D,
16,
16,
16,
1,
1,
};
Require(name, "3D tile policy", !TileGetTiledTextureLayout(description, invalid),
"Standard256B volume silently fell back to a 2D array layout");
}
{
constexpr u32 format =
Prospero::GpuEnumValue(Prospero::BufferFormat::kFmask8_S4_F4);
constexpr u32 tile = Prospero::GpuEnumValue(Prospero::TileMode::kStandard64KB);
TileSizeAlign total {};
TileGetTextureSize(format, 128, 128, 1, tile, &total, nullptr, nullptr);
const auto layout = TextureCalcUploadLayout(format, 128, 128, 1, 1, tile, total.size,
false, false, name);
const auto regions = TextureBuildImageCopies(layout);
std::vector<GpuTileInfo> infos;
Require(name, "FMASK policy",
!TextureBuildGpuTileInfos(total.size, regions, layout, 1, infos),
"FMASK entered the texel tiler through a non-depth family");
}
u32 format_cases = 0;
for (u32 format = 1; format <= Prospero::GpuEnumValue(Prospero::BufferFormat::kBc7Srgb);
++format) {
@@ -7847,30 +7884,28 @@ public:
continue;
}
for (const auto& mode: standard_modes) {
if (!mode.supported(format)) {
TileTextureBlockLayout texture {};
if (!TileGetTextureBlockLayout(format, mode.tile, false, texture)) {
continue;
}
const u32 bpe = std::max(Prospero::NumBytesPerElement(format),
Prospero::BlockCompressedBytesPerBlock(format));
TileBlockLayout block {};
Require(name, "format block", TileGetBlockLayout(mode.family, bpe, block),
"CPU-supported format has no GPU family/BPE mapping");
const u32 bpe = texture.block.bytes_per_element;
Require(name, "format block", texture.block.family == mode.family,
"CPU-supported format selected the wrong block family");
constexpr u32 width = 67;
constexpr u32 height = 51;
const u32 pitch = TileGetTexturePitch(format, width, 1, mode.tile);
const u32 pitch = TileGetTexturePitch(format, width, mode.tile);
TileSizeAlign total {};
TileGetTextureSize(format, width, height, pitch, 1, mode.tile, &total, nullptr,
TileGetTextureSize(format, width, height, 1, mode.tile, &total, nullptr,
nullptr);
Require(name, "format size", total.size != 0,
"supported format has an empty layout");
const auto layout = TextureCalcUploadLayout(
format, width, height, 1, 1, pitch, mode.tile, total.size, false, false, name);
const auto regions =
TextureBuildImageCopies(layout, width, height, 1, 1, false, false);
format, width, height, 1, 1, mode.tile, total.size, false, false, name);
const auto regions = TextureBuildImageCopies(layout);
std::vector<GpuTileInfo> infos;
if (!TextureBuildGpuTileInfos(total.size, regions, layout, format, 1, 1, infos)) {
if (!TextureBuildGpuTileInfos(total.size, regions, layout, 1, infos)) {
std::ostringstream out;
out << "format=" << format << " tile=" << mode.tile << " size=" << total.size
<< " pitch=" << pitch;
@@ -7894,27 +7929,31 @@ public:
Require(name, "format coverage", format_cases != 0,
"no CPU-supported standard formats were tested");
{
constexpr u32 format = Prospero::GpuEnumValue(Prospero::BufferFormat::k32_32_32Float);
TileTextureElementLayout element {};
Require(name, "RGB32 texture policy", !TileGetTextureElementLayout(format, element),
"12-byte texel layouts must be rejected");
}
{
constexpr u32 format = Prospero::GpuEnumValue(Prospero::BufferFormat::kBc1UNorm);
constexpr u32 tile = Prospero::GpuEnumValue(Prospero::TileMode::kStandard64KB);
constexpr u32 width = 256, height = 256, levels = 9;
const u32 pitch = TileGetTexturePitch(format, width, levels, tile);
TileSizeAlign total {};
TileGetTextureSize(format, width, height, pitch, levels, tile, &total, nullptr,
TileGetTextureSize(format, width, height, levels, tile, &total, nullptr,
nullptr);
const auto layout = TextureCalcUploadLayout(format, width, height, levels, 1, pitch,
tile, total.size, false, false, name);
const auto regions =
TextureBuildImageCopies(layout, width, height, 1, levels, false, false);
const auto layout = TextureCalcUploadLayout(format, width, height, levels, 1, tile,
total.size, false, false, name);
const auto regions = TextureBuildImageCopies(layout);
std::vector<GpuTileInfo> infos;
const bool built =
TextureBuildGpuTileInfos(total.size, regions, layout, format, 1, levels, infos);
const bool built = TextureBuildGpuTileInfos(total.size, regions, layout, levels, infos);
uint64_t linear_size = 0;
for (const auto& info: infos) {
linear_size = std::max(linear_size, info.linear_offset + info.linear_size);
}
Require(name, "BC1 mip-tail capacities",
built && total.size == 0x10000 && layout.first_tail_level == 0 &&
built && total.size == 0x10000 && layout.surface.first_tail_level == 0 &&
linear_size == 0x15560 && linear_size > total.size,
"BC1 mip tail conflated tiled and linear capacities");
check_round_trip("BC1 mip tail", total.size, infos);
@@ -7924,16 +7963,13 @@ public:
constexpr u32 format = Prospero::GpuEnumValue(Prospero::BufferFormat::k32Float);
constexpr u32 tile = Prospero::GpuEnumValue(Prospero::TileMode::kRenderTarget);
constexpr u32 width = 129, height = 65, layers = 3;
const u32 pitch = TileGetTexturePitch(format, width, 1, tile);
TileSizeAlign total {};
TileGetTextureTotalSize(format, width, height, layers, pitch, 1, tile, false, total);
const auto layout = TextureCalcUploadLayout(format, width, height, 1, layers, pitch,
tile, total.size, true, false, name);
const auto regions =
TextureBuildImageCopies(layout, width, height, layers, 1, true, false);
TileGetTextureTotalSize(format, width, height, layers, 1, tile, false, total);
const auto layout = TextureCalcUploadLayout(format, width, height, 1, layers, tile,
total.size, true, false, name);
const auto regions = TextureBuildImageCopies(layout);
std::vector<GpuTileInfo> infos;
const bool built =
TextureBuildGpuTileInfos(total.size, regions, layout, format, layers, 1, infos);
const bool built = TextureBuildGpuTileInfos(total.size, regions, layout, 1, infos);
Require(name, "array infos",
built && infos.size() == layers && infos[0].surface_z == 0 &&
infos[1].surface_z == 1 && infos[2].surface_z == 2,
@@ -7949,18 +7985,16 @@ public:
"odd multi-mip format has no block layout");
const u32 width = block.block_width * 2u + 1u;
const u32 height = block.block_height * 2u + 1u;
const u32 pitch = TileGetTexturePitch(format, width, levels, mode.tile);
TileSizeAlign total {};
TileGetTextureSize(format, width, height, pitch, levels, mode.tile, &total, nullptr,
TileGetTextureSize(format, width, height, levels, mode.tile, &total, nullptr,
nullptr);
const auto layout = TextureCalcUploadLayout(format, width, height, levels, 1, pitch,
mode.tile, total.size, false, false, name);
const auto regions =
TextureBuildImageCopies(layout, width, height, 1, levels, false, false);
const auto layout = TextureCalcUploadLayout(format, width, height, levels, 1, mode.tile,
total.size, false, false, name);
const auto regions = TextureBuildImageCopies(layout);
std::vector<GpuTileInfo> infos;
Require(
name, "odd mip infos",
TextureBuildGpuTileInfos(total.size, regions, layout, format, 1, levels, infos) &&
TextureBuildGpuTileInfos(total.size, regions, layout, levels, infos) &&
infos.size() == 2 && infos[1].tiled_width >= infos[1].pitch &&
infos[1].tiled_height >= infos[1].height &&
(mode.family == TileBlockFamily::Standard256B ||
@@ -7992,19 +8026,16 @@ public:
"2D tail mode has no block layout");
const u32 width = block.block_width * 2u;
const u32 height = block.block_height * 2u;
const u32 pitch = TileGetTexturePitch(format, width, levels, mode.tile);
TileSizeAlign total {};
TileGetTextureSize(format, width, height, pitch, levels, mode.tile, &total, nullptr,
TileGetTextureSize(format, width, height, levels, mode.tile, &total, nullptr,
nullptr);
const auto layout = TextureCalcUploadLayout(format, width, height, levels, 1, pitch,
mode.tile, total.size, true, false, name);
const auto regions =
TextureBuildImageCopies(layout, width, height, 1, levels, false, false);
const auto layout = TextureCalcUploadLayout(format, width, height, levels, 1, mode.tile,
total.size, true, false, name);
const auto regions = TextureBuildImageCopies(layout);
std::vector<GpuTileInfo> infos;
Require(name, "2D mip tail seam",
layout.first_tail_level == 2 &&
TextureBuildGpuTileInfos(total.size, regions, layout, format, 1, levels,
infos) &&
layout.surface.first_tail_level == 2 &&
TextureBuildGpuTileInfos(total.size, regions, layout, levels, infos) &&
infos.size() == levels && !infos[0].tail && !infos[1].tail &&
std::all_of(infos.begin() + 2, infos.end(),
[](const auto& info) { return info.tail; }),
@@ -8019,16 +8050,13 @@ public:
constexpr u32 height = 129;
constexpr u32 depth = 17;
constexpr u32 levels = 2;
const u32 pitch = TileGetTexturePitch(format, width, levels, tile);
TileSizeAlign total {};
TileGetTextureTotalSize(format, width, height, depth, pitch, levels, tile, true, total);
const auto layout = TextureCalcUploadLayout(format, width, height, levels, depth, pitch,
tile, total.size, false, true, name);
const auto regions =
TextureBuildImageCopies(layout, width, height, depth, levels, false, true);
TileGetTextureTotalSize(format, width, height, depth, levels, tile, true, total);
const auto layout = TextureCalcUploadLayout(format, width, height, levels, depth, tile,
total.size, false, true, name);
const auto regions = TextureBuildImageCopies(layout);
std::vector<GpuTileInfo> infos;
const bool built =
TextureBuildGpuTileInfos(total.size, regions, layout, format, depth, levels, infos);
const bool built = TextureBuildGpuTileInfos(total.size, regions, layout, levels, infos);
Require(name, "3D mip infos",
regions.size() == depth + (depth >> 1u) && built && infos.size() == 4 &&
infos[0].depth == 8 && infos[1].depth == 8 && infos[2].depth == 1 &&
@@ -8048,17 +8076,14 @@ public:
constexpr u32 height = 129;
constexpr u32 depth = 17;
constexpr u32 levels = 2;
const u32 pitch = TileGetTexturePitch(format, width, levels, tile);
TileSizeAlign total {};
TileGetTextureTotalSize(format, width, height, depth, pitch, levels, tile, true, total);
const auto layout = TextureCalcUploadLayout(format, width, height, levels, depth, pitch,
tile, total.size, false, true, name);
const auto regions =
TextureBuildImageCopies(layout, width, height, depth, levels, false, true);
TileGetTextureTotalSize(format, width, height, depth, levels, tile, true, total);
const auto layout = TextureCalcUploadLayout(format, width, height, levels, depth, tile,
total.size, false, true, name);
const auto regions = TextureBuildImageCopies(layout);
std::vector<GpuTileInfo> infos;
Require(name, "3D BC mip infos",
TextureBuildGpuTileInfos(total.size, regions, layout, format, depth, levels,
infos) &&
TextureBuildGpuTileInfos(total.size, regions, layout, levels, infos) &&
infos.size() == 4 && infos[3].pitch == 8 && infos[3].height == 16 &&
infos[3].tiled_width == 16 && infos[3].tiled_height == 24,
"block-compressed 3D mip lost its physical row or slice stride");
@@ -8069,14 +8094,12 @@ public:
constexpr u32 format = Prospero::GpuEnumValue(Prospero::BufferFormat::kBc3UNorm);
constexpr u32 tile = Prospero::GpuEnumValue(Prospero::TileMode::kLinear);
constexpr u32 width = 8, height = 8, levels = 4;
const u32 pitch = TileGetTexturePitch(format, width, levels, tile);
TileSizeAlign total {};
TileGetTextureSize(format, width, height, pitch, levels, tile, &total, nullptr,
TileGetTextureSize(format, width, height, levels, tile, &total, nullptr,
nullptr);
const auto layout = TextureCalcUploadLayout(format, width, height, levels, 1, pitch,
tile, total.size, false, false, name);
const auto regions =
TextureBuildImageCopies(layout, width, height, 1, levels, false, false);
const auto layout = TextureCalcUploadLayout(format, width, height, levels, 1, tile,
total.size, false, false, name);
const auto regions = TextureBuildImageCopies(layout);
Require(name, "linear BC native regions",
regions.size() == levels &&
std::all_of(regions.begin(), regions.end(),
@@ -8114,18 +8137,15 @@ public:
};
for (const auto test: volume_modes) {
constexpr u32 width = 65, height = 33, depth = 37, levels = 6;
const u32 pitch = TileGetTexturePitch(test.format, width, levels, test.tile);
TileSizeAlign total {};
TileGetTextureTotalSize(test.format, width, height, depth, pitch, levels, test.tile,
true, total);
TileGetTextureTotalSize(test.format, width, height, depth, levels, test.tile, true,
total);
const auto layout =
TextureCalcUploadLayout(test.format, width, height, levels, depth, pitch, test.tile,
TextureCalcUploadLayout(test.format, width, height, levels, depth, test.tile,
total.size, true, true, name);
const auto regions =
TextureBuildImageCopies(layout, width, height, depth, levels, false, true);
const auto regions = TextureBuildImageCopies(layout);
std::vector<GpuTileInfo> infos;
const bool built = TextureBuildGpuTileInfos(total.size, regions, layout, test.format,
depth, levels, infos);
const bool built = TextureBuildGpuTileInfos(total.size, regions, layout, levels, infos);
const bool uses_z = test.family == TileBlockFamily::RenderTarget64KB ||
test.family == TileBlockFamily::Depth64KB;
Require(
@@ -8168,21 +8188,18 @@ public:
const u32 width = block.block_width * (compressed ? 4u : 1u);
const u32 height = block.block_height / 2u * (compressed ? 4u : 1u);
const u32 depth = block.block_depth + 1u;
const u32 pitch = TileGetTexturePitch(tail.format, width, levels, tile);
TileSizeAlign total {};
TileGetTextureTotalSize(tail.format, width, height, depth, pitch, levels, tile, true,
TileGetTextureTotalSize(tail.format, width, height, depth, levels, tile, true,
total);
const auto layout = TextureCalcUploadLayout(tail.format, width, height, levels, depth,
pitch, tile, total.size, false, true, name);
const auto regions =
TextureBuildImageCopies(layout, width, height, depth, levels, false, true);
tile, total.size, false, true, name);
const auto regions = TextureBuildImageCopies(layout);
std::vector<GpuTileInfo> infos;
bool valid =
total.size == 8192 &&
regions.size() == depth + std::max(depth >> 1u, 1u) + std::max(depth >> 2u, 1u) +
std::max(depth >> 3u, 1u) + std::max(depth >> 4u, 1u) &&
TextureBuildGpuTileInfos(total.size, regions, layout, tail.format, depth, levels,
infos) &&
TextureBuildGpuTileInfos(total.size, regions, layout, levels, infos) &&
infos.size() == 6;
const u32 table = std::countr_zero(tail.bytes);
for (u32 level = 0; level < levels && valid; level++) {
@@ -8280,15 +8297,14 @@ public:
constexpr u32 volume_width = 8, volume_height = 4, volume_depth = 5;
constexpr u32 volume_levels = 3;
const u32 volume_pitch =
TileGetTexturePitch(volume_format, volume_width, volume_levels, volume_tile);
TileGetTexturePitch(volume_format, volume_width, volume_tile);
TileSizeAlign volume_size {};
TileGetTextureTotalSize(volume_format, volume_width, volume_height, volume_depth,
volume_pitch, volume_levels, volume_tile, true, volume_size);
volume_levels, volume_tile, true, volume_size);
const auto volume_layout = TextureCalcUploadLayout(
volume_format, volume_width, volume_height, volume_levels, volume_depth, volume_pitch,
volume_tile, volume_size.size, true, true, name);
const auto volume_copies = TextureBuildImageCopies(
volume_layout, volume_width, volume_height, volume_depth, volume_levels, false, true);
volume_format, volume_width, volume_height, volume_levels, volume_depth, volume_tile,
volume_size.size, true, true, name);
const auto volume_copies = TextureBuildImageCopies(volume_layout);
std::vector<u32> volume_source(volume_size.size / sizeof(u32), 0);
std::vector<std::pair<size_t, u32>> volume_probes;
for (const auto& copy: volume_copies) {
@@ -8323,9 +8339,10 @@ public:
volume_info.bytes_per_block = sizeof(u32);
volume_info.tile_mode = volume_tile;
for (u32 level = 0; level < volume_levels; level++) {
volume_info.mip_layout[level] = {
volume_layout.level_sizes[level].offset, volume_layout.level_sizes[level].size,
volume_layout.padded_sizes[level].width, volume_layout.padded_sizes[level].height};
volume_info.mip_layout[level] = {volume_layout.mips[level].offset,
volume_layout.mips[level].size,
volume_layout.mips[level].row_length,
volume_layout.mips[level].image_height};
}
Libs::Graphics::Image volume_image(m_runtime_context, scheduler, volume_info);
volume_image.Upload(volume_copies, volume_upload.buffer, 0, volume_size.size);
@@ -16988,12 +17005,10 @@ void CheckBasicStorageTextureDescriptor() {
}};
auto standard256b_resource = BasicBgraStorageTextureResource();
standard256b_resource.kind = ShaderRecompiler::IR::ResourceKind::StorageImageUint;
const auto standard256b_pitch = TileGetTexturePitch(
standard256b.Format(), standard256b.Width5() + 1u, 1, standard256b.TileMode());
TileSizeAlign standard256b_size {};
TileGetTextureTotalSize(standard256b.Format(), standard256b.Width5() + 1u,
standard256b.Height5() + 1u, standard256b.Depth() + 1u,
standard256b_pitch, 1, standard256b.TileMode(), false,
1, standard256b.TileMode(), false,
standard256b_size);
Require("BasicStorageTexture", "Standard256B uint 2D descriptor",
standard256b.Width5() + 1u == 2 && standard256b.Height5() + 1u == 2 &&
@@ -17009,10 +17024,8 @@ void CheckBasicStorageTextureDescriptor() {
ValidateStorageTexture(standard256b_resource, standard256b, standard256b_size.size);
const auto standard4kb_array = Standard4KBUintArrayStorageTextureDescriptor();
const auto standard4kb_pitch =
TileGetTexturePitch(standard4kb_array.Format(), 1, 1, standard4kb_array.TileMode());
TileSizeAlign standard4kb_size {};
TileGetTextureTotalSize(standard4kb_array.Format(), 1, 1, 1, standard4kb_pitch, 1,
TileGetTextureTotalSize(standard4kb_array.Format(), 1, 1, 1, 1,
standard4kb_array.TileMode(), false, standard4kb_size);
Require(
"BasicStorageTexture", "Standard4KB uint 2D-array descriptor",
@@ -17029,11 +17042,9 @@ void CheckBasicStorageTextureDescriptor() {
auto based_standard4kb_array = standard4kb_array;
based_standard4kb_array.fields[0] = 0x006c6800u;
based_standard4kb_array.fields[4] = 0x00010001u;
const auto based_standard4kb_pitch = TileGetTexturePitch(based_standard4kb_array.Format(), 1, 1,
based_standard4kb_array.TileMode());
TileSizeAlign based_standard4kb_size {};
TileGetTextureTotalSize(based_standard4kb_array.Format(), 1, 1,
based_standard4kb_array.Depth() + 1u, based_standard4kb_pitch, 1,
based_standard4kb_array.Depth() + 1u, 1,
based_standard4kb_array.TileMode(), false, based_standard4kb_size);
Require("BasicStorageTexture", "based Standard4KB array view",
based_standard4kb_array.Base40() == 0x6c680000ull &&
@@ -17044,12 +17055,10 @@ void CheckBasicStorageTextureDescriptor() {
based_standard4kb_size.size);
const auto standard64kb = Standard64KBStorageTextureDescriptor();
const auto standard64kb_pitch = TileGetTexturePitch(
standard64kb.Format(), standard64kb.Width5() + 1u, 1, standard64kb.TileMode());
TileSizeAlign standard64kb_size {};
TileGetTextureTotalSize(standard64kb.Format(), standard64kb.Width5() + 1u,
standard64kb.Height5() + 1u, standard64kb.Depth() + 1u,
standard64kb_pitch, 1, standard64kb.TileMode(), false,
1, standard64kb.TileMode(), false,
standard64kb_size);
Require("BasicStorageTexture", "Standard64KB 2D descriptor",
standard64kb.Type() == Prospero::GpuEnumValue(Prospero::ImageType::kColor2DArray) &&
@@ -17109,11 +17118,11 @@ void CheckBasicStorageTextureDescriptor() {
d16_depth_tile.DstSelXYZW() == DstSel(4, 0, 0, 1),
"PPSA10112 writable D16 depth-plane descriptor fixture is malformed");
const auto d16_pitch = TileGetTexturePitch(
d16_depth_tile.Format(), d16_depth_tile.Width5() + 1u, 1, d16_depth_tile.TileMode());
d16_depth_tile.Format(), d16_depth_tile.Width5() + 1u, d16_depth_tile.TileMode());
TileSizeAlign d16_size {};
TileGetTextureTotalSize(d16_depth_tile.Format(), d16_depth_tile.Width5() + 1u,
d16_depth_tile.Height5() + 1u, d16_depth_tile.Depth() + 1u, d16_pitch,
1, d16_depth_tile.TileMode(), false, d16_size);
d16_depth_tile.Height5() + 1u, d16_depth_tile.Depth() + 1u, 1,
d16_depth_tile.TileMode(), false, d16_size);
Require("BasicStorageTexture", "PPSA10112 D16 depth-tile footprint",
d16_pitch == 256 && d16_size.size == 0x20000 && d16_size.align == 0x10000,
"PPSA10112 writable D16 depth-plane footprint is incorrect");
@@ -17191,16 +17200,17 @@ void CheckStorageTextureLinearUploadLayout() {
constexpr uint32_t height = 2160;
constexpr uint32_t depth = 1;
constexpr uint32_t tile = Prospero::GpuEnumValue(Prospero::TileMode::kLinear);
const auto pitch = TileGetTexturePitch(format, width, 1, tile);
const auto pitch = TileGetTexturePitch(format, width, tile);
TileSizeAlign total {};
TileGetTextureTotalSize(format, width, height, depth, pitch, 1, tile, false, total);
TileGetTextureTotalSize(format, width, height, depth, 1, tile, false, total);
const auto layout =
TextureCalcUploadLayout(format, width, height, 1, depth, pitch, tile, total.size, true,
TextureCalcUploadLayout(format, width, height, 1, depth, tile, total.size, true,
false, "StorageTextureLinearTest");
const auto regions = TextureBuildImageCopies(layout, width, height, depth, 1, false, false);
const auto regions = TextureBuildImageCopies(layout);
Require("StorageTextureLinearUpload", "layout",
pitch == width && total.size == 0x1fa4000 && total.align == 256 &&
layout.tile == tile && layout.pitch == width && layout.slice_stride == total.size &&
layout.surface.description.tile_mode == tile && layout.pitch == width &&
layout.slice_stride == total.size &&
regions.size() == 1 && regions[0].bufferOffset == 0 &&
regions[0].imageExtent.width == width && regions[0].imageExtent.height == height &&
regions[0].bufferRowLength == width,
@@ -17214,25 +17224,27 @@ void CheckStorageTextureDepthTileUploadLayout() {
constexpr uint32_t height = 1;
constexpr uint32_t depth = 1;
constexpr uint32_t tile = Prospero::GpuEnumValue(Prospero::TileMode::kDepth);
const auto pitch = TileGetTexturePitch(format, width, 1, tile);
const auto pitch = TileGetTexturePitch(format, width, tile);
TileSizeAlign slice {};
TileSizeAlign total {};
TileSizeOffset level {};
TilePaddedSize padded {};
TileGetTextureSize(format, width, height, pitch, 1, tile, &slice, &level, &padded);
TileGetTextureTotalSize(format, width, height, depth, pitch, 1, tile, false, total);
TileGetTextureSize(format, width, height, 1, tile, &slice, &level, &padded);
TileGetTextureTotalSize(format, width, height, depth, 1, tile, false, total);
const auto layout =
TextureCalcUploadLayout(format, width, height, 1, depth, pitch, tile, total.size, true,
TextureCalcUploadLayout(format, width, height, 1, depth, tile, total.size, true,
false, "StorageTextureDepthTileTest");
const auto regions = TextureBuildImageCopies(layout, width, height, depth, 1, true, false);
const auto regions = TextureBuildImageCopies(layout);
Require("StorageTextureDepthTileUpload", "PPSA14053 layout",
pitch == 256 && padded.width == 256 && padded.height == 256 && slice.size == 0x10000 &&
slice.align == 0x10000 && level.size == slice.size && level.offset == 0 &&
total.size == slice.size && total.align == slice.align && layout.tile == tile &&
layout.tile_family == TileBlockFamily::Depth64KB && layout.pitch == pitch &&
total.size == slice.size && total.align == slice.align &&
layout.surface.description.tile_mode == tile &&
layout.surface.texture.block.family == TileBlockFamily::Depth64KB &&
layout.pitch == pitch &&
layout.slice_stride == pitch && layout.source_slice_stride == total.size &&
layout.level_sizes[0].size == pitch &&
layout.level_sizes[0].src_size == total.size && regions.size() == 1 &&
layout.mips[0].size == pitch &&
layout.surface.mips[0].size == total.size && regions.size() == 1 &&
regions[0].bufferOffset == 0 && regions[0].imageExtent.width == width &&
regions[0].imageExtent.height == height && regions[0].bufferRowLength == pitch,
"1x1 R8_UINT depth tile lost its 64 KiB source footprint");
@@ -17274,24 +17286,24 @@ void CheckStorageTextureVolumeUploadLayout() {
constexpr uint32_t height = 33;
constexpr uint32_t depth = 33;
const auto pitch = TileGetTexturePitch(
format, width, 1, Prospero::GpuEnumValue(Prospero::TileMode::kRenderTarget));
format, width, Prospero::GpuEnumValue(Prospero::TileMode::kRenderTarget));
TileSizeAlign total {};
TileGetTextureTotalSize(format, width, height, depth, pitch, 1,
TileGetTextureTotalSize(format, width, height, depth, 1,
Prospero::GpuEnumValue(Prospero::TileMode::kRenderTarget), true, total);
const auto layout =
TextureCalcUploadLayout(format, width, height, 1, depth, pitch,
TextureCalcUploadLayout(format, width, height, 1, depth,
Prospero::GpuEnumValue(Prospero::TileMode::kRenderTarget),
total.size, true, true, "StorageTextureVolumeTest");
const auto regions = TextureBuildImageCopies(layout, width, height, depth, 1, false, true);
const auto regions = TextureBuildImageCopies(layout);
Require("StorageTextureVolumeUpload", "layout",
pitch == 128 && total.size == 0x210000 && layout.slice_stride == 0x2208 &&
layout.source_slice_stride == 0 && layout.level_sizes[0].size == 0x2208 &&
layout.level_sizes[0].src_size == 0 && regions.size() == depth,
layout.source_slice_stride == 0 && layout.mips[0].size == 0x2208 &&
layout.surface.mips[0].size == 0x10000 && regions.size() == depth,
"3D render-target upload did not preserve its compact linear layout");
std::vector<GpuTileInfo> infos;
Require("StorageTextureVolumeUpload", "GPU records",
TextureBuildGpuTileInfos(total.size, regions, layout, format, depth, 1, infos) &&
TextureBuildGpuTileInfos(total.size, regions, layout, 1, infos) &&
infos.size() == depth,
"3D render-target GPU records were not built");
for (const uint32_t z: {0u, 1u, depth - 1u}) {
@@ -17311,13 +17323,12 @@ void CheckStorageTextureVolumeMipRegions() {
constexpr uint32_t depth = 5;
constexpr uint32_t levels = 3;
constexpr uint32_t tile = Prospero::GpuEnumValue(Prospero::TileMode::kLinear);
const auto pitch = TileGetTexturePitch(format, width, levels, tile);
TileSizeAlign total {};
TileGetTextureTotalSize(format, width, height, depth, pitch, levels, tile, true, total);
TileGetTextureTotalSize(format, width, height, depth, levels, tile, true, total);
const auto layout =
TextureCalcUploadLayout(format, width, height, levels, depth, pitch, tile, total.size, true,
TextureCalcUploadLayout(format, width, height, levels, depth, tile, total.size, true,
true, "StorageTextureVolumeMipTest");
const auto copies = TextureBuildImageCopies(layout, width, height, depth, levels, false, true);
const auto copies = TextureBuildImageCopies(layout);
bool valid = copies.size() == 8;
size_t index = 0;
@@ -17331,9 +17342,9 @@ void CheckStorageTextureVolumeMipRegions() {
copy.imageSubresource.mipLevel == level &&
copy.imageOffset.z == static_cast<int>(z) && copy.imageExtent.width == mip_width &&
copy.imageExtent.height == mip_height &&
copy.bufferOffset == layout.level_sizes[level].offset + z * layout.slice_stride &&
copy.bufferRowLength == layout.padded_sizes[level].width &&
copy.bufferImageHeight == layout.padded_sizes[level].height;
copy.bufferOffset == layout.mips[level].offset + z * layout.slice_stride &&
copy.bufferRowLength == layout.mips[level].row_length &&
copy.bufferImageHeight == layout.mips[level].image_height;
}
}
valid &= index == copies.size();
@@ -17348,9 +17359,9 @@ void CheckStandard64RenderTargetTileRoundTrip() {
constexpr uint32_t observed_width = 3840;
constexpr uint32_t observed_height = 2160;
const auto observed_pitch = TileGetTexturePitch(format, observed_width, 1, tile);
const auto observed_pitch = TileGetTexturePitch(format, observed_width, tile);
TileSizeAlign observed {};
TileGetTextureSize(format, observed_width, observed_height, observed_pitch, 1, tile, &observed,
TileGetTextureSize(format, observed_width, observed_height, 1, tile, &observed,
nullptr, nullptr);
Require("Standard64RenderTarget", "observed layout",
observed_pitch == 3840 && observed.size == 0x1fe0000 && observed.align == 0x10000,
@@ -17358,9 +17369,9 @@ void CheckStandard64RenderTargetTileRoundTrip() {
constexpr uint32_t width = 257;
constexpr uint32_t height = 131;
const auto pitch = TileGetTexturePitch(format, width, 1, tile);
const auto pitch = TileGetTexturePitch(format, width, tile);
TileSizeAlign storage {};
TileGetTextureSize(format, width, height, pitch, 1, tile, &storage, nullptr, nullptr);
TileGetTextureSize(format, width, height, 1, tile, &storage, nullptr, nullptr);
Require("Standard64RenderTarget", "partial layout",
pitch == 384 && storage.size == 0x60000 && storage.align == 0x10000,
"partial Standard64KB footprint was not padded in 128x128 blocks");
@@ -17838,11 +17849,11 @@ void CheckDepthTargetFootprints() {
"non-HTile depth/stencil footprint disagrees with Prospero block rules");
const auto depth_pitch =
TileGetTexturePitch(Prospero::GpuEnumValue(Prospero::BufferFormat::k32Float), 640, 1,
TileGetTexturePitch(Prospero::GpuEnumValue(Prospero::BufferFormat::k32Float), 640,
Prospero::GpuEnumValue(Prospero::TileMode::kDepth));
TileSizeAlign texture_depth {};
TileGetTextureTotalSize(Prospero::GpuEnumValue(Prospero::BufferFormat::k32Float), 640, 360, 1,
depth_pitch, 1, Prospero::GpuEnumValue(Prospero::TileMode::kDepth),
1, Prospero::GpuEnumValue(Prospero::TileMode::kDepth),
false, texture_depth);
Require("DepthTargetFootprints", "640x360 generic depth tile",
depth_pitch == 640 && texture_depth.size == 0xf0000 && texture_depth.align == 0x10000,