Commit b207daa5 by John Kessenich Committed by GitHub

Merge pull request #1017 from LoopDawg/texture-struct-return.1

HLSL: add methods to handle user structures in texture template type.
parents 786e8795 5ee05891
struct s1_t {
float c0;
float2 c1;
float c2;
};
struct s2_t {
float c0;
float3 c1;
};
struct s3_t {
float2 c0;
float1 c1;
};
struct s4_t {
int c0;
int2 c1;
int c2;
};
struct s5_t {
uint c0;
uint c1;
};
SamplerState g_sSamp;
Texture2D <s1_t> g_tTex2s1;
Texture2D <s2_t> g_tTex2s2;
Texture2D <s3_t> g_tTex2s3;
Texture2D <s4_t> g_tTex2s4;
Texture2D <s5_t> g_tTex2s5;
Texture2D <s1_t> g_tTex2s1a; // same type as g_tTex2s1, to test fn signature matching.
// function overloading to test name mangling with textures templatized on structs
s1_t fn1(Texture2D <s1_t> t1) { return t1 . Sample(g_sSamp, float2(0.6, 0.61)); }
s2_t fn1(Texture2D <s2_t> t2) { return t2 . Sample(g_sSamp, float2(0.6, 0.61)); }
float4 main() : SV_Target0
{
s1_t s1 = g_tTex2s1 . Sample(g_sSamp, float2(0.1, 0.11));
s2_t s2 = g_tTex2s2 . Sample(g_sSamp, float2(0.2, 0.21));
s3_t s3 = g_tTex2s3 . Sample(g_sSamp, float2(0.3, 0.31));
s4_t s4 = g_tTex2s4 . Sample(g_sSamp, float2(0.4, 0.41));
s5_t s5 = g_tTex2s5 . Sample(g_sSamp, float2(0.5, 0.51));
s1_t r0 = fn1(g_tTex2s1);
s2_t r1 = fn1(g_tTex2s2);
s1_t r2 = fn1(g_tTex2s1a);
return 0;
}
...@@ -11,7 +11,7 @@ Texture2D <float4> g_tTex2df4; ...@@ -11,7 +11,7 @@ Texture2D <float4> g_tTex2df4;
SamplerState g_sSamp; SamplerState g_sSamp;
float4 main() float4 main() : SV_Target0
{ {
uint MipLevel; uint MipLevel;
uint WidthU; uint WidthU;
......
...@@ -80,7 +80,19 @@ struct TSampler { // misnomer now; includes images, textures without sampler, ...@@ -80,7 +80,19 @@ struct TSampler { // misnomer now; includes images, textures without sampler,
bool combined : 1; // true means texture is combined with a sampler, false means texture with no sampler bool combined : 1; // true means texture is combined with a sampler, false means texture with no sampler
bool sampler : 1; // true means a pure sampler, other fields should be clear() bool sampler : 1; // true means a pure sampler, other fields should be clear()
bool external : 1; // GL_OES_EGL_image_external bool external : 1; // GL_OES_EGL_image_external
unsigned int vectorSize : 3; // return vector size. TODO: support arbitrary types. unsigned int vectorSize : 3; // vector return type size.
// Some languages support structures as sample results. Storing the whole structure in the
// TSampler is too large, so there is an index to a separate table.
static const unsigned structReturnIndexBits = 4; // number of index bits to use.
static const unsigned structReturnSlots = (1<<structReturnIndexBits)-1; // number of valid values
static const unsigned noReturnStruct = structReturnSlots; // value if no return struct type.
// Index into a language specific table of texture return structures.
unsigned int structReturnIndex : structReturnIndexBits;
// Encapsulate getting members' vector sizes packed into the vectorSize bitfield.
unsigned int getVectorSize() const { return vectorSize; }
bool isImage() const { return image && dim != EsdSubpass; } bool isImage() const { return image && dim != EsdSubpass; }
bool isSubpass() const { return dim == EsdSubpass; } bool isSubpass() const { return dim == EsdSubpass; }
...@@ -90,6 +102,7 @@ struct TSampler { // misnomer now; includes images, textures without sampler, ...@@ -90,6 +102,7 @@ struct TSampler { // misnomer now; includes images, textures without sampler,
bool isShadow() const { return shadow; } bool isShadow() const { return shadow; }
bool isArrayed() const { return arrayed; } bool isArrayed() const { return arrayed; }
bool isMultiSample() const { return ms; } bool isMultiSample() const { return ms; }
bool hasReturnStruct() const { return structReturnIndex != noReturnStruct; }
void clear() void clear()
{ {
...@@ -102,6 +115,9 @@ struct TSampler { // misnomer now; includes images, textures without sampler, ...@@ -102,6 +115,9 @@ struct TSampler { // misnomer now; includes images, textures without sampler,
combined = false; combined = false;
sampler = false; sampler = false;
external = false; external = false;
structReturnIndex = noReturnStruct;
// by default, returns a single vec4;
vectorSize = 4; vectorSize = 4;
} }
...@@ -160,16 +176,17 @@ struct TSampler { // misnomer now; includes images, textures without sampler, ...@@ -160,16 +176,17 @@ struct TSampler { // misnomer now; includes images, textures without sampler,
bool operator==(const TSampler& right) const bool operator==(const TSampler& right) const
{ {
return type == right.type && return type == right.type &&
dim == right.dim && dim == right.dim &&
arrayed == right.arrayed && arrayed == right.arrayed &&
shadow == right.shadow && shadow == right.shadow &&
ms == right.ms && ms == right.ms &&
image == right.image && image == right.image &&
combined == right.combined && combined == right.combined &&
sampler == right.sampler && sampler == right.sampler &&
external == right.external && external == right.external &&
vectorSize == right.vectorSize; vectorSize == right.vectorSize &&
structReturnIndex == right.structReturnIndex;
} }
bool operator!=(const TSampler& right) const bool operator!=(const TSampler& right) const
......
...@@ -104,11 +104,20 @@ void TType::buildMangledName(TString& mangledName) const ...@@ -104,11 +104,20 @@ void TType::buildMangledName(TString& mangledName) const
default: break; // some compilers want this default: break; // some compilers want this
} }
switch (sampler.vectorSize) { if (sampler.hasReturnStruct()) {
case 1: mangledName += "1"; break; // Name mangle for sampler return struct uses struct table index.
case 2: mangledName += "2"; break; mangledName += "-tx-struct";
case 3: mangledName += "3"; break;
case 4: break; // default to prior name mangle behavior char text[16]; // plenty enough space for the small integers.
snprintf(text, sizeof(text), "%d-", sampler.structReturnIndex);
mangledName += text;
} else {
switch (sampler.getVectorSize()) {
case 1: mangledName += "1"; break;
case 2: mangledName += "2"; break;
case 3: mangledName += "3"; break;
case 4: break; // default to prior name mangle behavior
}
} }
if (sampler.ms) if (sampler.ms)
......
...@@ -291,6 +291,7 @@ INSTANTIATE_TEST_CASE_P( ...@@ -291,6 +291,7 @@ INSTANTIATE_TEST_CASE_P(
{"hlsl.structIoFourWay.frag", "main"}, {"hlsl.structIoFourWay.frag", "main"},
{"hlsl.structStructName.frag", "main"}, {"hlsl.structStructName.frag", "main"},
{"hlsl.synthesizeInput.frag", "main"}, {"hlsl.synthesizeInput.frag", "main"},
{"hlsl.texture.struct.frag", "main"},
{"hlsl.texture.subvec4.frag", "main"}, {"hlsl.texture.subvec4.frag", "main"},
{"hlsl.this.frag", "main"}, {"hlsl.this.frag", "main"},
{"hlsl.intrinsics.vert", "VertexShaderFunction"}, {"hlsl.intrinsics.vert", "VertexShaderFunction"},
......
...@@ -1189,7 +1189,13 @@ bool HlslGrammar::acceptTextureType(TType& type) ...@@ -1189,7 +1189,13 @@ bool HlslGrammar::acceptTextureType(TType& type)
const TBasicType basicRetType = txType.getBasicType() ; const TBasicType basicRetType = txType.getBasicType() ;
if (basicRetType != EbtFloat && basicRetType != EbtUint && basicRetType != EbtInt) { switch (basicRetType) {
case EbtFloat:
case EbtUint:
case EbtInt:
case EbtStruct:
break;
default:
unimplemented("basic type in texture"); unimplemented("basic type in texture");
return false; return false;
} }
...@@ -1206,8 +1212,8 @@ bool HlslGrammar::acceptTextureType(TType& type) ...@@ -1206,8 +1212,8 @@ bool HlslGrammar::acceptTextureType(TType& type)
return false; return false;
} }
if (!txType.isScalar() && !txType.isVector()) { if (!txType.isScalar() && !txType.isVector() && !txType.isStruct()) {
expected("scalar or vector type"); expected("scalar, vector, or struct type");
return false; return false;
} }
...@@ -1244,20 +1250,24 @@ bool HlslGrammar::acceptTextureType(TType& type) ...@@ -1244,20 +1250,24 @@ bool HlslGrammar::acceptTextureType(TType& type)
if (image || dim == EsdBuffer) if (image || dim == EsdBuffer)
format = parseContext.getLayoutFromTxType(token.loc, txType); format = parseContext.getLayoutFromTxType(token.loc, txType);
const TBasicType txBasicType = txType.isStruct() ? (*txType.getStruct())[0].type->getBasicType()
: txType.getBasicType();
// Non-image Buffers are combined // Non-image Buffers are combined
if (dim == EsdBuffer && !image) { if (dim == EsdBuffer && !image) {
sampler.set(txType.getBasicType(), dim, array); sampler.set(txType.getBasicType(), dim, array);
} else { } else {
// DX10 textures are separated. TODO: DX9. // DX10 textures are separated. TODO: DX9.
if (image) { if (image) {
sampler.setImage(txType.getBasicType(), dim, array, shadow, ms); sampler.setImage(txBasicType, dim, array, shadow, ms);
} else { } else {
sampler.setTexture(txType.getBasicType(), dim, array, shadow, ms); sampler.setTexture(txBasicType, dim, array, shadow, ms);
} }
} }
// Remember the declared vector size. // Remember the declared return type. Function returns false on error.
sampler.vectorSize = txType.getVectorSize(); if (!parseContext.setTextureReturnType(sampler, txType, token.loc))
return false;
// Force uncombined, if necessary // Force uncombined, if necessary
if (!combined) if (!combined)
......
...@@ -213,6 +213,12 @@ public: ...@@ -213,6 +213,12 @@ public:
// Share struct buffer deep types // Share struct buffer deep types
void shareStructBufferType(TType&); void shareStructBufferType(TType&);
// Set texture return type of the given sampler. Returns success (not all types are valid).
bool setTextureReturnType(TSampler& sampler, const TType& retType, const TSourceLoc& loc);
// Obtain the sampler return type of the given sampler in retType.
void getTextureReturnType(const TSampler& sampler, TType& retType) const;
protected: protected:
struct TFlattenData { struct TFlattenData {
TFlattenData() : nextBinding(TQualifier::layoutBindingEnd), TFlattenData() : nextBinding(TQualifier::layoutBindingEnd),
...@@ -388,6 +394,10 @@ protected: ...@@ -388,6 +394,10 @@ protected:
// Structuredbuffer shared types. Typically there are only a few. // Structuredbuffer shared types. Typically there are only a few.
TVector<TType*> structBufferTypes; TVector<TType*> structBufferTypes;
// This tracks texture sample user structure return types. Only a limited number are supported, as
// may fit in TSampler::structReturnIndex.
TVector<TTypeList*> textureReturnStruct;
TMap<TString, bool> structBufferCounter; TMap<TString, bool> structBufferCounter;
......
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