refactor(shader): emit SPIR-V declarations on demand

This commit is contained in:
nmzik
2026-08-19 04:57:23 +02:00
parent e1bcc298a0
commit d34e30d892
20 changed files with 1629 additions and 1495 deletions
@@ -168,45 +168,54 @@ uint32_t ImageViewSpatialComponents(ImageViewKind view) {
}
}
uint32_t ImageViewImageType(const EmitterState& state, ImageViewKind view, bool integer) {
return state.sampled_images[SampledImageIndex(integer, view)].image_type;
uint32_t ImageViewImageType(EmitterState& state, ImageViewKind view, bool integer) {
const auto component = integer ? TypeU32(state) : TypeF32(state);
return state.builder.Type(OpTypeImage,
{component, ImageSpirvDimension(view), 0, ImageSpirvArrayed(view),
ImageSpirvMultisampled(view), 1, ImageFormatUnknown});
}
uint32_t ImageViewSampledImageType(const EmitterState& state, ImageViewKind view, bool integer) {
return state.sampled_images[SampledImageIndex(integer, view)].sampled_image_type;
uint32_t ImageViewSampledImageType(EmitterState& state, ImageViewKind view, bool integer) {
return state.builder.Type(OpTypeSampledImage, {ImageViewImageType(state, view, integer)});
}
uint32_t ImageViewSizeType(const EmitterState& state, ImageViewKind view) {
uint32_t ImageViewSizeType(EmitterState& state, ImageViewKind view) {
switch (ImageViewCoordinateComponents(view)) {
case 1u: return state.uint_type;
case 2u: return state.vec2_uint_type;
case 3u: return state.vec3_uint_type;
case 1u: return TypeU32(state);
case 2u: return TypeU32Vector(state, 2);
case 3u: return TypeU32Vector(state, 3);
default: return 0;
}
}
uint32_t StorageImageType(const EmitterState& state, bool uint_image, ImageViewKind view) {
return state.storage_images[StorageImageIndex(uint_image, view)].image_type;
uint32_t StorageImageType(EmitterState& state, bool uint_image, ImageViewKind view) {
const auto component = uint_image ? TypeU32(state) : TypeF32(state);
const auto format = uint_image ? ImageFormatR32ui : ImageFormatUnknown;
return state.builder.Type(OpTypeImage, {component, ImageSpirvDimension(view), 0,
ImageSpirvArrayed(view), 0, 2, format});
}
uint32_t StorageImagePointerType(const EmitterState& state, bool uint_image, ImageViewKind view) {
return state.storage_images[StorageImageIndex(uint_image, view)].pointer_type;
uint32_t StorageImagePointerType(EmitterState& state, bool uint_image, ImageViewKind view) {
return state.builder.Type(
OpTypePointer, {StorageClassUniformConstant, StorageImageType(state, uint_image, view)});
}
uint32_t StorageImageVariable(const EmitterState& state, bool uint_image, ImageViewKind view) {
return state.storage_images[StorageImageIndex(uint_image, view)].variable;
return state.storage_image_variables[StorageImageIndex(uint_image, view)];
}
uint32_t LoadSampledImageDescriptor(EmitterState& state, const IR::MemoryInfo& mem, uint32_t use_pc,
ImageViewKind view) {
(void)use_pc;
const bool integer = mem.kind == IR::ResourceKind::ImageUint;
const auto kind = SampledBindingKind(integer, view);
const auto binding = ResourceForDescriptor(state, kind, mem.resource);
const auto& descriptors = state.sampled_images[SampledImageIndex(integer, view)];
const auto pointer = DescriptorElementPointer(
state, descriptors.pointer_type, descriptors.variable, binding.array_index, kind,
mem.resource, "sampled image descriptor array was not emitted");
const bool integer = mem.kind == IR::ResourceKind::ImageUint;
const auto kind = SampledBindingKind(integer, view);
const auto binding = ResourceForDescriptor(state, kind, mem.resource);
const auto variable = state.sampled_image_variables[SampledImageIndex(integer, view)];
const auto pointer_type = state.builder.Type(
OpTypePointer, {StorageClassUniformConstant, ImageViewImageType(state, view, integer)});
const auto pointer =
DescriptorElementPointer(state, pointer_type, variable, binding.array_index, kind,
mem.resource, "sampled image descriptor array was not emitted");
const auto image = state.builder.AllocateId();
state.builder.AddFunction({OpLoad, ImageViewImageType(state, view, integer), image, pointer});
return image;
@@ -215,11 +224,14 @@ uint32_t LoadSampledImageDescriptor(EmitterState& state, const IR::MemoryInfo& m
uint32_t LoadSamplerDescriptor(EmitterState& state, uint32_t sampler, uint32_t use_pc) {
(void)use_pc;
const auto binding = ResourceForDescriptor(state, IR::DescriptorBindingKind::Samplers, sampler);
const auto sampler_type = state.builder.Type(OpTypeSampler);
const auto pointer_type =
state.builder.Type(OpTypePointer, {StorageClassUniformConstant, sampler_type});
const auto pointer = DescriptorElementPointer(
state, state.ptr_uniform_sampler, state.sampler_variable, binding.array_index,
state, pointer_type, state.sampler_variable, binding.array_index,
IR::DescriptorBindingKind::Samplers, sampler, "sampler descriptor array was not emitted");
const auto sampler_id = state.builder.AllocateId();
state.builder.AddFunction({OpLoad, state.sampler_type, sampler_id, pointer});
state.builder.AddFunction({OpLoad, sampler_type, sampler_id, pointer});
return sampler_id;
}
@@ -273,6 +285,9 @@ uint32_t LoadStorageImageDescriptor(EmitterState& state, uint32_t resource, bool
void EmitStorageImageWrite(EmitterState& state, uint32_t resource, bool uint_image,
ImageViewKind view, uint32_t mip_lod, uint32_t coord, uint32_t texel) {
if (!uint_image) {
state.builder.RequireCapability(CapabilityStorageImageWriteWithoutFormat);
}
const auto kind = StorageBindingKind(uint_image, view);
const auto binding = ResourceForDescriptor(state, kind, resource);
const auto& image = state.program.info.images.at(resource);