graphics: create depth images for comparison textures

This commit is contained in:
nmzik
2026-09-04 00:54:59 +02:00
parent d762d24f73
commit 0ce19357f6
3 changed files with 130 additions and 5 deletions
+3 -2
View File
@@ -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};
+110
View File
@@ -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();