summaryrefslogtreecommitdiffstats
path: root/tools/render-test
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2017-11-17 21:26:21 -0500
committerTim Foley <tfoleyNV@users.noreply.github.com>2017-11-17 18:26:21 -0800
commit54bf54bd0dda378f8400860b25855558f39cb52b (patch)
tree955931f37df819f3c6e22bc981089f644c1141e1 /tools/render-test
parent0298a0427bbfe19700169c4e239a1b9e91baa410 (diff)
Add support for global generic parameters (#285)
* Add support for global generic parameters (In-progress work) This commit include: 1. Update Slang API to allow specification of generic type arguments in an `EntryPointRequest` 2. Add parsing of `__generic_param` construct, which becomes a GlobalGenericParamDecl, contains members of `GenericTypeConstraintDecl`. 3. Semantics checking will check whether the provided type arguments conform to the interfaces as defined by the generic parameter, and store SubtypeWitness values in the EntryPointRequest, which will be used by `specializeIRForEntryPoint` when generating final IR. 4. Add a new type of substitution - `GlobalGenericParamSubstitution` for subsittuting references to `__generic_param` decls or to its member `GenericTypeConsraintDecl` with the actual type argument or witness tables. 5. Update `IRSpecContext` to apply `GlobalGenericParamSubstitution` when specializing the IR for an EntryPointRequest. 6. Update `render-test` to take additional `type` inputs, which specifies the type arguments to substitute into the global `__generic_param` types. This commit does not include ProgramLayout specialization. * IR: pass through `[unroll]` attribute (#284) The initial lowering was adding an `IRLoopControlDecoration` to the instruction at the head of a loop, but this was getting dropped when the IR gets cloned for a particular entry point. The fix was simply to add a case for loop-control decorations to `cloneDecoration`. * fix warnings * IR: support `CompileTimeForStmt` (#286) This statement type is a bit of a hack, to support loops that *must* be unrolled. The AST-to-AST pass handles them by cloning the AST for the loop body N times, and it was easy enough to do the same thing for the IR: emit the instructions for the body N times. The only thing that requires a bit of care is that now we might see the same variable declarations multiple times, so we need to play it safe and overwrite existing entries in our map from declarations to their IR values. Of course a better answer long-term would be to do the actual unrolling in the IR. This is especially true because we might some day want to support compile-time/must-unroll loops in functions, where the loop counter comes in as a parameter (but must still be compile-time-constant at every call site). * Add support for global generic parameters (In-progress work) This commit include: 1. Update Slang API to allow specification of generic type arguments in an `EntryPointRequest` 2. Add parsing of `__generic_param` construct, which becomes a GlobalGenericParamDecl, contains members of `GenericTypeConstraintDecl`. 3. Semantics checking will check whether the provided type arguments conform to the interfaces as defined by the generic parameter, and store SubtypeWitness values in the EntryPointRequest, which will be used by `specializeIRForEntryPoint` when generating final IR. 4. Add a new type of substitution - `GlobalGenericParamSubstitution` for subsittuting references to `__generic_param` decls or to its member `GenericTypeConsraintDecl` with the actual type argument or witness tables. 5. Update `IRSpecContext` to apply `GlobalGenericParamSubstitution` when specializing the IR for an EntryPointRequest. 6. Update `render-test` to take additional `type` inputs, which specifies the type arguments to substitute into the global `__generic_param` types. progress on parameter binding * Add a more contrived test case for specializing parameter bindings * update render-test to align buffers to 256 bytes (to get rid of D3D complains on minimal buffer size). * adding one more test case for parameter binding specialization. * Cleanup according to @tfoleyNV 's suggestions. * fix a bug introduced in the cleanup
Diffstat (limited to 'tools/render-test')
-rw-r--r--tools/render-test/main.cpp1
-rw-r--r--tools/render-test/render-d3d11.cpp20
-rw-r--r--tools/render-test/render.h1
-rw-r--r--tools/render-test/shader-input-layout.cpp357
-rw-r--r--tools/render-test/shader-input-layout.h1
-rw-r--r--tools/render-test/slang-support.cpp9
6 files changed, 210 insertions, 179 deletions
diff --git a/tools/render-test/main.cpp b/tools/render-test/main.cpp
index cb0eb927d..51a96436f 100644
--- a/tools/render-test/main.cpp
+++ b/tools/render-test/main.cpp
@@ -117,6 +117,7 @@ Error initializeShaders(
compileRequest.computeShader.name = computeEntryPointName;
compileRequest.computeShader.profile = computeProfileName;
}
+ compileRequest.entryPointTypeArguments = gShaderInputLayout.globalTypeArguments;
gShaderProgram = shaderCompiler->compileProgram(compileRequest);
if( !gShaderProgram )
{
diff --git a/tools/render-test/render-d3d11.cpp b/tools/render-test/render-d3d11.cpp
index 9bac24094..cdd6c778e 100644
--- a/tools/render-test/render-d3d11.cpp
+++ b/tools/render-test/render-d3d11.cpp
@@ -455,10 +455,18 @@ public:
ID3D11Buffer * buffer = nullptr;
};
+ UInt RoundUpToAlignment(UInt size, UInt alignment)
+ {
+ if (size % alignment)
+ return (size / alignment + 1) * alignment;
+ else
+ return Math::Max(size, alignment);
+ }
+
virtual Buffer* createBuffer(BufferDesc const& desc) override
{
D3D11_BUFFER_DESC dxBufferDesc = { 0 };
- dxBufferDesc.ByteWidth = (UINT) desc.size;
+ dxBufferDesc.ByteWidth = (UINT)RoundUpToAlignment(desc.size, 256);
switch( desc.flavor )
{
@@ -773,7 +781,11 @@ public:
{
auto dxContext = dxImmediateContext;
D3D11_BUFFER_DESC desc = {0};
- desc.ByteWidth = (UINT)(bufferData.Count() * sizeof(unsigned int));
+ List<unsigned int> newBuffer;
+ desc.ByteWidth = (UINT)RoundUpToAlignment((bufferData.Count() * sizeof(unsigned int)), 256);
+ newBuffer.SetSize(desc.ByteWidth / sizeof(unsigned int));
+ for (UInt i = 0; i < bufferData.Count(); i++)
+ newBuffer[i] = bufferData[i];
if (bufferDesc.type == InputBufferType::ConstantBuffer)
{
desc.Usage = D3D11_USAGE_DEFAULT;
@@ -794,7 +806,7 @@ public:
}
}
D3D11_SUBRESOURCE_DATA data = {0};
- data.pSysMem = bufferData.Buffer();
+ data.pSysMem = newBuffer.Buffer();
dxDevice->CreateBuffer(&desc, &data, &bufferOut);
int elemSize = bufferDesc.stride <= 0 ? 1 : bufferDesc.stride;
if (bufferDesc.type == InputBufferType::StorageBuffer)
@@ -1091,7 +1103,7 @@ public:
D3D11_BUFFER_DESC bufDesc;
memset(&bufDesc, 0, sizeof(bufDesc));
bufDesc.BindFlags = 0;
- bufDesc.ByteWidth = binding.bufferLength;
+ bufDesc.ByteWidth = (UINT)RoundUpToAlignment(binding.bufferLength, 256);
bufDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
bufDesc.Usage = D3D11_USAGE_STAGING;
dxDevice->CreateBuffer(&bufDesc, nullptr, &stageBuf);
diff --git a/tools/render-test/render.h b/tools/render-test/render.h
index dec48cda4..174ba0b7b 100644
--- a/tools/render-test/render.h
+++ b/tools/render-test/render.h
@@ -31,6 +31,7 @@ struct ShaderCompileRequest
EntryPoint vertexShader;
EntryPoint fragmentShader;
EntryPoint computeShader;
+ Slang::List<Slang::String> entryPointTypeArguments;
};
class ShaderCompiler
diff --git a/tools/render-test/shader-input-layout.cpp b/tools/render-test/shader-input-layout.cpp
index ef78fe3d5..01328eabd 100644
--- a/tools/render-test/shader-input-layout.cpp
+++ b/tools/render-test/shader-input-layout.cpp
@@ -7,6 +7,7 @@ namespace renderer_test
void ShaderInputLayout::Parse(const char * source)
{
entries.Clear();
+ globalTypeArguments.Clear();
auto lines = Split(source, '\n');
for (auto & line : lines)
{
@@ -16,200 +17,208 @@ namespace renderer_test
TokenReader parser(lineContent);
try
{
- ShaderInputLayoutEntry entry;
-
- if (parser.LookAhead("cbuffer"))
- {
- entry.type = ShaderInputType::Buffer;
- entry.bufferDesc.type = InputBufferType::ConstantBuffer;
- }
- else if (parser.LookAhead("ubuffer"))
- {
- entry.type = ShaderInputType::Buffer;
- entry.bufferDesc.type = InputBufferType::StorageBuffer;
- }
- else if (parser.LookAhead("Texture1D"))
- {
- entry.type = ShaderInputType::Texture;
- entry.textureDesc.dimension = 1;
- }
- else if (parser.LookAhead("Texture2D"))
- {
- entry.type = ShaderInputType::Texture;
- entry.textureDesc.dimension = 2;
- }
- else if (parser.LookAhead("Texture3D"))
- {
- entry.type = ShaderInputType::Texture;
- entry.textureDesc.dimension = 3;
- }
- else if (parser.LookAhead("TextureCube"))
- {
- entry.type = ShaderInputType::Texture;
- entry.textureDesc.dimension = 2;
- entry.textureDesc.isCube = true;
- }
- else if (parser.LookAhead("RWTexture1D"))
- {
- entry.type = ShaderInputType::Texture;
- entry.textureDesc.dimension = 1;
- entry.textureDesc.isRWTexture = true;
- }
- else if (parser.LookAhead("RWTexture2D"))
- {
- entry.type = ShaderInputType::Texture;
- entry.textureDesc.dimension = 2;
- entry.textureDesc.isRWTexture = true;
- }
- else if (parser.LookAhead("RWTexture3D"))
- {
- entry.type = ShaderInputType::Texture;
- entry.textureDesc.dimension = 3;
- entry.textureDesc.isRWTexture = true;
- }
- else if (parser.LookAhead("RWTextureCube"))
- {
- entry.type = ShaderInputType::Texture;
- entry.textureDesc.dimension = 2;
- entry.textureDesc.isCube = true;
- entry.textureDesc.isRWTexture = true;
- }
- else if (parser.LookAhead("Sampler"))
- {
- entry.type = ShaderInputType::Sampler;
- }
- else if (parser.LookAhead("Sampler1D"))
- {
- entry.type = ShaderInputType::CombinedTextureSampler;
- entry.textureDesc.dimension = 1;
- }
- else if (parser.LookAhead("Sampler2D"))
- {
- entry.type = ShaderInputType::CombinedTextureSampler;
- entry.textureDesc.dimension = 2;
- }
- else if (parser.LookAhead("Sampler3D"))
- {
- entry.type = ShaderInputType::CombinedTextureSampler;
- entry.textureDesc.dimension = 3;
- }
- else if (parser.LookAhead("SamplerCube"))
+ if (parser.LookAhead("type"))
{
- entry.type = ShaderInputType::CombinedTextureSampler;
- entry.textureDesc.dimension = 2;
- entry.textureDesc.isCube = true;
+ parser.ReadToken();
+ globalTypeArguments.Add(parser.ReadWord());
}
- else if (parser.LookAhead("render_targets"))
+ else
{
- numRenderTargets = parser.ReadInt();
- continue;
- }
- parser.ReadToken();
- // parse options
- if (parser.LookAhead("("))
- {
- parser.Read("(");
- while (!parser.IsEnd() && !parser.LookAhead(")"))
+ ShaderInputLayoutEntry entry;
+
+ if (parser.LookAhead("cbuffer"))
{
- auto word = parser.ReadWord();
- if (word == "depth")
- {
- entry.textureDesc.isDepthTexture = true;
- }
- else if (word == "depthCompare")
- {
- entry.samplerDesc.isCompareSampler = true;
- }
- else if (word == "arrayLength")
- {
- parser.Read("=");
- entry.textureDesc.arrayLength = parser.ReadInt();
- }
- else if (word == "stride")
- {
- parser.Read("=");
- entry.bufferDesc.stride = parser.ReadInt();
- }
- else if (word == "size")
- {
- parser.Read("=");
- entry.textureDesc.size = parser.ReadInt();
- }
- else if (word == "data")
+ entry.type = ShaderInputType::Buffer;
+ entry.bufferDesc.type = InputBufferType::ConstantBuffer;
+ }
+ else if (parser.LookAhead("ubuffer"))
+ {
+ entry.type = ShaderInputType::Buffer;
+ entry.bufferDesc.type = InputBufferType::StorageBuffer;
+ }
+ else if (parser.LookAhead("Texture1D"))
+ {
+ entry.type = ShaderInputType::Texture;
+ entry.textureDesc.dimension = 1;
+ }
+ else if (parser.LookAhead("Texture2D"))
+ {
+ entry.type = ShaderInputType::Texture;
+ entry.textureDesc.dimension = 2;
+ }
+ else if (parser.LookAhead("Texture3D"))
+ {
+ entry.type = ShaderInputType::Texture;
+ entry.textureDesc.dimension = 3;
+ }
+ else if (parser.LookAhead("TextureCube"))
+ {
+ entry.type = ShaderInputType::Texture;
+ entry.textureDesc.dimension = 2;
+ entry.textureDesc.isCube = true;
+ }
+ else if (parser.LookAhead("RWTexture1D"))
+ {
+ entry.type = ShaderInputType::Texture;
+ entry.textureDesc.dimension = 1;
+ entry.textureDesc.isRWTexture = true;
+ }
+ else if (parser.LookAhead("RWTexture2D"))
+ {
+ entry.type = ShaderInputType::Texture;
+ entry.textureDesc.dimension = 2;
+ entry.textureDesc.isRWTexture = true;
+ }
+ else if (parser.LookAhead("RWTexture3D"))
+ {
+ entry.type = ShaderInputType::Texture;
+ entry.textureDesc.dimension = 3;
+ entry.textureDesc.isRWTexture = true;
+ }
+ else if (parser.LookAhead("RWTextureCube"))
+ {
+ entry.type = ShaderInputType::Texture;
+ entry.textureDesc.dimension = 2;
+ entry.textureDesc.isCube = true;
+ entry.textureDesc.isRWTexture = true;
+ }
+ else if (parser.LookAhead("Sampler"))
+ {
+ entry.type = ShaderInputType::Sampler;
+ }
+ else if (parser.LookAhead("Sampler1D"))
+ {
+ entry.type = ShaderInputType::CombinedTextureSampler;
+ entry.textureDesc.dimension = 1;
+ }
+ else if (parser.LookAhead("Sampler2D"))
+ {
+ entry.type = ShaderInputType::CombinedTextureSampler;
+ entry.textureDesc.dimension = 2;
+ }
+ else if (parser.LookAhead("Sampler3D"))
+ {
+ entry.type = ShaderInputType::CombinedTextureSampler;
+ entry.textureDesc.dimension = 3;
+ }
+ else if (parser.LookAhead("SamplerCube"))
+ {
+ entry.type = ShaderInputType::CombinedTextureSampler;
+ entry.textureDesc.dimension = 2;
+ entry.textureDesc.isCube = true;
+ }
+ else if (parser.LookAhead("render_targets"))
+ {
+ numRenderTargets = parser.ReadInt();
+ continue;
+ }
+ parser.ReadToken();
+ // parse options
+ if (parser.LookAhead("("))
+ {
+ parser.Read("(");
+ while (!parser.IsEnd() && !parser.LookAhead(")"))
{
- parser.Read("=");
- parser.Read("[");
- while (!parser.IsEnd() && !parser.LookAhead("]"))
+ auto word = parser.ReadWord();
+ if (word == "depth")
+ {
+ entry.textureDesc.isDepthTexture = true;
+ }
+ else if (word == "depthCompare")
+ {
+ entry.samplerDesc.isCompareSampler = true;
+ }
+ else if (word == "arrayLength")
{
- if (parser.NextToken().Type == TokenType::IntLiteral)
+ parser.Read("=");
+ entry.textureDesc.arrayLength = parser.ReadInt();
+ }
+ else if (word == "stride")
+ {
+ parser.Read("=");
+ entry.bufferDesc.stride = parser.ReadInt();
+ }
+ else if (word == "size")
+ {
+ parser.Read("=");
+ entry.textureDesc.size = parser.ReadInt();
+ }
+ else if (word == "data")
+ {
+ parser.Read("=");
+ parser.Read("[");
+ while (!parser.IsEnd() && !parser.LookAhead("]"))
{
- entry.bufferData.Add(parser.ReadUInt());
+ if (parser.NextToken().Type == TokenType::IntLiteral)
+ {
+ entry.bufferData.Add(parser.ReadUInt());
+ }
+ else
+ {
+ auto floatNum = parser.ReadFloat();
+ entry.bufferData.Add(*(unsigned int*)&floatNum);
+ }
}
+ parser.Read("]");
+ }
+ else if (word == "content")
+ {
+ parser.Read("=");
+ auto contentWord = parser.ReadWord();
+ if (contentWord == "zero")
+ entry.textureDesc.content = InputTextureContent::Zero;
+ else if (contentWord == "one")
+ entry.textureDesc.content = InputTextureContent::One;
+ else if (contentWord == "chessboard")
+ entry.textureDesc.content = InputTextureContent::ChessBoard;
else
- {
- auto floatNum = parser.ReadFloat();
- entry.bufferData.Add(*(unsigned int*)&floatNum);
- }
+ entry.textureDesc.content = InputTextureContent::Gradient;
}
- parser.Read("]");
- }
- else if (word == "content")
- {
- parser.Read("=");
- auto contentWord = parser.ReadWord();
- if (contentWord == "zero")
- entry.textureDesc.content = InputTextureContent::Zero;
- else if (contentWord == "one")
- entry.textureDesc.content = InputTextureContent::One;
- else if (contentWord == "chessboard")
- entry.textureDesc.content = InputTextureContent::ChessBoard;
+ if (parser.LookAhead(","))
+ parser.Read(",");
else
- entry.textureDesc.content = InputTextureContent::Gradient;
+ break;
}
- if (parser.LookAhead(","))
- parser.Read(",");
- else
- break;
+ parser.Read(")");
}
- parser.Read(")");
- }
- // parse bindings
- if (parser.LookAhead(":"))
- {
- parser.Read(":");
- while (!parser.IsEnd())
+ // parse bindings
+ if (parser.LookAhead(":"))
{
- if (parser.LookAhead("dxbinding"))
- {
- parser.ReadToken();
- parser.Read("(");
- entry.hlslBinding = parser.ReadInt();
- parser.Read(")");
- }
- else if (parser.LookAhead("glbinding"))
+ parser.Read(":");
+ while (!parser.IsEnd())
{
- parser.ReadToken();
- parser.Read("(");
- while (!parser.IsEnd() && !parser.LookAhead(")"))
+ if (parser.LookAhead("dxbinding"))
{
- entry.glslBinding.Add(parser.ReadInt());
- if (parser.LookAhead(","))
- parser.Read(",");
- else
- break;
+ parser.ReadToken();
+ parser.Read("(");
+ entry.hlslBinding = parser.ReadInt();
+ parser.Read(")");
}
- parser.Read(")");
- }
- else if (parser.LookAhead("out"))
- {
- parser.ReadToken();
- entry.isOutput = true;
+ else if (parser.LookAhead("glbinding"))
+ {
+ parser.ReadToken();
+ parser.Read("(");
+ while (!parser.IsEnd() && !parser.LookAhead(")"))
+ {
+ entry.glslBinding.Add(parser.ReadInt());
+ if (parser.LookAhead(","))
+ parser.Read(",");
+ else
+ break;
+ }
+ parser.Read(")");
+ }
+ else if (parser.LookAhead("out"))
+ {
+ parser.ReadToken();
+ entry.isOutput = true;
+ }
+ if (parser.LookAhead(","))
+ parser.Read(",");
}
- if (parser.LookAhead(","))
- parser.Read(",");
}
+ entries.Add(entry);
}
- entries.Add(entry);
}
catch (TextFormatException)
{
diff --git a/tools/render-test/shader-input-layout.h b/tools/render-test/shader-input-layout.h
index 9602e4fe8..c4c3d9d8c 100644
--- a/tools/render-test/shader-input-layout.h
+++ b/tools/render-test/shader-input-layout.h
@@ -63,6 +63,7 @@ namespace renderer_test
{
public:
Slang::List<ShaderInputLayoutEntry> entries;
+ Slang::List<Slang::String> globalTypeArguments;
int numRenderTargets = 1;
void Parse(const char * source);
};
diff --git a/tools/render-test/slang-support.cpp b/tools/render-test/slang-support.cpp
index 63e24126c..746967cb7 100644
--- a/tools/render-test/slang-support.cpp
+++ b/tools/render-test/slang-support.cpp
@@ -84,7 +84,14 @@ struct SlangShaderCompilerWrapper : public ShaderCompiler
ShaderProgram * result = nullptr;
if (request.computeShader.name)
{
- int computeEntryPoint = spAddEntryPoint(slangRequest, computeTranslationUnit, computeEntryPointName, spFindProfile(slangSession, request.computeShader.profile));
+ Slang::List<const char*> rawTypeNames;
+ for (auto typeName : request.entryPointTypeArguments)
+ rawTypeNames.Add(typeName.Buffer());
+ int computeEntryPoint = spAddEntryPointEx(slangRequest, computeTranslationUnit,
+ computeEntryPointName,
+ spFindProfile(slangSession, request.computeShader.profile),
+ (int)rawTypeNames.Count(),
+ rawTypeNames.Buffer());
int compileErr = spCompile(slangRequest);
if (auto diagnostics = spGetDiagnosticOutput(slangRequest))
{