shader: support signed sampled images

This commit is contained in:
nmzik
2026-09-02 03:20:34 +04:00
parent fc91fd2b1a
commit 894bc7de3c
13 changed files with 402 additions and 153 deletions
@@ -103,11 +103,11 @@ SelectSampledDepthView(vk::Format image_format, vk::Format view_format, uint32_t
[[nodiscard]] inline bool
IsSupportedSampledDepthResource(const ShaderRecompiler::IR::ImageResource& resource) noexcept {
if (resource.kind != ShaderRecompiler::IR::ResourceKind::Image &&
resource.kind != ShaderRecompiler::IR::ResourceKind::ImageUint) {
if (!ShaderRecompiler::IR::ImageResourceKindMatches(
resource.kind, ShaderRecompiler::IR::ImageResourceClass::Sampled)) {
return false;
}
if (resource.kind == ShaderRecompiler::IR::ResourceKind::ImageUint && resource.depth_compare) {
if (resource.kind != ShaderRecompiler::IR::ResourceKind::Image && resource.depth_compare) {
return false;
}
return (resource.dimension == ShaderRecompiler::Decoder::ImageDimension::Dim2D ||
@@ -63,7 +63,14 @@ bool IsSampledImage(BindingKind kind) {
case BindingKind::SampledUint2DArray:
case BindingKind::SampledUint2DMsaa:
case BindingKind::SampledUint2DMsaaArray:
case BindingKind::SampledUint3D: return true;
case BindingKind::SampledUint3D:
case BindingKind::SampledSint1D:
case BindingKind::SampledSint1DArray:
case BindingKind::SampledSint2D:
case BindingKind::SampledSint2DArray:
case BindingKind::SampledSint2DMsaa:
case BindingKind::SampledSint2DMsaaArray:
case BindingKind::SampledSint3D: return true;
default: return false;
}
}
@@ -229,8 +236,8 @@ static bool IsSupportedSampledColorResource(const ShaderRecompiler::IR::ImageRes
break;
default: break;
}
const bool sampled_kind = resource.kind == ShaderRecompiler::IR::ResourceKind::Image ||
resource.kind == ShaderRecompiler::IR::ResourceKind::ImageUint;
const bool sampled_kind = ShaderRecompiler::IR::ImageResourceKindMatches(
resource.kind, ShaderRecompiler::IR::ImageResourceClass::Sampled);
return sampled_kind && supported_dimension &&
resource.mip_mode == ShaderRecompiler::IR::ImageMipMode::None && resource.read &&
!resource.written && !resource.atomic && !resource.depth_compare;
@@ -512,10 +519,13 @@ void ValidateStorageTexture(const ShaderRecompiler::IR::ImageResource& resource,
resource.kind == ShaderRecompiler::IR::ResourceKind::StorageImageUint;
const bool raw_sint_storage = format == Prospero::BufferFormat::k32SInt && uint_resource &&
resource.written && !resource.read && !resource.atomic;
const auto numeric_class = Prospero::SampledTextureNumericClass(format);
const bool format_ok =
raw_sint_storage || (Prospero::IsSampledTextureFormat(format) &&
uint_resource == Prospero::IsUintTextureFormat(format) &&
(!resource.atomic || format == Prospero::BufferFormat::k32UInt));
raw_sint_storage ||
(numeric_class != Prospero::TextureNumericClass::Unsupported &&
numeric_class != Prospero::TextureNumericClass::Sint &&
uint_resource == (numeric_class == Prospero::TextureNumericClass::Uint) &&
(!resource.atomic || format == Prospero::BufferFormat::k32UInt));
if (resource_ok && descriptor_ok && encoding_ok && format_ok && size != 0) {
return;
}
@@ -547,6 +557,9 @@ struct NullImageSpec {
};
static NullImageSpec NullTextureSpec(const ShaderRecompiler::IR::ImageResource& resource) {
if (resource.kind == ShaderRecompiler::IR::ResourceKind::ImageSint) {
return {vk::Format::eR32Sint, Prospero::BufferFormat::k32SInt};
}
const bool uint_image = resource.kind == ShaderRecompiler::IR::ResourceKind::ImageUint ||
resource.kind == ShaderRecompiler::IR::ResourceKind::StorageImageUint;
return uint_image ? NullImageSpec {vk::Format::eR32Uint, Prospero::BufferFormat::k32UInt}
@@ -736,13 +749,25 @@ TextureBinding RenderExecutor::ResolveTexture(const ShaderRecompiler::IR::ImageR
const auto surface_format = TextureGetSurfaceFormatInfo(format);
const bool shader_conversion =
surface_format.conversion_format != Prospero::BufferFormat::kInvalid;
Prospero::TextureNumericClass resource_numeric_class =
Prospero::TextureNumericClass::Unsupported;
switch (resource.kind) {
case ShaderRecompiler::IR::ResourceKind::Image:
resource_numeric_class = Prospero::TextureNumericClass::Float;
break;
case ShaderRecompiler::IR::ResourceKind::ImageUint:
resource_numeric_class = Prospero::TextureNumericClass::Uint;
break;
case ShaderRecompiler::IR::ResourceKind::ImageSint:
resource_numeric_class = Prospero::TextureNumericClass::Sint;
break;
default: break;
}
const bool sampled_numeric_class =
storage || (Prospero::IsSampledTextureFormat(format) &&
(resource.kind == ShaderRecompiler::IR::ResourceKind::ImageUint) ==
Prospero::IsUintTextureFormat(format));
storage || resource_numeric_class == Prospero::SampledTextureNumericClass(format);
if (!storage &&
(resource.kind == ShaderRecompiler::IR::ResourceKind::Image ||
resource.kind == ShaderRecompiler::IR::ResourceKind::ImageUint) &&
ShaderRecompiler::IR::ImageResourceKindMatches(
resource.kind, ShaderRecompiler::IR::ImageResourceClass::Sampled) &&
!sampled_numeric_class) {
EXIT("sampled image numeric class mismatch: kind=%u format=%u addr=0x%016" PRIx64 "\n",
static_cast<uint32_t>(resource.kind), static_cast<uint32_t>(format), address);
@@ -236,8 +236,8 @@ void RenderExecutor::DispatchDirect(uint64_t submit_id, CommandBuffer& buffer,
}
const auto sampled_images = std::count_if(
program.info.images.begin(), program.info.images.end(), [](const auto& image) {
return image.kind == ShaderRecompiler::IR::ResourceKind::Image ||
image.kind == ShaderRecompiler::IR::ResourceKind::ImageUint;
return ShaderRecompiler::IR::ImageResourceKindMatches(
image.kind, ShaderRecompiler::IR::ImageResourceClass::Sampled);
});
const bool has_sampler = !program.info.samplers.empty();
static std::atomic<uint32_t> dispatch_log_count {0};
@@ -265,8 +265,8 @@ void RenderExecutor::DispatchDirect(uint64_t submit_id, CommandBuffer& buffer,
LOGF(" CS texture[%u]: source=%u usage=%s sampled=%s addr=0x%010" PRIx64
" type=%u fmt=%u extent=%ux%u depth=%u levels=%u tile=%u\n",
i, image.source, image.written ? "read-write" : "read-only",
(image.kind == ShaderRecompiler::IR::ResourceKind::Image ||
image.kind == ShaderRecompiler::IR::ResourceKind::ImageUint)
ShaderRecompiler::IR::ImageResourceKindMatches(
image.kind, ShaderRecompiler::IR::ImageResourceClass::Sampled)
? "true"
: "false",
r.Base40(), static_cast<uint32_t>(r.Type()), static_cast<uint32_t>(r.Format()),
@@ -199,8 +199,8 @@ static void LogDrawTargetState(const char* draw_name, const RenderColorInfo& col
const auto& ps_resources = ps_input_info.stage.program->info;
const auto sampled_images = std::count_if(
ps_resources.images.begin(), ps_resources.images.end(), [](const auto& image) {
return image.kind == ShaderRecompiler::IR::ResourceKind::Image ||
image.kind == ShaderRecompiler::IR::ResourceKind::ImageUint;
return ShaderRecompiler::IR::ImageResourceKindMatches(
image.kind, ShaderRecompiler::IR::ImageResourceClass::Sampled);
});
vk::Extent2D extent = color.image_id ? color.extent : vk::Extent2D {};