From b51af1a2ca01090cbcbd4855dc29adf40d3bd612 Mon Sep 17 00:00:00 2001 From: Frodo Baggins Date: Wed, 18 Sep 2024 23:04:20 -0700 Subject: [PATCH] Add NonSemantic DebugPrintf --- include/sirit/sirit.h | 173 +++++++++++++++++---------------- src/instructions/extension.cpp | 9 ++ src/sirit.cpp | 13 ++- 3 files changed, 111 insertions(+), 84 deletions(-) diff --git a/include/sirit/sirit.h b/include/sirit/sirit.h index c7f3e2b..e656603 100644 --- a/include/sirit/sirit.h +++ b/include/sirit/sirit.h @@ -73,9 +73,9 @@ public: // TODO: Change std::is_convertible_v to std::convertible_to when compilers // support it; same elsewhere. template - requires(...&& std::is_convertible_v) void AddEntryPoint( - spv::ExecutionModel execution_model, Id entry_point, std::string_view name, - Ts&&... interfaces) { + requires(... && std::is_convertible_v) + void AddEntryPoint(spv::ExecutionModel execution_model, Id entry_point, std::string_view name, + Ts&&... interfaces) { AddEntryPoint(execution_model, std::move(entry_point), name, std::span({interfaces...})); } @@ -86,8 +86,8 @@ public: /// Declare an execution mode for an entry point. template - requires(...&& std::is_convertible_v) void AddExecutionMode( - Id entry_point, spv::ExecutionMode mode, Ts&&... literals) { + requires(... && std::is_convertible_v) + void AddExecutionMode(Id entry_point, spv::ExecutionMode mode, Ts&&... literals) { AddExecutionMode(entry_point, mode, std::span({literals...})); } @@ -162,7 +162,8 @@ public: /// Returns type struct. template - requires(...&& std::is_convertible_v) Id TypeStruct(Ts&&... members) { + requires(... && std::is_convertible_v) + Id TypeStruct(Ts&&... members) { return TypeStruct(std::span({members...})); } @@ -177,8 +178,8 @@ public: /// Returns type function. template - requires(...&& std::is_convertible_v) Id - TypeFunction(Id return_type, Ts&&... arguments) { + requires(... && std::is_convertible_v) + Id TypeFunction(Id return_type, Ts&&... arguments) { return TypeFunction(return_type, std::span({arguments...})); } @@ -213,8 +214,8 @@ public: /// Returns a numeric scalar constant. template - requires(...&& std::is_convertible_v) Id - ConstantComposite(Id result_type, Ts&&... constituents) { + requires(... && std::is_convertible_v) + Id ConstantComposite(Id result_type, Ts&&... constituents) { return ConstantComposite(result_type, std::span({constituents...})); } @@ -238,8 +239,8 @@ public: /// Call a function. template - requires(...&& std::is_convertible_v) Id - OpFunctionCall(Id result_type, Id function, Ts&&... arguments) { + requires(... && std::is_convertible_v) + Id OpFunctionCall(Id result_type, Id function, Ts&&... arguments) { return OpFunctionCall(result_type, function, std::span({arguments...})); } @@ -257,11 +258,11 @@ public: Id OpPhi(Id result_type, std::span operands); template - requires(...&& std::is_convertible_v) Id - OpPhi(Id result_type, Ts&&... operands) { + requires(... && std::is_convertible_v) + Id OpPhi(Id result_type, Ts&&... operands) { return OpPhi(result_type, std::span({operands...})); } - + /** * The SSA phi function. This instruction will be revisited when patching phi nodes. * @@ -276,9 +277,9 @@ public: /// Declare a structured loop. template - requires(...&& std::is_convertible_v) Id - OpLoopMerge(Id merge_block, Id continue_target, spv::LoopControlMask loop_control, - Ts&&... literals) { + requires(... && std::is_convertible_v) + Id OpLoopMerge(Id merge_block, Id continue_target, spv::LoopControlMask loop_control, + Ts&&... literals) { return OpLoopMerge(merge_block, continue_target, loop_control, std::span({literals...})); } @@ -356,8 +357,8 @@ public: /// Create a pointer into a composite object that can be used with OpLoad and OpStore. template - requires(...&& std::is_convertible_v) Id - OpAccessChain(Id result_type, Id base, Ts&&... indexes) { + requires(... && std::is_convertible_v) + Id OpAccessChain(Id result_type, Id base, Ts&&... indexes) { return OpAccessChain(result_type, base, std::span({indexes...})); } @@ -368,14 +369,16 @@ public: Id OpVectorInsertDynamic(Id result_type, Id vector, Id component, Id index); /// Select arbitrary components from two vectors to make a new vector. - Id OpVectorShuffle(Id result_type, Id vector_1, Id vector_2, std::span components); + Id OpVectorShuffle(Id result_type, Id vector_1, Id vector_2, + std::span components); /// Select arbitrary components from two vectors to make a new vector. template - requires(...&& std::is_convertible_v) Id - OpVectorShuffle(Id result_type, Id vector_1, Id vector_2, Ts&&... components) { + requires(... && std::is_convertible_v) + Id OpVectorShuffle(Id result_type, Id vector_1, Id vector_2, Ts&&... components) { const Literal stack_literals[] = {std::forward(components)...}; - return OpVectorShuffle(result_type, vector_1, vector_2, std::span{stack_literals}); + return OpVectorShuffle(result_type, vector_1, vector_2, + std::span{stack_literals}); } /// 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. template - requires(...&& std::is_convertible_v) Id - OpCompositeInsert(Id result_type, Id object, Id composite, Ts&&... indexes) { + requires(... && std::is_convertible_v) + Id OpCompositeInsert(Id result_type, Id object, Id composite, Ts&&... indexes) { const Literal stack_indexes[] = {std::forward(indexes)...}; return OpCompositeInsert(result_type, object, composite, std::span{stack_indexes}); @@ -396,8 +399,8 @@ public: /// Extract a part of a composite object. template - requires(...&& std::is_convertible_v) Id - OpCompositeExtract(Id result_type, Id composite, Ts&&... indexes) { + requires(... && std::is_convertible_v) + Id OpCompositeExtract(Id result_type, Id composite, Ts&&... indexes) { const Literal stack_indexes[] = {std::forward(indexes)...}; return OpCompositeExtract(result_type, composite, std::span{stack_indexes}); } @@ -407,8 +410,8 @@ public: /// Construct a new composite object from a set of constituent objects that will fully form it. template - requires(...&& std::is_convertible_v) Id - OpCompositeConstruct(Id result_type, Ts&&... ids) { + requires(... && std::is_convertible_v) + Id OpCompositeConstruct(Id result_type, Ts&&... ids) { return OpCompositeConstruct(result_type, std::span({ids...})); } @@ -419,15 +422,16 @@ public: /// Add a decoration to target. template - requires(...&& std::is_convertible_v) Id - Decorate(Id target, spv::Decoration decoration, Ts&&... literals) { + requires(... && std::is_convertible_v) + Id Decorate(Id target, spv::Decoration decoration, Ts&&... literals) { const Literal stack_literals[] = {std::forward(literals)...}; return Decorate(target, decoration, std::span{stack_literals}); } /// Add a decoration to target. template - requires std::is_enum_v Id Decorate(Id target, spv::Decoration decoration, T literal) { + requires std::is_enum_v + Id Decorate(Id target, spv::Decoration decoration, T literal) { return Decorate(target, decoration, static_cast(literal)); } @@ -435,9 +439,9 @@ public: std::span literals = {}); template - requires(...&& std::is_convertible_v) Id - MemberDecorate(Id structure_type, Literal member, spv::Decoration decoration, - Ts&&... literals) { + requires(... && std::is_convertible_v) + Id MemberDecorate(Id structure_type, Literal member, spv::Decoration decoration, + Ts&&... literals) { const Literal stack_literals[] = {std::forward(literals)...}; return MemberDecorate(structure_type, member, decoration, std::span{stack_literals}); @@ -718,8 +722,8 @@ public: /// Execute an instruction in an imported set of extended instructions. template - requires(...&& std::is_convertible_v) Id - OpExtInst(Id result_type, Id set, std::uint32_t instruction, Ts&&... operands) { + requires(... && std::is_convertible_v) + Id OpExtInst(Id result_type, Id set, std::uint32_t instruction, Ts&&... operands) { return OpExtInst(result_type, set, instruction, std::span({operands...})); } @@ -793,7 +797,8 @@ public: /// Result is the reciprocal of sqrt x. Result is undefined if x <= 0. 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); /// 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. 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 - /// operand is the result. If both operands are NaN, the result is a NaN. + /// 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 operand is the result. If both operands are NaN, the result is a NaN. 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 @@ -824,8 +829,8 @@ public: /// integers. 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 - /// operand is the result. If both operands are NaN, the result is a NaN. + /// 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 operand is the result. If both operands are NaN, the result is a NaN. Id OpNMax(Id result_type, Id x, Id y); /// 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. template - requires(...&& std::is_convertible_v) Id - OpImageSampleImplicitLod(Id result_type, Id sampled_image, Id coordinate, - spv::ImageOperandsMask image_operands, Ts&&... operands) { + requires(... && std::is_convertible_v) + Id OpImageSampleImplicitLod(Id result_type, Id sampled_image, Id coordinate, + spv::ImageOperandsMask image_operands, Ts&&... operands) { return OpImageSampleImplicitLod(result_type, sampled_image, coordinate, image_operands, std::span({operands...})); } @@ -957,9 +962,9 @@ public: /// Sample an image using an explicit level of detail. template - requires(...&& std::is_convertible_v) Id - OpImageSampleExplicitLod(Id result_type, Id sampled_image, Id coordinate, - spv::ImageOperandsMask image_operands, Ts&&... operands) { + requires(... && std::is_convertible_v) + Id OpImageSampleExplicitLod(Id result_type, Id sampled_image, Id coordinate, + spv::ImageOperandsMask image_operands, Ts&&... operands) { return OpImageSampleExplicitLod(result_type, sampled_image, coordinate, image_operands, std::span({operands...})); } @@ -972,9 +977,9 @@ public: /// Sample an image doing depth-comparison with an implicit level of detail. template - requires(...&& std::is_convertible_v) Id - OpImageSampleDrefImplicitLod(Id result_type, Id sampled_image, Id coordinate, Id dref, - spv::ImageOperandsMask image_operands, Ts&&... operands) { + requires(... && std::is_convertible_v) + Id OpImageSampleDrefImplicitLod(Id result_type, Id sampled_image, Id coordinate, Id dref, + spv::ImageOperandsMask image_operands, Ts&&... operands) { return OpImageSampleDrefImplicitLod(result_type, sampled_image, coordinate, dref, image_operands, std::span({operands...})); } @@ -986,9 +991,9 @@ public: /// Sample an image doing depth-comparison using an explicit level of detail. template - requires(...&& std::is_convertible_v) Id - OpImageSampleDrefExplicitLod(Id result_type, Id sampled_image, Id coordinate, Id dref, - spv::ImageOperandsMask image_operands, Ts&&... operands) { + requires(... && std::is_convertible_v) + Id OpImageSampleDrefExplicitLod(Id result_type, Id sampled_image, Id coordinate, Id dref, + spv::ImageOperandsMask image_operands, Ts&&... operands) { return OpImageSampleDrefExplicitLod(result_type, sampled_image, coordinate, dref, image_operands, std::span({operands...})); } @@ -1001,9 +1006,9 @@ public: /// Sample an image with with a project coordinate and an implicit level of detail. template - requires(...&& std::is_convertible_v) Id - OpImageSampleProjImplicitLod(Id result_type, Id sampled_image, Id coordinate, - spv::ImageOperandsMask image_operands, Ts&&... operands) { + requires(... && std::is_convertible_v) + Id OpImageSampleProjImplicitLod(Id result_type, Id sampled_image, Id coordinate, + spv::ImageOperandsMask image_operands, Ts&&... operands) { return OpImageSampleProjImplicitLod(result_type, sampled_image, coordinate, image_operands, std::span({operands...})); } @@ -1015,9 +1020,9 @@ public: /// Sample an image with a project coordinate using an explicit level of detail. template - requires(...&& std::is_convertible_v) Id - OpImageSampleProjExplicitLod(Id result_type, Id sampled_image, Id coordinate, - spv::ImageOperandsMask image_operands, Ts&&... operands) { + requires(... && std::is_convertible_v) + Id OpImageSampleProjExplicitLod(Id result_type, Id sampled_image, Id coordinate, + spv::ImageOperandsMask image_operands, Ts&&... operands) { return OpImageSampleProjExplicitLod(result_type, sampled_image, coordinate, image_operands, std::span({operands...})); } @@ -1032,9 +1037,9 @@ public: /// Sample an image with a project coordinate, doing depth-comparison, with an implicit level of /// detail. template - requires(...&& std::is_convertible_v) Id - OpImageSampleProjDrefImplicitLod(Id result_type, Id sampled_image, Id coordinate, Id dref, - spv::ImageOperandsMask image_operands, Ts&&... operands) { + requires(... && std::is_convertible_v) + Id OpImageSampleProjDrefImplicitLod(Id result_type, Id sampled_image, Id coordinate, Id dref, + spv::ImageOperandsMask image_operands, Ts&&... operands) { return OpImageSampleProjDrefImplicitLod(result_type, sampled_image, coordinate, dref, image_operands, std::span({operands...})); } @@ -1048,9 +1053,9 @@ public: /// Sample an image with a project coordinate, doing depth-comparison, using an explicit level /// of detail. template - requires(...&& std::is_convertible_v) Id - OpImageSampleProjDrefExplicitLod(Id result_type, Id sampled_image, Id coordinate, Id dref, - spv::ImageOperandsMask image_operands, Ts&&... operands) { + requires(... && std::is_convertible_v) + Id OpImageSampleProjDrefExplicitLod(Id result_type, Id sampled_image, Id coordinate, Id dref, + spv::ImageOperandsMask image_operands, Ts&&... operands) { return OpImageSampleProjDrefExplicitLod(result_type, sampled_image, coordinate, dref, image_operands, std::span({operands...})); } @@ -1062,9 +1067,9 @@ public: /// Fetch a single texel from an image whose Sampled operand is 1. template - requires(...&& std::is_convertible_v) Id - OpImageFetch(Id result_type, Id sampled_image, Id coordinate, - spv::ImageOperandsMask image_operands, Ts&&... operands) { + requires(... && std::is_convertible_v) + Id OpImageFetch(Id result_type, Id sampled_image, Id coordinate, + spv::ImageOperandsMask image_operands, Ts&&... operands) { return OpImageFetch(result_type, sampled_image, coordinate, image_operands, std::span({operands...})); } @@ -1076,9 +1081,9 @@ public: /// Gathers the requested component from four texels. template - requires(...&& std::is_convertible_v) Id - OpImageGather(Id result_type, Id sampled_image, Id coordinate, Id component, - spv::ImageOperandsMask image_operands, Ts&&... operands) { + requires(... && std::is_convertible_v) + Id OpImageGather(Id result_type, Id sampled_image, Id coordinate, Id component, + spv::ImageOperandsMask image_operands, Ts&&... operands) { return OpImageGather(result_type, sampled_image, coordinate, component, image_operands, std::span({operands...})); } @@ -1090,9 +1095,9 @@ public: /// Gathers the requested depth-comparison from four texels. template - requires(...&& std::is_convertible_v) Id - OpImageDrefGather(Id result_type, Id sampled_image, Id coordinate, Id dref, - spv::ImageOperandsMask image_operands, Ts&&... operands) { + requires(... && std::is_convertible_v) + Id OpImageDrefGather(Id result_type, Id sampled_image, Id coordinate, Id dref, + spv::ImageOperandsMask image_operands, Ts&&... operands) { return OpImageDrefGather(result_type, sampled_image, coordinate, dref, image_operands, std::span({operands...})); } @@ -1104,9 +1109,9 @@ public: /// Read a texel from an image without a sampler. template - requires(...&& std::is_convertible_v) Id - OpImageRead(Id result_type, Id sampled_image, Id coordinate, - spv::ImageOperandsMask image_operands, Ts&&... operands) { + requires(... && std::is_convertible_v) + Id OpImageRead(Id result_type, Id sampled_image, Id coordinate, + spv::ImageOperandsMask image_operands, Ts&&... operands) { return OpImageRead(result_type, sampled_image, coordinate, image_operands, std::span({operands...})); } @@ -1118,9 +1123,9 @@ public: /// Write a texel to an image without a sampler. template - requires(...&& std::is_convertible_v) Id - OpImageWrite(Id image, Id coordinate, Id texel, spv::ImageOperandsMask image_operands, - Ts&&... operands) { + requires(... && std::is_convertible_v) + Id OpImageWrite(Id image, Id coordinate, Id texel, spv::ImageOperandsMask image_operands, + Ts&&... operands) { return OpImageWrite(image, coordinate, texel, image_operands, std::span({operands...})); } @@ -1347,8 +1352,11 @@ public: /// 3) store the New Value back through Pointer. Id OpAtomicXor(Id result_type, Id pointer, Id memory, Id semantics, Id value); + Id OpDebugPrintf(Id fmt, std::span fmt_args); + private: Id GetGLSLstd450(); + Id GetNonSemanticDebugPrintf(); std::uint32_t version{}; std::uint32_t bound{}; @@ -1356,6 +1364,7 @@ private: std::unordered_set extensions; std::unordered_set capabilities; std::optional glsl_std_450; + std::optional non_semantic_debug_printf; spv::AddressingModel addressing_model{spv::AddressingModel::Logical}; spv::MemoryModel memory_model{spv::MemoryModel::GLSL450}; diff --git a/src/instructions/extension.cpp b/src/instructions/extension.cpp index 44dc691..4eff1a7 100644 --- a/src/instructions/extension.cpp +++ b/src/instructions/extension.cpp @@ -5,6 +5,7 @@ */ #include +#include #include "sirit/sirit.h" @@ -80,4 +81,12 @@ DEFINE_BINARY(OpCross, GLSLstd450Cross) DEFINE_UNARY(OpLength, GLSLstd450Length) DEFINE_TRINARY(OpFMix, GLSLstd450FMix) +Id Module::OpDebugPrintf(Id fmt, std::span fmt_args) { + std::vector operands; + operands.push_back(fmt); + std::copy(fmt_args.begin(), fmt_args.end(), operands.end()); + return OpExtInst(TypeVoid(), GetNonSemanticDebugPrintf(), NonSemanticDebugPrintfDebugPrintf, + operands); +} + } // namespace Sirit diff --git a/src/sirit.cpp b/src/sirit.cpp index 7075f23..b30379a 100644 --- a/src/sirit.cpp +++ b/src/sirit.cpp @@ -21,8 +21,8 @@ Module::Module(u32 version_) : version{version_}, ext_inst_imports{std::make_unique(&bound)}, entry_points{std::make_unique(&bound)}, execution_modes{std::make_unique(&bound)}, debug{std::make_unique(&bound)}, - annotations{std::make_unique(&bound)}, declarations{std::make_unique( - &bound)}, + annotations{std::make_unique(&bound)}, + declarations{std::make_unique(&bound)}, global_variables{std::make_unique(&bound)}, code{std::make_unique(&bound)} {} Module::~Module() = default; @@ -139,4 +139,13 @@ Id Module::GetGLSLstd450() { 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