vk_shader_decompiler: Implement atomic image operations

Implement atomic operations on images.
On GLSL these are atomicImage* functions (e.g. atomicImageAdd).
This commit is contained in:
ReinUsesLisp 2020-06-02 02:12:25 -03:00
parent 4a6b9a1a71
commit 866c1165af
2 changed files with 25 additions and 41 deletions

2
externals/sirit vendored

@ -1 +1 @@
Subproject commit a62c5bbc100a5e5a31ea0ccc4a78d8fa6a4167ce Subproject commit eefca56afd49379bdebc97ded8b480839f930881

View file

@ -971,7 +971,7 @@ private:
constexpr int depth = 0; constexpr int depth = 0;
constexpr bool ms = false; constexpr bool ms = false;
constexpr int sampled = 2; // This won't be accessed with a sampler constexpr int sampled = 2; // This won't be accessed with a sampler
constexpr auto format = spv::ImageFormat::Unknown; const auto format = image.is_atomic ? spv::ImageFormat::R32ui : spv::ImageFormat::Unknown;
const Id image_type = TypeImage(t_uint, dim, depth, arrayed, ms, sampled, format, {}); const Id image_type = TypeImage(t_uint, dim, depth, arrayed, ms, sampled, format, {});
const Id pointer_type = TypePointer(spv::StorageClass::UniformConstant, image_type); const Id pointer_type = TypePointer(spv::StorageClass::UniformConstant, image_type);
const Id id = OpVariable(pointer_type, spv::StorageClass::UniformConstant); const Id id = OpVariable(pointer_type, spv::StorageClass::UniformConstant);
@ -1274,7 +1274,7 @@ private:
} else { } else {
UNREACHABLE_MSG("Unmanaged offset node type"); UNREACHABLE_MSG("Unmanaged offset node type");
} }
pointer = OpAccessChain(t_cbuf_float, buffer_id, Constant(t_uint, 0), buffer_index, pointer = OpAccessChain(t_cbuf_float, buffer_id, v_uint_zero, buffer_index,
buffer_element); buffer_element);
} }
return {OpLoad(t_float, pointer), Type::Float}; return {OpLoad(t_float, pointer), Type::Float};
@ -1629,7 +1629,7 @@ private:
const Id result = OpIAddCarry(TypeStruct({t_uint, t_uint}), op_a, op_b); const Id result = OpIAddCarry(TypeStruct({t_uint, t_uint}), op_a, op_b);
const Id carry = OpCompositeExtract(t_uint, result, 1); const Id carry = OpCompositeExtract(t_uint, result, 1);
return {OpINotEqual(t_bool, carry, Constant(t_uint, 0)), Type::Bool}; return {OpINotEqual(t_bool, carry, v_uint_zero), Type::Bool};
} }
Expression LogicalAssign(Operation operation) { Expression LogicalAssign(Operation operation) {
@ -1969,39 +1969,20 @@ private:
return {}; return {};
} }
Expression AtomicImageAdd(Operation operation) { template <Id (Module::*func)(Id, Id, Id, Id, Id)>
UNIMPLEMENTED(); Expression AtomicImage(Operation operation) {
return {}; const auto& meta{std::get<MetaImage>(operation.GetMeta())};
} ASSERT(meta.values.size() == 1);
Expression AtomicImageMin(Operation operation) { const Id coordinate = GetCoordinates(operation, Type::Int);
UNIMPLEMENTED(); const Id image = images.at(meta.image.index).image;
return {}; const Id sample = v_uint_zero;
} const Id pointer = OpImageTexelPointer(t_image_uint, image, coordinate, sample);
Expression AtomicImageMax(Operation operation) { const Id scope = Constant(t_uint, static_cast<u32>(spv::Scope::Device));
UNIMPLEMENTED(); const Id semantics = v_uint_zero;
return {}; const Id value = AsUint(Visit(meta.values[0]));
} return {(this->*func)(t_uint, pointer, scope, semantics, value), Type::Uint};
Expression AtomicImageAnd(Operation operation) {
UNIMPLEMENTED();
return {};
}
Expression AtomicImageOr(Operation operation) {
UNIMPLEMENTED();
return {};
}
Expression AtomicImageXor(Operation operation) {
UNIMPLEMENTED();
return {};
}
Expression AtomicImageExchange(Operation operation) {
UNIMPLEMENTED();
return {};
} }
template <Id (Module::*func)(Id, Id, Id, Id, Id)> template <Id (Module::*func)(Id, Id, Id, Id, Id)>
@ -2016,7 +1997,7 @@ private:
return {v_float_zero, Type::Float}; return {v_float_zero, Type::Float};
} }
const Id scope = Constant(t_uint, static_cast<u32>(spv::Scope::Device)); const Id scope = Constant(t_uint, static_cast<u32>(spv::Scope::Device));
const Id semantics = Constant(t_uint, 0); const Id semantics = v_uint_zero;
const Id value = AsUint(Visit(operation[1])); const Id value = AsUint(Visit(operation[1]));
return {(this->*func)(t_uint, pointer, scope, semantics, value), Type::Uint}; return {(this->*func)(t_uint, pointer, scope, semantics, value), Type::Uint};
@ -2640,11 +2621,11 @@ private:
&SPIRVDecompiler::ImageLoad, &SPIRVDecompiler::ImageLoad,
&SPIRVDecompiler::ImageStore, &SPIRVDecompiler::ImageStore,
&SPIRVDecompiler::AtomicImageAdd, &SPIRVDecompiler::AtomicImage<&Module::OpAtomicIAdd>,
&SPIRVDecompiler::AtomicImageAnd, &SPIRVDecompiler::AtomicImage<&Module::OpAtomicAnd>,
&SPIRVDecompiler::AtomicImageOr, &SPIRVDecompiler::AtomicImage<&Module::OpAtomicOr>,
&SPIRVDecompiler::AtomicImageXor, &SPIRVDecompiler::AtomicImage<&Module::OpAtomicXor>,
&SPIRVDecompiler::AtomicImageExchange, &SPIRVDecompiler::AtomicImage<&Module::OpAtomicExchange>,
&SPIRVDecompiler::Atomic<&Module::OpAtomicExchange>, &SPIRVDecompiler::Atomic<&Module::OpAtomicExchange>,
&SPIRVDecompiler::Atomic<&Module::OpAtomicIAdd>, &SPIRVDecompiler::Atomic<&Module::OpAtomicIAdd>,
@ -2786,8 +2767,11 @@ private:
Decorate(TypeStruct(t_gmem_array), spv::Decoration::Block), 0, spv::Decoration::Offset, 0); Decorate(TypeStruct(t_gmem_array), spv::Decoration::Block), 0, spv::Decoration::Offset, 0);
const Id t_gmem_ssbo = TypePointer(spv::StorageClass::StorageBuffer, t_gmem_struct); const Id t_gmem_ssbo = TypePointer(spv::StorageClass::StorageBuffer, t_gmem_struct);
const Id t_image_uint = TypePointer(spv::StorageClass::Image, t_uint);
const Id v_float_zero = Constant(t_float, 0.0f); const Id v_float_zero = Constant(t_float, 0.0f);
const Id v_float_one = Constant(t_float, 1.0f); const Id v_float_one = Constant(t_float, 1.0f);
const Id v_uint_zero = Constant(t_uint, 0);
// Nvidia uses these defaults for varyings (e.g. position and generic attributes) // Nvidia uses these defaults for varyings (e.g. position and generic attributes)
const Id v_varying_default = const Id v_varying_default =