Commit f02bea28 by John Kessenich Committed by GitHub

Merge pull request #380 from steve-lunarg/samplers

HLSL: Sampler/texture declarations, method syntax, partial Sample method
parents d8509b33 4886f697
......@@ -3,6 +3,7 @@
*.so
*.exe
tags
TAGS
build/
Test/localResults/
Test/multiThread.out
......
SamplerState g_sSamp : register(s0);
uniform sampler2D g_sSamp2d
{
AddressU = MIRROR;
AddressV = WRAP;
MinLOD = 0;
MaxLOD = 10;
MaxAnisotropy = 2;
MipLodBias = 0.2;
}, g_sSamp2D_b;
Texture1D g_tTex1df4a : register(t1);
uniform Texture1D <float4> g_tTex1df4 : register(t0);
Texture1D <int4> g_tTex1di4;
Texture1D <uint4> g_tTex1du4;
Texture2D <float4> g_tTex2df4;
Texture2D <int4> g_tTex2di4;
Texture2D <uint4> g_tTex2du4;
Texture3D <float4> g_tTex3df4;
Texture3D <int4> g_tTex3di4;
Texture3D <uint4> g_tTex3du4;
TextureCube <float4> g_tTexcdf4;
TextureCube <int4> g_tTexcdi4;
TextureCube <uint4> g_tTexcdu4;
struct MemberTest
{
int Sample; // in HLSL, method names are valid struct members.
int CalculateLevelOfDetail; // ...
int CalculateLevelOfDetailUnclamped; // ...
int Gather; // ...
int GetDimensions; // ...
int GetSamplePosition; // ...
int Load; // ...
int SampleBias; // ...
int SampleCmp; // ...
int SampleCmpLevelZero; // ...
int SampleGrad; // ...
int SampleLevel; // ...
};
struct PS_OUTPUT
{
float4 Color : SV_Target0;
float Depth : SV_Depth;
};
PS_OUTPUT main()
{
PS_OUTPUT psout;
MemberTest mtest;
mtest.CalculateLevelOfDetail = 1; // in HLSL, method names are valid struct members.
mtest.CalculateLevelOfDetailUnclamped = 1; // ...
mtest.Gather = 1; // ...
mtest.GetDimensions = 1; // ...
mtest.GetSamplePosition = 1; // ...
mtest.Load = 1; // ...
mtest.Sample = 1; // ...
mtest.SampleBias = 1; // ...
mtest.SampleCmp = 1; // ...
mtest.SampleCmpLevelZero = 1; // ...
mtest.SampleGrad = 1; // ...
mtest.SampleLevel = 1; // ...
float4 txval10 = g_tTex1df4 . Sample(g_sSamp, 0.1);
int4 txval11 = g_tTex1di4 . Sample(g_sSamp, 0.2);
uint4 txval12 = g_tTex1du4 . Sample(g_sSamp, 0.3);
float4 txval20 = g_tTex2df4 . Sample(g_sSamp, float2(0.1, 0.2));
int4 txval21 = g_tTex2di4 . Sample(g_sSamp, float2(0.3, 0.4));
uint4 txval22 = g_tTex2du4 . Sample(g_sSamp, float2(0.5, 0.6));
float4 txval30 = g_tTex3df4 . Sample(g_sSamp, float3(0.1, 0.2, 0.3));
int4 txval31 = g_tTex3di4 . Sample(g_sSamp, float3(0.4, 0.5, 0.6));
uint4 txval32 = g_tTex3du4 . Sample(g_sSamp, float3(0.7, 0.8, 0.9));
float4 txval40 = g_tTexcdf4 . Sample(g_sSamp, float3(0.1, 0.2, 0.3));
int4 txval41 = g_tTexcdi4 . Sample(g_sSamp, float3(0.4, 0.5, 0.6));
uint4 txval42 = g_tTexcdu4 . Sample(g_sSamp, float3(0.7, 0.8, 0.9));
psout.Color = 1.0;
psout.Depth = 1.0;
return psout;
}
......@@ -84,6 +84,7 @@ struct TSampler { // misnomer now; includes images, textures without sampler,
bool isCombined() const { return combined; }
bool isPureSampler() const { return sampler; }
bool isTexture() const { return !sampler && !image; }
bool isShadow() const { return shadow; }
void clear()
{
......@@ -1080,6 +1081,15 @@ public:
typeName = NewPoolTString(p.userDef->getTypeName().c_str());
}
}
// for construction of sampler types
TType(const TSampler& sampler, TStorageQualifier q = EvqUniform, TArraySizes* as = nullptr) :
basicType(EbtSampler), vectorSize(1), matrixCols(0), matrixRows(0), vector1(false),
arraySizes(as), structure(nullptr), fieldName(nullptr), typeName(nullptr),
sampler(sampler)
{
qualifier.clear();
qualifier.storage = q;
}
// to efficiently make a dereferenced type
// without ever duplicating the outer structure that will be thrown away
// and using only shallow copy
......
......@@ -525,6 +525,8 @@ enum TOperator {
EOpLit, // HLSL lighting coefficient vector
EOpTextureBias, // HLSL texture bias: will be lowered to EOpTexture
EOpAsDouble, // slightly different from EOpUint64BitsToDouble
EOpMethodSample,
};
class TIntermTraverser;
......
......@@ -93,6 +93,7 @@ INSTANTIATE_TEST_CASE_P(
{"hlsl.intrinsics.negative.comp", "ComputeShaderFunction"},
{"hlsl.intrinsics.negative.frag", "PixelShaderFunction"},
{"hlsl.intrinsics.negative.vert", "VertexShaderFunction"},
{"hlsl.sample.basicdx10.frag", "main"},
{"hlsl.intrinsics.vert", "VertexShaderFunction"},
{"hlsl.matType.frag", "PixelShaderFunction"},
{"hlsl.max.frag", "PixelShaderFunction"},
......
......@@ -59,16 +59,21 @@ namespace glslang {
HlslGrammar& operator=(const HlslGrammar&);
void expected(const char*);
void unimplemented(const char*);
bool acceptIdentifier(HlslToken&);
bool acceptCompilationUnit();
bool acceptDeclaration(TIntermNode*& node);
bool acceptControlDeclaration(TIntermNode*& node);
bool acceptSamplerDeclarationDX9(TType&);
bool acceptSamplerState();
bool acceptFullySpecifiedType(TType&);
void acceptQualifier(TQualifier&);
bool acceptType(TType&);
bool acceptTemplateType(TBasicType&);
bool acceptVectorTemplateType(TType&);
bool acceptMatrixTemplateType(TType&);
bool acceptSamplerType(TType&);
bool acceptTextureType(TType&);
bool acceptStruct(TType&);
bool acceptStructDeclarationList(TTypeList*&);
bool acceptFunctionParameters(TFunction&);
......@@ -82,7 +87,7 @@ namespace glslang {
bool acceptUnaryExpression(TIntermTyped*&);
bool acceptPostfixExpression(TIntermTyped*&);
bool acceptConstructor(TIntermTyped*&);
bool acceptFunctionCall(HlslToken, TIntermTyped*&);
bool acceptFunctionCall(HlslToken, TIntermTyped*&, TIntermTyped* base = nullptr);
bool acceptArguments(TFunction*, TIntermTyped*&);
bool acceptLiteral(TIntermTyped*&);
bool acceptCompoundStatement(TIntermNode*&);
......
......@@ -564,12 +564,32 @@ TIntermTyped* HlslParseContext::handleDotDereference(const TSourceLoc& loc, TInt
variableCheck(base);
//
// .length() can't be resolved until we later see the function-calling syntax.
// methods can't be resolved until we later see the function-calling syntax.
// Save away the name in the AST for now. Processing is completed in
// handleLengthMethod().
// handleLengthMethod(), etc.
//
if (field == "length") {
return intermediate.addMethod(base, TType(EbtInt), &field, loc);
} else if (field == "CalculateLevelOfDetail" ||
field == "CalculateLevelOfDetailUnclamped" ||
field == "Gather" ||
field == "GetDimensions" ||
field == "GetSamplePosition" ||
field == "Load" ||
field == "Sample" ||
field == "SampleBias" ||
field == "SampleCmp" ||
field == "SampleCmpLevelZero" ||
field == "SampleGrad" ||
field == "SampleLevel") {
// If it's not a method on a sampler object, we fall through in case it is a struct member.
if (base->getType().getBasicType() == EbtSampler) {
const TSampler& texType = base->getType().getSampler();
if (! texType.isPureSampler()) {
const int vecSize = texType.isShadow() ? 1 : 4;
return intermediate.addMethod(base, TType(texType.type, EvqTemporary, vecSize), &field, loc);
}
}
}
// It's not .length() if we get to here.
......@@ -1006,9 +1026,7 @@ void HlslParseContext::decomposeIntrinsic(const TSourceLoc& loc, TIntermTyped*&
TIntermTyped* arg0 = argAggregate->getSequence()[0]->getAsTyped();
TIntermTyped* arg1 = argAggregate->getSequence()[1]->getAsTyped();
TBasicType type0 = arg0->getBasicType();
TIntermTyped* x = intermediate.addConstantUnion(0, loc, true);
TIntermTyped* y = intermediate.addConstantUnion(1, loc, true);
TIntermTyped* z = intermediate.addConstantUnion(2, loc, true);
TIntermTyped* w = intermediate.addConstantUnion(3, loc, true);
......@@ -1205,6 +1223,49 @@ void HlslParseContext::decomposeIntrinsic(const TSourceLoc& loc, TIntermTyped*&
}
//
// Decompose sample methods into AST
//
void HlslParseContext::decomposeSampleMethods(const TSourceLoc& loc, TIntermTyped*& node, TIntermNode* arguments)
{
if (!node || !node->getAsOperator())
return;
const TIntermAggregate* argAggregate = arguments ? arguments->getAsAggregate() : nullptr;
const TOperator op = node->getAsOperator()->getOp();
switch (op) {
case EOpMethodSample:
{
TIntermTyped* argTex = argAggregate->getSequence()[0]->getAsTyped();
TIntermTyped* argSamp = argAggregate->getSequence()[1]->getAsTyped();
TIntermTyped* argCoord = argAggregate->getSequence()[2]->getAsTyped();
TIntermAggregate* txcombine = new TIntermAggregate(EOpConstructTextureSampler);
txcombine->getSequence().push_back(argTex);
txcombine->getSequence().push_back(argSamp);
TSampler samplerType = argTex->getType().getSampler();
samplerType.combined = true;
txcombine->setType(TType(samplerType, EvqTemporary));
txcombine->setLoc(loc);
TIntermAggregate* txsample = new TIntermAggregate(EOpTexture);
txsample->getSequence().push_back(txcombine);
txsample->getSequence().push_back(argCoord);
txsample->setType(node->getType());
txsample->setLoc(loc);
node = txsample;
break;
}
default:
break; // most pass through unchanged
}
}
//
// Handle seeing function call syntax in the grammar, which could be any of
// - .length() method
// - constructor
......@@ -1307,8 +1368,9 @@ TIntermTyped* HlslParseContext::handleFunctionCall(const TSourceLoc& loc, TFunct
result = addOutputArgumentConversions(*fnCandidate, *result->getAsAggregate());
}
decomposeIntrinsic(loc, result, arguments);
textureParameters(loc, result, arguments);
decomposeIntrinsic(loc, result, arguments); // HLSL->AST intrinsic decompositions
decomposeSampleMethods(loc, result, arguments); // HLSL->AST sample method decompositions
textureParameters(loc, result, arguments); // HLSL->AST texture intrinsics
}
}
......
......@@ -87,6 +87,7 @@ public:
void handleFunctionArgument(TFunction*, TIntermTyped*& arguments, TIntermTyped* newArg);
TIntermTyped* handleFunctionCall(const TSourceLoc&, TFunction*, TIntermNode*);
void decomposeIntrinsic(const TSourceLoc&, TIntermTyped*& node, TIntermNode* arguments);
void decomposeSampleMethods(const TSourceLoc&, TIntermTyped*& node, TIntermNode* arguments);
void textureParameters(const TSourceLoc&, TIntermTyped*& node, TIntermNode* arguments);
TIntermTyped* handleLengthMethod(const TSourceLoc&, TFunction*, TIntermNode*);
void addInputArgumentConversions(const TFunction&, TIntermNode*&) const;
......
//
//Copyright (C) 2016 Google, Inc.
//Copyright (C) 2016 LunarG, Inc.
//
//All rights reserved.
//
......@@ -249,6 +250,9 @@ void HlslScanContext::fillInKeywordMap()
(*KeywordMap)["Texture2DArray"] = EHTokTexture2darray;
(*KeywordMap)["Texture3D"] = EHTokTexture3d;
(*KeywordMap)["TextureCube"] = EHTokTextureCube;
(*KeywordMap)["TextureCubeArray"] = EHTokTextureCubearray;
(*KeywordMap)["Texture2DMS"] = EHTokTexture2DMS;
(*KeywordMap)["Texture2DMSArray"] = EHTokTexture2DMSarray;
(*KeywordMap)["struct"] = EHTokStruct;
(*KeywordMap)["typedef"] = EHTokTypedef;
......@@ -556,6 +560,9 @@ EHlslTokenClass HlslScanContext::tokenizeIdentifier()
case EHTokTexture2darray:
case EHTokTexture3d:
case EHTokTextureCube:
case EHTokTextureCubearray:
case EHTokTexture2DMS:
case EHTokTexture2DMSarray:
return keyword;
// variable, user type, ...
......
//
//Copyright (C) 2016 Google, Inc.
//Copyright (C) 2016 LunarG, Inc.
//
//All rights reserved.
//
......@@ -200,6 +201,9 @@ enum EHlslTokenClass {
EHTokTexture2darray,
EHTokTexture3d,
EHTokTextureCube,
EHTokTextureCubearray,
EHTokTexture2DMS,
EHTokTexture2DMSarray,
// variable, user type, ...
EHTokIdentifier,
......@@ -278,4 +282,4 @@ enum EHlslTokenClass {
} // end namespace glslang
#endif // EHLSLTOKENS_H_
\ No newline at end of file
#endif // EHLSLTOKENS_H_
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment