HLSL: Add support for printf().

Translate printf() to what GL_EXT_debug_printf has done. HLSL could
define non-constant string variable and we don't have such features
in SPIR-V, so just support constant string variable.
This commit is contained in:
Rex Xu 2020-10-23 22:54:35 +08:00
parent 3b334b2b8e
commit f6e0fe8600
9 changed files with 216 additions and 5 deletions

View File

@ -1720,6 +1720,12 @@ void TGlslangToSpvTraverser::visitSymbol(glslang::TIntermSymbol* symbol)
if (symbol->getType().getQualifier().isSpecConstant())
spec_constant_op_mode_setter.turnOnSpecConstantOpMode();
#ifdef ENABLE_HLSL
// Skip symbol handling if it is string-typed
if (symbol->getBasicType() == glslang::EbtString)
return;
#endif
// getSymbolId() will set up all the IO decorations on the first call.
// Formal function parameters were mapped during makeFunctions().
spv::Id id = getSymbolId(symbol);

View File

@ -0,0 +1,178 @@
hlsl.printf.comp
Shader version: 500
local_size = (1, 1, 1)
0:? Sequence
0:4 Function Definition: @main( ( temp void)
0:4 Function Parameters:
0:? Sequence
0:5 Debug printf ( temp void)
0:5 Constant:
0:5 "first string"
0:6 Debug printf ( temp void)
0:6 Constant:
0:6 "please print this message."
0:7 Debug printf ( temp void)
0:7 Constant:
0:7 "Variables are: %d %d %.2f"
0:7 Constant:
0:7 1 (const uint)
0:7 Constant:
0:7 2 (const uint)
0:7 Constant:
0:7 1.500000
0:8 Debug printf ( temp void)
0:8 Constant:
0:8 "Integers are: %d %d %d"
0:8 Constant:
0:8 1 (const int)
0:8 Constant:
0:8 2 (const int)
0:8 Constant:
0:8 3 (const int)
0:9 Debug printf ( temp void)
0:9 Constant:
0:9 "More: %d %d %d %d %d %d %d %d %d %d"
0:9 Constant:
0:9 1 (const int)
0:9 Constant:
0:9 2 (const int)
0:9 Constant:
0:9 3 (const int)
0:9 Constant:
0:9 4 (const int)
0:9 Constant:
0:9 5 (const int)
0:9 Constant:
0:9 6 (const int)
0:9 Constant:
0:9 7 (const int)
0:9 Constant:
0:9 8 (const int)
0:9 Constant:
0:9 9 (const int)
0:9 Constant:
0:9 10 (const int)
0:4 Function Definition: main( ( temp void)
0:4 Function Parameters:
0:? Sequence
0:4 Function Call: @main( ( temp void)
0:? Linker Objects
0:? 'first' ( const string)
0:? "first string"
Linked compute stage:
Shader version: 500
local_size = (1, 1, 1)
0:? Sequence
0:4 Function Definition: @main( ( temp void)
0:4 Function Parameters:
0:? Sequence
0:5 Debug printf ( temp void)
0:5 Constant:
0:5 "first string"
0:6 Debug printf ( temp void)
0:6 Constant:
0:6 "please print this message."
0:7 Debug printf ( temp void)
0:7 Constant:
0:7 "Variables are: %d %d %.2f"
0:7 Constant:
0:7 1 (const uint)
0:7 Constant:
0:7 2 (const uint)
0:7 Constant:
0:7 1.500000
0:8 Debug printf ( temp void)
0:8 Constant:
0:8 "Integers are: %d %d %d"
0:8 Constant:
0:8 1 (const int)
0:8 Constant:
0:8 2 (const int)
0:8 Constant:
0:8 3 (const int)
0:9 Debug printf ( temp void)
0:9 Constant:
0:9 "More: %d %d %d %d %d %d %d %d %d %d"
0:9 Constant:
0:9 1 (const int)
0:9 Constant:
0:9 2 (const int)
0:9 Constant:
0:9 3 (const int)
0:9 Constant:
0:9 4 (const int)
0:9 Constant:
0:9 5 (const int)
0:9 Constant:
0:9 6 (const int)
0:9 Constant:
0:9 7 (const int)
0:9 Constant:
0:9 8 (const int)
0:9 Constant:
0:9 9 (const int)
0:9 Constant:
0:9 10 (const int)
0:4 Function Definition: main( ( temp void)
0:4 Function Parameters:
0:? Sequence
0:4 Function Call: @main( ( temp void)
0:? Linker Objects
0:? 'first' ( const string)
0:? "first string"
// Module Version 10000
// Generated by (magic number): 8000a
// Id's are bound by 36
Capability Shader
Extension "SPV_KHR_non_semantic_info"
1: ExtInstImport "GLSL.std.450"
9: ExtInstImport "NonSemantic.DebugPrintf"
MemoryModel Logical GLSL450
EntryPoint GLCompute 4 "main"
ExecutionMode 4 LocalSize 1 1 1
8: String "first string"
11: String "please print this message."
13: String "Variables are: %d %d %.2f"
20: String "Integers are: %d %d %d"
26: String "More: %d %d %d %d %d %d %d %d %d %d"
Source HLSL 500
Name 4 "main"
Name 6 "@main("
2: TypeVoid
3: TypeFunction 2
14: TypeInt 32 0
15: 14(int) Constant 1
16: 14(int) Constant 2
17: TypeFloat 32
18: 17(float) Constant 1069547520
21: TypeInt 32 1
22: 21(int) Constant 1
23: 21(int) Constant 2
24: 21(int) Constant 3
27: 21(int) Constant 4
28: 21(int) Constant 5
29: 21(int) Constant 6
30: 21(int) Constant 7
31: 21(int) Constant 8
32: 21(int) Constant 9
33: 21(int) Constant 10
4(main): 2 Function None 3
5: Label
35: 2 FunctionCall 6(@main()
Return
FunctionEnd
6(@main(): 2 Function None 3
7: Label
10: 2 ExtInst 9(NonSemantic.DebugPrintf) 1(DebugPrintf) 8
12: 2 ExtInst 9(NonSemantic.DebugPrintf) 1(DebugPrintf) 11
19: 2 ExtInst 9(NonSemantic.DebugPrintf) 1(DebugPrintf) 13 15 16 18
25: 2 ExtInst 9(NonSemantic.DebugPrintf) 1(DebugPrintf) 20 22 23 24
34: 2 ExtInst 9(NonSemantic.DebugPrintf) 1(DebugPrintf) 26 22 23 24 27 28 29 30 31 32 33
Return
FunctionEnd

11
Test/hlsl.printf.comp Normal file
View File

@ -0,0 +1,11 @@
const string first = "first string";
[numthreads(1,1,1)]
void main() {
printf(first);
printf("please print this message.");
printf("Variables are: %d %d %.2f", 1u, 2u, 1.5f);
printf("Integers are: %d %d %d", 1, 2, 3);
printf("More: %d %d %d %d %d %d %d %d %d %d", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
}

View File

@ -480,8 +480,9 @@ bool HlslGrammar::acceptDeclaration(TIntermNode*& nodeList)
}
// TODO: things scoped within an annotation need their own name space;
// TODO: strings are not yet handled.
if (variableType.getBasicType() != EbtString && parseContext.getAnnotationNestingLevel() == 0) {
// TODO: non-constant strings are not yet handled.
if (!(variableType.getBasicType() == EbtString && !variableType.getQualifier().isConstant()) &&
parseContext.getAnnotationNestingLevel() == 0) {
if (typedefDecl)
parseContext.declareTypedef(idToken.loc, *fullName, variableType);
else if (variableType.getBasicType() == EbtBlock) {

View File

@ -7628,7 +7628,17 @@ const TFunction* HlslParseContext::findFunction(const TSourceLoc& loc, TFunction
bool tie = false;
// send to the generic selector
const TFunction* bestMatch = selectFunction(candidateList, call, convertible, better, tie);
const TFunction* bestMatch = nullptr;
// printf has var args and is in the symbol table as "printf()",
// mangled to "printf("
if (call.getName() == "printf") {
TSymbol* symbol = symbolTable.find("printf(", &builtIn);
if (symbol)
return symbol->getAsFunction();
}
bestMatch = selectFunction(candidateList, call, convertible, better, tie);
if (bestMatch == nullptr) {
// If there is nothing selected by allowing only up-conversions (to a larger linearize() value),

View File

@ -605,7 +605,7 @@ void TBuiltInParseablesHlsl::initialize(int /*version*/, EProfile /*profile*/, c
{ "noise", "S", "F", "V", "F", EShLangPS, false },
{ "normalize", nullptr, nullptr, "V", "F", EShLangAll, false },
{ "pow", nullptr, nullptr, "SVM,", "F,", EShLangAll, false },
// { "printf", "-", "-", "", "", EShLangAll, false }, TODO: varargs
{ "printf", nullptr, nullptr, "-", "-", EShLangAll, false },
{ "Process2DQuadTessFactorsAvg", "-", "-", "V4,V2,>V4,>V2,", "F,,,,", EShLangHS, false },
{ "Process2DQuadTessFactorsMax", "-", "-", "V4,V2,>V4,>V2,", "F,,,,", EShLangHS, false },
{ "Process2DQuadTessFactorsMin", "-", "-", "V4,V2,>V4,>V2,", "F,,,,", EShLangHS, false },
@ -1107,7 +1107,7 @@ void TBuiltInParseablesHlsl::identifyBuiltIns(int /*version*/, EProfile /*profil
// symbolTable.relateToOperator("noise", EOpNoise); // TODO: check return type
symbolTable.relateToOperator("normalize", EOpNormalize);
symbolTable.relateToOperator("pow", EOpPow);
// symbolTable.relateToOperator("printf", EOpPrintf);
symbolTable.relateToOperator("printf", EOpDebugPrintf);
// symbolTable.relateToOperator("Process2DQuadTessFactorsAvg");
// symbolTable.relateToOperator("Process2DQuadTessFactorsMax");
// symbolTable.relateToOperator("Process2DQuadTessFactorsMin");

View File

@ -1986,6 +1986,7 @@ public:
case EbtAccStruct: return "accelerationStructureNV";
case EbtRayQuery: return "rayQueryEXT";
case EbtReference: return "reference";
case EbtString: return "string";
#endif
default: return "unknown type";
}

View File

@ -1321,6 +1321,9 @@ static void OutputConstantUnion(TInfoSink& out, const TIntermTyped* node, const
out.debug << buf << "\n";
}
break;
case EbtString:
out.debug << "\"" << constUnion[i].getSConst()->c_str() << "\"\n";
break;
default:
out.info.message(EPrefixInternalError, "Unknown constant", node->getLoc());
break;

View File

@ -308,6 +308,7 @@ INSTANTIATE_TEST_SUITE_P(
{"hlsl.pp.vert", "main"},
{"hlsl.pp.line.frag", "main"},
{"hlsl.precise.frag", "main"},
{"hlsl.printf.comp", "main"},
{"hlsl.promote.atomic.frag", "main"},
{"hlsl.promote.binary.frag", "main"},
{"hlsl.promote.vec1.frag", "main"},