Commit 7a7217c8 by John Kessenich Committed by GitHub

Merge pull request #540 from steve-lunarg/rwbuffers

HLSL: phase 1: add RWTexture and RWBuffer
parents 9065ed83 bb0183f8
SamplerState g_sSamp : register(s0);
RWTexture1D <float4> g_tTex1df4 : register(t0);
RWTexture1D <int4> g_tTex1di4;
RWTexture1D <uint4> g_tTex1du4;
RWTexture2D <float4> g_tTex2df4;
RWTexture2D <int4> g_tTex2di4;
RWTexture2D <uint4> g_tTex2du4;
RWTexture3D <float4> g_tTex3df4;
RWTexture3D <int4> g_tTex3di4;
RWTexture3D <uint4> g_tTex3du4;
RWTexture1DArray <float4> g_tTex1df4a;
RWTexture1DArray <int4> g_tTex1di4a;
RWTexture1DArray <uint4> g_tTex1du4a;
RWTexture2DArray <float4> g_tTex2df4a;
RWTexture2DArray <int4> g_tTex2di4a;
RWTexture2DArray <uint4> g_tTex2du4a;
RWBuffer <float4> g_tBuffF;
RWBuffer <int4> g_tBuffI;
RWBuffer <uint4> g_tBuffU;
struct PS_OUTPUT
{
float4 Color : SV_Target0;
float Depth : SV_Depth;
};
uniform int c1;
uniform int2 c2;
uniform int3 c3;
uniform int4 c4;
uniform int o1;
uniform int2 o2;
uniform int3 o3;
uniform int4 o4;
PS_OUTPUT main()
{
PS_OUTPUT psout;
uint MipLevel;
uint WidthU;
uint HeightU;
uint ElementsU;
uint DepthU;
uint NumberOfLevelsU;
uint NumberOfSamplesU;
float WidthF;
float HeightF;
float ElementsF;
float DepthF;
float NumberOfLevelsF;
float NumberOfSamplesF;
// 1D, float/int/uint, uint params
g_tTex1df4.GetDimensions(WidthU);
g_tTex1di4.GetDimensions(WidthU);
g_tTex1du4.GetDimensions(WidthU);
// buffer, float/int/uint, uint params
g_tBuffF.GetDimensions(WidthU);
g_tBuffI.GetDimensions(WidthU);
g_tBuffU.GetDimensions(WidthU);
// 1DArray, float/int/uint, uint params
g_tTex1df4a.GetDimensions(WidthU, ElementsU);
g_tTex1di4a.GetDimensions(WidthU, ElementsU);
g_tTex1du4a.GetDimensions(WidthU, ElementsU);
// 2D, float/int/uint, uint params
g_tTex2df4.GetDimensions(WidthU, HeightU);
g_tTex2di4.GetDimensions(WidthU, HeightU);
g_tTex2du4.GetDimensions(WidthU, HeightU);
// 2DArray, float/int/uint, uint params
g_tTex2df4a.GetDimensions(WidthU, HeightU, ElementsU);
g_tTex2di4a.GetDimensions(WidthU, HeightU, ElementsU);
g_tTex2du4a.GetDimensions(WidthU, HeightU, ElementsU);
// 3D, float/int/uint, uint params
g_tTex3df4.GetDimensions(WidthU, HeightU, DepthU);
g_tTex3di4.GetDimensions(WidthU, HeightU, DepthU);
g_tTex3du4.GetDimensions(WidthU, HeightU, DepthU);
psout.Color = 1.0;
psout.Depth = 1.0;
return psout;
}
RWBuffer <float4> g_tBuffF;
RWBuffer <int4> g_tBuffI;
RWBuffer <uint4> g_tBuffU;
struct PS_OUTPUT
{
float4 Color : SV_Target0;
};
uniform int c1;
uniform int2 c2;
uniform int3 c3;
uniform int4 c4;
uniform int o1;
uniform int2 o2;
uniform int3 o3;
uniform int4 o4;
PS_OUTPUT main()
{
PS_OUTPUT psout;
g_tBuffF.Load(c1);
g_tBuffU.Load(c1);
g_tBuffI.Load(c1);
psout.Color = 1.0;
return psout;
}
SamplerState g_sSamp : register(s0);
RWTexture1D <float4> g_tTex1df4 : register(t0);
RWTexture1D <int4> g_tTex1di4;
RWTexture1D <uint4> g_tTex1du4;
RWTexture2D <float4> g_tTex2df4;
RWTexture2D <int4> g_tTex2di4;
RWTexture2D <uint4> g_tTex2du4;
RWTexture3D <float4> g_tTex3df4;
RWTexture3D <int4> g_tTex3di4;
RWTexture3D <uint4> g_tTex3du4;
RWTexture1DArray <float4> g_tTex1df4a;
RWTexture1DArray <int4> g_tTex1di4a;
RWTexture1DArray <uint4> g_tTex1du4a;
RWTexture2DArray <float4> g_tTex2df4a;
RWTexture2DArray <int4> g_tTex2di4a;
RWTexture2DArray <uint4> g_tTex2du4a;
struct PS_OUTPUT
{
float4 Color : SV_Target0;
float Depth : SV_Depth;
};
uniform int c1;
uniform int2 c2;
uniform int3 c3;
uniform int4 c4;
uniform int o1;
uniform int2 o2;
uniform int3 o3;
uniform int4 o4;
PS_OUTPUT main()
{
PS_OUTPUT psout;
// 1D
g_tTex1df4a.Load(c2);
g_tTex1di4a.Load(c2);
g_tTex1du4a.Load(c2);
// 2D
g_tTex2df4a.Load(c3);
g_tTex2di4a.Load(c3);
g_tTex2du4a.Load(c3);
psout.Color = 1.0;
psout.Depth = 1.0;
return psout;
}
SamplerState g_sSamp : register(s0);
RWTexture1D <float4> g_tTex1df4 : register(t0);
RWTexture1D <int4> g_tTex1di4;
RWTexture1D <uint4> g_tTex1du4;
RWTexture2D <float4> g_tTex2df4;
RWTexture2D <int4> g_tTex2di4;
RWTexture2D <uint4> g_tTex2du4;
RWTexture3D <float4> g_tTex3df4;
RWTexture3D <int4> g_tTex3di4;
RWTexture3D <uint4> g_tTex3du4;
RWTexture1DArray <float4> g_tTex1df4a;
RWTexture1DArray <int4> g_tTex1di4a;
RWTexture1DArray <uint4> g_tTex1du4a;
RWTexture2DArray <float4> g_tTex2df4a;
RWTexture2DArray <int4> g_tTex2di4a;
RWTexture2DArray <uint4> g_tTex2du4a;
struct PS_OUTPUT
{
float4 Color : SV_Target0;
float Depth : SV_Depth;
};
uniform int c1;
uniform int2 c2;
uniform int3 c3;
uniform int4 c4;
uniform int o1;
uniform int2 o2;
uniform int3 o3;
uniform int4 o4;
PS_OUTPUT main()
{
PS_OUTPUT psout;
// 1D
g_tTex1df4.Load(c1);
g_tTex1di4.Load(c1);
g_tTex1du4.Load(c1);
// 2D
g_tTex2df4.Load(c2);
g_tTex2di4.Load(c2);
g_tTex2du4.Load(c2);
// 3D
g_tTex3df4.Load(c3);
g_tTex3di4.Load(c3);
g_tTex3du4.Load(c3);
psout.Color = 1.0;
psout.Depth = 1.0;
return psout;
}
......@@ -111,6 +111,7 @@ INSTANTIATE_TEST_CASE_P(
{"hlsl.gatherRGBA.offset.dx10.frag", "main"},
{"hlsl.gatherRGBA.offsetarray.dx10.frag", "main"},
{"hlsl.getdimensions.dx10.frag", "main"},
{"hlsl.getdimensions.rw.dx10.frag", "main"},
{"hlsl.getdimensions.dx10.vert", "main"},
{"hlsl.getsampleposition.dx10.frag", "main"},
{"hlsl.if.frag", "PixelShaderFunction"},
......@@ -133,6 +134,9 @@ INSTANTIATE_TEST_CASE_P(
{"hlsl.load.basic.dx10.frag", "main"},
{"hlsl.load.basic.dx10.vert", "main"},
{"hlsl.load.buffer.dx10.frag", "main"},
{"hlsl.load.rwbuffer.dx10.frag", "main"},
{"hlsl.load.rwtexture.dx10.frag", "main"},
{"hlsl.load.rwtexture.array.dx10.frag", "main"},
{"hlsl.load.offset.dx10.frag", "main"},
{"hlsl.load.offsetarray.dx10.frag", "main"},
{"hlsl.multiEntry.vert", "RealEntrypoint"},
......
......@@ -460,8 +460,14 @@ bool HlslGrammar::acceptFullySpecifiedType(TType& type)
// further, it can create an anonymous instance of the block
if (peekTokenClass(EHTokSemicolon))
parseContext.declareBlock(loc, type);
} else
} else {
// Some qualifiers are set when parsing the type. Merge those with
// whatever comes from acceptQualifier.
assert(qualifier.layoutFormat == ElfNone);
qualifier.layoutFormat = type.getQualifier().layoutFormat;
type.getQualifier() = qualifier;
}
return true;
}
......@@ -827,6 +833,13 @@ bool HlslGrammar::acceptSamplerType(TType& type)
// | TEXTURECUBEARRAY
// | TEXTURE2DMS
// | TEXTURE2DMSARRAY
// | RWBUFFER
// | RWTEXTURE1D
// | RWTEXTURE1DARRAY
// | RWTEXTURE2D
// | RWTEXTURE2DARRAY
// | RWTEXTURE3D
bool HlslGrammar::acceptTextureType(TType& type)
{
const EHlslTokenClass textureType = peek();
......@@ -834,6 +847,7 @@ bool HlslGrammar::acceptTextureType(TType& type)
TSamplerDim dim = EsdNone;
bool array = false;
bool ms = false;
bool image = false;
switch (textureType) {
case EHTokBuffer: dim = EsdBuffer; break;
......@@ -846,6 +860,12 @@ bool HlslGrammar::acceptTextureType(TType& type)
case EHTokTextureCubearray: dim = EsdCube; array = true; break;
case EHTokTexture2DMS: dim = Esd2D; ms = true; break;
case EHTokTexture2DMSarray: dim = Esd2D; array = true; ms = true; break;
case EHTokRWBuffer: dim = EsdBuffer; image=true; break;
case EHTokRWTexture1d: dim = Esd1D; array=false; image=true; break;
case EHTokRWTexture1darray: dim = Esd1D; array=true; image=true; break;
case EHTokRWTexture2d: dim = Esd2D; array=false; image=true; break;
case EHTokRWTexture2darray: dim = Esd2D; array=true; image=true; break;
case EHTokRWTexture3d: dim = Esd3D; array=false; image=true; break;
default:
return false; // not a texture declaration
}
......@@ -856,7 +876,7 @@ bool HlslGrammar::acceptTextureType(TType& type)
TIntermTyped* msCount = nullptr;
// texture type: required for multisample types!
// texture type: required for multisample types and RWBuffer/RWTextures!
if (acceptTokenClass(EHTokLeftAngle)) {
if (! acceptType(txType)) {
expected("scalar or vector type");
......@@ -911,22 +931,45 @@ bool HlslGrammar::acceptTextureType(TType& type)
} else if (ms) {
expected("texture type for multisample");
return false;
} else if (image) {
expected("type for RWTexture/RWBuffer");
return false;
}
TArraySizes* arraySizes = nullptr;
const bool shadow = txType.isScalar() || (txType.isVector() && txType.getVectorSize() == 1);
const bool shadow = !image && (txType.isScalar() || (txType.isVector() && txType.getVectorSize() == 1));
TSampler sampler;
TLayoutFormat format = ElfNone;
// RWBuffer and RWTexture (images) require a TLayoutFormat. We handle only a limit set.
if (image) {
if (txType.getVectorSize() != 4)
expected("4 component image");
// Buffers are combined.
if (dim == EsdBuffer) {
switch (txType.getBasicType()) {
case EbtFloat: format = ElfRgba32f; break;
case EbtInt: format = ElfRgba32i; break;
case EbtUint: format = ElfRgba32ui; break;
default:
expected("unknown basic type in image format");
}
}
// Non-image Buffers are combined
if (dim == EsdBuffer && !image) {
sampler.set(txType.getBasicType(), dim, array);
} else {
// DX10 textures are separated. TODO: DX9.
sampler.setTexture(txType.getBasicType(), dim, array, shadow, ms);
if (image) {
sampler.setImage(txType.getBasicType(), dim, array, shadow, ms);
} else {
sampler.setTexture(txType.getBasicType(), dim, array, shadow, ms);
}
}
type.shallowCopy(TType(sampler, EvqUniform, arraySizes));
type.getQualifier().layoutFormat = format;
return true;
}
......@@ -966,6 +1009,12 @@ bool HlslGrammar::acceptType(TType& type)
case EHTokTextureCubearray: // ...
case EHTokTexture2DMS: // ...
case EHTokTexture2DMSarray: // ...
case EHTokRWTexture1d: // ...
case EHTokRWTexture1darray: // ...
case EHTokRWTexture2d: // ...
case EHTokRWTexture2darray: // ...
case EHTokRWTexture3d: // ...
case EHTokRWBuffer: // ...
return acceptTextureType(type);
break;
......
......@@ -1252,15 +1252,17 @@ void HlslParseContext::decomposeSampleMethods(const TSourceLoc& loc, TIntermType
const TSampler& texSampler = texType.getSampler();
const TSamplerDim dim = texSampler.dim;
const bool isImage = texSampler.isImage();
const int numArgs = (int)argAggregate->getSequence().size();
int numDims = 0;
switch (dim) {
case Esd1D: numDims = 1; break; // W
case Esd2D: numDims = 2; break; // W, H
case Esd3D: numDims = 3; break; // W, H, D
case EsdCube: numDims = 2; break; // W, H (cube)
case Esd1D: numDims = 1; break; // W
case Esd2D: numDims = 2; break; // W, H
case Esd3D: numDims = 3; break; // W, H, D
case EsdCube: numDims = 2; break; // W, H (cube)
case EsdBuffer: numDims = 1; break; // buffers
default:
assert(0 && "unhandled texture dimension");
}
......@@ -1273,7 +1275,7 @@ void HlslParseContext::decomposeSampleMethods(const TSourceLoc& loc, TIntermType
const bool mipQuery = (numArgs > (numDims + 1)) && (!texSampler.isMultiSample());
// AST assumes integer return. Will be converted to float if required.
TIntermAggregate* sizeQuery = new TIntermAggregate(EOpTextureQuerySize);
TIntermAggregate* sizeQuery = new TIntermAggregate(isImage ? EOpImageQuerySize : EOpTextureQuerySize);
sizeQuery->getSequence().push_back(argTex);
// If we're querying an explicit LOD, add the LOD, which is always arg #1
if (mipQuery) {
......@@ -1419,11 +1421,12 @@ void HlslParseContext::decomposeSampleMethods(const TSourceLoc& loc, TIntermType
const bool isMS = argTex->getType().getSampler().isMultiSample();
const bool isBuffer = argTex->getType().getSampler().dim == EsdBuffer;
const bool isImage = argTex->getType().getSampler().isImage();
const TBasicType coordBaseType = argCoord->getType().getBasicType();
// Last component of coordinate is the mip level, for non-MS. we separate them here:
if (isMS || isBuffer) {
// MS and Buffer have no LOD
if (isMS || isBuffer || isImage) {
// MS, Buffer, and Image have no LOD
coordSwizzle = argCoord;
} else {
// Extract coordinate
......@@ -1443,7 +1446,9 @@ void HlslParseContext::decomposeSampleMethods(const TSourceLoc& loc, TIntermType
const bool hasOffset = ((!isMS && numArgs == 3) || (isMS && numArgs == 4));
// Create texel fetch
const TOperator fetchOp = (hasOffset ? EOpTextureFetchOffset : EOpTextureFetch);
const TOperator fetchOp = (isImage ? EOpImageLoad :
hasOffset ? EOpTextureFetchOffset :
EOpTextureFetch);
TIntermAggregate* txfetch = new TIntermAggregate(fetchOp);
// Build up the fetch
......@@ -1456,6 +1461,8 @@ void HlslParseContext::decomposeSampleMethods(const TSourceLoc& loc, TIntermType
txfetch->getSequence().push_back(argSampleIdx);
} else if (isBuffer) {
// Nothing else to do for buffers.
} else if (isImage) {
// Nothing else to do for images.
} else {
// 2DMS and buffer have no LOD, but everything else does.
txfetch->getSequence().push_back(lodComponent);
......
......@@ -258,6 +258,13 @@ void HlslScanContext::fillInKeywordMap()
(*KeywordMap)["TextureCubeArray"] = EHTokTextureCubearray;
(*KeywordMap)["Texture2DMS"] = EHTokTexture2DMS;
(*KeywordMap)["Texture2DMSArray"] = EHTokTexture2DMSarray;
(*KeywordMap)["RWTexture1D"] = EHTokRWTexture1d;
(*KeywordMap)["RWTexture1DArray"] = EHTokRWTexture1darray;
(*KeywordMap)["RWTexture2D"] = EHTokRWTexture2d;
(*KeywordMap)["RWTexture2DArray"] = EHTokRWTexture2darray;
(*KeywordMap)["RWTexture3D"] = EHTokRWTexture3d;
(*KeywordMap)["RWBuffer"] = EHTokRWBuffer;
(*KeywordMap)["struct"] = EHTokStruct;
(*KeywordMap)["cbuffer"] = EHTokCBuffer;
......@@ -581,6 +588,12 @@ EHlslTokenClass HlslScanContext::tokenizeIdentifier()
case EHTokTextureCubearray:
case EHTokTexture2DMS:
case EHTokTexture2DMSarray:
case EHTokRWTexture1d:
case EHTokRWTexture1darray:
case EHTokRWTexture2d:
case EHTokRWTexture2darray:
case EHTokRWTexture3d:
case EHTokRWBuffer:
return keyword;
// variable, user type, ...
......
......@@ -209,6 +209,13 @@ enum EHlslTokenClass {
EHTokTextureCubearray,
EHTokTexture2DMS,
EHTokTexture2DMSarray,
EHTokRWTexture1d,
EHTokRWTexture1darray,
EHTokRWTexture2d,
EHTokRWTexture2darray,
EHTokRWTexture3d,
EHTokRWBuffer,
// variable, user type, ...
EHTokIdentifier,
......
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