graphics: support compute stores to 2D MSAA images

This commit is contained in:
nmzik
2026-10-22 19:15:32 +02:00
parent aafe014d0c
commit 79837b423d
11 changed files with 156 additions and 27 deletions
@@ -121,6 +121,9 @@ uint32_t ImageType(EmitterState& state, const IR::ImageResource& image) {
EXIT("invalid image resource class");
}
const auto& info = ImageDimensionInfoFor(image.dimension);
if (sampled == 2 && info.multisampled != 0u) {
state.builder.RequireCapability(spv::CapabilityStorageImageMultisample);
}
const auto scalar_type =
image.atomic64 ? TypeU64(state) : ImageScalarType(state, image.numeric_class);
return state.builder.Type(spv::OpTypeImage, scalar_type,
@@ -213,15 +216,20 @@ uint32_t ImageDescriptorPointer(EmitterState& state, uint32_t resource, uint32_t
}
void EmitStorageImageWrite(EmitterState& state, uint32_t resource, uint32_t mip_lod, uint32_t coord,
uint32_t texel, uint32_t array_index) {
uint32_t texel, uint32_t array_index, uint32_t sample) {
const auto& image = state.program.info.images.at(resource);
EXIT_IF(image.resource_class != IR::ImageResourceClass::Storage);
if (!image.atomic) {
state.builder.RequireCapability(spv::CapabilityStorageImageWriteWithoutFormat);
}
const auto EmitWrite = [&](uint32_t mip) {
state.builder.AddFunction(spv::OpImageWrite, LoadImageDescriptor(state, resource, mip, array_index),
coord, texel);
const auto descriptor = LoadImageDescriptor(state, resource, mip, array_index);
if (sample == 0u) {
state.builder.AddFunction(spv::OpImageWrite, descriptor, coord, texel);
} else {
state.builder.AddFunction(spv::OpImageWrite, descriptor, coord, texel,
spv::ImageOperandsSampleMask, sample);
}
};
if (image.mip_mode != IR::ImageMipMode::Dynamic) {
EmitWrite(0);
@@ -941,9 +941,12 @@ void EmitImage(ValueEmitContext& ctx, const IR::Inst& inst) {
const auto mip_lod = candidate.mip_mode == IR::ImageMipMode::Dynamic
? LodU32(ctx, mem, *address, mem.image_dimension) : 0u;
const auto coord = CoordU32(ctx, mem, *address, candidate.dimension);
const auto& dimension_info = ImageDimensionInfoFor(candidate.dimension);
const auto sample = dimension_info.multisampled != 0u
? AddressU32(ctx, mem, *address, dimension_info.coordinate_components) : 0u;
const auto texel = StoreTexel(ctx, selected, ctx.Arg(inst, 2),
candidate.numeric_class == Prospero::TextureNumericClass::Uint);
EmitStorageImageWrite(state, resource, mip_lod, coord, texel, array_index);
EmitStorageImageWrite(state, resource, mip_lod, coord, texel, array_index, sample);
});
});
return;
@@ -339,8 +339,9 @@ uint32_t MakeSampledImage(EmitterState& state, uint32_t resource, uint32_t sampl
uint32_t mip = 0, uint32_t array_index = 0,
bool sampler_dynamic = false);
// sample is 0 (no id) for single-sampled images.
void EmitStorageImageWrite(EmitterState& state, uint32_t resource, uint32_t mip_lod, uint32_t coord,
uint32_t texel, uint32_t array_index);
uint32_t texel, uint32_t array_index, uint32_t sample);
spv::ExecutionModel ExecutionModelForStage(ShaderType stage);
+7 -7
View File
@@ -343,7 +343,7 @@ struct StageOutput {
inline constexpr uint32_t FirstImageBinding = 1u;
inline constexpr uint32_t FirstComparisonImageBinding = 22u;
inline constexpr uint32_t FirstStorageImageBinding = 29u;
inline constexpr uint32_t ImageBindingCount = 48u;
inline constexpr uint32_t ImageBindingCount = 50u;
enum class DescriptorBindingKind : uint32_t {
Buffers = 0u,
@@ -357,8 +357,8 @@ enum class DescriptorBindingKind : uint32_t {
Count,
};
static_assert(static_cast<uint32_t>(DescriptorBindingKind::Samplers) == 49u);
static_assert(static_cast<uint32_t>(DescriptorBindingKind::Count) == 56u);
static_assert(static_cast<uint32_t>(DescriptorBindingKind::Samplers) == 51u);
static_assert(static_cast<uint32_t>(DescriptorBindingKind::Count) == 58u);
struct PushData {
static constexpr uint32_t DwordCount = 32;
@@ -419,8 +419,8 @@ DescriptorBindingForImage(const ImageResource& image) {
constexpr uint32_t SampledUintBinding = 8u;
constexpr uint32_t SampledSintBinding = 15u;
constexpr uint32_t StorageFloatBinding = FirstStorageImageBinding;
constexpr uint32_t StorageUintBinding = StorageFloatBinding + 5u;
constexpr uint32_t AtomicUintBinding = StorageUintBinding + 5u;
constexpr uint32_t StorageUintBinding = StorageFloatBinding + 6u;
constexpr uint32_t AtomicUintBinding = StorageUintBinding + 6u;
uint32_t base = 0;
bool sampled = false;
@@ -467,10 +467,10 @@ DescriptorBindingForImage(const ImageResource& image) {
case Decoder::ImageDimension::Dim2D: dimension = 2u; break;
case Decoder::ImageDimension::Dim2DArray: dimension = 3u; break;
case Decoder::ImageDimension::Dim2DMsaa:
if (!sampled) {
if (image.atomic) {
return std::nullopt;
}
dimension = 4u;
dimension = sampled ? 4u : 5u;
break;
case Decoder::ImageDimension::Dim2DMsaaArray:
if (!sampled) {