support storage descriptors and tracked image aliases

This commit is contained in:
nmzik
2026-07-17 22:37:02 +02:00
parent 2890d5f7bb
commit 8a6afc428d
8 changed files with 530 additions and 57 deletions
+314 -2
View File
@@ -8858,6 +8858,17 @@ void CheckSampledColorViews() {
VK_FORMAT_R16G16B16A16_SFLOAT,
DstSel(7, 6, 5, 4)) == VulkanImage::VIEW_ABGR,
"reverse RGBA16F target did not select its reciprocal ABGR sampled view");
Require("SampledColorViews", "mutable integer-class views",
SelectSampledColorView(VK_FORMAT_R16G16B16A16_SFLOAT,
VK_FORMAT_R16G16B16A16_UINT,
DstSel(4, 5, 6, 7)) == VulkanImage::VIEW_DEFAULT &&
SelectSampledColorView(VK_FORMAT_R8G8B8A8_UNORM,
VK_FORMAT_R8G8B8A8_UINT,
DstSel(4, 5, 6, 7)) == VulkanImage::VIEW_DEFAULT &&
SelectSampledColorView(VK_FORMAT_R8G8B8A8_UINT,
VK_FORMAT_R8G8B8A8_UNORM,
DstSel(4, 5, 6, 7)) == VulkanImage::VIEW_DEFAULT,
"compatible integer render-target sampled view was rejected");
Require("SampledColorViews", "D32 depth target",
SelectSampledDepthView(VK_FORMAT_D32_SFLOAT_S8_UINT,
VK_FORMAT_R32_SFLOAT,
@@ -8905,6 +8916,10 @@ void CheckSampledColorViews() {
SelectStorageColorView(VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM,
DstSel(6, 5, 4, 7)) == VulkanImage::VIEW_STORAGE,
"RGBA8 BGRA storage did not select the identity storage view");
Require("SampledColorViews", "storage uint BGRA write mapping",
SelectStorageColorView(VK_FORMAT_R8G8B8A8_UINT, VK_FORMAT_R8G8B8A8_UINT,
DstSel(6, 5, 4, 7)) == VulkanImage::VIEW_STORAGE,
"RGBA8_UINT BGRA storage did not select the identity storage view");
Require(
"SampledColorViews", "mutable BGRA sRGB storage view",
SelectStorageColorView(VK_FORMAT_B8G8R8A8_SRGB, VK_FORMAT_R8G8B8A8_UNORM,
@@ -8964,7 +8979,7 @@ void CheckSampledColorViews() {
"GetModuleFileName failed");
for (const char *kind :
{"sampled", "sampled-compatible-swizzle", "sampled-compatible-reverse",
"sampled-compatible-class", "sampled-compatible-colorspace",
"sampled-compatible-colorspace",
"sampled-compatible-snorm", "sampled-rgb10-swizzle",
"sampled-rgb10-reverse", "sampled-abgr-format", "sampled-depth-format",
"sampled-depth-swizzle", "storage", "storage-format",
@@ -9040,6 +9055,17 @@ void CheckSampledDepthResource() {
Require("SampledDepthResource", "integer rejected",
!IsSupportedSampledDepthResource(resource),
"integer depth resource was accepted");
Require("SampledDepthResource", "integer reinterpret resource",
IsSupportedSampledDepthUintResource(resource),
"read-only uint depth reinterpretation resource was rejected");
Require("SampledDepthResource", "D32 to R32_UINT",
IsDepthUintTextureReinterpretation(
VK_FORMAT_D32_SFLOAT,
Prospero::GpuEnumValue(Prospero::BufferFormat::k32UInt), VK_FORMAT_R32_UINT) &&
!IsDepthUintTextureReinterpretation(
VK_FORMAT_D16_UNORM,
Prospero::GpuEnumValue(Prospero::BufferFormat::k32UInt), VK_FORMAT_R32_UINT),
"depth uint reinterpretation format boundary changed");
std::printf("[host] %-32s ok\n", "SampledDepthResource");
}
@@ -9074,6 +9100,53 @@ void CheckSampledDepthDescriptor() {
Require("SampledDepthDescriptor", "non-depth tile",
!IsSupportedDepthTargetDescriptor(descriptor, image),
"non-depth texture descriptor was accepted");
DepthTargetInfo target{};
target.address = 0x4a8c00000;
target.size = 0x100000;
target.width = 512;
target.height = 512;
target.pitch = 512;
target.layers = 1;
target.bytes_per_element = 4;
target.guest_format = Prospero::GpuEnumValue(Prospero::BufferFormat::k32Float);
target.format = VK_FORMAT_D32_SFLOAT;
target.tile_mode = Prospero::GpuEnumValue(Prospero::TileMode::kDepth);
ImageInfo expanded{};
expanded.address = target.address;
expanded.size = 0x400000;
expanded.format = target.guest_format;
expanded.width = target.width;
expanded.height = target.height;
expanded.pitch = target.pitch;
expanded.levels = 1;
expanded.view_levels = 1;
expanded.depth = 4;
expanded.tile = target.tile_mode;
expanded.type = Prospero::GpuEnumValue(Prospero::ImageType::kColor2DArray);
Require("SampledDepthDescriptor", "PPSA01530 layer expansion",
IsSampledDepthExpansion(expanded, target),
"exact D32 per-layer expansion was rejected");
auto invalid_expansion = expanded;
invalid_expansion.pitch *= 2;
const bool rejects_pitch = !IsSampledDepthExpansion(invalid_expansion, target);
invalid_expansion = expanded;
invalid_expansion.address++;
const bool rejects_address = !IsSampledDepthExpansion(invalid_expansion, target);
invalid_expansion = expanded;
invalid_expansion.levels = 2;
const bool rejects_mips = !IsSampledDepthExpansion(invalid_expansion, target);
invalid_expansion = expanded;
invalid_expansion.type = Prospero::GpuEnumValue(Prospero::ImageType::kColor2D);
const bool rejects_topology = !IsSampledDepthExpansion(invalid_expansion, target);
auto metadata_target = target;
metadata_target.htile_address = 0x4a9c00000;
metadata_target.htile_size = 0x10000;
const bool rejects_metadata = !IsSampledDepthExpansion(expanded, metadata_target);
Require("SampledDepthDescriptor", "expansion boundaries",
rejects_pitch && rejects_address && rejects_mips && rejects_topology &&
rejects_metadata,
"unsupported depth expansion topology was accepted");
std::printf("[host] %-32s ok\n", "SampledDepthDescriptor");
}
@@ -9144,6 +9217,17 @@ ShaderTextureResource BasicBgraStorageTextureDescriptor() {
0x00000000u, 0x00700000u, 0x00000000u, 0x00000000u}};
}
ShaderTextureResource Ppsa01530MaxMipStorageTextureDescriptor() {
return {{0x04a42900u, 0xc3e00000u, 0x000fc00fu, 0x91b0022cu,
0x00000000u, 0x00700050u, 0x00000000u, 0x00000000u}};
}
ShaderRecompiler::IR::ImageResource Ppsa01530MaxMipStorageTextureResource() {
auto resource = BasicBgraStorageTextureResource();
resource.kind = ShaderRecompiler::IR::ResourceKind::StorageImageUint;
return resource;
}
ShaderTextureResource Ppsa02527R16FloatStorageTextureDescriptor() {
return {{0x00ce3500u, 0xc0d00000u, 0x010dc1dfu, 0x91b00204u,
0x00000000u, 0x00700000u, 0x00000000u, 0x00000000u}};
@@ -9255,6 +9339,11 @@ ShaderTextureResource BasicUintVolumeStorageTextureDescriptor() {
resource = BasicArrayStorageTextureResource();
descriptor = BasicArrayStorageTextureDescriptor();
descriptor.fields[4] |= 1u << 16u;
} else if (std::strcmp(kind, "array-mip-view") == 0) {
resource = BasicArrayStorageTextureResource();
descriptor = BasicArrayStorageTextureDescriptor();
descriptor.fields[3] |= (1u << 12u) | (1u << 16u);
descriptor.fields[5] |= 1u << 4u;
} else if (std::strcmp(kind, "reserved") == 0) {
descriptor.fields[1] |= 1u << 29u;
} else if (std::strcmp(kind, "metadata") == 0) {
@@ -9308,6 +9397,26 @@ void CheckBasicStorageTextureDescriptor() {
"PPSA02604 BGRA 2D storage descriptor fixture is malformed");
ValidateStorageTexture(BasicBgraStorageTextureResource(), bgra, 0x870000);
const auto max_mip = Ppsa01530MaxMipStorageTextureDescriptor();
Require("BasicStorageTexture", "PPSA01530 max-mip descriptor",
max_mip.Base40() == 0x4a4290000ull && max_mip.Width5() + 1u == 64 &&
max_mip.Height5() + 1u == 64 && max_mip.Depth() + 1u == 1 &&
max_mip.BaseLevel() == 0 && max_mip.LastLevel() == 0 &&
max_mip.MaxMip() == 5 &&
max_mip.Format() ==
Prospero::GpuEnumValue(Prospero::BufferFormat::k32_32UInt) &&
max_mip.TileMode() ==
Prospero::GpuEnumValue(Prospero::TileMode::kRenderTarget) &&
max_mip.DstSelXYZW() == DstSel(4, 5, 0, 1),
"PPSA01530 max-mip storage descriptor fixture is malformed");
ValidateStorageTexture(Ppsa01530MaxMipStorageTextureResource(), max_mip, 0x20000);
auto mip_one = max_mip;
mip_one.fields[3] |= (1u << 12u) | (1u << 16u);
Require("BasicStorageTexture", "PPSA01530 mip-one descriptor",
mip_one.BaseLevel() == 1 && mip_one.LastLevel() == 1 && mip_one.MaxMip() == 5,
"PPSA01530 mip-one storage descriptor fixture is malformed");
ValidateStorageTexture(Ppsa01530MaxMipStorageTextureResource(), mip_one, 0x20000);
const auto r16_float = Ppsa02527R16FloatStorageTextureDescriptor();
Require("BasicStorageTexture", "PPSA02527 R16F descriptor",
r16_float.Base40() == 0xce350000ull && r16_float.Width5() + 1u == 1920 &&
@@ -9404,6 +9513,16 @@ void CheckBasicStorageTextureDescriptor() {
depth_tile.DstSelXYZW() == DstSel(4, 0, 0, 1),
"PPSA14053 write-only depth-tile storage descriptor fixture is malformed");
ValidateStorageTexture(Ppsa14053DepthTileStorageTextureResource(), depth_tile, 0x10000);
Require("BasicStorageTexture", "D32-compatible R32_UINT depth tile",
IsSupportedStorageDepthTile(
Prospero::GpuEnumValue(Prospero::BufferFormat::k32UInt),
Prospero::GpuEnumValue(Prospero::ImageType::kColor2D), 64, 64, 1),
"write-only R32_UINT depth-tile recreation was rejected");
Require("BasicStorageTexture", "R32_UINT replicated write mapping",
IsSupportedStorageSwizzle(
Prospero::GpuEnumValue(Prospero::BufferFormat::k32UInt),
DstSel(4, 4, 4, 4)),
"single-channel replicated destination selection was rejected");
char path[MAX_PATH]{};
Require("BasicStorageTexture", "host",
@@ -9412,7 +9531,7 @@ void CheckBasicStorageTextureDescriptor() {
for (const char *kind : {"resource", "type", "tile", "mip", "swizzle",
"linear-rgb1-read", "bgra-read", "r16-float-read", "r8-unorm-read",
"yzwx-read", "yzwx-format",
"array-base-view", "reserved", "metadata", "uint-format",
"array-base-view", "array-mip-view", "reserved", "metadata", "uint-format",
"uint-resource-float-format", "depth-tile-read",
"depth-tile-extent"}) {
std::string command = std::string("\"") + path +
@@ -9933,6 +10052,75 @@ void CheckRenderTargetTileRoundTrip() {
std::printf("[host] %-32s ok\n", "RenderTargetTileRoundTrip");
}
void CheckStorageTextureMipTailRoundTrip() {
constexpr uint32_t format =
Prospero::GpuEnumValue(Prospero::BufferFormat::k32_32UInt);
ImageInfo info{};
info.address = 0x4a4290000ull;
info.format = format;
info.width = 64;
info.height = 64;
info.pitch = TileGetTexturePitch(
format, info.width, 6,
Prospero::GpuEnumValue(Prospero::TileMode::kRenderTarget));
info.levels = 6;
info.view_levels = 1;
info.tile = Prospero::GpuEnumValue(Prospero::TileMode::kRenderTarget);
info.depth = 1;
info.type = Prospero::GpuEnumValue(Prospero::ImageType::kColor2D);
TileSizeAlign total{};
TileSizeOffset levels[16]{};
TilePaddedSize padded[16]{};
TileGetTextureSize(format, info.width, info.height, info.pitch, info.levels,
info.tile, &total, levels, padded);
info.size = total.size;
Require("StorageTextureMipTail", "layout",
info.pitch == 128 && info.size == 0x20000 &&
levels[0].src_offset == 0x10000 && levels[0].src_size == 0x10000 &&
levels[1].src_offset == 0 && levels[1].src_size == 0x10000,
"PPSA01530 mip-tail fixture disagrees with the PS5 layout");
auto layout = TextureCalcUploadLayout(
format, info.width, info.height, info.levels, info.depth, info.pitch,
info.tile, info.size, true, false, false, "StorageTextureMipTailTest");
auto regions = TextureBuildUploadRegions(
layout, VK_FORMAT_R32G32_UINT, info.width, info.height, info.depth,
info.levels, false, false, TextureUploadDestination::MipLevels,
TextureUploadSliceLayout::MipChainPerSlice);
std::vector<uint8_t> linear(info.size, 0);
for (uint32_t level = 0; level < info.levels; level++) {
auto &region = regions[level];
for (uint32_t y = 0; y < region.height; y++) {
auto *row = linear.data() + region.offset +
static_cast<uint64_t>(y) * region.pitch * 8u;
for (uint32_t x = 0; x < region.width * 8u; x++) {
row[x] = static_cast<uint8_t>((level * 43u + y * 17u + x * 7u) & 0xffu);
}
}
}
std::vector<uint8_t> guest(info.size, 0xcd);
Tiler tiler;
tiler.TileImage(guest.data(), linear.data(), info);
std::vector<uint8_t> restored(info.size, 0);
for (uint32_t level = 0; level < info.levels; level++) {
const auto &region = regions[level];
const auto &level_size = layout.level_sizes[level];
const auto guest_offset = level_size.src_size != 0 ? level_size.src_offset
: level_size.offset;
TileConvertTiledToLinearRenderTarget(
restored.data() + region.offset, guest.data() + guest_offset,
region.width, region.height, region.pitch, 8u, level_size.size,
level_size.src_size, level_size.x, level_size.y);
for (uint32_t y = 0; y < region.height; y++) {
const auto row = region.offset + static_cast<uint64_t>(y) * region.pitch * 8u;
Require("StorageTextureMipTail", "contents",
std::memcmp(linear.data() + row, restored.data() + row,
region.width * 8u) == 0,
"multi-mip storage texture did not round-trip through its packed tail");
}
}
std::printf("[host] %-32s ok\n", "StorageTextureMipTail");
}
void CheckDepthTargetTileRoundTrip() {
struct Case {
uint32_t width;
@@ -10247,6 +10435,28 @@ void CheckStorageTextureSampledReuse() {
VK_FORMAT_R8G8B8A8_UNORM, true, false, true) ==
StorageSampledOverlap::ExactImage,
"exact storage backing rejected a distinct sampled descriptor swizzle");
ImageInfo depth_uint_storage{};
depth_uint_storage.address = 0x4a5c90000;
depth_uint_storage.size = 0x10000;
depth_uint_storage.format = Prospero::GpuEnumValue(Prospero::BufferFormat::k32UInt);
depth_uint_storage.width = 64;
depth_uint_storage.height = 64;
depth_uint_storage.pitch = 128;
depth_uint_storage.levels = 1;
depth_uint_storage.view_levels = 1;
depth_uint_storage.depth = 1;
depth_uint_storage.tile = Prospero::GpuEnumValue(Prospero::TileMode::kDepth);
depth_uint_storage.swizzle = DstSel(4, 4, 4, 4);
depth_uint_storage.type = image_2d;
auto depth_float_sampled = depth_uint_storage;
depth_float_sampled.format = Prospero::GpuEnumValue(Prospero::BufferFormat::k32Float);
depth_float_sampled.swizzle = DstSel(4, 0, 0, 1);
Require("StorageTextureSampledReuse", "PPSA01530 R32 view",
ClassifyStorageSampledOverlap(depth_float_sampled, depth_uint_storage,
VK_FORMAT_R32_SFLOAT, VK_FORMAT_R32_UINT,
true, false, true) ==
StorageSampledOverlap::ExactImage,
"PPSA01530 GPU-owned R32_UINT storage image did not accept its exact R32_SFLOAT view");
const auto usage = TextureFormatUsage::Sampled | TextureFormatUsage::Storage;
Require("StorageTextureSampledReuse", "usage",
(TextureGetUsage(usage) &
@@ -10598,6 +10808,8 @@ void CheckBufferImageWrites() {
constexpr uint64_t video_size = 0x1fe0000ull;
constexpr uint64_t target = 0x1158d80000ull;
constexpr uint64_t target_size = 0x870000ull;
constexpr uint64_t storage_address = 0x4a4290000ull;
constexpr uint64_t storage_size = 0x20000ull;
struct Case {
const char *name;
uint64_t buffer_address;
@@ -10681,6 +10893,22 @@ void CheckBufferImageWrites() {
Case{"target unaligned", target + 0x100, target_size, target + 0x100,
target_size, BufferImageBinding::RenderTarget, true, true,
BufferImageWrite::Unsupported},
Case{"storage mip page", storage_address + 0x10000, 0x10000, storage_address, storage_size,
BufferImageBinding::StorageTexture, true, true,
BufferImageWrite::SynchronizeStorageTexture},
Case{"storage unformatted", storage_address + 0x10000, 0x10000, storage_address, storage_size,
BufferImageBinding::StorageTexture, true, false,
BufferImageWrite::Unsupported},
Case{"storage unaligned", storage_address + 0x100, 0x10000, storage_address, storage_size,
BufferImageBinding::StorageTexture, true, true,
BufferImageWrite::Unsupported},
Case{"depth exact", 0x4a5c80000ull, 0x10000, 0x4a5c80000ull, 0x10000,
BufferImageBinding::DepthTarget, true, true,
BufferImageWrite::SynchronizeDepthTarget},
Case{"depth partial", 0x4a5c80000ull, 0x8000, 0x4a5c80000ull, 0x10000,
BufferImageBinding::DepthTarget, true, true, BufferImageWrite::Unsupported},
Case{"depth unformatted", 0x4a5c80000ull, 0x10000, 0x4a5c80000ull, 0x10000,
BufferImageBinding::DepthTarget, true, false, BufferImageWrite::Unsupported},
};
for (const auto &test : cases) {
const auto actual = ClassifyBufferImageWrite(
@@ -10689,6 +10917,80 @@ void CheckBufferImageWrites() {
Require("BufferImageWrite", test.name, actual == test.expected,
"buffer/image write classification mismatch");
}
Require("BufferImageWrite", "storage containing overwrite",
ClassifyBufferImageWrite(storage_address - 0x80000, 0x100000, storage_address,
storage_size, BufferImageBinding::StorageTexture, false, true,
true) == BufferImageWrite::InvalidateStorageTexture,
"formatted containing overwrite did not retain refreshable storage ownership");
Require("BufferImageWrite", "storage containing overwrite GPU-owned",
ClassifyBufferImageWrite(storage_address - 0x80000, 0x100000, storage_address,
storage_size, BufferImageBinding::StorageTexture, true, true,
false) == BufferImageWrite::Unsupported,
"containing overwrite bypassed GPU-owned storage synchronization");
Require("BufferImageWrite", "depth repeated buffer overwrite",
ClassifyBufferImageWrite(0x4a5cd0000ull, 0x10000, 0x4a5cd0000ull, 0x10000,
BufferImageBinding::DepthTarget, false, true, true) ==
BufferImageWrite::InvalidateDepthTarget,
"buffer-owned exact depth overwrite was rejected");
// PPSA01530's packed mip0 page is first synchronized out of a GPU-owned storage image,
// written through a persistent formatted buffer, and then rebound as the same storage image.
const auto partial_refresh = ClassifyStorageBufferRebind(
true, false, true, false, false, true);
const auto refreshed_reuse = ClassifyStorageBufferRebind(
true, true, false, true, false, true);
Require("BufferImageWrite", "storage partial lifecycle",
partial_refresh == StorageBufferRebind::RefreshFromBacking &&
refreshed_reuse == StorageBufferRebind::Reuse,
"storage-to-partial-buffer-to-storage lifecycle was rejected");
Require("BufferImageWrite", "storage partial incoherent",
ClassifyStorageBufferRebind(true, false, true, false, false, false) ==
StorageBufferRebind::Unsupported,
"incoherent partial storage backing was admitted");
Require("BufferImageWrite", "storage contradictory ownership",
ClassifyStorageBufferRebind(true, false, true, true, false, true) ==
StorageBufferRebind::Unsupported,
"contradictory storage tracker ownership was admitted");
Require("BufferImageWrite", "storage mip-one cache miss",
SelectImageBackingBaseLevel(true, 1) == 0 &&
SelectImageBackingBaseLevel(false, 1) == 1,
"storage backing creation remained dependent on first-bound view mip");
Require("BufferImageWrite", "dynamic one-layer array view",
!NeedsStaticSampledArrayView(true, true) &&
NeedsStaticSampledArrayView(true, false) &&
!NeedsStaticSampledArrayView(false, false),
"dynamic sampled array view was replaced by a missing static view");
DepthTargetInfo old_depth{};
old_depth.address = 0x4a5c90000ull;
old_depth.size = 0x10000;
old_depth.width = old_depth.height = 32;
old_depth.layers = 1;
DepthTargetInfo cleared_depth = old_depth;
cleared_depth.width = cleared_depth.height = 64;
cleared_depth.depth_load_clear = true;
Require("BufferImageWrite", "cleared depth reinterpretation",
ClassifyDepthTargetOverlap(old_depth, true, false, true, cleared_depth) ==
DepthOverlap::DiscardTarget,
"exact cleared depth allocation could not discard its old native shape");
cleared_depth.depth_load_clear = false;
Require("BufferImageWrite", "loaded depth reinterpretation",
ClassifyDepthTargetOverlap(old_depth, true, false, true, cleared_depth) ==
DepthOverlap::Unsupported,
"loaded depth reinterpretation discarded live native contents");
RenderTargetInfo color_alias{};
color_alias.address = old_depth.address;
color_alias.size = old_depth.size;
Require("BufferImageWrite", "buffer-owned depth to color",
CanRetireBufferOwnedDepthForRenderTarget(old_depth, false, true, true, true,
color_alias) &&
!CanRetireBufferOwnedDepthForRenderTarget(old_depth, true, false, true, true,
color_alias),
"depth-to-color recreation did not require coherent buffer ownership");
Require("BufferImageWrite", "page-neighbor depth to color",
!CanRetireBufferOwnedDepthForRenderTarget(old_depth, false, true, true, false,
color_alias),
"same-page byte-disjoint buffer authorized depth-to-color recreation");
TileSizeAlign storage{};
Require("BufferImageWrite", "target layout",
@@ -11763,6 +12065,14 @@ void CheckDepthTargetFootprints() {
}
void CheckHtileClearTargetResolution() {
HW::DepthDepthSizeXY one_pixel{};
one_pixel.valid = true;
Require("HtileClearTargetResolution", "1x1 encoded depth extent",
one_pixel.valid && one_pixel.x_max + 1u == 1u && one_pixel.y_max + 1u == 1u,
"zero DB_DEPTH_SIZE_XY fields were mistaken for an absent register");
HW::DepthDepthSizeXY absent{};
Require("HtileClearTargetResolution", "absent depth extent", !absent.valid,
"an unwritten DB_DEPTH_SIZE_XY register was admitted");
HW::DepthRenderTarget descriptor_backed{};
descriptor_backed.z_info.format = Prospero::GpuEnumValue(Prospero::DepthFormat::kZ16);
descriptor_backed.z_info.tile_surface_enable = true;
@@ -12041,6 +12351,7 @@ int main(int argc, char **argv) {
if (argc == 2 && std::strcmp(argv[1], "--layered-image-only") == 0) {
CheckColorResolveLayers();
CheckRenderTargetTileRoundTrip();
CheckStorageTextureMipTailRoundTrip();
CheckDepthTargetTileRoundTrip();
CheckGpuMetadataReuse();
return 0;
@@ -12115,6 +12426,7 @@ int main(int argc, char **argv) {
CheckColorResolveLayers();
CheckStandard64RenderTargetTileRoundTrip();
CheckRenderTargetTileRoundTrip();
CheckStorageTextureMipTailRoundTrip();
CheckDepthTargetTileRoundTrip();
CheckStencilTargetTileRoundTrip();
CheckStorageTextureVolumeUploadLayout();