mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-28 22:06:59 +01:00
graphics: resolve Standard4KB color targets
This commit is contained in:
@@ -1351,6 +1351,7 @@ uint32_t TileGetTexturePitch(Prospero::BufferFormat format, uint32_t width,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case Prospero::TileMode::kStandard4KB:
|
||||||
case Prospero::TileMode::kStandard64KB:
|
case Prospero::TileMode::kStandard64KB:
|
||||||
case Prospero::TileMode::kPrt:
|
case Prospero::TileMode::kPrt:
|
||||||
case Prospero::TileMode::kDepth:
|
case Prospero::TileMode::kDepth:
|
||||||
|
|||||||
@@ -130,12 +130,15 @@ void RenderExecutor::ResolveRenderColorTarget(uint64_t submit_id, RenderCommandB
|
|||||||
if (volume && samples != 1) {
|
if (volume && samples != 1) {
|
||||||
EXIT("multisampled 3D render targets are unsupported\n");
|
EXIT("multisampled 3D render targets are unsupported\n");
|
||||||
}
|
}
|
||||||
const uint32_t depth = volume ? rt.attrib3.depth + 1u : 1u;
|
const uint32_t depth = volume ? rt.attrib3.depth + 1u : 1u;
|
||||||
const bool standard64 = rt.attrib3.tile_mode == Prospero::TileMode::kStandard64KB;
|
const bool standard4 = rt.attrib3.tile_mode == Prospero::TileMode::kStandard4KB;
|
||||||
const bool depth_tile = rt.attrib3.tile_mode == Prospero::TileMode::kDepth;
|
const bool standard64 = rt.attrib3.tile_mode == Prospero::TileMode::kStandard64KB;
|
||||||
|
const bool depth_tile = rt.attrib3.tile_mode == Prospero::TileMode::kDepth;
|
||||||
|
const bool texture_tile = standard4 || standard64 || depth_tile;
|
||||||
|
|
||||||
switch (rt.attrib3.tile_mode) {
|
switch (rt.attrib3.tile_mode) {
|
||||||
case Prospero::TileMode::kLinear:
|
case Prospero::TileMode::kLinear:
|
||||||
|
case Prospero::TileMode::kStandard4KB:
|
||||||
case Prospero::TileMode::kStandard64KB:
|
case Prospero::TileMode::kStandard64KB:
|
||||||
case Prospero::TileMode::kDepth:
|
case Prospero::TileMode::kDepth:
|
||||||
case Prospero::TileMode::kRenderTarget:
|
case Prospero::TileMode::kRenderTarget:
|
||||||
@@ -149,8 +152,8 @@ void RenderExecutor::ResolveRenderColorTarget(uint64_t submit_id, RenderCommandB
|
|||||||
if (samples > 1 && (!tile || levels != 1)) {
|
if (samples > 1 && (!tile || levels != 1)) {
|
||||||
EXIT("multisampled render targets require a single-mip tiled surface\n");
|
EXIT("multisampled render targets require a single-mip tiled surface\n");
|
||||||
}
|
}
|
||||||
if (depth_tile && samples != 1) {
|
if (texture_tile && samples != 1) {
|
||||||
EXIT("depth-tiled color render targets do not support multisampling\n");
|
EXIT("texture-tiled color render targets do not support multisampling\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
width = rt.attrib2.width + 1;
|
width = rt.attrib2.width + 1;
|
||||||
@@ -162,15 +165,17 @@ void RenderExecutor::ResolveRenderColorTarget(uint64_t submit_id, RenderCommandB
|
|||||||
EXIT("render-target format has no valid element size\n");
|
EXIT("render-target format has no valid element size\n");
|
||||||
}
|
}
|
||||||
const auto transfer_format = ImageOps::RenderTargetTransferFormat(bytes_per_element);
|
const auto transfer_format = ImageOps::RenderTargetTransferFormat(bytes_per_element);
|
||||||
if ((standard64 || depth_tile) &&
|
TileTextureBlockLayout texture_tile_layout {};
|
||||||
(rt.attrib3.dimension != 1 || rt.attrib3.depth != 0 || view.base_layer != 0 ||
|
if (texture_tile &&
|
||||||
view.image_layers != 1 || samples != 1 || rt.pitch.pitch_div8_minus1 != 0 ||
|
(!TileGetTextureBlockLayout(transfer_format, rt.attrib3.tile_mode, volume,
|
||||||
(rt.base.addr & 0xffffu) != 0 || rt.info.fmask_compression_enable ||
|
texture_tile_layout) ||
|
||||||
rt.info.fmask_data_compression_disable || rt.info.fmask_one_frag_mode ||
|
rt.pitch.pitch_div8_minus1 != 0 ||
|
||||||
rt.info.cmask_fast_clear_enable || rt.info.dcc_compression_enable ||
|
(rt.base.addr & (texture_tile_layout.block.block_size - 1u)) != 0 ||
|
||||||
rt.info.cmask_is_linear != 0 || rt.info.cmask_addr_type != 0 || rt.info.alt_tile_mode ||
|
rt.info.fmask_compression_enable || rt.info.fmask_data_compression_disable ||
|
||||||
rt.cmask.addr != 0 || rt.fmask.addr != 0 || rt.dcc_addr.addr != 0 ||
|
rt.info.fmask_one_frag_mode || rt.info.cmask_fast_clear_enable ||
|
||||||
rt.dcc.data_write_on_dcc_clear_to_reg)) {
|
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"
|
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"
|
" 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",
|
" cmask=0x%016" PRIx64 " fmask=0x%016" PRIx64 " dcc=0x%016" PRIx64 "\n",
|
||||||
@@ -179,12 +184,18 @@ void RenderExecutor::ResolveRenderColorTarget(uint64_t submit_id, RenderCommandB
|
|||||||
rt.attrib.num_fragments, bytes_per_element, rt.cmask.addr, rt.fmask.addr,
|
rt.attrib.num_fragments, bytes_per_element, rt.cmask.addr, rt.fmask.addr,
|
||||||
rt.dcc_addr.addr);
|
rt.dcc_addr.addr);
|
||||||
}
|
}
|
||||||
|
if ((standard64 || depth_tile) && (rt.attrib3.dimension != 1 || rt.attrib3.depth != 0 ||
|
||||||
|
view.base_layer != 0 || view.image_layers != 1)) {
|
||||||
|
EXIT("unsupported 64KB texture-tiled render-target view: dimension=%u depth=%u"
|
||||||
|
" layer=%u/%u\n",
|
||||||
|
rt.attrib3.dimension, rt.attrib3.depth, view.base_layer, view.image_layers);
|
||||||
|
}
|
||||||
if (rt.pitch.pitch_div8_minus1 != 0) {
|
if (rt.pitch.pitch_div8_minus1 != 0) {
|
||||||
pitch = (rt.pitch.pitch_div8_minus1 + 1u) << 3u;
|
pitch = (rt.pitch.pitch_div8_minus1 + 1u) << 3u;
|
||||||
} else if (tile) {
|
} else if (tile) {
|
||||||
if (volume) {
|
if (volume) {
|
||||||
pitch = TileGetTexturePitch(transfer_format, width, rt.attrib3.tile_mode);
|
pitch = TileGetTexturePitch(transfer_format, width, rt.attrib3.tile_mode);
|
||||||
} else if (standard64 || depth_tile) {
|
} else if (texture_tile) {
|
||||||
pitch = TileGetTexturePitch(transfer_format, width, rt.attrib3.tile_mode);
|
pitch = TileGetTexturePitch(transfer_format, width, rt.attrib3.tile_mode);
|
||||||
} else {
|
} else {
|
||||||
pitch = TileGetRenderTargetPitch(width, bytes_per_element, rt.attrib.num_fragments);
|
pitch = TileGetRenderTargetPitch(width, bytes_per_element, rt.attrib.num_fragments);
|
||||||
@@ -218,10 +229,10 @@ void RenderExecutor::ResolveRenderColorTarget(uint64_t submit_id, RenderCommandB
|
|||||||
} else if (tile) {
|
} else if (tile) {
|
||||||
TileSizeAlign layout {};
|
TileSizeAlign layout {};
|
||||||
bool valid_layout = false;
|
bool valid_layout = false;
|
||||||
if (standard64 || depth_tile) {
|
if (texture_tile) {
|
||||||
TileGetTextureSize(transfer_format, width, height, levels, rt.attrib3.tile_mode,
|
TileGetTextureSize(transfer_format, width, height, levels, rt.attrib3.tile_mode,
|
||||||
&layout, mip_sizes, mip_padded);
|
&layout, mip_sizes, mip_padded);
|
||||||
valid_layout = layout.size != 0 && layout.align == 65536;
|
valid_layout = layout.size != 0 && layout.align == texture_tile_layout.block.block_size;
|
||||||
} else {
|
} else {
|
||||||
valid_layout =
|
valid_layout =
|
||||||
levels == 1 ? TileGetRenderTargetSize(width, height, pitch, bytes_per_element,
|
levels == 1 ? TileGetRenderTargetSize(width, height, pitch, bytes_per_element,
|
||||||
|
|||||||
@@ -6266,6 +6266,109 @@ public:
|
|||||||
std::printf("[gpu] %-32s ok\n", name);
|
std::printf("[gpu] %-32s ok\n", name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CheckRenderExecutorColorStandard4TileDiscovery() {
|
||||||
|
constexpr const char *name = "RenderExecutorColorStandard4Tile";
|
||||||
|
constexpr uintptr_t base = 0x0000000203b00000ull;
|
||||||
|
constexpr uint64_t target_address = base + 0x4000;
|
||||||
|
constexpr uint64_t target_size = 0x180000;
|
||||||
|
constexpr uint64_t allocation_size = 0x184000;
|
||||||
|
constexpr uint64_t allocation_alignment = 0x4000;
|
||||||
|
constexpr auto format = Prospero::BufferFormat::k32Float;
|
||||||
|
constexpr auto tile = Prospero::TileMode::kStandard4KB;
|
||||||
|
EnsureRuntimeContext();
|
||||||
|
|
||||||
|
const auto pitch = TileGetTexturePitch(format, 256, tile);
|
||||||
|
TileSizeAlign slice{};
|
||||||
|
TileGetTextureSize(format, 256, 256, 1, tile, &slice, nullptr, nullptr);
|
||||||
|
const auto odd_pitch = TileGetTexturePitch(format, 257, tile);
|
||||||
|
TileSizeAlign odd_slice{};
|
||||||
|
TileGetTextureSize(format, 257, 131, 1, tile, &odd_slice, nullptr, nullptr);
|
||||||
|
Require(name, "tile layout",
|
||||||
|
pitch == 256 && slice.size == 0x40000 && slice.align == 0x1000 &&
|
||||||
|
odd_pitch == 288 && odd_slice.size == 0x2d000 &&
|
||||||
|
odd_slice.align == 0x1000,
|
||||||
|
"Standard4KB pitch, footprint, or block alignment is incorrect");
|
||||||
|
|
||||||
|
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,
|
||||||
|
"Standard4KB 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),
|
||||||
|
"Standard4KB color mapping failed");
|
||||||
|
std::memset(mapped, 0, 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 = target_address});
|
||||||
|
registers.SetColorInfo(
|
||||||
|
0, {.format = Prospero::ChannelLayout::k32,
|
||||||
|
.channel_type = Prospero::ChannelType::kFloat,
|
||||||
|
.channel_order = Prospero::ChannelOrder::kStandard});
|
||||||
|
registers.SetColorView(
|
||||||
|
0, {.base_array_slice_index = 5, .last_array_slice_index = 5});
|
||||||
|
registers.SetColorAttrib2(0, {.height = 255, .width = 255});
|
||||||
|
registers.SetColorAttrib3(0, {.tile_mode = tile,
|
||||||
|
.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.base_array_layer == 5 &&
|
||||||
|
color.desc.info.data.address == target_address &&
|
||||||
|
color.desc.info.data.size == target_size &&
|
||||||
|
color.desc.info.tile_mode == tile &&
|
||||||
|
color.desc.info.extent == vk::Extent3D{256, 256, 1} &&
|
||||||
|
color.desc.info.resources == ImageSubresources{1, 6} &&
|
||||||
|
color.desc.info.pitch == pitch &&
|
||||||
|
color.desc.info.mip_layout[0].offset == 0 &&
|
||||||
|
color.desc.info.mip_layout[0].size == target_size &&
|
||||||
|
color.desc.view_info.type == vk::ImageViewType::e2D &&
|
||||||
|
color.desc.view_info.base_layer == 5 &&
|
||||||
|
color.desc.view_info.layer_count == 1 &&
|
||||||
|
(target_address & 0xffffu) == 0x4000 &&
|
||||||
|
image.usage.render_target && image.IsGpuModified(),
|
||||||
|
"slice 5 Standard4KB render target was not resolved");
|
||||||
|
|
||||||
|
RenderExecutorTestAccess::ResetBindings(executor);
|
||||||
|
resources.UnmapMemory(base, allocation_size);
|
||||||
|
scheduler.Finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
Require(name, "unmap direct backing",
|
||||||
|
Libs::LibKernel::Memory::KernelMunmap(base, allocation_size) == 0,
|
||||||
|
"Standard4KB color mapping release failed");
|
||||||
|
Require(name, "release direct backing",
|
||||||
|
Libs::LibKernel::Memory::KernelReleaseDirectMemory(
|
||||||
|
direct_offset, allocation_size) == 0,
|
||||||
|
"Standard4KB color allocation release failed");
|
||||||
|
std::printf("[gpu] %-32s ok\n", name);
|
||||||
|
}
|
||||||
|
|
||||||
void CheckRenderExecutorColorDepthTileDiscovery() {
|
void CheckRenderExecutorColorDepthTileDiscovery() {
|
||||||
constexpr const char *name = "RenderExecutorColorDepthTile";
|
constexpr const char *name = "RenderExecutorColorDepthTile";
|
||||||
constexpr uintptr_t base = 0x0000000203d00000ull;
|
constexpr uintptr_t base = 0x0000000203d00000ull;
|
||||||
@@ -21177,6 +21280,11 @@ int main(int argc, char **argv) {
|
|||||||
CheckStandard64RenderTargetTileRoundTrip();
|
CheckStandard64RenderTargetTileRoundTrip();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
if (argc == 2 && std::strcmp(argv[1], "--standard4-rt-only") == 0) {
|
||||||
|
VulkanHarness vulkan;
|
||||||
|
vulkan.CheckRenderExecutorColorStandard4TileDiscovery();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
if (argc == 2 && std::strcmp(argv[1], "--image-view-only") == 0) {
|
if (argc == 2 && std::strcmp(argv[1], "--image-view-only") == 0) {
|
||||||
VulkanHarness vulkan;
|
VulkanHarness vulkan;
|
||||||
CheckSampledColorViews();
|
CheckSampledColorViews();
|
||||||
@@ -21286,6 +21394,7 @@ int main(int argc, char **argv) {
|
|||||||
vulkan.CheckGpuTilerCpuParity();
|
vulkan.CheckGpuTilerCpuParity();
|
||||||
#if KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS
|
#if KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS
|
||||||
vulkan.CheckRenderExecutorColorVolumeDiscovery();
|
vulkan.CheckRenderExecutorColorVolumeDiscovery();
|
||||||
|
vulkan.CheckRenderExecutorColorStandard4TileDiscovery();
|
||||||
vulkan.CheckRenderExecutorColorDepthTileDiscovery();
|
vulkan.CheckRenderExecutorColorDepthTileDiscovery();
|
||||||
vulkan.CheckRenderExecutorStencilBindingDiscovery();
|
vulkan.CheckRenderExecutorStencilBindingDiscovery();
|
||||||
vulkan.CheckUnifiedTextureCacheFlow();
|
vulkan.CheckUnifiedTextureCacheFlow();
|
||||||
|
|||||||
Reference in New Issue
Block a user