mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-21 03:16:54 +02:00
graphics: create depth images for comparison textures
This commit is contained in:
+3
-2
@@ -939,7 +939,7 @@ void TextureCache::UploadImage(Image& image, const ImageDesc& desc, Buffer& sour
|
||||
image.Upload(copies, linear.buffer, linear.offset, linear.size);
|
||||
};
|
||||
|
||||
if (desc.type != BindingType::DepthTarget) {
|
||||
if (!info.IsDepth()) {
|
||||
auto plan = BuildColorTransfer(image, desc.type, TransferDirection::Upload);
|
||||
if (!plan.valid) {
|
||||
EXIT("TextureCache: invalid color upload: binding=%u addr=0x%016" PRIx64
|
||||
@@ -963,7 +963,8 @@ void TextureCache::UploadImage(Image& image, const ImageDesc& desc, Buffer& sour
|
||||
return;
|
||||
}
|
||||
|
||||
if (desc.type != BindingType::DepthTarget || info.samples != 1 || image.backing.samples != 1 ||
|
||||
if ((desc.type != BindingType::Texture && desc.type != BindingType::DepthTarget) ||
|
||||
info.samples != 1 || image.backing.samples != 1 ||
|
||||
info.resources.layers == 0 || info.data.size % info.resources.layers != 0 ||
|
||||
Prospero::NumBytesPerElement(info.guest_format) != info.bytes_per_block) {
|
||||
EXIT("TextureCache: invalid depth upload\n");
|
||||
|
||||
@@ -512,6 +512,20 @@ struct NullImageSpec {
|
||||
Prospero::BufferFormat guest_format;
|
||||
};
|
||||
|
||||
static vk::Format TextureBackingFormat(const ShaderRecompiler::IR::ImageResource& resource,
|
||||
Prospero::BufferFormat guest_format,
|
||||
vk::Format view_format) {
|
||||
if (!resource.depth_compare) {
|
||||
return view_format;
|
||||
}
|
||||
const auto* policy = FindGuestDepthFormatPolicy(guest_format);
|
||||
if (!IsSupportedSampledDepthResource(resource) || policy == nullptr) {
|
||||
EXIT("unsupported comparison-sampled texture: format=%u\n",
|
||||
static_cast<uint32_t>(guest_format));
|
||||
}
|
||||
return policy->depth_attachment_format;
|
||||
}
|
||||
|
||||
static NullImageSpec NullTextureSpec(const ShaderRecompiler::IR::ImageResource& resource) {
|
||||
switch (resource.numeric_class) {
|
||||
case Prospero::TextureNumericClass::Float:
|
||||
@@ -529,7 +543,7 @@ static TextureCache::ImageDesc NullTextureDesc(const ShaderRecompiler::IR::Image
|
||||
TextureCache::BindingType binding) {
|
||||
const auto spec = NullTextureSpec(resource);
|
||||
TextureCache::ImageDesc desc {};
|
||||
desc.info.pixel_format = spec.format;
|
||||
desc.info.pixel_format = TextureBackingFormat(resource, spec.guest_format, spec.format);
|
||||
desc.info.guest_format = spec.guest_format;
|
||||
desc.info.type = Prospero::ImageType::kColor2D;
|
||||
desc.info.extent = {1, 1, 1};
|
||||
@@ -537,7 +551,7 @@ static TextureCache::ImageDesc NullTextureDesc(const ShaderRecompiler::IR::Image
|
||||
desc.info.bytes_per_block = 4;
|
||||
desc.info.samples = 1;
|
||||
desc.info.mip_layout[0] = {0, 0, 1, 1};
|
||||
desc.view_info.format = desc.info.pixel_format;
|
||||
desc.view_info.format = spec.format;
|
||||
desc.view_info.type = vk::ImageViewType::e2D;
|
||||
desc.view_info.aspect = vk::ImageAspectFlagBits::eColor;
|
||||
desc.view_info.usage = binding == TextureCache::BindingType::Storage
|
||||
@@ -753,7 +767,7 @@ TextureBinding RenderExecutor::ResolveTexture(const ShaderRecompiler::IR::ImageR
|
||||
const auto block_bytes = Prospero::BlockCompressedBytesPerBlock(format);
|
||||
TextureCache::ImageDesc desc {};
|
||||
desc.info.data = {address, size.size};
|
||||
desc.info.pixel_format = pixel_format;
|
||||
desc.info.pixel_format = TextureBackingFormat(resource, format, pixel_format);
|
||||
desc.info.guest_format = format;
|
||||
desc.info.type = TextureBaseType(type);
|
||||
desc.info.extent = {width, height, volume ? depth : 1u};
|
||||
|
||||
@@ -9328,6 +9328,114 @@ public:
|
||||
std::printf("[host] %-32s ok\n", name);
|
||||
}
|
||||
|
||||
void CheckSampledDepthTextureDiscovery() {
|
||||
constexpr const char *name = "SampledDepthTextureDiscovery";
|
||||
constexpr uintptr_t base = 0x0000000204200000ull;
|
||||
constexpr uint64_t allocation_size = 0x200000;
|
||||
constexpr uint32_t width = 64;
|
||||
constexpr uint32_t height = 64;
|
||||
constexpr auto format = Prospero::BufferFormat::k32Float;
|
||||
constexpr auto tile = Prospero::TileMode::kDepth;
|
||||
EnsureRuntimeContext();
|
||||
|
||||
int64_t direct_offset = -1;
|
||||
Require(name, "direct allocation",
|
||||
Libs::LibKernel::Memory::KernelAllocateDirectMemory(
|
||||
0, Libs::LibKernel::Memory::KernelGetDirectMemorySize(),
|
||||
allocation_size, allocation_size, 0, &direct_offset) == 0,
|
||||
"sampled-depth direct-memory allocation failed");
|
||||
void *mapped = reinterpret_cast<void *>(base);
|
||||
Require(name, "direct mapping",
|
||||
Libs::LibKernel::Memory::KernelMapDirectMemory(
|
||||
&mapped, allocation_size, 0x3, 0x10, direct_offset,
|
||||
allocation_size) == 0 &&
|
||||
mapped == reinterpret_cast<void *>(base),
|
||||
"sampled-depth fixed 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{};
|
||||
scheduler.Begin(registers, user_config, shaders);
|
||||
auto &resources = context.GetGpuResources();
|
||||
auto &cache = resources.GetTextureCache();
|
||||
auto &executor = context.GetRenderExecutor();
|
||||
resources.MapMemory(base, allocation_size);
|
||||
|
||||
const auto encoded_address = base >> 8u;
|
||||
ShaderTextureResource descriptor{};
|
||||
descriptor.fields[0] = static_cast<uint32_t>(encoded_address);
|
||||
descriptor.fields[1] =
|
||||
static_cast<uint32_t>(encoded_address >> 32u) |
|
||||
(static_cast<uint32_t>(format) << 20u) | (((width - 1u) & 3u) << 30u);
|
||||
descriptor.fields[2] = ((width - 1u) >> 2u) | ((height - 1u) << 14u);
|
||||
descriptor.fields[3] =
|
||||
DstSel(4, 4, 4, 4) | (static_cast<uint32_t>(tile) << 20u) |
|
||||
(static_cast<uint32_t>(Prospero::ImageType::kColor2D) << 28u);
|
||||
descriptor.fields[5] = 0x00700000u;
|
||||
ShaderRecompiler::IR::DescriptorValue value{};
|
||||
std::copy(std::begin(descriptor.fields), std::end(descriptor.fields),
|
||||
value.dwords.begin());
|
||||
value.dword_count = 8;
|
||||
ShaderRecompiler::IR::ImageResource resource{};
|
||||
resource.resource_class =
|
||||
ShaderRecompiler::IR::ImageResourceClass::Sampled;
|
||||
resource.numeric_class = Prospero::TextureNumericClass::Float;
|
||||
resource.dimension = ShaderRecompiler::Decoder::ImageDimension::Dim2D;
|
||||
resource.read = true;
|
||||
resource.depth_compare = true;
|
||||
|
||||
auto binding =
|
||||
RenderExecutorTestAccess::ResolveTexture(executor, resource, value);
|
||||
const auto view = cache.FindTexture(binding.image_id, binding.desc);
|
||||
const auto &image = cache.GetImage(binding.image_id);
|
||||
const bool depth_view = std::ranges::any_of(image.views, [&](const auto &cached) {
|
||||
return cached.view == view && cached.info.format == vk::Format::eD32Sfloat &&
|
||||
cached.info.aspect == vk::ImageAspectFlagBits::eDepth;
|
||||
});
|
||||
Require(name, "uncached comparison image",
|
||||
binding.desc.info.pixel_format == vk::Format::eD32Sfloat &&
|
||||
binding.desc.view_info.format == vk::Format::eR32Sfloat &&
|
||||
image.backing.format == vk::Format::eD32Sfloat && view != nullptr &&
|
||||
depth_view,
|
||||
"comparison texture cache miss did not create a sampled D32 image");
|
||||
|
||||
ShaderRecompiler::IR::DescriptorValue null_value{};
|
||||
null_value.dword_count = 8;
|
||||
auto null_binding =
|
||||
RenderExecutorTestAccess::ResolveTexture(executor, resource, null_value);
|
||||
const auto null_view =
|
||||
cache.FindTexture(null_binding.image_id, null_binding.desc);
|
||||
const auto &null_image = cache.GetImage(null_binding.image_id);
|
||||
const bool null_depth_view =
|
||||
std::ranges::any_of(null_image.views, [&](const auto &cached) {
|
||||
return cached.view == null_view &&
|
||||
cached.info.format == vk::Format::eD32Sfloat &&
|
||||
cached.info.aspect == vk::ImageAspectFlagBits::eDepth;
|
||||
});
|
||||
Require(name, "null comparison image",
|
||||
null_binding.image_id != binding.image_id && null_image.info.data.Empty() &&
|
||||
null_image.backing.format == vk::Format::eD32Sfloat &&
|
||||
null_view != nullptr && null_depth_view,
|
||||
"null comparison texture did not use a sampled D32 image");
|
||||
|
||||
resources.UnmapMemory(base, allocation_size);
|
||||
scheduler.Finish();
|
||||
}
|
||||
|
||||
Require(name, "unmap direct backing",
|
||||
Libs::LibKernel::Memory::KernelMunmap(base, allocation_size) == 0,
|
||||
"sampled-depth direct mapping release failed");
|
||||
Require(name, "release direct backing",
|
||||
Libs::LibKernel::Memory::KernelReleaseDirectMemory(
|
||||
direct_offset, allocation_size) == 0,
|
||||
"sampled-depth direct-memory allocation release failed");
|
||||
std::printf("[gpu] %-32s ok\n", name);
|
||||
}
|
||||
|
||||
Buffer CreateStorageBuffer(const char *shader_name,
|
||||
const std::vector<u32> &initial,
|
||||
size_t dword_count, bool device_address = false) {
|
||||
@@ -26097,6 +26205,7 @@ int main(int argc, char **argv) {
|
||||
VulkanHarness vulkan;
|
||||
CheckSampledDepthResource();
|
||||
CheckSampledDepthDescriptor(vulkan.RuntimeRenderer());
|
||||
vulkan.CheckSampledDepthTextureDiscovery();
|
||||
CheckDepthComparisonBindings();
|
||||
RunCase(nullptr, ImageSampleOpcodeAliasUsesNormalCoords());
|
||||
RunCase(nullptr, ImageSampleA16CompareBiasRdna2AddressOrder());
|
||||
@@ -26213,6 +26322,7 @@ int main(int argc, char **argv) {
|
||||
vulkan.CheckRenderExecutorDccFixedClearFloat();
|
||||
vulkan.CheckRenderExecutorColorStandardTileDiscovery();
|
||||
vulkan.CheckRenderExecutorColorDepthTileDiscovery();
|
||||
vulkan.CheckSampledDepthTextureDiscovery();
|
||||
vulkan.CheckRenderExecutorStencilBindingDiscovery();
|
||||
vulkan.CheckUnifiedTextureCacheFlow();
|
||||
vulkan.CheckBgra16Readback();
|
||||
|
||||
Reference in New Issue
Block a user