HLSL: add .mips[][] operator for texture types

This implements mytex.mips[mip][coord] for texture types.  There is
some error testing, but not comprehensive.  The constructs can be
nested, e.g in this case the inner .mips is parsed before the completion
of the outer [][] operator.

   tx.mips[tx.mips[a][b].x][c]
This commit is contained in:
LoopDawg 2017-05-12 17:14:31 -06:00
parent c70bbc831c
commit 726bf96a72
10 changed files with 446 additions and 11 deletions

View File

@ -0,0 +1,68 @@
hlsl.mip.negative.frag
ERROR: 0:5: '' : unterminated mips operator:
ERROR: 1 compilation errors. No code generated.
Shader version: 500
gl_FragCoord origin is upper left
ERROR: node is still EOpNull!
0:4 Function Definition: @main( ( temp 4-component vector of float)
0:4 Function Parameters:
0:? Sequence
0:? textureFetch ( temp 4-component vector of float)
0:5 'g_tTex2df4' ( uniform texture2D)
0:? Constant:
0:? 3 (const uint)
0:? 4 (const uint)
0:5 Constant:
0:5 2 (const int)
0:7 Branch: Return with expression
0:7 Constant:
0:7 0.000000
0:7 0.000000
0:7 0.000000
0:7 0.000000
0:4 Function Definition: main( ( temp void)
0:4 Function Parameters:
0:? Sequence
0:4 move second child to first child ( temp 4-component vector of float)
0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float)
0:4 Function Call: @main( ( temp 4-component vector of float)
0:? Linker Objects
0:? 'g_tTex2df4' ( uniform texture2D)
0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float)
Linked fragment stage:
Shader version: 500
gl_FragCoord origin is upper left
ERROR: node is still EOpNull!
0:4 Function Definition: @main( ( temp 4-component vector of float)
0:4 Function Parameters:
0:? Sequence
0:? textureFetch ( temp 4-component vector of float)
0:5 'g_tTex2df4' ( uniform texture2D)
0:? Constant:
0:? 3 (const uint)
0:? 4 (const uint)
0:5 Constant:
0:5 2 (const int)
0:7 Branch: Return with expression
0:7 Constant:
0:7 0.000000
0:7 0.000000
0:7 0.000000
0:7 0.000000
0:4 Function Definition: main( ( temp void)
0:4 Function Parameters:
0:? Sequence
0:4 move second child to first child ( temp 4-component vector of float)
0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float)
0:4 Function Call: @main( ( temp 4-component vector of float)
0:? Linker Objects
0:? 'g_tTex2df4' ( uniform texture2D)
0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float)
SPIR-V is not generated for failed compile or link

View File

@ -0,0 +1,74 @@
hlsl.mip.negative2.frag
ERROR: 0:5: 'r' : unexpected operator on texture type: uniform texture2D
ERROR: 1 compilation errors. No code generated.
Shader version: 500
gl_FragCoord origin is upper left
ERROR: node is still EOpNull!
0:4 Function Definition: @main( ( temp 4-component vector of float)
0:4 Function Parameters:
0:? Sequence
0:5 direct index ( temp float)
0:5 textureFetch ( temp 4-component vector of float)
0:5 'g_tTex2df4' ( uniform texture2D)
0:5 Constant:
0:5 2 (const int)
0:5 Constant:
0:5 0 (const int)
0:? Constant:
0:? 3 (const uint)
0:? 4 (const uint)
0:7 Branch: Return with expression
0:7 Constant:
0:7 0.000000
0:7 0.000000
0:7 0.000000
0:7 0.000000
0:4 Function Definition: main( ( temp void)
0:4 Function Parameters:
0:? Sequence
0:4 move second child to first child ( temp 4-component vector of float)
0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float)
0:4 Function Call: @main( ( temp 4-component vector of float)
0:? Linker Objects
0:? 'g_tTex2df4' ( uniform texture2D)
0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float)
Linked fragment stage:
Shader version: 500
gl_FragCoord origin is upper left
ERROR: node is still EOpNull!
0:4 Function Definition: @main( ( temp 4-component vector of float)
0:4 Function Parameters:
0:? Sequence
0:5 direct index ( temp float)
0:5 textureFetch ( temp 4-component vector of float)
0:5 'g_tTex2df4' ( uniform texture2D)
0:5 Constant:
0:5 2 (const int)
0:5 Constant:
0:5 0 (const int)
0:? Constant:
0:? 3 (const uint)
0:? 4 (const uint)
0:7 Branch: Return with expression
0:7 Constant:
0:7 0.000000
0:7 0.000000
0:7 0.000000
0:7 0.000000
0:4 Function Definition: main( ( temp void)
0:4 Function Parameters:
0:? Sequence
0:4 move second child to first child ( temp 4-component vector of float)
0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float)
0:4 Function Call: @main( ( temp 4-component vector of float)
0:? Linker Objects
0:? 'g_tTex2df4' ( uniform texture2D)
0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float)
SPIR-V is not generated for failed compile or link

View File

@ -0,0 +1,209 @@
hlsl.mip.operator.frag
Shader version: 500
gl_FragCoord origin is upper left
0:? Sequence
0:5 Function Definition: @main( ( temp 4-component vector of float)
0:5 Function Parameters:
0:? Sequence
0:13 Branch: Return with expression
0:9 add ( temp 4-component vector of float)
0:6 add ( temp 4-component vector of float)
0:? textureFetch ( temp 4-component vector of float)
0:6 'g_tTex2df4' ( uniform texture2D)
0:? Constant:
0:? 3 (const uint)
0:? 4 (const uint)
0:6 Constant:
0:6 2 (const int)
0:? textureFetch ( temp 4-component vector of float)
0:9 'g_tTex2df4a' ( uniform texture2DArray)
0:? Constant:
0:? 6 (const uint)
0:? 7 (const uint)
0:? 8 (const uint)
0:9 Constant:
0:9 5 (const uint)
0:13 textureFetch ( temp 4-component vector of float)
0:13 'g_tTex2df4' ( uniform texture2D)
0:13 Convert float to uint ( temp 2-component vector of uint)
0:13 vector swizzle ( temp 2-component vector of float)
0:? textureFetch ( temp 4-component vector of float)
0:13 'g_tTex2df4' ( uniform texture2D)
0:? Constant:
0:? 14 (const uint)
0:? 15 (const uint)
0:13 Constant:
0:13 13 (const int)
0:13 Sequence
0:13 Constant:
0:13 0 (const int)
0:13 Constant:
0:13 1 (const int)
0:13 Convert float to uint ( temp uint)
0:13 direct index ( temp float)
0:? textureFetch ( temp 4-component vector of float)
0:13 'g_tTex2df4' ( uniform texture2D)
0:? Constant:
0:? 10 (const uint)
0:? 11 (const uint)
0:13 Constant:
0:13 9 (const int)
0:13 Constant:
0:13 0 (const int)
0:5 Function Definition: main( ( temp void)
0:5 Function Parameters:
0:? Sequence
0:5 move second child to first child ( temp 4-component vector of float)
0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float)
0:5 Function Call: @main( ( temp 4-component vector of float)
0:? Linker Objects
0:? 'g_tTex2df4a' ( uniform texture2DArray)
0:? 'g_tTex2df4' ( uniform texture2D)
0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float)
Linked fragment stage:
Shader version: 500
gl_FragCoord origin is upper left
0:? Sequence
0:5 Function Definition: @main( ( temp 4-component vector of float)
0:5 Function Parameters:
0:? Sequence
0:13 Branch: Return with expression
0:9 add ( temp 4-component vector of float)
0:6 add ( temp 4-component vector of float)
0:? textureFetch ( temp 4-component vector of float)
0:6 'g_tTex2df4' ( uniform texture2D)
0:? Constant:
0:? 3 (const uint)
0:? 4 (const uint)
0:6 Constant:
0:6 2 (const int)
0:? textureFetch ( temp 4-component vector of float)
0:9 'g_tTex2df4a' ( uniform texture2DArray)
0:? Constant:
0:? 6 (const uint)
0:? 7 (const uint)
0:? 8 (const uint)
0:9 Constant:
0:9 5 (const uint)
0:13 textureFetch ( temp 4-component vector of float)
0:13 'g_tTex2df4' ( uniform texture2D)
0:13 Convert float to uint ( temp 2-component vector of uint)
0:13 vector swizzle ( temp 2-component vector of float)
0:? textureFetch ( temp 4-component vector of float)
0:13 'g_tTex2df4' ( uniform texture2D)
0:? Constant:
0:? 14 (const uint)
0:? 15 (const uint)
0:13 Constant:
0:13 13 (const int)
0:13 Sequence
0:13 Constant:
0:13 0 (const int)
0:13 Constant:
0:13 1 (const int)
0:13 Convert float to uint ( temp uint)
0:13 direct index ( temp float)
0:? textureFetch ( temp 4-component vector of float)
0:13 'g_tTex2df4' ( uniform texture2D)
0:? Constant:
0:? 10 (const uint)
0:? 11 (const uint)
0:13 Constant:
0:13 9 (const int)
0:13 Constant:
0:13 0 (const int)
0:5 Function Definition: main( ( temp void)
0:5 Function Parameters:
0:? Sequence
0:5 move second child to first child ( temp 4-component vector of float)
0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float)
0:5 Function Call: @main( ( temp 4-component vector of float)
0:? Linker Objects
0:? 'g_tTex2df4a' ( uniform texture2DArray)
0:? 'g_tTex2df4' ( uniform texture2D)
0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float)
// Module Version 10000
// Generated by (magic number): 80001
// Id's are bound by 61
Capability Shader
1: ExtInstImport "GLSL.std.450"
MemoryModel Logical GLSL450
EntryPoint Fragment 4 "main" 59
ExecutionMode 4 OriginUpperLeft
Source HLSL 500
Name 4 "main"
Name 9 "@main("
Name 13 "g_tTex2df4"
Name 25 "g_tTex2df4a"
Name 59 "@entryPointOutput"
Decorate 13(g_tTex2df4) DescriptorSet 0
Decorate 25(g_tTex2df4a) DescriptorSet 0
Decorate 59(@entryPointOutput) Location 0
2: TypeVoid
3: TypeFunction 2
6: TypeFloat 32
7: TypeVector 6(float) 4
8: TypeFunction 7(fvec4)
11: TypeImage 6(float) 2D sampled format:Unknown
12: TypePointer UniformConstant 11
13(g_tTex2df4): 12(ptr) Variable UniformConstant
15: TypeInt 32 0
16: TypeVector 15(int) 2
17: 15(int) Constant 3
18: 15(int) Constant 4
19: 16(ivec2) ConstantComposite 17 18
20: TypeInt 32 1
21: 20(int) Constant 2
23: TypeImage 6(float) 2D array sampled format:Unknown
24: TypePointer UniformConstant 23
25(g_tTex2df4a): 24(ptr) Variable UniformConstant
27: TypeVector 15(int) 3
28: 15(int) Constant 6
29: 15(int) Constant 7
30: 15(int) Constant 8
31: 27(ivec3) ConstantComposite 28 29 30
32: 15(int) Constant 5
37: 15(int) Constant 14
38: 15(int) Constant 15
39: 16(ivec2) ConstantComposite 37 38
40: 20(int) Constant 13
42: TypeVector 6(float) 2
46: 15(int) Constant 10
47: 15(int) Constant 11
48: 16(ivec2) ConstantComposite 46 47
49: 20(int) Constant 9
51: 15(int) Constant 0
58: TypePointer Output 7(fvec4)
59(@entryPointOutput): 58(ptr) Variable Output
4(main): 2 Function None 3
5: Label
60: 7(fvec4) FunctionCall 9(@main()
Store 59(@entryPointOutput) 60
Return
FunctionEnd
9(@main(): 7(fvec4) Function None 8
10: Label
14: 11 Load 13(g_tTex2df4)
22: 7(fvec4) ImageFetch 14 19 Lod 21
26: 23 Load 25(g_tTex2df4a)
33: 7(fvec4) ImageFetch 26 31 Lod 32
34: 7(fvec4) FAdd 22 33
35: 11 Load 13(g_tTex2df4)
36: 11 Load 13(g_tTex2df4)
41: 7(fvec4) ImageFetch 36 39 Lod 40
43: 42(fvec2) VectorShuffle 41 41 0 1
44: 16(ivec2) ConvertFToU 43
45: 11 Load 13(g_tTex2df4)
50: 7(fvec4) ImageFetch 45 48 Lod 49
52: 6(float) CompositeExtract 50 0
53: 15(int) ConvertFToU 52
54: 7(fvec4) ImageFetch 35 44 Lod 53
55: 7(fvec4) FAdd 34 54
ReturnValue 55
FunctionEnd

View File

@ -0,0 +1,9 @@
Texture2D g_tTex2df4;
float4 main() : SV_Target0
{
g_tTex2df4.mips.mips[2][uint2(3, 4)]; // error to chain like this
return 0;
}

View File

@ -0,0 +1,9 @@
Texture2D g_tTex2df4;
float4 main() : SV_Target0
{
g_tTex2df4.r[2][uint2(3, 4)]; // '.r' not valid on texture object
return 0;
}

View File

@ -0,0 +1,14 @@
Texture2DArray g_tTex2df4a;
Texture2D g_tTex2df4;
float4 main() : SV_Target0
{
return g_tTex2df4.mips[2][uint2(3, 4)] +
// test float->uint cast on the mip arg
g_tTex2df4a.mips[5.2][uint3(6, 7, 8)] +
// Test nesting involving .mips operators:
// ....outer operator mip level...... .....outer operator coordinate....
g_tTex2df4.mips[ g_tTex2df4.mips[9][uint2(10,11)][0] ][ g_tTex2df4.mips[13][uint2(14,15)].xy ];
}

View File

@ -0,0 +1,7 @@
#version 450
layout (local_size_x_id = 0, local_size_y_id = 1, local_size_z_id = 2) in;
shared int foo[gl_WorkGroupSize.x + gl_WorkGroupSize.y * gl_WorkGroupSize.z];
void main () {}

View File

@ -177,6 +177,9 @@ INSTANTIATE_TEST_CASE_P(
{"hlsl.logicalConvert.frag", "main"}, {"hlsl.logicalConvert.frag", "main"},
{"hlsl.logical.unary.frag", "main"}, {"hlsl.logical.unary.frag", "main"},
{"hlsl.loopattr.frag", "main"}, {"hlsl.loopattr.frag", "main"},
{"hlsl.mip.operator.frag", "main"},
{"hlsl.mip.negative.frag", "main"},
{"hlsl.mip.negative2.frag", "main"},
{"hlsl.namespace.frag", "main"}, {"hlsl.namespace.frag", "main"},
{"hlsl.nonint-index.frag", "main"}, {"hlsl.nonint-index.frag", "main"},
{"hlsl.matNx1.frag", "main"}, {"hlsl.matNx1.frag", "main"},

View File

@ -677,19 +677,30 @@ TIntermTyped* HlslParseContext::handleBracketOperator(const TSourceLoc& loc, TIn
if (base->getType().getBasicType() == EbtSampler && !base->isArray()) { if (base->getType().getBasicType() == EbtSampler && !base->isArray()) {
const TSampler& sampler = base->getType().getSampler(); const TSampler& sampler = base->getType().getSampler();
if (sampler.isImage() || sampler.isTexture()) { if (sampler.isImage() || sampler.isTexture()) {
TIntermAggregate* load = new TIntermAggregate(sampler.isImage() ? EOpImageLoad : EOpTextureFetch); if (! mipsOperatorMipArg.empty() && mipsOperatorMipArg.back().mipLevel == nullptr) {
// The first operator[] to a .mips[] sequence is the mip level. We'll remember it.
mipsOperatorMipArg.back().mipLevel = index;
return base; // next [] index is to the same base.
} else {
TIntermAggregate* load = new TIntermAggregate(sampler.isImage() ? EOpImageLoad : EOpTextureFetch);
load->setType(TType(sampler.type, EvqTemporary, sampler.vectorSize)); load->setType(TType(sampler.type, EvqTemporary, sampler.vectorSize));
load->setLoc(loc); load->setLoc(loc);
load->getSequence().push_back(base); load->getSequence().push_back(base);
load->getSequence().push_back(index); load->getSequence().push_back(index);
// Textures need a MIP. First indirection is always to mip 0. If there's another, we'll add it // Textures need a MIP. If we saw one go by, use it. Otherwise, use zero.
// later. if (sampler.isTexture()) {
if (sampler.isTexture()) if (! mipsOperatorMipArg.empty()) {
load->getSequence().push_back(intermediate.addConstantUnion(0, loc, true)); load->getSequence().push_back(mipsOperatorMipArg.back().mipLevel);
mipsOperatorMipArg.pop_back();
} else {
load->getSequence().push_back(intermediate.addConstantUnion(0, loc, true));
}
}
return load; return load;
}
} }
} }
@ -874,7 +885,21 @@ TIntermTyped* HlslParseContext::handleDotDereference(const TSourceLoc& loc, TInt
} }
TIntermTyped* result = base; TIntermTyped* result = base;
if (base->isVector() || base->isScalar()) {
if (base->getType().getBasicType() == EbtSampler) {
// Handle .mips[mipid][pos] operation on textures
const TSampler& sampler = base->getType().getSampler();
if (sampler.isTexture() && field == "mips") {
// Push a null to signify that we expect a mip level under operator[] next.
mipsOperatorMipArg.push_back(tMipsOperatorData(loc, nullptr));
// Keep 'result' pointing to 'base', since we expect an operator[] to go by next.
} else {
if (field == "mips")
error(loc, "unexpected texture type for .mips[][] operator:", base->getType().getCompleteString().c_str(), "");
else
error(loc, "unexpected operator on texture type:", field.c_str(), base->getType().getCompleteString().c_str());
}
} else if (base->isVector() || base->isScalar()) {
TSwizzleSelectors<TVectorSelector> selectors; TSwizzleSelectors<TVectorSelector> selectors;
parseSwizzleSelector(loc, field, base->getVectorSize(), selectors); parseSwizzleSelector(loc, field, base->getVectorSize(), selectors);
@ -8426,6 +8451,12 @@ void HlslParseContext::removeUnusedStructBufferCounters()
// post-processing // post-processing
void HlslParseContext::finish() void HlslParseContext::finish()
{ {
// Error check: There was a dangling .mips operator. These are not nested constructs in the grammar, so
// cannot be detected there. This is not strictly needed in a non-validating parser; it's just helpful.
if (! mipsOperatorMipArg.empty()) {
error(mipsOperatorMipArg.back().loc, "unterminated mips operator:", "", "");
}
removeUnusedStructBufferCounters(); removeUnusedStructBufferCounters();
addPatchConstantInvocation(); addPatchConstantInvocation();
addInterstageIoToLinkage(); addInterstageIoToLinkage();

View File

@ -429,6 +429,17 @@ protected:
TVector<TVariable*> implicitThisStack; // currently active 'this' variables for nested structures TVector<TVariable*> implicitThisStack; // currently active 'this' variables for nested structures
TVariable* gsStreamOutput; // geometry shader stream outputs, for emit (Append method) TVariable* gsStreamOutput; // geometry shader stream outputs, for emit (Append method)
// This tracks the first (mip level) argument to the .mips[][] operator. Since this can be nested as
// in tx.mips[tx.mips[0][1].x][2], we need a stack. We also track the TSourceLoc for error reporting
// purposes.
struct tMipsOperatorData {
tMipsOperatorData(TSourceLoc l, TIntermTyped* m) : loc(l), mipLevel(m) { }
TSourceLoc loc;
TIntermTyped* mipLevel;
};
TVector<tMipsOperatorData> mipsOperatorMipArg;
}; };
// This is the prefix we use for builtin methods to avoid namespace collisions with // This is the prefix we use for builtin methods to avoid namespace collisions with