summaryrefslogtreecommitdiffstats
path: root/tools/render-test
diff options
context:
space:
mode:
authorYONGH\yongh <yonghe@outlook.com>2017-10-19 18:18:21 -0400
committerYONGH\yongh <yonghe@outlook.com>2017-10-19 18:18:21 -0400
commit8ff7412f988c77f21196b907820b94aa67eb6f21 (patch)
tree27bea95dec68c42e5d3dd924da0cd8fa74f0d9e4 /tools/render-test
parent88023aea669f258d66e53eab10215337a7f72853 (diff)
Support running and comparing execution results of compute shaders in testing framework.
Diffstat (limited to 'tools/render-test')
-rw-r--r--tools/render-test/main.cpp140
-rw-r--r--tools/render-test/options.cpp8
-rw-r--r--tools/render-test/options.h7
-rw-r--r--tools/render-test/render-d3d11.cpp129
-rw-r--r--tools/render-test/render-gl.cpp68
-rw-r--r--tools/render-test/render.h16
-rw-r--r--tools/render-test/slang-support.cpp198
7 files changed, 381 insertions, 185 deletions
diff --git a/tools/render-test/main.cpp b/tools/render-test/main.cpp
index f2688d275..6907ba40f 100644
--- a/tools/render-test/main.cpp
+++ b/tools/render-test/main.cpp
@@ -49,21 +49,24 @@ static const Vertex kVertexData[kVertexCount] = {
// Global variables for state to be used for rendering...
-uintptr_t gConstantBufferSize;
+uintptr_t gConstantBufferSize, gComputeResultBufferSize;
Buffer* gConstantBuffer;
InputLayout* gInputLayout;
Buffer* gVertexBuffer;
+Buffer* gComputeResultBuffer;
ShaderProgram* gShaderProgram;
// Entry point name to use for vertex/fragment shader
static char const* vertexEntryPointName = "vertexMain";
static char const* fragmentEntryPointName = "fragmentMain";
+static char const* computeEntryPointName = "computeMain";
// "Profile" to use when compiling for HLSL targets
// TODO: does this belong here?
static char const* vertexProfileName = "vs_4_0";
static char const* fragmentProfileName = "ps_4_0";
+static char const* computeProfileName = "cs_4_0";
Error initializeShaders(
ShaderCompiler* shaderCompiler)
@@ -95,13 +98,21 @@ Error initializeShaders(
ShaderCompileRequest compileRequest;
compileRequest.source = sourceInfo;
- compileRequest.vertexShader.source = sourceInfo;
- compileRequest.vertexShader.name = vertexEntryPointName;
- compileRequest.vertexShader.profile = vertexProfileName;
- compileRequest.fragmentShader.source = sourceInfo;
- compileRequest.fragmentShader.name = fragmentEntryPointName;
- compileRequest.fragmentShader.profile = fragmentProfileName;
-
+ if (gOptions.shaderType == ShaderProgramType::Graphics)
+ {
+ compileRequest.vertexShader.source = sourceInfo;
+ compileRequest.vertexShader.name = vertexEntryPointName;
+ compileRequest.vertexShader.profile = vertexProfileName;
+ compileRequest.fragmentShader.source = sourceInfo;
+ compileRequest.fragmentShader.name = fragmentEntryPointName;
+ compileRequest.fragmentShader.profile = fragmentProfileName;
+ }
+ else
+ {
+ compileRequest.computeShader.source = sourceInfo;
+ compileRequest.computeShader.name = computeEntryPointName;
+ compileRequest.computeShader.profile = computeProfileName;
+ }
gShaderProgram = shaderCompiler->compileProgram(compileRequest);
if( !gShaderProgram )
{
@@ -111,6 +122,15 @@ Error initializeShaders(
return Error::None;
}
+void outputComputeResult(Renderer* renderer, const char * fileName)
+{
+ float* data = (float*)renderer->map(gComputeResultBuffer, MapFlavor::HostRead);
+ FILE* f = fopen(fileName, "wt");
+ for (auto i = 0u; i < gComputeResultBufferSize / sizeof(UInt); i++)
+ fprintf(f, "%.9g\n", data[i]);
+ fclose(f);
+}
+
//
// At initialization time, we are going to load and compile our Slang shader
// code, and then create the D3D11 API objects we need for rendering.
@@ -138,6 +158,19 @@ Error initializeInner(
if(!gConstantBuffer)
return Error::Unexpected;
+ gComputeResultBufferSize = 512 * sizeof(float);
+ BufferDesc computeResultBufferDesc;
+ computeResultBufferDesc.size = gComputeResultBufferSize;
+ computeResultBufferDesc.flavor = BufferFlavor::Storage;
+ gComputeResultBuffer = renderer->createBuffer(computeResultBufferDesc);
+ if (!gComputeResultBufferSize)
+ return Error::Unexpected;
+ // initialize buffer to 0
+ char * ptr = (char*)renderer->map(gComputeResultBuffer, MapFlavor::HostWrite);
+ for (auto i = 0u; i < gComputeResultBufferSize; i++)
+ ptr[i] = 0;
+ renderer->unmap(gComputeResultBuffer);
+
// Input Assembler (IA)
InputElementDesc inputElements[] = {
@@ -195,6 +228,13 @@ void renderFrameInner(
renderer->draw(3);
}
+void runCompute(Renderer * renderer)
+{
+ renderer->setShaderProgram(gShaderProgram);
+ renderer->setStorageBuffer(0, gComputeResultBuffer);
+ renderer->dispatchCompute(1, 1, 1);
+}
+
void finalize()
{
}
@@ -352,44 +392,52 @@ int main(
// Once initialization is all complete, we show the window...
ShowWindow(windowHandle, showCommand);
-
- // ... and enter the event loop:
- for(;;)
- {
- MSG message;
-
- int result = PeekMessageW(&message, NULL, 0, 0, PM_REMOVE);
- if (result != 0)
- {
- if (message.message == WM_QUIT)
- {
- return (int)message.wParam;
- }
-
- TranslateMessage(&message);
- DispatchMessageW(&message);
- }
- else
- {
- // Whenver we don't have Windows events to process,
- // we render a frame.
-
- static const float kClearColor[] = { 0.25, 0.25, 0.25, 1.0 };
- renderer->setClearColor(kClearColor);
- renderer->clearFrame();
-
- renderFrameInner(renderer);
-
- // If we are in a mode where output is requested, we need to snapshot the back buffer here
- if( gOptions.outputPath )
- {
- renderer->captureScreenShot(gOptions.outputPath);
- return 0;
- }
-
- renderer->presentFrame();
- }
- }
+
+ // ... and enter the event loop:
+ for (;;)
+ {
+ MSG message;
+
+ int result = PeekMessageW(&message, NULL, 0, 0, PM_REMOVE);
+ if (result != 0)
+ {
+ if (message.message == WM_QUIT)
+ {
+ return (int)message.wParam;
+ }
+
+ TranslateMessage(&message);
+ DispatchMessageW(&message);
+ }
+ else
+ {
+ // Whenver we don't have Windows events to process,
+ // we render a frame.
+ static const float kClearColor[] = { 0.25, 0.25, 0.25, 1.0 };
+ renderer->setClearColor(kClearColor);
+ renderer->clearFrame();
+
+ if (gOptions.shaderType == ShaderProgramType::Compute)
+ {
+ runCompute(renderer);
+ }
+ else
+ {
+ renderFrameInner(renderer);
+ }
+ // If we are in a mode where output is requested, we need to snapshot the back buffer here
+ if (gOptions.outputPath)
+ {
+ if (gOptions.shaderType == ShaderProgramType::Compute)
+ outputComputeResult(renderer, gOptions.outputPath);
+ else
+ renderer->captureScreenShot(gOptions.outputPath);
+ return 0;
+ }
+
+ renderer->presentFrame();
+ }
+ }
return 0;
}
diff --git a/tools/render-test/options.cpp b/tools/render-test/options.cpp
index 53f88b7a9..89a68b27f 100644
--- a/tools/render-test/options.cpp
+++ b/tools/render-test/options.cpp
@@ -92,6 +92,14 @@ void parseOptions(int* argc, char** argv)
}
gOptions.slangArgs[gOptions.slangArgCount++] = *argCursor++;
}
+ else if (strcmp(arg, "-compute") == 0)
+ {
+ gOptions.shaderType = ShaderProgramType::Compute;
+ }
+ else if (strcmp(arg, "-graphics") == 0)
+ {
+ gOptions.shaderType = ShaderProgramType::Graphics;
+ }
else
{
fprintf(stderr, "unknown option '%s'\n", arg);
diff --git a/tools/render-test/options.h b/tools/render-test/options.h
index fbc615d56..a36e0a809 100644
--- a/tools/render-test/options.h
+++ b/tools/render-test/options.h
@@ -31,11 +31,18 @@ enum
kMaxSlangArgs = 16,
};
+enum class ShaderProgramType
+{
+ Graphics,
+ Compute
+};
+
struct Options
{
char const* appName = "render-test";
char const* sourcePath = nullptr;
char const* outputPath = nullptr;
+ ShaderProgramType shaderType = ShaderProgramType::Graphics;
Mode mode = Mode::Slang;
char const* slangArgs[kMaxSlangArgs];
diff --git a/tools/render-test/render-d3d11.cpp b/tools/render-test/render-d3d11.cpp
index bc86809e6..6e9e04a78 100644
--- a/tools/render-test/render-d3d11.cpp
+++ b/tools/render-test/render-d3d11.cpp
@@ -1,4 +1,4 @@
-// render-d3d11.cpp
+// render-d3d11.cpp
#include "render-d3d11.h"
#include "options.h"
@@ -418,6 +418,12 @@ public:
return this;
}
+ struct D3DBuffer
+ {
+ ID3D11UnorderedAccessView * view = nullptr;
+ ID3D11Buffer * buffer = nullptr;
+ };
+
virtual Buffer* createBuffer(BufferDesc const& desc) override
{
D3D11_BUFFER_DESC dxBufferDesc = { 0 };
@@ -437,6 +443,14 @@ public:
dxBufferDesc.CPUAccessFlags = 0;
break;
+ case BufferFlavor::Storage:
+ dxBufferDesc.Usage = D3D11_USAGE_DEFAULT;
+ dxBufferDesc.BindFlags = D3D11_BIND_UNORDERED_ACCESS;
+ dxBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
+ dxBufferDesc.StructureByteStride = sizeof(float);
+ dxBufferDesc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED;
+ break;
+
default:
return nullptr;
}
@@ -452,7 +466,20 @@ public:
&dxBuffer);
if(FAILED(hr)) return nullptr;
- return (Buffer*) dxBuffer;
+ D3DBuffer * rs = new D3DBuffer();
+ rs->buffer = dxBuffer;
+ if (desc.flavor == BufferFlavor::Storage)
+ {
+ D3D11_UNORDERED_ACCESS_VIEW_DESC viewDesc;
+ memset(&viewDesc, 0, sizeof(viewDesc));
+ viewDesc.Buffer.FirstElement = 0;
+ viewDesc.Buffer.NumElements = 512;
+ viewDesc.Buffer.Flags = 0;
+ viewDesc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
+ viewDesc.Format = DXGI_FORMAT_UNKNOWN;
+ dxDevice->CreateUnorderedAccessView(dxBuffer, &viewDesc, &rs->view);
+ }
+ return (Buffer*) rs;
}
static DXGI_FORMAT mapFormat(Format format)
@@ -535,7 +562,7 @@ public:
{
auto dxContext = dxImmediateContext;
- auto dxBuffer = (ID3D11Buffer*) buffer;
+ auto dxBuffer = ((D3DBuffer*)buffer)->buffer;
D3D11_MAP dxMapFlavor;
switch( flavor )
@@ -543,7 +570,12 @@ public:
case MapFlavor::WriteDiscard:
dxMapFlavor = D3D11_MAP_WRITE_DISCARD;
break;
-
+ case MapFlavor::HostWrite:
+ dxMapFlavor = D3D11_MAP_WRITE;
+ break;
+ case MapFlavor::HostRead:
+ dxMapFlavor = D3D11_MAP_READ;
+ break;
default:
return nullptr;
}
@@ -563,7 +595,7 @@ public:
{
auto dxContext = dxImmediateContext;
- auto dxBuffer = (ID3D11Buffer*) buffer;
+ auto dxBuffer = ((D3DBuffer*)buffer)->buffer;
dxContext->Unmap(dxBuffer, 0);
}
@@ -609,11 +641,11 @@ public:
dxVertexOffsets[ii] = (UINT) offsets[ii];
}
- auto dxVertexBuffers = (ID3D11Buffer* const*) buffers;
+ auto dxVertexBuffers = (D3DBuffer* const*) buffers;
dxContext->IASetVertexBuffers(
(UINT) startSlot,
- (UINT) slotCount, &dxVertexBuffers[0], &dxVertexStrides[0], &dxVertexOffsets[0]);
+ (UINT) slotCount, &(dxVertexBuffers[0])->buffer, &dxVertexStrides[0], &dxVertexOffsets[0]);
}
virtual void setShaderProgram(ShaderProgram* inProgram) override
@@ -621,7 +653,7 @@ public:
auto dxContext = dxImmediateContext;
auto program = (D3D11ShaderProgram*) inProgram;
-
+ dxContext->CSSetShader(program->dxComputeShader, NULL, 0);
dxContext->VSSetShader(program->dxVertexShader, NULL, 0);
dxContext->PSSetShader(program->dxPixelShader, NULL, 0);
}
@@ -632,14 +664,24 @@ public:
// TODO: actually use those offsets
- auto dxConstantBuffers = (ID3D11Buffer* const*) buffers;
-
+ auto dxConstantBuffers = (D3DBuffer* const*) buffers;
dxContext->VSSetConstantBuffers(
- (UINT) startSlot, (UINT) slotCount, &dxConstantBuffers[0]);
+ (UINT) startSlot, (UINT) slotCount, &dxConstantBuffers[0]->buffer);
dxContext->VSSetConstantBuffers(
- (UINT) startSlot, (UINT) slotCount, &dxConstantBuffers[0]);
+ (UINT) startSlot, (UINT) slotCount, &dxConstantBuffers[0]->buffer);
}
+ virtual void setStorageBuffers(UInt startSlot, UInt slotCount, Buffer* const* buffers, UInt const* offsets) override
+ {
+ auto dxContext = dxImmediateContext;
+
+ // TODO: actually use those offsets
+
+ auto dxStorageBuffers = (D3DBuffer* const*)buffers;
+ dxContext->CSSetUnorderedAccessViews(
+ (UINT)startSlot, (UINT)slotCount, &dxStorageBuffers[0]->view, 0);
+ }
+
virtual void draw(UInt vertexCount, UInt startVertex) override
{
@@ -653,35 +695,62 @@ public:
struct D3D11ShaderProgram
{
- ID3D11VertexShader* dxVertexShader;
- ID3D11PixelShader* dxPixelShader;
+ ID3D11VertexShader* dxVertexShader = nullptr;
+ ID3D11PixelShader* dxPixelShader = nullptr;
+ ID3D11ComputeShader* dxComputeShader = nullptr;
};
virtual ShaderProgram* compileProgram(ShaderCompileRequest const& request) override
{
- auto dxVertexShaderBlob = compileHLSLShader(request.vertexShader.source.path, request.vertexShader.source.text, request.vertexShader .name, request.vertexShader .profile);
- if(!dxVertexShaderBlob) return nullptr;
+ if (request.computeShader.name)
+ {
+ auto dxComputeShaderBlob = compileHLSLShader(request.computeShader.source.path, request.computeShader.source.text, request.computeShader.name, request.computeShader.profile);
+ if (!dxComputeShaderBlob) return nullptr;
+
+ ID3D11ComputeShader* dxComputeShader;
+
+ HRESULT csResult = dxDevice->CreateComputeShader(dxComputeShaderBlob->GetBufferPointer(), dxComputeShaderBlob->GetBufferSize(), nullptr, &dxComputeShader);
+
+ dxComputeShaderBlob->Release();
- auto dxFragmentShaderBlob = compileHLSLShader(request.fragmentShader.source.path, request.fragmentShader.source.text, request.fragmentShader .name, request.fragmentShader .profile);
- if(!dxFragmentShaderBlob) return nullptr;
+ if (FAILED(csResult)) return nullptr;
- ID3D11VertexShader* dxVertexShader;
- ID3D11PixelShader* dxPixelShader;
+ D3D11ShaderProgram* shaderProgram = new D3D11ShaderProgram();
+ shaderProgram->dxComputeShader = dxComputeShader;
+ return (ShaderProgram*)shaderProgram;
+ }
+ else
+ {
+ auto dxVertexShaderBlob = compileHLSLShader(request.vertexShader.source.path, request.vertexShader.source.text, request.vertexShader.name, request.vertexShader.profile);
+ if (!dxVertexShaderBlob) return nullptr;
- HRESULT vsResult = dxDevice->CreateVertexShader( dxVertexShaderBlob ->GetBufferPointer(), dxVertexShaderBlob ->GetBufferSize(), nullptr, &dxVertexShader);
- HRESULT psResult = dxDevice->CreatePixelShader( dxFragmentShaderBlob->GetBufferPointer(), dxFragmentShaderBlob->GetBufferSize(), nullptr, &dxPixelShader);
+ auto dxFragmentShaderBlob = compileHLSLShader(request.fragmentShader.source.path, request.fragmentShader.source.text, request.fragmentShader.name, request.fragmentShader.profile);
+ if (!dxFragmentShaderBlob) return nullptr;
- dxVertexShaderBlob ->Release();
- dxFragmentShaderBlob->Release();
+ ID3D11VertexShader* dxVertexShader;
+ ID3D11PixelShader* dxPixelShader;
- if(FAILED(vsResult)) return nullptr;
- if(FAILED(psResult)) return nullptr;
+ HRESULT vsResult = dxDevice->CreateVertexShader(dxVertexShaderBlob->GetBufferPointer(), dxVertexShaderBlob->GetBufferSize(), nullptr, &dxVertexShader);
+ HRESULT psResult = dxDevice->CreatePixelShader(dxFragmentShaderBlob->GetBufferPointer(), dxFragmentShaderBlob->GetBufferSize(), nullptr, &dxPixelShader);
- D3D11ShaderProgram* shaderProgram = new D3D11ShaderProgram();
- shaderProgram->dxVertexShader = dxVertexShader;
- shaderProgram->dxPixelShader = dxPixelShader;
- return (ShaderProgram*) shaderProgram;
+ dxVertexShaderBlob->Release();
+ dxFragmentShaderBlob->Release();
+
+ if (FAILED(vsResult)) return nullptr;
+ if (FAILED(psResult)) return nullptr;
+
+ D3D11ShaderProgram* shaderProgram = new D3D11ShaderProgram();
+ shaderProgram->dxVertexShader = dxVertexShader;
+ shaderProgram->dxPixelShader = dxPixelShader;
+ return (ShaderProgram*)shaderProgram;
+ }
}
+
+ virtual void dispatchCompute(int x, int y, int z) override
+ {
+ auto dxContext = dxImmediateContext;
+ dxContext->Dispatch(x, y, z);
+ }
};
diff --git a/tools/render-test/render-gl.cpp b/tools/render-test/render-gl.cpp
index f02ac36c4..55647fb25 100644
--- a/tools/render-test/render-gl.cpp
+++ b/tools/render-test/render-gl.cpp
@@ -58,6 +58,7 @@
F(glEnableVertexAttribArray, PFNGLENABLEVERTEXATTRIBARRAYPROC) \
F(glDisableVertexAttribArray, PFNGLDISABLEVERTEXATTRIBARRAYPROC) \
F(glDebugMessageCallback, PFNGLDEBUGMESSAGECALLBACKPROC) \
+ F(glDispatchCompute, PFNGLDISPATCHCOMPUTEPROC) \
/* end */
namespace renderer_test {
@@ -311,8 +312,12 @@ public:
switch (flavor)
{
case MapFlavor::WriteDiscard:
+ case MapFlavor::HostWrite:
access = GL_WRITE_ONLY;
break;
+ case MapFlavor::HostRead:
+ access = GL_READ_ONLY;
+ break;
}
auto bufferID = (GLuint)(uintptr_t)buffer;
@@ -377,21 +382,32 @@ public:
glUseProgram(programID);
}
- virtual void setConstantBuffers(UInt startSlot, UInt slotCount, Buffer* const* buffers, UInt const* offsets) override
- {
- for (UInt ii = 0; ii < slotCount; ++ii)
- {
- UInt slot = startSlot + ii;
+ void bindBufferImpl(int target, UInt startSlot, UInt slotCount, Buffer* const* buffers, UInt const* offsets)
+ {
+ for (UInt ii = 0; ii < slotCount; ++ii)
+ {
+ UInt slot = startSlot + ii;
- Buffer* buffer = buffers[ii];
- GLuint bufferID = (GLuint)(uintptr_t)buffer;
+ Buffer* buffer = buffers[ii];
+ GLuint bufferID = (GLuint)(uintptr_t)buffer;
- assert(!offsets || !offsets[ii]);
+ assert(!offsets || !offsets[ii]);
- glBindBufferBase(GL_UNIFORM_BUFFER, (GLuint) slot, bufferID);
- }
+ glBindBufferBase(target, (GLuint)slot, bufferID);
+ }
+ }
+
+ virtual void setConstantBuffers(UInt startSlot, UInt slotCount, Buffer* const* buffers, UInt const* offsets) override
+ {
+ bindBufferImpl(GL_UNIFORM_BUFFER, startSlot, slotCount, buffers, offsets);
}
+
+ virtual void setStorageBuffers(UInt startSlot, UInt slotCount, Buffer* const* buffers, UInt const* offsets) override
+ {
+ bindBufferImpl(GL_SHADER_STORAGE_BUFFER, startSlot, slotCount, buffers, offsets);
+ }
+
void flushStateForDraw()
{
auto layout = this->boundInputLayout;
@@ -432,18 +448,31 @@ public:
virtual ShaderProgram* compileProgram(ShaderCompileRequest const& request) override
{
auto programID = glCreateProgram();
+ if (request.computeShader.name)
+ {
+ auto computeShaderID = loadShader(GL_COMPUTE_SHADER, request.computeShader.source.text);
- auto vertexShaderID = loadShader(GL_VERTEX_SHADER, request.vertexShader .source.text);
- auto fragmentShaderID = loadShader(GL_FRAGMENT_SHADER, request.fragmentShader.source.text);
+ glAttachShader(programID, computeShaderID);
- glAttachShader(programID, vertexShaderID);
- glAttachShader(programID, fragmentShaderID);
- glLinkProgram(programID);
+ glLinkProgram(programID);
- glDeleteShader(vertexShaderID);
- glDeleteShader(fragmentShaderID);
+ glDeleteShader(computeShaderID);
+ }
+ else
+ {
+ auto vertexShaderID = loadShader(GL_VERTEX_SHADER, request.vertexShader.source.text);
+ auto fragmentShaderID = loadShader(GL_FRAGMENT_SHADER, request.fragmentShader.source.text);
+ glAttachShader(programID, vertexShaderID);
+ glAttachShader(programID, fragmentShaderID);
+
+
+ glLinkProgram(programID);
+
+ glDeleteShader(vertexShaderID);
+ glDeleteShader(fragmentShaderID);
+ }
GLint success = GL_FALSE;
glGetProgramiv(programID, GL_LINK_STATUS, &success);
if( !success )
@@ -579,6 +608,11 @@ public:
return shaderID;
}
+
+ virtual void dispatchCompute(int x, int y, int z) override
+ {
+ glDispatchCompute(x, y, z);
+ }
};
diff --git a/tools/render-test/render.h b/tools/render-test/render.h
index afa279c66..7f8f2fffa 100644
--- a/tools/render-test/render.h
+++ b/tools/render-test/render.h
@@ -20,8 +20,8 @@ struct ShaderCompileRequest
struct EntryPoint
{
- char const* name;
- char const* profile;
+ char const* name = nullptr;
+ char const* profile = nullptr;
SourceInfo source;
};
@@ -29,6 +29,7 @@ struct ShaderCompileRequest
SourceInfo source;
EntryPoint vertexShader;
EntryPoint fragmentShader;
+ EntryPoint computeShader;
};
class ShaderCompiler
@@ -47,6 +48,7 @@ enum class BufferFlavor
{
Constant,
Vertex,
+ Storage,
};
struct BufferDesc
@@ -66,6 +68,8 @@ struct InputElementDesc
enum class MapFlavor
{
+ HostRead,
+ HostWrite,
WriteDiscard,
};
@@ -108,13 +112,17 @@ public:
virtual void setShaderProgram(ShaderProgram* program) = 0;
virtual void setConstantBuffers(UInt startSlot, UInt slotCount, Buffer* const* buffers, UInt const* offsets) = 0;
-
+ virtual void setStorageBuffers(UInt startSlot, UInt slotCount, Buffer* const* buffers, UInt const* offsets) = 0;
inline void setConstantBuffer(UInt slot, Buffer* buffer, UInt offset = 0)
{
setConstantBuffers(slot, 1, &buffer, &offset);
}
-
+ inline void setStorageBuffer(UInt slot, Buffer* buffer, UInt offset = 0)
+ {
+ setStorageBuffers(slot, 1, &buffer, &offset);
+ }
virtual void draw(UInt vertexCount, UInt startVertex = 0) = 0;
+ virtual void dispatchCompute(int x, int y, int z) = 0;
};
} // renderer_test
diff --git a/tools/render-test/slang-support.cpp b/tools/render-test/slang-support.cpp
index bf8b7b9c7..63e24126c 100644
--- a/tools/render-test/slang-support.cpp
+++ b/tools/render-test/slang-support.cpp
@@ -13,94 +13,116 @@ struct SlangShaderCompilerWrapper : public ShaderCompiler
SlangCompileTarget target;
SlangSourceLanguage sourceLanguage;
- virtual ShaderProgram* compileProgram(ShaderCompileRequest const& request) override
- {
- SlangSession* slangSession = spCreateSession(NULL);
- SlangCompileRequest* slangRequest = spCreateCompileRequest(slangSession);
-
- spSetCodeGenTarget(slangRequest, target);
-
- // Define a macro so that shader code in a test can detect what language we
- // are nominally working with.
- char const* langDefine = nullptr;
- switch (sourceLanguage)
- {
- case SLANG_SOURCE_LANGUAGE_GLSL: langDefine = "__GLSL__"; break;
- case SLANG_SOURCE_LANGUAGE_HLSL: langDefine = "__HLSL__"; break;
- case SLANG_SOURCE_LANGUAGE_SLANG: langDefine = "__SLANG__"; break;
- default:
- assert(!"unexpected");
- break;
- }
- spAddPreprocessorDefine(slangRequest, langDefine, "1");
-
- spProcessCommandLineArguments(slangRequest, &gOptions.slangArgs[0], gOptions.slangArgCount);
-
- int vertexTranslationUnit = 0;
- int fragmentTranslationUnit = 0;
- char const* vertexEntryPointName = request.vertexShader.name;
- char const* fragmentEntryPointName = request.fragmentShader.name;
- if( sourceLanguage == SLANG_SOURCE_LANGUAGE_GLSL )
- {
- // GLSL presents unique challenges because, frankly, it got the whole
- // compilation model wrong. One aspect of working around this is that
- // we will compile the same source file multiple times: once per
- // entry point, and we will have different preprocessor definitions
- // active in each case.
-
- vertexTranslationUnit = spAddTranslationUnit(slangRequest, sourceLanguage, nullptr);
- spAddTranslationUnitSourceString(slangRequest, vertexTranslationUnit, request.source.path, request.source.text);
- spTranslationUnit_addPreprocessorDefine(slangRequest, vertexTranslationUnit, "__GLSL_VERTEX__", "1");
- vertexEntryPointName = "main";
-
- fragmentTranslationUnit = spAddTranslationUnit(slangRequest, sourceLanguage, nullptr);
- spAddTranslationUnitSourceString(slangRequest, fragmentTranslationUnit, request.source.path, request.source.text);
- spTranslationUnit_addPreprocessorDefine(slangRequest, fragmentTranslationUnit, "__GLSL_FRAGMENT__", "1");
- fragmentEntryPointName = "main";
- }
- else
- {
- int translationUnit = spAddTranslationUnit(slangRequest, sourceLanguage, nullptr);
- spAddTranslationUnitSourceString(slangRequest, translationUnit, request.source.path, request.source.text);
-
- vertexTranslationUnit = translationUnit;
- fragmentTranslationUnit = translationUnit;
- }
-
-
- // If we aren't dealing with true Slang input, then don't enable checking.
- if (sourceLanguage != SLANG_SOURCE_LANGUAGE_SLANG)
- {
- spSetCompileFlags(slangRequest, SLANG_COMPILE_FLAG_NO_CHECKING);
- }
-
- int vertexEntryPoint = spAddEntryPoint(slangRequest, vertexTranslationUnit, vertexEntryPointName, spFindProfile(slangSession, request.vertexShader.profile));
- int fragmentEntryPoint = spAddEntryPoint(slangRequest, fragmentTranslationUnit, fragmentEntryPointName, spFindProfile(slangSession, request.fragmentShader.profile));
-
- int compileErr = spCompile(slangRequest);
- if(auto diagnostics = spGetDiagnosticOutput(slangRequest))
- {
- // TODO(tfoley): re-enable when I get a logging solution in place
-// OutputDebugStringA(diagnostics);
- fprintf(stderr, "%s", diagnostics);
- }
- if(compileErr)
- {
- return nullptr;
- }
-
-
- ShaderCompileRequest innerRequest = request;
-
- char const* vertexCode = spGetEntryPointSource(slangRequest, vertexEntryPoint);
- char const* fragmentCode = spGetEntryPointSource(slangRequest, fragmentEntryPoint);
-
- innerRequest.vertexShader.source.text = vertexCode;
- innerRequest.fragmentShader.source.text = fragmentCode;
-
-
- auto result = innerCompiler->compileProgram(innerRequest);
-
+ virtual ShaderProgram* compileProgram(ShaderCompileRequest const& request) override
+ {
+ SlangSession* slangSession = spCreateSession(NULL);
+ SlangCompileRequest* slangRequest = spCreateCompileRequest(slangSession);
+
+ spSetCodeGenTarget(slangRequest, target);
+
+ // Define a macro so that shader code in a test can detect what language we
+ // are nominally working with.
+ char const* langDefine = nullptr;
+ switch (sourceLanguage)
+ {
+ case SLANG_SOURCE_LANGUAGE_GLSL: langDefine = "__GLSL__"; break;
+ case SLANG_SOURCE_LANGUAGE_HLSL: langDefine = "__HLSL__"; break;
+ case SLANG_SOURCE_LANGUAGE_SLANG: langDefine = "__SLANG__"; break;
+ default:
+ assert(!"unexpected");
+ break;
+ }
+ spAddPreprocessorDefine(slangRequest, langDefine, "1");
+
+ spProcessCommandLineArguments(slangRequest, &gOptions.slangArgs[0], gOptions.slangArgCount);
+ int computeTranslationUnit = 0;
+ int vertexTranslationUnit = 0;
+ int fragmentTranslationUnit = 0;
+ char const* vertexEntryPointName = request.vertexShader.name;
+ char const* fragmentEntryPointName = request.fragmentShader.name;
+ char const* computeEntryPointName = request.computeShader.name;
+
+ if (sourceLanguage == SLANG_SOURCE_LANGUAGE_GLSL)
+ {
+ // GLSL presents unique challenges because, frankly, it got the whole
+ // compilation model wrong. One aspect of working around this is that
+ // we will compile the same source file multiple times: once per
+ // entry point, and we will have different preprocessor definitions
+ // active in each case.
+
+ vertexTranslationUnit = spAddTranslationUnit(slangRequest, sourceLanguage, nullptr);
+ spAddTranslationUnitSourceString(slangRequest, vertexTranslationUnit, request.source.path, request.source.text);
+ spTranslationUnit_addPreprocessorDefine(slangRequest, vertexTranslationUnit, "__GLSL_VERTEX__", "1");
+ vertexEntryPointName = "main";
+
+ fragmentTranslationUnit = spAddTranslationUnit(slangRequest, sourceLanguage, nullptr);
+ spAddTranslationUnitSourceString(slangRequest, fragmentTranslationUnit, request.source.path, request.source.text);
+ spTranslationUnit_addPreprocessorDefine(slangRequest, fragmentTranslationUnit, "__GLSL_FRAGMENT__", "1");
+ fragmentEntryPointName = "main";
+
+ computeTranslationUnit = spAddTranslationUnit(slangRequest, sourceLanguage, nullptr);
+ spAddTranslationUnitSourceString(slangRequest, computeTranslationUnit, request.source.path, request.source.text);
+ spTranslationUnit_addPreprocessorDefine(slangRequest, computeTranslationUnit, "__GLSL_COMPUTE__", "1");
+ computeEntryPointName = "main";
+ }
+ else
+ {
+ int translationUnit = spAddTranslationUnit(slangRequest, sourceLanguage, nullptr);
+ spAddTranslationUnitSourceString(slangRequest, translationUnit, request.source.path, request.source.text);
+
+ vertexTranslationUnit = translationUnit;
+ fragmentTranslationUnit = translationUnit;
+ computeTranslationUnit = translationUnit;
+ }
+
+
+ // If we aren't dealing with true Slang input, then don't enable checking.
+ if (sourceLanguage != SLANG_SOURCE_LANGUAGE_SLANG)
+ {
+ spSetCompileFlags(slangRequest, SLANG_COMPILE_FLAG_NO_CHECKING);
+ }
+ ShaderProgram * result = nullptr;
+ if (request.computeShader.name)
+ {
+ int computeEntryPoint = spAddEntryPoint(slangRequest, computeTranslationUnit, computeEntryPointName, spFindProfile(slangSession, request.computeShader.profile));
+ int compileErr = spCompile(slangRequest);
+ if (auto diagnostics = spGetDiagnosticOutput(slangRequest))
+ {
+ fprintf(stderr, "%s", diagnostics);
+ }
+ if (!compileErr)
+ {
+ ShaderCompileRequest innerRequest = request;
+ char const* computeCode = spGetEntryPointSource(slangRequest, computeEntryPoint);
+ innerRequest.computeShader.source.text = computeCode;
+ result = innerCompiler->compileProgram(innerRequest);
+ }
+ }
+ else
+ {
+ int vertexEntryPoint = spAddEntryPoint(slangRequest, vertexTranslationUnit, vertexEntryPointName, spFindProfile(slangSession, request.vertexShader.profile));
+ int fragmentEntryPoint = spAddEntryPoint(slangRequest, fragmentTranslationUnit, fragmentEntryPointName, spFindProfile(slangSession, request.fragmentShader.profile));
+
+ int compileErr = spCompile(slangRequest);
+ if (auto diagnostics = spGetDiagnosticOutput(slangRequest))
+ {
+ // TODO(tfoley): re-enable when I get a logging solution in place
+ // OutputDebugStringA(diagnostics);
+ fprintf(stderr, "%s", diagnostics);
+ }
+ if (!compileErr)
+ {
+ ShaderCompileRequest innerRequest = request;
+
+ char const* vertexCode = spGetEntryPointSource(slangRequest, vertexEntryPoint);
+ char const* fragmentCode = spGetEntryPointSource(slangRequest, fragmentEntryPoint);
+
+ innerRequest.vertexShader.source.text = vertexCode;
+ innerRequest.fragmentShader.source.text = fragmentCode;
+
+ result = innerCompiler->compileProgram(innerRequest);
+ }
+ }
// We clean up the Slang compilation context and result *after*
// we have run the downstream compiler, because Slang
// owns the memory allocation for the generated text, and will