Skip to content

Commit

Permalink
Cleanup definition of printf. (#5330)
Browse files Browse the repository at this point in the history
* Cleanup definition of `printf`.

* Fix.

* Fix spirv generation.

* Fix.

* enhance test.
  • Loading branch information
csyonghe authored Oct 18, 2024
1 parent a618b8c commit 12e891e
Show file tree
Hide file tree
Showing 8 changed files with 115 additions and 48 deletions.
63 changes: 17 additions & 46 deletions source/slang/hlsl.meta.slang
Original file line number Diff line number Diff line change
Expand Up @@ -10788,53 +10788,24 @@ vector<T, N> powr(vector<T, N> x, vector<T, N> y)
// Output message
// TODO: add check to ensure format is const literal.

${{{{
for (int argCount = 0; argCount < 12; argCount++)
{
StringBuilder paramList;
StringBuilder argList;
StringBuilder spirvArgList;
StringBuilder genericParamList;
if (argCount > 0)
genericParamList << "<";
for (int i = 0; i < argCount; i++)
{
if (i > 0)
genericParamList << ", ";
genericParamList << "T" << i;

paramList << ", T" << i << " v" << i;
argList << ", $" << i+1;
spirvArgList << " $v" << i;
}
if (argCount > 0)
genericParamList << ">";
auto params = paramList.toString();
auto args = argList.toString();
auto spirvArgs = spirvArgList.toString();
}}}}
__glsl_extension(GL_EXT_debug_printf)
/// Print a message to the debug output.
/// @param T The variadic type pack parameter for the arguments to be printed.
/// @param format The format string.
/// @param args (optional) The arguments to be printed.
/// @remarks The function maps to `printf` for HLSL, CPU and CUDA targets, and maps to `OpDebugPrintf` for SPIR-V target,
/// and maps to `debugPrintfEXT` for GLSL target. Depending on the target and execution environment, the function may have
/// no effect.
/// @example
/// ```cpp
/// void test(int x, float y)
/// {
/// printf("hello world!\n");
/// printf(R"(x = "%d", y = "%f")", x, y);
/// }
/// ```
[require(cpp_cuda_glsl_hlsl_spirv, printf)]
void printf$(genericParamList.toString())(NativeString format $(paramList))
{
__target_switch
{
case hlsl:
case cpp:
case cuda:
__intrinsic_asm "printf";
case glsl:
__intrinsic_asm "debugPrintfEXT($0 $(argList))";
case spirv:
spirv_asm {
OpExtension "SPV_KHR_non_semantic_info";
result:$$void = OpExtInst debugPrintf 1 $format $(spirvArgs);
};
}
}
${{{{
}
}}}}
__intrinsic_op($(kIROp_Printf))
void printf<each T>(NativeString format, expand each T args);

// Tessellation factor fixup routines
/// @category tessellation Tessellation functions
Expand Down
20 changes: 20 additions & 0 deletions source/slang/slang-emit-c-like.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2847,6 +2847,26 @@ void CLikeSourceEmitter::defaultEmitInstExpr(IRInst* inst, const EmitOpInfo& inO
}
break;
}
case kIROp_Printf:
{
m_writer->emit("printf(");
emitOperand(inst->getOperand(0), getInfo(EmitOp::General));
if (inst->getOperandCount() == 2)
{
auto operand = inst->getOperand(1);
if (auto makeStruct = as<IRMakeStruct>(operand))
{
// Flatten the tuple resulting from the variadic pack.
for (UInt bb = 0; bb < makeStruct->getOperandCount(); ++bb)
{
m_writer->emit(", ");
emitOperand(makeStruct->getOperand(bb), getInfo(EmitOp::General));
}
}
}
m_writer->emit(")");
break;
}
case kIROp_RequireGLSLExtension:
{
break; //should already have set requirement; case covered for empty intrinsic block
Expand Down
21 changes: 21 additions & 0 deletions source/slang/slang-emit-glsl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2146,6 +2146,27 @@ bool GLSLSourceEmitter::tryEmitInstExprImpl(IRInst* inst, const EmitOpInfo& inOu
m_writer->emit("endInvocationInterlockARB()");
return true;
}
case kIROp_Printf:
{
m_glslExtensionTracker->requireExtension(toSlice("GL_EXT_debug_printf"));
m_writer->emit("debugPrintfEXT(");
emitOperand(inst->getOperand(0), getInfo(EmitOp::General));
if (inst->getOperandCount() == 2)
{
auto operand = inst->getOperand(1);
if (auto makeStruct = as<IRMakeStruct>(operand))
{
// Flatten the tuple resulting from the variadic pack.
for (UInt bb = 0; bb < makeStruct->getOperandCount(); ++bb)
{
m_writer->emit(", ");
emitOperand(makeStruct->getOperand(bb), getInfo(EmitOp::General));
}
}
}
m_writer->emit(")");
return true;
}
default: break;
}

Expand Down
21 changes: 21 additions & 0 deletions source/slang/slang-emit-spirv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3426,6 +3426,27 @@ struct SPIRVEmitContext
emitInst(parent, inst, SpvOpControlBarrier, executionScope, memoryScope, memorySemantics);
}
break;
case kIROp_Printf:
{
List<IRInst*> operands;
operands.add(inst->getOperand(0));
if (inst->getOperandCount() == 2)
{
auto operand = inst->getOperand(1);
if (auto makeStruct = as<IRMakeStruct>(operand))
{
// Flatten the tuple resulting from the variadic pack.
for (UInt bb = 0; bb < makeStruct->getOperandCount(); ++bb)
{
operands.add(makeStruct->getOperand(bb));
}
}
}
ensureExtensionDeclaration(toSlice("SPV_KHR_non_semantic_info"));
result = emitInst(parent, inst, SpvOpExtInst, inst->getFullType(), kResultID,
getNonSemanticDebugPrintfExtInst(), SpvLiteralInteger::from32(1), operands.getArrayView());
}
break;
}
if (result)
emitDecorations(inst, getID(result));
Expand Down
1 change: 1 addition & 0 deletions source/slang/slang-ir-inst-defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -649,6 +649,7 @@ INST(RequirePrelude, RequirePrelude, 1, 0)
INST(RequireGLSLExtension, RequireGLSLExtension, 1, 0)
INST(RequireComputeDerivative, RequireComputeDerivative, 0, 0)
INST(StaticAssert, StaticAssert, 2, 0)
INST(Printf, Printf, 1, 0)

// TODO: We should consider splitting the basic arithmetic/comparison
// ops into cases for signed integers, unsigned integers, and floating-point
Expand Down
5 changes: 5 additions & 0 deletions source/slang/slang-ir-insts.h
Original file line number Diff line number Diff line change
Expand Up @@ -2930,6 +2930,11 @@ struct IRMakeValuePack : IRInst
IR_LEAF_ISA(MakeValuePack)
};

struct IRMakeStruct : IRInst
{
IR_LEAF_ISA(MakeStruct)
};

struct IRMakeWitnessPack : IRInst
{
IR_LEAF_ISA(MakeWitnessPack)
Expand Down
28 changes: 28 additions & 0 deletions source/slang/slang-ir-legalize-types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -817,6 +817,31 @@ static LegalVal legalizeLoad(
}
}

static LegalVal legalizePrintf(IRTypeLegalizationContext* context, ArrayView<LegalVal> args)
{
ShortList<IRInst*> legalArgs;
for (auto arg : args)
{
switch (arg.flavor)
{
case LegalVal::Flavor::none:
break;
case LegalVal::Flavor::simple:
legalArgs.add(arg.getSimple());
break;
case LegalVal::Flavor::pair:
legalArgs.add(arg.getPair()->ordinaryVal.getSimple());
break;
default:
SLANG_UNIMPLEMENTED_X("Unknown legalized val flavor for printf operand");
}
}
return LegalVal::simple(context->builder->emitIntrinsicInst(context->builder->getVoidType(),
kIROp_Printf,
(UInt)legalArgs.getCount(),
legalArgs.getArrayView().getBuffer()));
}

static LegalVal legalizeDebugVar(IRTypeLegalizationContext* context, LegalType type, IRDebugVar* originalInst)
{
// For now we just discard any special part and keep the ordinary part.
Expand Down Expand Up @@ -2167,6 +2192,9 @@ static LegalVal legalizeInst(
case kIROp_loop:
result = legalizeUnconditionalBranch(context, args, (IRUnconditionalBranch*)inst);
break;
case kIROp_Printf:
result = legalizePrintf(context, args);
break;
case kIROp_undefined:
return LegalVal();
case kIROp_GpuForeach:
Expand Down
4 changes: 2 additions & 2 deletions tests/spirv/debug-printf.slang
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
void main()
{
printf("test");
printf("test1 %d", 5);
printf(R"(test1 "%d %d")", 5, 6);
// CHECK: %[[SET:[0-9]+]] = OpExtInstImport "NonSemantic.DebugPrintf"
// CHECK: {{.*}} = OpExtInst %{{[a-zA-Z0-9_]+}} %[[SET]] 1 %{{[a-zA-Z0-9_]+}}
// CHECK: {{.*}} = OpExtInst %{{[a-zA-Z0-9_]+}} %[[SET]] 1 %{{[a-zA-Z0-9_]+}} %{{[a-zA-Z0-9_]+}}
// CHECK: {{.*}} = OpExtInst %{{[a-zA-Z0-9_]+}} %[[SET]] 1 %{{[a-zA-Z0-9_]+}} %int_5 %int_6
}

0 comments on commit 12e891e

Please sign in to comment.