Add NonSemantic DebugPrintf

This commit is contained in:
Frodo Baggins 2024-09-18 23:04:20 -07:00
parent 37090c74cc
commit b51af1a2ca
3 changed files with 111 additions and 84 deletions

View File

@ -73,9 +73,9 @@ public:
// TODO: Change std::is_convertible_v to std::convertible_to when compilers // TODO: Change std::is_convertible_v to std::convertible_to when compilers
// support it; same elsewhere. // support it; same elsewhere.
template <typename... Ts> template <typename... Ts>
requires(...&& std::is_convertible_v<Ts, Id>) void AddEntryPoint( requires(... && std::is_convertible_v<Ts, Id>)
spv::ExecutionModel execution_model, Id entry_point, std::string_view name, void AddEntryPoint(spv::ExecutionModel execution_model, Id entry_point, std::string_view name,
Ts&&... interfaces) { Ts&&... interfaces) {
AddEntryPoint(execution_model, std::move(entry_point), name, AddEntryPoint(execution_model, std::move(entry_point), name,
std::span<const Id>({interfaces...})); std::span<const Id>({interfaces...}));
} }
@ -86,8 +86,8 @@ public:
/// Declare an execution mode for an entry point. /// Declare an execution mode for an entry point.
template <typename... Ts> template <typename... Ts>
requires(...&& std::is_convertible_v<Ts, Literal>) void AddExecutionMode( requires(... && std::is_convertible_v<Ts, Literal>)
Id entry_point, spv::ExecutionMode mode, Ts&&... literals) { void AddExecutionMode(Id entry_point, spv::ExecutionMode mode, Ts&&... literals) {
AddExecutionMode(entry_point, mode, std::span<const Literal>({literals...})); AddExecutionMode(entry_point, mode, std::span<const Literal>({literals...}));
} }
@ -162,7 +162,8 @@ public:
/// Returns type struct. /// Returns type struct.
template <typename... Ts> template <typename... Ts>
requires(...&& std::is_convertible_v<Ts, Id>) Id TypeStruct(Ts&&... members) { requires(... && std::is_convertible_v<Ts, Id>)
Id TypeStruct(Ts&&... members) {
return TypeStruct(std::span<const Id>({members...})); return TypeStruct(std::span<const Id>({members...}));
} }
@ -177,8 +178,8 @@ public:
/// Returns type function. /// Returns type function.
template <typename... Ts> template <typename... Ts>
requires(...&& std::is_convertible_v<Ts, Id>) Id requires(... && std::is_convertible_v<Ts, Id>)
TypeFunction(Id return_type, Ts&&... arguments) { Id TypeFunction(Id return_type, Ts&&... arguments) {
return TypeFunction(return_type, std::span<const Id>({arguments...})); return TypeFunction(return_type, std::span<const Id>({arguments...}));
} }
@ -213,8 +214,8 @@ public:
/// Returns a numeric scalar constant. /// Returns a numeric scalar constant.
template <typename... Ts> template <typename... Ts>
requires(...&& std::is_convertible_v<Ts, Id>) Id requires(... && std::is_convertible_v<Ts, Id>)
ConstantComposite(Id result_type, Ts&&... constituents) { Id ConstantComposite(Id result_type, Ts&&... constituents) {
return ConstantComposite(result_type, std::span<const Id>({constituents...})); return ConstantComposite(result_type, std::span<const Id>({constituents...}));
} }
@ -238,8 +239,8 @@ public:
/// Call a function. /// Call a function.
template <typename... Ts> template <typename... Ts>
requires(...&& std::is_convertible_v<Ts, Id>) Id requires(... && std::is_convertible_v<Ts, Id>)
OpFunctionCall(Id result_type, Id function, Ts&&... arguments) { Id OpFunctionCall(Id result_type, Id function, Ts&&... arguments) {
return OpFunctionCall(result_type, function, std::span<const Id>({arguments...})); return OpFunctionCall(result_type, function, std::span<const Id>({arguments...}));
} }
@ -257,11 +258,11 @@ public:
Id OpPhi(Id result_type, std::span<const Id> operands); Id OpPhi(Id result_type, std::span<const Id> operands);
template <typename... Ts> template <typename... Ts>
requires(...&& std::is_convertible_v<Ts, Id>) Id requires(... && std::is_convertible_v<Ts, Id>)
OpPhi(Id result_type, Ts&&... operands) { Id OpPhi(Id result_type, Ts&&... operands) {
return OpPhi(result_type, std::span<const Id>({operands...})); return OpPhi(result_type, std::span<const Id>({operands...}));
} }
/** /**
* The SSA phi function. This instruction will be revisited when patching phi nodes. * The SSA phi function. This instruction will be revisited when patching phi nodes.
* *
@ -276,9 +277,9 @@ public:
/// Declare a structured loop. /// Declare a structured loop.
template <typename... Ts> template <typename... Ts>
requires(...&& std::is_convertible_v<Ts, Id>) Id requires(... && std::is_convertible_v<Ts, Id>)
OpLoopMerge(Id merge_block, Id continue_target, spv::LoopControlMask loop_control, Id OpLoopMerge(Id merge_block, Id continue_target, spv::LoopControlMask loop_control,
Ts&&... literals) { Ts&&... literals) {
return OpLoopMerge(merge_block, continue_target, loop_control, return OpLoopMerge(merge_block, continue_target, loop_control,
std::span<const Id>({literals...})); std::span<const Id>({literals...}));
} }
@ -356,8 +357,8 @@ public:
/// Create a pointer into a composite object that can be used with OpLoad and OpStore. /// Create a pointer into a composite object that can be used with OpLoad and OpStore.
template <typename... Ts> template <typename... Ts>
requires(...&& std::is_convertible_v<Ts, Id>) Id requires(... && std::is_convertible_v<Ts, Id>)
OpAccessChain(Id result_type, Id base, Ts&&... indexes) { Id OpAccessChain(Id result_type, Id base, Ts&&... indexes) {
return OpAccessChain(result_type, base, std::span<const Id>({indexes...})); return OpAccessChain(result_type, base, std::span<const Id>({indexes...}));
} }
@ -368,14 +369,16 @@ public:
Id OpVectorInsertDynamic(Id result_type, Id vector, Id component, Id index); Id OpVectorInsertDynamic(Id result_type, Id vector, Id component, Id index);
/// Select arbitrary components from two vectors to make a new vector. /// Select arbitrary components from two vectors to make a new vector.
Id OpVectorShuffle(Id result_type, Id vector_1, Id vector_2, std::span<const Literal> components); Id OpVectorShuffle(Id result_type, Id vector_1, Id vector_2,
std::span<const Literal> components);
/// Select arbitrary components from two vectors to make a new vector. /// Select arbitrary components from two vectors to make a new vector.
template <typename... Ts> template <typename... Ts>
requires(...&& std::is_convertible_v<Ts, Literal>) Id requires(... && std::is_convertible_v<Ts, Literal>)
OpVectorShuffle(Id result_type, Id vector_1, Id vector_2, Ts&&... components) { Id OpVectorShuffle(Id result_type, Id vector_1, Id vector_2, Ts&&... components) {
const Literal stack_literals[] = {std::forward<Ts>(components)...}; const Literal stack_literals[] = {std::forward<Ts>(components)...};
return OpVectorShuffle(result_type, vector_1, vector_2, std::span<const Literal>{stack_literals}); return OpVectorShuffle(result_type, vector_1, vector_2,
std::span<const Literal>{stack_literals});
} }
/// Make a copy of a composite object, while modifying one part of it. /// Make a copy of a composite object, while modifying one part of it.
@ -384,8 +387,8 @@ public:
/// Make a copy of a composite object, while modifying one part of it. /// Make a copy of a composite object, while modifying one part of it.
template <typename... Ts> template <typename... Ts>
requires(...&& std::is_convertible_v<Ts, Literal>) Id requires(... && std::is_convertible_v<Ts, Literal>)
OpCompositeInsert(Id result_type, Id object, Id composite, Ts&&... indexes) { Id OpCompositeInsert(Id result_type, Id object, Id composite, Ts&&... indexes) {
const Literal stack_indexes[] = {std::forward<Ts>(indexes)...}; const Literal stack_indexes[] = {std::forward<Ts>(indexes)...};
return OpCompositeInsert(result_type, object, composite, return OpCompositeInsert(result_type, object, composite,
std::span<const Literal>{stack_indexes}); std::span<const Literal>{stack_indexes});
@ -396,8 +399,8 @@ public:
/// Extract a part of a composite object. /// Extract a part of a composite object.
template <typename... Ts> template <typename... Ts>
requires(...&& std::is_convertible_v<Ts, Literal>) Id requires(... && std::is_convertible_v<Ts, Literal>)
OpCompositeExtract(Id result_type, Id composite, Ts&&... indexes) { Id OpCompositeExtract(Id result_type, Id composite, Ts&&... indexes) {
const Literal stack_indexes[] = {std::forward<Ts>(indexes)...}; const Literal stack_indexes[] = {std::forward<Ts>(indexes)...};
return OpCompositeExtract(result_type, composite, std::span<const Literal>{stack_indexes}); return OpCompositeExtract(result_type, composite, std::span<const Literal>{stack_indexes});
} }
@ -407,8 +410,8 @@ public:
/// Construct a new composite object from a set of constituent objects that will fully form it. /// Construct a new composite object from a set of constituent objects that will fully form it.
template <typename... Ts> template <typename... Ts>
requires(...&& std::is_convertible_v<Ts, Id>) Id requires(... && std::is_convertible_v<Ts, Id>)
OpCompositeConstruct(Id result_type, Ts&&... ids) { Id OpCompositeConstruct(Id result_type, Ts&&... ids) {
return OpCompositeConstruct(result_type, std::span<const Id>({ids...})); return OpCompositeConstruct(result_type, std::span<const Id>({ids...}));
} }
@ -419,15 +422,16 @@ public:
/// Add a decoration to target. /// Add a decoration to target.
template <typename... Ts> template <typename... Ts>
requires(...&& std::is_convertible_v<Ts, Literal>) Id requires(... && std::is_convertible_v<Ts, Literal>)
Decorate(Id target, spv::Decoration decoration, Ts&&... literals) { Id Decorate(Id target, spv::Decoration decoration, Ts&&... literals) {
const Literal stack_literals[] = {std::forward<Ts>(literals)...}; const Literal stack_literals[] = {std::forward<Ts>(literals)...};
return Decorate(target, decoration, std::span<const Literal>{stack_literals}); return Decorate(target, decoration, std::span<const Literal>{stack_literals});
} }
/// Add a decoration to target. /// Add a decoration to target.
template <typename T> template <typename T>
requires std::is_enum_v<T> Id Decorate(Id target, spv::Decoration decoration, T literal) { requires std::is_enum_v<T>
Id Decorate(Id target, spv::Decoration decoration, T literal) {
return Decorate(target, decoration, static_cast<std::uint32_t>(literal)); return Decorate(target, decoration, static_cast<std::uint32_t>(literal));
} }
@ -435,9 +439,9 @@ public:
std::span<const Literal> literals = {}); std::span<const Literal> literals = {});
template <typename... Ts> template <typename... Ts>
requires(...&& std::is_convertible_v<Ts, Literal>) Id requires(... && std::is_convertible_v<Ts, Literal>)
MemberDecorate(Id structure_type, Literal member, spv::Decoration decoration, Id MemberDecorate(Id structure_type, Literal member, spv::Decoration decoration,
Ts&&... literals) { Ts&&... literals) {
const Literal stack_literals[] = {std::forward<Ts>(literals)...}; const Literal stack_literals[] = {std::forward<Ts>(literals)...};
return MemberDecorate(structure_type, member, decoration, return MemberDecorate(structure_type, member, decoration,
std::span<const Literal>{stack_literals}); std::span<const Literal>{stack_literals});
@ -718,8 +722,8 @@ public:
/// Execute an instruction in an imported set of extended instructions. /// Execute an instruction in an imported set of extended instructions.
template <typename... Ts> template <typename... Ts>
requires(...&& std::is_convertible_v<Ts, Id>) Id requires(... && std::is_convertible_v<Ts, Id>)
OpExtInst(Id result_type, Id set, std::uint32_t instruction, Ts&&... operands) { Id OpExtInst(Id result_type, Id set, std::uint32_t instruction, Ts&&... operands) {
return OpExtInst(result_type, set, instruction, std::span<const Id>({operands...})); return OpExtInst(result_type, set, instruction, std::span<const Id>({operands...}));
} }
@ -793,7 +797,8 @@ public:
/// Result is the reciprocal of sqrt x. Result is undefined if x <= 0. /// Result is the reciprocal of sqrt x. Result is undefined if x <= 0.
Id OpInverseSqrt(Id result_type, Id x); Id OpInverseSqrt(Id result_type, Id x);
/// Result is a floating-point number from x and the corresponding integral exponent of two in exp. /// Result is a floating-point number from x and the corresponding integral exponent of two in
/// exp.
Id OpLdexp(Id result_type, Id x, Id exp); Id OpLdexp(Id result_type, Id x, Id exp);
/// Result is y if y < x; otherwise result is x. Which operand is the result is undefined if one /// Result is y if y < x; otherwise result is x. Which operand is the result is undefined if one
@ -808,8 +813,8 @@ public:
/// integers. /// integers.
Id OpSMin(Id result_type, Id x, Id y); Id OpSMin(Id result_type, Id x, Id y);
/// Result is y if y < x, either x or y if both x and y are zeros, otherwise x. If one operand is a NaN, the other /// Result is y if y < x, either x or y if both x and y are zeros, otherwise x. If one operand
/// operand is the result. If both operands are NaN, the result is a NaN. /// is a NaN, the other operand is the result. If both operands are NaN, the result is a NaN.
Id OpNMin(Id result_type, Id x, Id y); Id OpNMin(Id result_type, Id x, Id y);
/// Result is y if x < y; otherwise result is x. Which operand is the result is undefined if one /// Result is y if x < y; otherwise result is x. Which operand is the result is undefined if one
@ -824,8 +829,8 @@ public:
/// integers. /// integers.
Id OpSMax(Id result_type, Id x, Id y); Id OpSMax(Id result_type, Id x, Id y);
/// Result is y if x < y, either x or y if both x and y are zeros, otherwise x. If one operand is a NaN, the other /// Result is y if x < y, either x or y if both x and y are zeros, otherwise x. If one operand
/// operand is the result. If both operands are NaN, the result is a NaN. /// is a NaN, the other operand is the result. If both operands are NaN, the result is a NaN.
Id OpNMax(Id result_type, Id x, Id y); Id OpNMax(Id result_type, Id x, Id y);
/// Result is min(max(x, minVal), maxVal). Result is undefined if minVal > maxVal.The semantics /// Result is min(max(x, minVal), maxVal). Result is undefined if minVal > maxVal.The semantics
@ -943,9 +948,9 @@ public:
/// Sample an image with an implicit level of detail. /// Sample an image with an implicit level of detail.
template <typename... Ts> template <typename... Ts>
requires(...&& std::is_convertible_v<Ts, Id>) Id requires(... && std::is_convertible_v<Ts, Id>)
OpImageSampleImplicitLod(Id result_type, Id sampled_image, Id coordinate, Id OpImageSampleImplicitLod(Id result_type, Id sampled_image, Id coordinate,
spv::ImageOperandsMask image_operands, Ts&&... operands) { spv::ImageOperandsMask image_operands, Ts&&... operands) {
return OpImageSampleImplicitLod(result_type, sampled_image, coordinate, image_operands, return OpImageSampleImplicitLod(result_type, sampled_image, coordinate, image_operands,
std::span<const Id>({operands...})); std::span<const Id>({operands...}));
} }
@ -957,9 +962,9 @@ public:
/// Sample an image using an explicit level of detail. /// Sample an image using an explicit level of detail.
template <typename... Ts> template <typename... Ts>
requires(...&& std::is_convertible_v<Ts, Id>) Id requires(... && std::is_convertible_v<Ts, Id>)
OpImageSampleExplicitLod(Id result_type, Id sampled_image, Id coordinate, Id OpImageSampleExplicitLod(Id result_type, Id sampled_image, Id coordinate,
spv::ImageOperandsMask image_operands, Ts&&... operands) { spv::ImageOperandsMask image_operands, Ts&&... operands) {
return OpImageSampleExplicitLod(result_type, sampled_image, coordinate, image_operands, return OpImageSampleExplicitLod(result_type, sampled_image, coordinate, image_operands,
std::span<const Id>({operands...})); std::span<const Id>({operands...}));
} }
@ -972,9 +977,9 @@ public:
/// Sample an image doing depth-comparison with an implicit level of detail. /// Sample an image doing depth-comparison with an implicit level of detail.
template <typename... Ts> template <typename... Ts>
requires(...&& std::is_convertible_v<Ts, Id>) Id requires(... && std::is_convertible_v<Ts, Id>)
OpImageSampleDrefImplicitLod(Id result_type, Id sampled_image, Id coordinate, Id dref, Id OpImageSampleDrefImplicitLod(Id result_type, Id sampled_image, Id coordinate, Id dref,
spv::ImageOperandsMask image_operands, Ts&&... operands) { spv::ImageOperandsMask image_operands, Ts&&... operands) {
return OpImageSampleDrefImplicitLod(result_type, sampled_image, coordinate, dref, return OpImageSampleDrefImplicitLod(result_type, sampled_image, coordinate, dref,
image_operands, std::span<const Id>({operands...})); image_operands, std::span<const Id>({operands...}));
} }
@ -986,9 +991,9 @@ public:
/// Sample an image doing depth-comparison using an explicit level of detail. /// Sample an image doing depth-comparison using an explicit level of detail.
template <typename... Ts> template <typename... Ts>
requires(...&& std::is_convertible_v<Ts, Id>) Id requires(... && std::is_convertible_v<Ts, Id>)
OpImageSampleDrefExplicitLod(Id result_type, Id sampled_image, Id coordinate, Id dref, Id OpImageSampleDrefExplicitLod(Id result_type, Id sampled_image, Id coordinate, Id dref,
spv::ImageOperandsMask image_operands, Ts&&... operands) { spv::ImageOperandsMask image_operands, Ts&&... operands) {
return OpImageSampleDrefExplicitLod(result_type, sampled_image, coordinate, dref, return OpImageSampleDrefExplicitLod(result_type, sampled_image, coordinate, dref,
image_operands, std::span<const Id>({operands...})); image_operands, std::span<const Id>({operands...}));
} }
@ -1001,9 +1006,9 @@ public:
/// Sample an image with with a project coordinate and an implicit level of detail. /// Sample an image with with a project coordinate and an implicit level of detail.
template <typename... Ts> template <typename... Ts>
requires(...&& std::is_convertible_v<Ts, Id>) Id requires(... && std::is_convertible_v<Ts, Id>)
OpImageSampleProjImplicitLod(Id result_type, Id sampled_image, Id coordinate, Id OpImageSampleProjImplicitLod(Id result_type, Id sampled_image, Id coordinate,
spv::ImageOperandsMask image_operands, Ts&&... operands) { spv::ImageOperandsMask image_operands, Ts&&... operands) {
return OpImageSampleProjImplicitLod(result_type, sampled_image, coordinate, image_operands, return OpImageSampleProjImplicitLod(result_type, sampled_image, coordinate, image_operands,
std::span<const Id>({operands...})); std::span<const Id>({operands...}));
} }
@ -1015,9 +1020,9 @@ public:
/// Sample an image with a project coordinate using an explicit level of detail. /// Sample an image with a project coordinate using an explicit level of detail.
template <typename... Ts> template <typename... Ts>
requires(...&& std::is_convertible_v<Ts, Id>) Id requires(... && std::is_convertible_v<Ts, Id>)
OpImageSampleProjExplicitLod(Id result_type, Id sampled_image, Id coordinate, Id OpImageSampleProjExplicitLod(Id result_type, Id sampled_image, Id coordinate,
spv::ImageOperandsMask image_operands, Ts&&... operands) { spv::ImageOperandsMask image_operands, Ts&&... operands) {
return OpImageSampleProjExplicitLod(result_type, sampled_image, coordinate, image_operands, return OpImageSampleProjExplicitLod(result_type, sampled_image, coordinate, image_operands,
std::span<const Id>({operands...})); std::span<const Id>({operands...}));
} }
@ -1032,9 +1037,9 @@ public:
/// Sample an image with a project coordinate, doing depth-comparison, with an implicit level of /// Sample an image with a project coordinate, doing depth-comparison, with an implicit level of
/// detail. /// detail.
template <typename... Ts> template <typename... Ts>
requires(...&& std::is_convertible_v<Ts, Id>) Id requires(... && std::is_convertible_v<Ts, Id>)
OpImageSampleProjDrefImplicitLod(Id result_type, Id sampled_image, Id coordinate, Id dref, Id OpImageSampleProjDrefImplicitLod(Id result_type, Id sampled_image, Id coordinate, Id dref,
spv::ImageOperandsMask image_operands, Ts&&... operands) { spv::ImageOperandsMask image_operands, Ts&&... operands) {
return OpImageSampleProjDrefImplicitLod(result_type, sampled_image, coordinate, dref, return OpImageSampleProjDrefImplicitLod(result_type, sampled_image, coordinate, dref,
image_operands, std::span<const Id>({operands...})); image_operands, std::span<const Id>({operands...}));
} }
@ -1048,9 +1053,9 @@ public:
/// Sample an image with a project coordinate, doing depth-comparison, using an explicit level /// Sample an image with a project coordinate, doing depth-comparison, using an explicit level
/// of detail. /// of detail.
template <typename... Ts> template <typename... Ts>
requires(...&& std::is_convertible_v<Ts, Id>) Id requires(... && std::is_convertible_v<Ts, Id>)
OpImageSampleProjDrefExplicitLod(Id result_type, Id sampled_image, Id coordinate, Id dref, Id OpImageSampleProjDrefExplicitLod(Id result_type, Id sampled_image, Id coordinate, Id dref,
spv::ImageOperandsMask image_operands, Ts&&... operands) { spv::ImageOperandsMask image_operands, Ts&&... operands) {
return OpImageSampleProjDrefExplicitLod(result_type, sampled_image, coordinate, dref, return OpImageSampleProjDrefExplicitLod(result_type, sampled_image, coordinate, dref,
image_operands, std::span<const Id>({operands...})); image_operands, std::span<const Id>({operands...}));
} }
@ -1062,9 +1067,9 @@ public:
/// Fetch a single texel from an image whose Sampled operand is 1. /// Fetch a single texel from an image whose Sampled operand is 1.
template <typename... Ts> template <typename... Ts>
requires(...&& std::is_convertible_v<Ts, Id>) Id requires(... && std::is_convertible_v<Ts, Id>)
OpImageFetch(Id result_type, Id sampled_image, Id coordinate, Id OpImageFetch(Id result_type, Id sampled_image, Id coordinate,
spv::ImageOperandsMask image_operands, Ts&&... operands) { spv::ImageOperandsMask image_operands, Ts&&... operands) {
return OpImageFetch(result_type, sampled_image, coordinate, image_operands, return OpImageFetch(result_type, sampled_image, coordinate, image_operands,
std::span<const Id>({operands...})); std::span<const Id>({operands...}));
} }
@ -1076,9 +1081,9 @@ public:
/// Gathers the requested component from four texels. /// Gathers the requested component from four texels.
template <typename... Ts> template <typename... Ts>
requires(...&& std::is_convertible_v<Ts, Id>) Id requires(... && std::is_convertible_v<Ts, Id>)
OpImageGather(Id result_type, Id sampled_image, Id coordinate, Id component, Id OpImageGather(Id result_type, Id sampled_image, Id coordinate, Id component,
spv::ImageOperandsMask image_operands, Ts&&... operands) { spv::ImageOperandsMask image_operands, Ts&&... operands) {
return OpImageGather(result_type, sampled_image, coordinate, component, image_operands, return OpImageGather(result_type, sampled_image, coordinate, component, image_operands,
std::span<const Id>({operands...})); std::span<const Id>({operands...}));
} }
@ -1090,9 +1095,9 @@ public:
/// Gathers the requested depth-comparison from four texels. /// Gathers the requested depth-comparison from four texels.
template <typename... Ts> template <typename... Ts>
requires(...&& std::is_convertible_v<Ts, Id>) Id requires(... && std::is_convertible_v<Ts, Id>)
OpImageDrefGather(Id result_type, Id sampled_image, Id coordinate, Id dref, Id OpImageDrefGather(Id result_type, Id sampled_image, Id coordinate, Id dref,
spv::ImageOperandsMask image_operands, Ts&&... operands) { spv::ImageOperandsMask image_operands, Ts&&... operands) {
return OpImageDrefGather(result_type, sampled_image, coordinate, dref, image_operands, return OpImageDrefGather(result_type, sampled_image, coordinate, dref, image_operands,
std::span<const Id>({operands...})); std::span<const Id>({operands...}));
} }
@ -1104,9 +1109,9 @@ public:
/// Read a texel from an image without a sampler. /// Read a texel from an image without a sampler.
template <typename... Ts> template <typename... Ts>
requires(...&& std::is_convertible_v<Ts, Id>) Id requires(... && std::is_convertible_v<Ts, Id>)
OpImageRead(Id result_type, Id sampled_image, Id coordinate, Id OpImageRead(Id result_type, Id sampled_image, Id coordinate,
spv::ImageOperandsMask image_operands, Ts&&... operands) { spv::ImageOperandsMask image_operands, Ts&&... operands) {
return OpImageRead(result_type, sampled_image, coordinate, image_operands, return OpImageRead(result_type, sampled_image, coordinate, image_operands,
std::span<const Id>({operands...})); std::span<const Id>({operands...}));
} }
@ -1118,9 +1123,9 @@ public:
/// Write a texel to an image without a sampler. /// Write a texel to an image without a sampler.
template <typename... Ts> template <typename... Ts>
requires(...&& std::is_convertible_v<Ts, Id>) Id requires(... && std::is_convertible_v<Ts, Id>)
OpImageWrite(Id image, Id coordinate, Id texel, spv::ImageOperandsMask image_operands, Id OpImageWrite(Id image, Id coordinate, Id texel, spv::ImageOperandsMask image_operands,
Ts&&... operands) { Ts&&... operands) {
return OpImageWrite(image, coordinate, texel, image_operands, return OpImageWrite(image, coordinate, texel, image_operands,
std::span<const Id>({operands...})); std::span<const Id>({operands...}));
} }
@ -1347,8 +1352,11 @@ public:
/// 3) store the New Value back through Pointer. /// 3) store the New Value back through Pointer.
Id OpAtomicXor(Id result_type, Id pointer, Id memory, Id semantics, Id value); Id OpAtomicXor(Id result_type, Id pointer, Id memory, Id semantics, Id value);
Id OpDebugPrintf(Id fmt, std::span<const Id> fmt_args);
private: private:
Id GetGLSLstd450(); Id GetGLSLstd450();
Id GetNonSemanticDebugPrintf();
std::uint32_t version{}; std::uint32_t version{};
std::uint32_t bound{}; std::uint32_t bound{};
@ -1356,6 +1364,7 @@ private:
std::unordered_set<std::string> extensions; std::unordered_set<std::string> extensions;
std::unordered_set<spv::Capability> capabilities; std::unordered_set<spv::Capability> capabilities;
std::optional<Id> glsl_std_450; std::optional<Id> glsl_std_450;
std::optional<Id> non_semantic_debug_printf;
spv::AddressingModel addressing_model{spv::AddressingModel::Logical}; spv::AddressingModel addressing_model{spv::AddressingModel::Logical};
spv::MemoryModel memory_model{spv::MemoryModel::GLSL450}; spv::MemoryModel memory_model{spv::MemoryModel::GLSL450};

View File

@ -5,6 +5,7 @@
*/ */
#include <spirv/unified1/GLSL.std.450.h> #include <spirv/unified1/GLSL.std.450.h>
#include <spirv/unified1/NonSemanticDebugPrintf.h>
#include "sirit/sirit.h" #include "sirit/sirit.h"
@ -80,4 +81,12 @@ DEFINE_BINARY(OpCross, GLSLstd450Cross)
DEFINE_UNARY(OpLength, GLSLstd450Length) DEFINE_UNARY(OpLength, GLSLstd450Length)
DEFINE_TRINARY(OpFMix, GLSLstd450FMix) DEFINE_TRINARY(OpFMix, GLSLstd450FMix)
Id Module::OpDebugPrintf(Id fmt, std::span<const Id> fmt_args) {
std::vector<Id> operands;
operands.push_back(fmt);
std::copy(fmt_args.begin(), fmt_args.end(), operands.end());
return OpExtInst(TypeVoid(), GetNonSemanticDebugPrintf(), NonSemanticDebugPrintfDebugPrintf,
operands);
}
} // namespace Sirit } // namespace Sirit

View File

@ -21,8 +21,8 @@ Module::Module(u32 version_)
: version{version_}, ext_inst_imports{std::make_unique<Stream>(&bound)}, : version{version_}, ext_inst_imports{std::make_unique<Stream>(&bound)},
entry_points{std::make_unique<Stream>(&bound)}, entry_points{std::make_unique<Stream>(&bound)},
execution_modes{std::make_unique<Stream>(&bound)}, debug{std::make_unique<Stream>(&bound)}, execution_modes{std::make_unique<Stream>(&bound)}, debug{std::make_unique<Stream>(&bound)},
annotations{std::make_unique<Stream>(&bound)}, declarations{std::make_unique<Declarations>( annotations{std::make_unique<Stream>(&bound)},
&bound)}, declarations{std::make_unique<Declarations>(&bound)},
global_variables{std::make_unique<Stream>(&bound)}, code{std::make_unique<Stream>(&bound)} {} global_variables{std::make_unique<Stream>(&bound)}, code{std::make_unique<Stream>(&bound)} {}
Module::~Module() = default; Module::~Module() = default;
@ -139,4 +139,13 @@ Id Module::GetGLSLstd450() {
return *glsl_std_450; return *glsl_std_450;
} }
Id Module::GetNonSemanticDebugPrintf() {
if (!non_semantic_debug_printf) {
ext_inst_imports->Reserve(3 + 4);
non_semantic_debug_printf = *ext_inst_imports << OpId{spv::Op::OpExtInstImport}
<< "NonSemantic.DebugPrintf" << EndOp{};
}
return *non_semantic_debug_printf;
}
} // namespace Sirit } // namespace Sirit