graphics: support depth-tiled color targets
This commit is contained in:
parent
484433b180
commit
4f1bc505cc
|
|
@ -924,7 +924,7 @@ TextureCache::BuildColorTransfer(const Image& image, BindingType binding,
|
|||
EXIT("TextureCache: invalid color-attachment upload\n");
|
||||
}
|
||||
format = ImageOps::RenderTargetTransferFormat(info.bytes_per_block);
|
||||
allow_depth_tile = false;
|
||||
allow_depth_tile = true;
|
||||
plan.swap_bgra16 = info.bgra16;
|
||||
owner = "RenderTarget";
|
||||
break;
|
||||
|
|
@ -950,7 +950,7 @@ TextureCache::BuildColorTransfer(const Image& image, BindingType binding,
|
|||
format = binding == BindingType::RenderTarget
|
||||
? ImageOps::RenderTargetTransferFormat(info.bytes_per_block)
|
||||
: info.guest_format;
|
||||
allow_depth_tile = binding == BindingType::Storage;
|
||||
allow_depth_tile = binding == BindingType::Storage || binding == BindingType::RenderTarget;
|
||||
plan.swap_bgra16 = info.bgra16;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -132,10 +132,12 @@ void RenderExecutor::ResolveRenderColorTarget(uint64_t submit_id, RenderCommandB
|
|||
}
|
||||
const uint32_t depth = volume ? rt.attrib3.depth + 1u : 1u;
|
||||
const bool standard64 = rt.attrib3.tile_mode == Prospero::TileMode::kStandard64KB;
|
||||
const bool depth_tile = rt.attrib3.tile_mode == Prospero::TileMode::kDepth;
|
||||
|
||||
switch (rt.attrib3.tile_mode) {
|
||||
case Prospero::TileMode::kLinear:
|
||||
case Prospero::TileMode::kStandard64KB:
|
||||
case Prospero::TileMode::kDepth:
|
||||
case Prospero::TileMode::kRenderTarget:
|
||||
tile = !RenderIsColorTileModeLinear(rt.attrib3.tile_mode);
|
||||
break;
|
||||
|
|
@ -147,6 +149,9 @@ void RenderExecutor::ResolveRenderColorTarget(uint64_t submit_id, RenderCommandB
|
|||
if (samples > 1 && (!tile || levels != 1)) {
|
||||
EXIT("multisampled render targets require a single-mip tiled surface\n");
|
||||
}
|
||||
if (depth_tile && samples != 1) {
|
||||
EXIT("depth-tiled color render targets do not support multisampling\n");
|
||||
}
|
||||
|
||||
width = rt.attrib2.width + 1;
|
||||
height = rt.attrib2.height + 1;
|
||||
|
|
@ -157,31 +162,31 @@ void RenderExecutor::ResolveRenderColorTarget(uint64_t submit_id, RenderCommandB
|
|||
EXIT("render-target format has no valid element size\n");
|
||||
}
|
||||
const auto transfer_format = ImageOps::RenderTargetTransferFormat(bytes_per_element);
|
||||
if (standard64 &&
|
||||
if ((standard64 || depth_tile) &&
|
||||
(rt.attrib3.dimension != 1 || rt.attrib3.depth != 0 || levels != 1 ||
|
||||
rt.view.current_mip_level != 0 || view.base_layer != 0 || view.image_layers != 1 ||
|
||||
samples != 1 || bytes_per_element != 4 || rt.pitch.pitch_div8_minus1 != 0 ||
|
||||
(rt.base.addr & 0xffffu) != 0 || rt.info.fmask_compression_enable ||
|
||||
rt.info.fmask_data_compression_disable || rt.info.fmask_one_frag_mode ||
|
||||
rt.info.cmask_fast_clear_enable || rt.info.dcc_compression_enable ||
|
||||
rt.info.cmask_is_linear != 0 || rt.info.cmask_addr_type != 0 || rt.info.alt_tile_mode ||
|
||||
rt.cmask.addr != 0 || rt.fmask.addr != 0 || rt.dcc_addr.addr != 0 ||
|
||||
rt.dcc.data_write_on_dcc_clear_to_reg)) {
|
||||
EXIT("unsupported Standard64KB render target: addr=0x%016" PRIx64
|
||||
samples != 1 || (standard64 && bytes_per_element != 4) ||
|
||||
rt.pitch.pitch_div8_minus1 != 0 || (rt.base.addr & 0xffffu) != 0 ||
|
||||
rt.info.fmask_compression_enable || rt.info.fmask_data_compression_disable ||
|
||||
rt.info.fmask_one_frag_mode || rt.info.cmask_fast_clear_enable ||
|
||||
rt.info.dcc_compression_enable || rt.info.cmask_is_linear != 0 ||
|
||||
rt.info.cmask_addr_type != 0 || rt.info.alt_tile_mode || rt.cmask.addr != 0 ||
|
||||
rt.fmask.addr != 0 || rt.dcc_addr.addr != 0 || rt.dcc.data_write_on_dcc_clear_to_reg)) {
|
||||
EXIT("unsupported texture-tiled render target: addr=0x%016" PRIx64 " tile=%u"
|
||||
" dimension=%u depth=%u levels=%u layer=%u/%u samples=%u fragments=%u bpe=%u"
|
||||
" cmask=0x%016" PRIx64 " fmask=0x%016" PRIx64 " dcc=0x%016" PRIx64 "\n",
|
||||
rt.base.addr, rt.attrib3.dimension, rt.attrib3.depth, levels, view.base_layer,
|
||||
view.image_layers, rt.attrib.num_samples, rt.attrib.num_fragments, bytes_per_element,
|
||||
rt.cmask.addr, rt.fmask.addr, rt.dcc_addr.addr);
|
||||
rt.base.addr, static_cast<uint32_t>(rt.attrib3.tile_mode), rt.attrib3.dimension,
|
||||
rt.attrib3.depth, levels, view.base_layer, view.image_layers, rt.attrib.num_samples,
|
||||
rt.attrib.num_fragments, bytes_per_element, rt.cmask.addr, rt.fmask.addr,
|
||||
rt.dcc_addr.addr);
|
||||
}
|
||||
if (rt.pitch.pitch_div8_minus1 != 0) {
|
||||
pitch = (rt.pitch.pitch_div8_minus1 + 1u) << 3u;
|
||||
} else if (tile) {
|
||||
if (volume) {
|
||||
pitch = TileGetTexturePitch(transfer_format, width, rt.attrib3.tile_mode);
|
||||
} else if (standard64) {
|
||||
pitch =
|
||||
TileGetTexturePitch(Prospero::BufferFormat::k32Float, width, rt.attrib3.tile_mode);
|
||||
} else if (standard64 || depth_tile) {
|
||||
pitch = TileGetTexturePitch(transfer_format, width, rt.attrib3.tile_mode);
|
||||
} else {
|
||||
pitch = TileGetRenderTargetPitch(width, bytes_per_element, rt.attrib.num_fragments);
|
||||
}
|
||||
|
|
@ -214,9 +219,9 @@ void RenderExecutor::ResolveRenderColorTarget(uint64_t submit_id, RenderCommandB
|
|||
} else if (tile) {
|
||||
TileSizeAlign layout {};
|
||||
bool valid_layout = false;
|
||||
if (standard64) {
|
||||
TileGetTextureSize(Prospero::BufferFormat::k32Float, width, height, levels,
|
||||
rt.attrib3.tile_mode, &layout, mip_sizes, mip_padded);
|
||||
if (standard64 || depth_tile) {
|
||||
TileGetTextureSize(transfer_format, width, height, levels, rt.attrib3.tile_mode,
|
||||
&layout, mip_sizes, mip_padded);
|
||||
valid_layout = layout.size != 0 && layout.align == 65536;
|
||||
} else {
|
||||
valid_layout =
|
||||
|
|
|
|||
|
|
@ -6216,6 +6216,138 @@ public:
|
|||
std::printf("[gpu] %-32s ok\n", name);
|
||||
}
|
||||
|
||||
void CheckRenderExecutorColorDepthTileDiscovery() {
|
||||
constexpr const char *name = "RenderExecutorColorDepthTile";
|
||||
constexpr uintptr_t base = 0x0000000203d00000ull;
|
||||
constexpr uint64_t allocation_size = 0x10000;
|
||||
constexpr uint64_t allocation_alignment = 0x10000;
|
||||
EnsureRuntimeContext();
|
||||
|
||||
int64_t direct_offset = -1;
|
||||
Require(name, "direct allocation",
|
||||
Libs::LibKernel::Memory::KernelAllocateDirectMemory(
|
||||
0, Libs::LibKernel::Memory::KernelGetDirectMemorySize(),
|
||||
allocation_size, allocation_alignment, 0, &direct_offset) == 0,
|
||||
"depth-tiled color allocation failed");
|
||||
void *mapped = reinterpret_cast<void *>(base);
|
||||
Require(name, "direct mapping",
|
||||
Libs::LibKernel::Memory::KernelMapDirectMemory(
|
||||
&mapped, allocation_size, 0x3, 0x10, direct_offset,
|
||||
allocation_alignment) == 0 &&
|
||||
mapped == reinterpret_cast<void *>(base),
|
||||
"depth-tiled color mapping failed");
|
||||
constexpr uint32_t width = 64;
|
||||
constexpr uint32_t height = 64;
|
||||
TileTextureBlockLayout tile_layout{};
|
||||
Require(name, "tile layout",
|
||||
TileGetTextureBlockLayout(Prospero::BufferFormat::k32Float,
|
||||
Prospero::TileMode::kDepth, false,
|
||||
tile_layout),
|
||||
"depth-tiled color block layout is unavailable");
|
||||
uint32_t block_xor = 0;
|
||||
Require(name, "block xor",
|
||||
TileGetBlockXor(tile_layout.block, 0, 0, 0, block_xor),
|
||||
"depth-tiled color block XOR is unavailable");
|
||||
std::vector<uint32_t> expected(allocation_size / sizeof(uint32_t));
|
||||
for (uint32_t y = 0; y < height; ++y) {
|
||||
for (uint32_t x = 0; x < width; ++x) {
|
||||
uint32_t offset = 0;
|
||||
Require(name, "texel offset",
|
||||
TileGetBlockOffset(tile_layout.block, x, y, 0, offset),
|
||||
"depth-tiled color texel offset is unavailable");
|
||||
const auto index = (offset ^ block_xor) / sizeof(uint32_t);
|
||||
Require(name, "texel address", index < expected.size(),
|
||||
"depth-tiled color texel address exceeds its backing");
|
||||
expected[index] = 0x3f000000u + y * width + x;
|
||||
}
|
||||
}
|
||||
std::memcpy(mapped, expected.data(), allocation_size);
|
||||
|
||||
{
|
||||
RenderContext context(m_runtime_context);
|
||||
auto &scheduler = context.GetCommandScheduler();
|
||||
HW::Context registers{};
|
||||
HW::UserConfig user_config{};
|
||||
HW::Shader shaders{};
|
||||
registers.SetColorBase(0, {.addr = base});
|
||||
registers.SetColorInfo(
|
||||
0, {.format = Prospero::ChannelLayout::k32,
|
||||
.channel_type = Prospero::ChannelType::kFloat,
|
||||
.channel_order = Prospero::ChannelOrder::kStandard});
|
||||
registers.SetColorAttrib2(0, {.height = 63, .width = 63});
|
||||
registers.SetColorAttrib3(
|
||||
0, {.tile_mode = Prospero::TileMode::kDepth,
|
||||
.dimension = 1,
|
||||
.cmask_pipe_aligned = true,
|
||||
.dcc_pipe_aligned = true});
|
||||
registers.SetRenderTargetMask(0x0f);
|
||||
scheduler.Begin(registers, user_config, shaders);
|
||||
|
||||
auto &resources = context.GetGpuResources();
|
||||
auto &texture_cache = resources.GetTextureCache();
|
||||
auto &executor = context.GetRenderExecutor();
|
||||
resources.MapMemory(base, allocation_size);
|
||||
|
||||
RenderColorInfo color{};
|
||||
RenderExecutorTestAccess::ResolveRenderColorTarget(
|
||||
executor, 1, scheduler.Current(), color, 0);
|
||||
const auto attachment =
|
||||
texture_cache.FindRenderTarget(color.image_id, color.desc);
|
||||
const auto &image = texture_cache.GetImage(color.image_id);
|
||||
Require(name, "captured target",
|
||||
color.image_id && attachment != nullptr &&
|
||||
color.desc.info.tile_mode == Prospero::TileMode::kDepth &&
|
||||
color.desc.info.pitch == 128 &&
|
||||
color.desc.info.data.size == allocation_size &&
|
||||
color.desc.info.mip_layout[0].size == allocation_size &&
|
||||
image.usage.render_target && image.IsGpuModified(),
|
||||
"supported depth-tiled color target was not resolved");
|
||||
scheduler.FinishCurrent();
|
||||
scheduler.DrainPriorityOperations();
|
||||
std::vector<uint8_t> cleared(allocation_size);
|
||||
Require(name, "clear guest backing",
|
||||
Libs::LibKernel::Memory::TryWriteBacking(
|
||||
base, cleared.data(), allocation_size),
|
||||
"depth-tiled color backing could not be cleared");
|
||||
Require(name, "readback queue",
|
||||
TextureCacheTestAccess::TryDownload(texture_cache, color.image_id),
|
||||
"depth-tiled color target could not be queued for readback");
|
||||
|
||||
RenderExecutorTestAccess::ResetBindings(executor);
|
||||
scheduler.Finish();
|
||||
scheduler.DrainPriorityOperations();
|
||||
std::vector<uint32_t> observed(expected.size());
|
||||
Require(name, "readback backing",
|
||||
Libs::LibKernel::Memory::TryReadBacking(
|
||||
base, observed.data(), allocation_size),
|
||||
"depth-tiled color readback is unavailable");
|
||||
bool recovered = true;
|
||||
for (uint32_t y = 0; y < height; ++y) {
|
||||
for (uint32_t x = 0; x < width; ++x) {
|
||||
uint32_t offset = 0;
|
||||
const auto valid =
|
||||
TileGetBlockOffset(tile_layout.block, x, y, 0, offset);
|
||||
const auto index = (offset ^ block_xor) / sizeof(uint32_t);
|
||||
recovered &= valid && index < observed.size() &&
|
||||
observed[index] == expected[index];
|
||||
}
|
||||
}
|
||||
Require(name, "round trip", recovered,
|
||||
"depth-tiled color upload/readback changed active texels");
|
||||
resources.UnmapMemory(base, allocation_size);
|
||||
scheduler.Finish();
|
||||
}
|
||||
|
||||
Require(name, "unmap direct backing",
|
||||
Libs::LibKernel::Memory::KernelMunmap(base, allocation_size) == 0,
|
||||
"depth-tiled color mapping release failed");
|
||||
Require(name, "release direct backing",
|
||||
Libs::LibKernel::Memory::KernelReleaseDirectMemory(
|
||||
direct_offset, allocation_size) == 0,
|
||||
"depth-tiled color allocation release failed");
|
||||
std::printf("[gpu] %-32s ok\n", name);
|
||||
}
|
||||
|
||||
void CheckRenderExecutorStencilBindingDiscovery() {
|
||||
constexpr const char *name = "RenderExecutorStencilBindingDiscovery";
|
||||
constexpr uintptr_t base = 0x0000000203600000ull;
|
||||
|
|
@ -20414,6 +20546,7 @@ int main(int argc, char **argv) {
|
|||
CheckDynamicRenderingState();
|
||||
VulkanHarness vulkan;
|
||||
vulkan.CheckRenderExecutorColorVolumeDiscovery();
|
||||
vulkan.CheckRenderExecutorColorDepthTileDiscovery();
|
||||
vulkan.CheckRenderExecutorStencilBindingDiscovery();
|
||||
vulkan.CheckUnifiedTextureCacheFlow();
|
||||
vulkan.CheckBgra16Readback();
|
||||
|
|
@ -20559,6 +20692,7 @@ int main(int argc, char **argv) {
|
|||
vulkan.CheckGpuTilerCpuParity();
|
||||
#if KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS
|
||||
vulkan.CheckRenderExecutorColorVolumeDiscovery();
|
||||
vulkan.CheckRenderExecutorColorDepthTileDiscovery();
|
||||
vulkan.CheckRenderExecutorStencilBindingDiscovery();
|
||||
vulkan.CheckUnifiedTextureCacheFlow();
|
||||
vulkan.CheckBgra16Readback();
|
||||
|
|
|
|||
Loading…
Reference in New Issue