summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorTim Foley <tfoleyNV@users.noreply.github.com>2018-02-02 07:49:32 -0800
committerGitHub <noreply@github.com>2018-02-02 07:49:32 -0800
commitb034398ab12d3cc3a5fc04174688cb707404791d (patch)
treeffa3f01046a7dca55cf004855ca9424c82eaa46f /tools
parent652a3c987d2b42d069bf54ba251126208d00d9e7 (diff)
Initial work on getting render-test to support vulkan (#391)
* Basic fixes to gets some Vulkan GLSL out of the IR path We haven't been paying much attention to the Vulkan output from the IR path, but that needs to change ASAP. This commit really just implements quick fixes, without concern for whether they are a good fit in the long term. - Add some more mappings from D3D `SV_*` semantics to built-in GLSL variables, and stop redeclaring those built-in variables in our output GLSL. - Add custom output logic for HLSL `*StructuredBuffer<T>` types, so that they emit as `buffer` declarations with an unsized array inside. This has some real limitations: - What if the user passes the type into a function? The parameter should be typed as an (unsized) array, and not a buffer. - What happens if we have an array of structured buffers? We need to declare an array of blocks (which GLSL allows), but this changes the GLSL we should emit when indexing. - Customize the way that we emit entry point attributes (e.g., `[numthread(...)]`) to also support outputting equivalent GLSL `layout` qualifiers. In many of these cases, a better fix might involve doing more of this work in the IR as part of legalization (e.g., we already have a pass that deals with varying input/output for GLSL, so that should probalby be responsible for swapping the `SV_*` to `gl_*`, especially in cases where the types don't match perfectly across langauges). * Start adding Vulkan support to render-test - Add both Vulkan and D3D12 as nominally supported back-ends - Add a git submodule to pull in the Vulkan SDK dependencies - I don't want our users to have to install it manually, since the SDK is huge - Checking in the binaries to our main repository seems like a bad idea, but my hope is that we can prune the bloat using a subodule with the `shallow` cloning option - Implement enough logic for the Vulkan back-end to get a single test passing on Vulkan * Fix warning * Fixup: disable new compute tests for Linux * Fixup: ignore Vulkan tests on AppVeyor * Dynamically load Vulkan implementation Rather than statically link to the Vulkan library, we will dynamically load all of the required functions. This removes the need to have the stub libs involved at all. * Remove vulkan submodule I had set up a `vulkan` submodule to pull in the headers and stub libs, but now that we are going to dynamically load all the symbols anyway, the stub lib binaries aren't needed and we can just commit the headers. * Add Vulkan headers to external/
Diffstat (limited to 'tools')
-rw-r--r--tools/render-test/main.cpp53
-rw-r--r--tools/render-test/options.cpp28
-rw-r--r--tools/render-test/options.h23
-rw-r--r--tools/render-test/render-d3d11.cpp6
-rw-r--r--tools/render-test/render-d3d12.cpp337
-rw-r--r--tools/render-test/render-d3d12.h10
-rw-r--r--tools/render-test/render-gl.cpp6
-rw-r--r--tools/render-test/render-test.vcxproj18
-rw-r--r--tools/render-test/render-test.vcxproj.filters12
-rw-r--r--tools/render-test/render-vk.cpp1033
-rw-r--r--tools/render-test/render-vk.h10
-rw-r--r--tools/render-test/render.h9
-rw-r--r--tools/render-test/slang-support.cpp29
-rw-r--r--tools/slang-test/main.cpp11
14 files changed, 1524 insertions, 61 deletions
diff --git a/tools/render-test/main.cpp b/tools/render-test/main.cpp
index 51a96436f..3255f4b9b 100644
--- a/tools/render-test/main.cpp
+++ b/tools/render-test/main.cpp
@@ -4,6 +4,7 @@
#include "render.h"
#include "render-d3d11.h"
#include "render-gl.h"
+#include "render-vk.h"
#include "slang-support.h"
#include "shader-input-layout.h"
#include <stdio.h>
@@ -98,7 +99,8 @@ Error initializeShaders(
ShaderCompileRequest::SourceInfo sourceInfo;
sourceInfo.path = sourcePath;
- sourceInfo.text = sourceText;
+ sourceInfo.dataBegin = sourceText;
+ sourceInfo.dataEnd = sourceText + sourceSize;
ShaderCompileRequest compileRequest;
compileRequest.source = sourceInfo;
@@ -322,18 +324,28 @@ int main(
Renderer* renderer = nullptr;
- switch( gOptions.mode )
+ SlangSourceLanguage nativeLanguage = SLANG_SOURCE_LANGUAGE_UNKNOWN;
+ SlangCompileTarget slangTarget = SLANG_TARGET_NONE;
+ switch( gOptions.rendererID )
{
- case Mode::Slang:
- case Mode::HLSL:
- case Mode::HLSLRewrite:
+ case RendererID::D3D11:
renderer = createD3D11Renderer();
+ slangTarget = SLANG_HLSL;
+ nativeLanguage = SLANG_SOURCE_LANGUAGE_HLSL;
break;
- case Mode::GLSL:
- case Mode::GLSLRewrite:
- case Mode::GLSLCrossCompile:
+ // TODO: `RendererID::D3D12`
+
+ case RendererID::GL:
renderer = createGLRenderer();
+ slangTarget = SLANG_GLSL;
+ nativeLanguage = SLANG_SOURCE_LANGUAGE_GLSL;
+ break;
+
+ case RendererID::VK:
+ renderer = createVKRenderer();
+ slangTarget = SLANG_SPIRV;
+ nativeLanguage = SLANG_SOURCE_LANGUAGE_GLSL;
break;
default:
@@ -345,22 +357,14 @@ int main(
renderer->initialize(windowHandle);
auto shaderCompiler = renderer->getShaderCompiler();
- switch( gOptions.mode )
+ switch( gOptions.inputLanguageID )
{
- case Mode::Slang:
- shaderCompiler = createSlangShaderCompiler(shaderCompiler, SLANG_SOURCE_LANGUAGE_SLANG, SLANG_HLSL);
- break;
-
- case Mode::HLSLRewrite:
- shaderCompiler = createSlangShaderCompiler(shaderCompiler, SLANG_SOURCE_LANGUAGE_HLSL, SLANG_HLSL);
- break;
-
- case Mode::GLSLRewrite:
- shaderCompiler = createSlangShaderCompiler(shaderCompiler, SLANG_SOURCE_LANGUAGE_GLSL, SLANG_GLSL);
+ case InputLanguageID::Slang:
+ shaderCompiler = createSlangShaderCompiler(shaderCompiler, SLANG_SOURCE_LANGUAGE_SLANG, slangTarget);
break;
- case Mode::GLSLCrossCompile:
- shaderCompiler = createSlangShaderCompiler(shaderCompiler, SLANG_SOURCE_LANGUAGE_SLANG, SLANG_GLSL);
+ case InputLanguageID::NativeRewrite:
+ shaderCompiler = createSlangShaderCompiler(shaderCompiler, nativeLanguage, slangTarget);
break;
default:
@@ -397,9 +401,6 @@ int main(
{
// 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)
{
@@ -407,6 +408,10 @@ int main(
}
else
{
+ 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
diff --git a/tools/render-test/options.cpp b/tools/render-test/options.cpp
index 629016155..45a94e137 100644
--- a/tools/render-test/options.cpp
+++ b/tools/render-test/options.cpp
@@ -54,27 +54,33 @@ void parseOptions(int* argc, char** argv)
}
else if( strcmp(arg, "-hlsl") == 0 )
{
- gOptions.mode = Mode::HLSL;
+ gOptions.rendererID = RendererID::D3D11;
+ gOptions.inputLanguageID = InputLanguageID::Native;
}
else if( strcmp(arg, "-glsl") == 0 )
{
- gOptions.mode = Mode::GLSL;
+ gOptions.rendererID = RendererID::GL;
+ gOptions.inputLanguageID = InputLanguageID::Native;
}
else if( strcmp(arg, "-hlsl-rewrite") == 0 )
{
- gOptions.mode = Mode::HLSLRewrite;
+ gOptions.rendererID = RendererID::D3D11;
+ gOptions.inputLanguageID = InputLanguageID::NativeRewrite;
}
else if( strcmp(arg, "-glsl-rewrite") == 0 )
{
- gOptions.mode = Mode::GLSLRewrite;
+ gOptions.rendererID = RendererID::GL;
+ gOptions.inputLanguageID = InputLanguageID::NativeRewrite;
}
else if( strcmp(arg, "-slang") == 0 )
{
- gOptions.mode = Mode::Slang;
+ gOptions.rendererID = RendererID::D3D11;
+ gOptions.inputLanguageID = InputLanguageID::Slang;
}
else if( strcmp(arg, "-glsl-cross") == 0 )
{
- gOptions.mode = Mode::GLSLCrossCompile;
+ gOptions.rendererID = RendererID::GL;
+ gOptions.inputLanguageID = InputLanguageID::Slang;
}
else if( strcmp(arg, "-xslang") == 0 )
{
@@ -104,6 +110,16 @@ void parseOptions(int* argc, char** argv)
{
gOptions.shaderType = ShaderProgramType::GraphicsCompute;
}
+ else if (strcmp(arg, "-vk") == 0
+ || strcmp(arg, "-vulkan") == 0)
+ {
+ gOptions.rendererID = RendererID::VK;
+ }
+ else if (strcmp(arg, "-d3d12") == 0
+ || strcmp(arg, "-dx12") == 0)
+ {
+ gOptions.rendererID = RendererID::D3D12;
+ }
else
{
fprintf(stderr, "unknown option '%s'\n", arg);
diff --git a/tools/render-test/options.h b/tools/render-test/options.h
index 2c48c4ceb..b48295878 100644
--- a/tools/render-test/options.h
+++ b/tools/render-test/options.h
@@ -8,21 +8,24 @@ namespace renderer_test {
typedef intptr_t Int;
typedef uintptr_t UInt;
-enum class Mode
+enum class RendererID
+{
+ D3D11,
+ D3D12,
+ GL,
+ VK,
+};
+
+enum class InputLanguageID
{
// Slang being used as an HLSL-ish compiler
Slang,
// Raw HLSL or GLSL input, bypassing Slang
- HLSL,
- GLSL,
+ Native,
// Raw HLSL or GLSL input, passed through the Slang rewriter
- HLSLRewrite,
- GLSLRewrite,
-
- // Slang/HLSL input -> GLSL output
- GLSLCrossCompile,
+ NativeRewrite
};
enum
@@ -44,7 +47,9 @@ struct Options
char const* sourcePath = nullptr;
char const* outputPath = nullptr;
ShaderProgramType shaderType = ShaderProgramType::Graphics;
- Mode mode = Mode::Slang;
+
+ RendererID rendererID;
+ InputLanguageID inputLanguageID = InputLanguageID::Slang;
char const* slangArgs[kMaxSlangArgs];
int slangArgCount = 0;
diff --git a/tools/render-test/render-d3d11.cpp b/tools/render-test/render-d3d11.cpp
index 7d5c79b19..690e6299f 100644
--- a/tools/render-test/render-d3d11.cpp
+++ b/tools/render-test/render-d3d11.cpp
@@ -719,7 +719,7 @@ public:
{
if (request.computeShader.name)
{
- auto dxComputeShaderBlob = compileHLSLShader(request.computeShader.source.path, request.computeShader.source.text, request.computeShader.name, request.computeShader.profile);
+ auto dxComputeShaderBlob = compileHLSLShader(request.computeShader.source.path, request.computeShader.source.dataBegin, request.computeShader.name, request.computeShader.profile);
if (!dxComputeShaderBlob)
return nullptr;
@@ -737,10 +737,10 @@ public:
}
else
{
- auto dxVertexShaderBlob = compileHLSLShader(request.vertexShader.source.path, request.vertexShader.source.text, request.vertexShader.name, request.vertexShader.profile);
+ auto dxVertexShaderBlob = compileHLSLShader(request.vertexShader.source.path, request.vertexShader.source.dataBegin, request.vertexShader.name, request.vertexShader.profile);
if (!dxVertexShaderBlob) return nullptr;
- auto dxFragmentShaderBlob = compileHLSLShader(request.fragmentShader.source.path, request.fragmentShader.source.text, request.fragmentShader.name, request.fragmentShader.profile);
+ auto dxFragmentShaderBlob = compileHLSLShader(request.fragmentShader.source.path, request.fragmentShader.source.dataBegin, request.fragmentShader.name, request.fragmentShader.profile);
if (!dxFragmentShaderBlob) return nullptr;
ID3D11VertexShader* dxVertexShader;
diff --git a/tools/render-test/render-d3d12.cpp b/tools/render-test/render-d3d12.cpp
new file mode 100644
index 000000000..2308c601a
--- /dev/null
+++ b/tools/render-test/render-d3d12.cpp
@@ -0,0 +1,337 @@
+// render-d3d12.cpp
+#include "render-d3d12.h"
+
+#include "options.h"
+#include "render.h"
+
+// In order to use the Slang API, we need to include its header
+
+#include <slang.h>
+
+// We will be rendering with Direct3D 12, so we need to include
+// the Windows and D3D12 headers
+
+#define WIN32_LEAN_AND_MEAN
+#define NOMINMAX
+#include <Windows.h>
+#undef WIN32_LEAN_AND_MEAN
+#undef NOMINMAX
+
+#include <dxgi1_4.h>
+#include <d3d12.h>
+#include <d3dcompiler.h>
+
+// We will use the C standard library just for printing error messages.
+#include <stdio.h>
+
+#ifdef _MSC_VER
+#include <stddef.h>
+#if (_MSC_VER < 1900)
+#define snprintf sprintf_s
+#endif
+#endif
+//
+using namespace Slang;
+
+#define ENABLE_DEBUG_LAYER 1
+
+namespace renderer_test {
+
+// The Slang compiler currently generates HLSL source, so we'll need a utility
+// routine (defined later) to translate that into D3D11 shader bytecode.
+ID3DBlob* compileHLSLShader(
+ char const* sourcePath,
+ char const* source,
+ char const* entryPointName,
+ char const* dxProfileName);
+
+static char const* vertexProfileName = "vs_4_0";
+static char const* fragmentProfileName = "ps_4_0";
+
+//
+
+class D3D12Renderer : public Renderer, public ShaderCompiler
+{
+public:
+ IDXGISwapChain* dxSwapChain = NULL;
+
+ ID3D12Device* dxDevice = NULL;
+
+ virtual PROC loadProc(
+ HMODULE module,
+ char const* name)
+ {
+ PROC proc = GetProcAddress(module, name);
+ if( !proc )
+ {
+ fprintf(stderr,
+ "error: failed load symbol '%s'\n", name);
+ exit(1);
+ }
+ return proc;
+ }
+
+ void checkResult(HRESULT result)
+ {
+ assert(SUCCEEDED(result));
+ }
+
+ virtual void initialize(void* inWindowHandle) override
+ {
+ auto windowHandle = (HWND) inWindowHandle;
+ // Rather than statically link against D3D, we load it dynamically.
+
+ HMODULE d3d12 = LoadLibraryA("d3d12.dll");
+ if(!d3d12)
+ {
+ fprintf(stderr, "error: failed load 'd3d12.dll'\n");
+ exit(1);
+ }
+
+#define LOAD_PROC(TYPE, NAME) \
+ TYPE NAME##_ = (TYPE) loadProc(d3d12, #NAME)
+
+
+ UINT dxgiFactoryFlags = 0;
+
+#if ENABLE_DEBUG_LAYER
+ LOAD_PROC(PFN_D3D12_GET_DEBUG_INTERFACE, D3D12GetDebugInterface);
+
+ ID3D12Debug* debugController;
+ if(SUCCEEDED(D3D12GetDebugInterface_(IID_PPV_ARGS(&debugController))))
+ {
+ debugController->EnableDebugLayer();
+ dxgiFactoryFlags |= DXGI_CREATE_FACTORY_DEBUG;
+ }
+#endif
+
+ typedef HRESULT (WINAPI *PFN_DXGI_CREATE_FACTORY_2)(UINT Flags, REFIID riid, _COM_Outptr_ void **ppFactory);
+
+
+ LOAD_PROC(PFN_DXGI_CREATE_FACTORY_2, CreateDXGIFactory2);
+
+ IDXGIFactory4* dxgiFactory;
+ checkResult(CreateDXGIFactory2_(dxgiFactoryFlags, IID_PPV_ARGS(&dxgiFactory)));
+
+ D3D_FEATURE_LEVEL featureLevel = D3D_FEATURE_LEVEL_11_0;
+
+ // Search for an adapter that meets our requirements
+ IDXGIAdapter* adapter = nullptr;
+
+ LOAD_PROC(PFN_D3D12_CREATE_DEVICE, D3D12CreateDevice);
+
+ UINT adapterCounter = 0;
+ for(;;)
+ {
+ UINT adapterIndex = adapterCounter++;
+ IDXGIAdapter1* candidateAdapter = nullptr;
+ if(dxgiFactory->EnumAdapters1(adapterIndex, &candidateAdapter) == DXGI_ERROR_NOT_FOUND)
+ break;
+
+ DXGI_ADAPTER_DESC1 desc;
+ candidateAdapter->GetDesc1(&desc);
+
+ if( desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE )
+ {
+ // TODO: may want to allow software driver as fallback
+ }
+ else if( SUCCEEDED(D3D12CreateDevice_(
+ candidateAdapter, featureLevel, IID_PPV_ARGS(&dxDevice))) )
+ {
+ // We found one!
+ adapter = candidateAdapter;
+ break;
+ }
+
+ candidateAdapter->Release();
+ }
+
+ if(!adapter)
+ {
+ return;
+ }
+
+ // Command Queue
+
+ D3D12_COMMAND_QUEUE_DESC queueDesc = {};
+ queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
+
+ ID3D12CommandQueue* commandQueue;
+ checkResult(dxDevice->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&commandQueue)));
+
+ // Swap Chain
+
+
+ UINT frameCount = 2; // TODO: configure
+
+ DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {};
+ swapChainDesc.BufferCount = frameCount;
+ swapChainDesc.Width = gWindowWidth;
+ swapChainDesc.Height = gWindowHeight;
+ swapChainDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+ swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
+ swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
+ swapChainDesc.SampleDesc.Count = 1;
+
+ IDXGISwapChain1* swapChain;
+ checkResult(dxgiFactory->CreateSwapChainForHwnd(
+ commandQueue,
+ windowHandle,
+ &swapChainDesc,
+ nullptr,
+ nullptr,
+ &swapChain));
+
+ // Is this needed?
+ dxgiFactory->MakeWindowAssociation(
+ windowHandle, DXGI_MWA_NO_ALT_ENTER);
+
+ IDXGISwapChain3* swapChainEx;
+ swapChain->QueryInterface(IID_PPV_ARGS(&swapChainEx));
+
+ UINT frameIndex = swapChainEx->GetCurrentBackBufferIndex();
+
+ // Descriptor heaps
+
+ D3D12_DESCRIPTOR_HEAP_DESC rtvHeapDesc = {};
+ rtvHeapDesc.NumDescriptors = frameCount;
+ rtvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
+
+ ID3D12DescriptorHeap* rtvHeap;
+ checkResult(dxDevice->CreateDescriptorHeap(&rtvHeapDesc, IID_PPV_ARGS(&rtvHeap)));
+
+ UINT rtvDescriptorSize = dxDevice->GetDescriptorHandleIncrementSize(
+ D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
+
+ D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = rtvHeap->GetCPUDescriptorHandleForHeapStart();
+
+ // Create per-frame RTVs
+ ID3D12Resource* backBufferResources[2];
+ for( UINT ff = 0; ff < frameCount; ++ff )
+ {
+ checkResult(swapChainEx->GetBuffer(ff, IID_PPV_ARGS(&backBufferResources[ff])));
+ dxDevice->CreateRenderTargetView(
+ backBufferResources[ff],
+ nullptr,
+ rtvHandle);
+ rtvHandle.ptr += rtvDescriptorSize;
+ }
+
+ ID3D12CommandAllocator* commandAllocator;
+ checkResult(dxDevice->CreateCommandAllocator(
+ D3D12_COMMAND_LIST_TYPE_DIRECT,
+ IID_PPV_ARGS(&commandAllocator)));
+ }
+
+ float clearColor[4] = { 0, 0, 0, 0 };
+ virtual void setClearColor(float const* color) override
+ {
+ memcpy(clearColor, color, sizeof(clearColor));
+ }
+
+ virtual void clearFrame() override
+ {
+ }
+
+ virtual void presentFrame() override
+ {
+ }
+
+ virtual void captureScreenShot(char const* outputPath) override
+ {
+ }
+
+ virtual ShaderCompiler* getShaderCompiler() override
+ {
+ return this;
+ }
+
+ virtual Buffer* createBuffer(BufferDesc const& desc) override
+ {
+ return nullptr;
+ }
+
+ static DXGI_FORMAT mapFormat(Format format)
+ {
+ switch( format )
+ {
+ case Format::RGB_Float32:
+ return DXGI_FORMAT_R32G32B32_FLOAT;
+ case Format::RG_Float32:
+ return DXGI_FORMAT_R32G32_FLOAT;
+ default:
+ return DXGI_FORMAT_UNKNOWN;
+ }
+ }
+
+ virtual InputLayout* createInputLayout(InputElementDesc const* inputElements, UInt inputElementCount) override
+ {
+ return nullptr;
+ }
+
+ virtual void* map(Buffer* buffer, MapFlavor flavor) override
+ {
+ return nullptr;
+ }
+
+ virtual void unmap(Buffer* buffer) override
+ {
+ }
+
+ virtual void setInputLayout(InputLayout* inputLayout) override
+ {
+ }
+
+ virtual void setPrimitiveTopology(PrimitiveTopology topology) override
+ {
+ }
+
+ virtual void setVertexBuffers(UInt startSlot, UInt slotCount, Buffer* const* buffers, UInt const* strides, UInt const* offsets) override
+ {
+ }
+
+ virtual void setShaderProgram(ShaderProgram* inProgram) override
+ {
+ }
+
+ virtual void setConstantBuffers(UInt startSlot, UInt slotCount, Buffer* const* buffers, UInt const* offsets) override
+ {
+ }
+
+ virtual void draw(UInt vertexCount, UInt startVertex) override
+ {
+ }
+
+
+ virtual void dispatchCompute(int x, int y, int z) override
+ {
+ }
+
+ virtual BindingState * createBindingState(const ShaderInputLayout & layout)
+ {
+ return nullptr;
+ }
+
+ virtual void setBindingState(BindingState * state)
+ {
+ }
+
+ virtual void serializeOutput(BindingState* state, const char * fileName)
+ {
+ }
+
+ // ShaderCompiler interface
+
+ virtual ShaderProgram* compileProgram(ShaderCompileRequest const& request) override
+ {
+ return nullptr;
+ }
+
+};
+
+Renderer* createD3D12Renderer()
+{
+ return new D3D12Renderer();
+}
+
+} // renderer_test
diff --git a/tools/render-test/render-d3d12.h b/tools/render-test/render-d3d12.h
new file mode 100644
index 000000000..259af7f7b
--- /dev/null
+++ b/tools/render-test/render-d3d12.h
@@ -0,0 +1,10 @@
+// render-d3d12.h
+#pragma once
+
+namespace renderer_test {
+
+class Renderer;
+
+Renderer* createD3D12Renderer();
+
+} // renderer_test
diff --git a/tools/render-test/render-gl.cpp b/tools/render-test/render-gl.cpp
index f07e27985..99b61c03c 100644
--- a/tools/render-test/render-gl.cpp
+++ b/tools/render-test/render-gl.cpp
@@ -453,7 +453,7 @@ public:
auto programID = glCreateProgram();
if (request.computeShader.name)
{
- auto computeShaderID = loadShader(GL_COMPUTE_SHADER, request.computeShader.source.text);
+ auto computeShaderID = loadShader(GL_COMPUTE_SHADER, request.computeShader.source.dataBegin);
glAttachShader(programID, computeShaderID);
@@ -464,8 +464,8 @@ public:
}
else
{
- auto vertexShaderID = loadShader(GL_VERTEX_SHADER, request.vertexShader.source.text);
- auto fragmentShaderID = loadShader(GL_FRAGMENT_SHADER, request.fragmentShader.source.text);
+ auto vertexShaderID = loadShader(GL_VERTEX_SHADER, request.vertexShader.source.dataBegin);
+ auto fragmentShaderID = loadShader(GL_FRAGMENT_SHADER, request.fragmentShader.source.dataBegin);
glAttachShader(programID, vertexShaderID);
glAttachShader(programID, fragmentShaderID);
diff --git a/tools/render-test/render-test.vcxproj b/tools/render-test/render-test.vcxproj
index a175d3973..1b022f913 100644
--- a/tools/render-test/render-test.vcxproj
+++ b/tools/render-test/render-test.vcxproj
@@ -22,7 +22,7 @@
<ProjectGuid>{96610759-07B9-4EEB-A974-5C634A2E742B}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>rendertest</RootNamespace>
- <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
+ <WindowsTargetPlatformVersion>10.0.14393.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
@@ -75,19 +75,23 @@
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
- <IncludePath>$(SolutionDir);$(IncludePath)</IncludePath>
+ <IncludePath>$(SolutionDir)external\;$(SolutionDir);$(IncludePath)</IncludePath>
+ <LibraryPath>$(SolutionDir)external\vulkan\lib\windows-$(PlatformShortName)\;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
- <IncludePath>$(SolutionDir);$(IncludePath)</IncludePath>
+ <IncludePath>$(SolutionDir)external\;$(SolutionDir);$(IncludePath)</IncludePath>
+ <LibraryPath>$(SolutionDir)external\vulkan\lib\windows-$(PlatformShortName)\;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
- <IncludePath>$(SolutionDir);$(IncludePath)</IncludePath>
+ <IncludePath>$(SolutionDir)external\;$(SolutionDir);$(IncludePath)</IncludePath>
+ <LibraryPath>$(SolutionDir)external\vulkan\lib\windows-$(PlatformShortName)\;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
- <IncludePath>$(SolutionDir);$(IncludePath)</IncludePath>
+ <IncludePath>$(SolutionDir)external\;$(SolutionDir);$(IncludePath)</IncludePath>
+ <LibraryPath>$(SolutionDir)external\vulkan\lib\windows-$(PlatformShortName)\;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
@@ -165,14 +169,18 @@
<ClCompile Include="main.cpp" />
<ClCompile Include="options.cpp" />
<ClCompile Include="render-d3d11.cpp" />
+ <ClCompile Include="render-d3d12.cpp" />
<ClCompile Include="render-gl.cpp" />
+ <ClCompile Include="render-vk.cpp" />
<ClCompile Include="shader-input-layout.cpp" />
<ClCompile Include="slang-support.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="options.h" />
<ClInclude Include="render-d3d11.h" />
+ <ClInclude Include="render-d3d12.h" />
<ClInclude Include="render-gl.h" />
+ <ClInclude Include="render-vk.h" />
<ClInclude Include="render.h" />
<ClInclude Include="shader-input-layout.h" />
<ClInclude Include="slang-support.h" />
diff --git a/tools/render-test/render-test.vcxproj.filters b/tools/render-test/render-test.vcxproj.filters
index 985e24b8b..e1077e4e8 100644
--- a/tools/render-test/render-test.vcxproj.filters
+++ b/tools/render-test/render-test.vcxproj.filters
@@ -33,6 +33,12 @@
<ClCompile Include="shader-input-layout.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="render-vk.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="render-d3d12.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="options.h">
@@ -56,5 +62,11 @@
<ClInclude Include="shader-input-layout.h">
<Filter>Header Files</Filter>
</ClInclude>
+ <ClInclude Include="render-vk.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="render-d3d12.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
</ItemGroup>
</Project> \ No newline at end of file
diff --git a/tools/render-test/render-vk.cpp b/tools/render-test/render-vk.cpp
new file mode 100644
index 000000000..fd080931d
--- /dev/null
+++ b/tools/render-test/render-vk.cpp
@@ -0,0 +1,1033 @@
+// render-vk.cpp
+#include "render-vk.h"
+
+#include "options.h"
+#include "render.h"
+
+#ifdef _WIN32
+#define VK_USE_PLATFORM_WIN32_KHR 1
+#endif
+
+#define VK_NO_PROTOTYPES
+#include <vulkan/vulkan.h>
+
+#define ENABLE_VALIDATION_LAYER 1
+
+
+#ifdef _MSC_VER
+
+#include <stddef.h>
+
+#pragma warning(disable: 4996)
+
+#if (_MSC_VER < 1900)
+#define snprintf sprintf_s
+#endif
+#endif
+
+#define FOREACH_GLOBAL_PROC(M) \
+ M(vkCreateInstance) \
+ /* */
+
+#define FOREACH_INSTANCE_PROC(M) \
+ M(vkCreateDevice) \
+ M(vkCreateDebugReportCallbackEXT) \
+ M(vkDestroyDebugReportCallbackEXT) \
+ M(vkDebugReportMessageEXT) \
+ M(vkEnumeratePhysicalDevices) \
+ M(vkGetPhysicalDeviceProperties) \
+ M(vkGetPhysicalDeviceFeatures) \
+ M(vkGetPhysicalDeviceMemoryProperties) \
+ M(vkGetPhysicalDeviceQueueFamilyProperties) \
+ M(vkGetDeviceProcAddr) \
+ /* */
+
+#define FOREACH_DEVICE_PROC(M) \
+ M(vkCreateDescriptorPool) \
+ M(vkCreateCommandPool) \
+ M(vkGetDeviceQueue) \
+ M(vkAllocateCommandBuffers) \
+ M(vkBeginCommandBuffer) \
+ M(vkEndCommandBuffer) \
+ M(vkQueueSubmit) \
+ M(vkQueueWaitIdle) \
+ M(vkFreeCommandBuffers) \
+ M(vkCreateBuffer) \
+ M(vkGetBufferMemoryRequirements) \
+ M(vkAllocateMemory) \
+ M(vkBindBufferMemory) \
+ M(vkMapMemory) \
+ M(vkUnmapMemory) \
+ M(vkCmdCopyBuffer) \
+ M(vkDestroyBuffer) \
+ M(vkFreeMemory) \
+ M(vkCreateDescriptorSetLayout) \
+ M(vkAllocateDescriptorSets) \
+ M(vkUpdateDescriptorSets) \
+ M(vkCreatePipelineLayout) \
+ M(vkCreateComputePipelines) \
+ M(vkCmdBindPipeline) \
+ M(vkCmdBindDescriptorSets) \
+ M(vkCmdDispatch) \
+ M(vkDestroyPipeline) \
+ M(vkCreateShaderModule) \
+ /* */
+
+namespace renderer_test {
+
+class VKRenderer : public Renderer, public ShaderCompiler
+{
+public:
+
+ VkInstance instance;
+ VkPhysicalDevice physicalDevice;
+ VkPhysicalDeviceProperties deviceProperties;
+ VkPhysicalDeviceFeatures deviceFeatures;
+ VkPhysicalDeviceMemoryProperties deviceMemoryProperties;
+ VkPhysicalDeviceFeatures enabledFeatures;
+ VkDevice device;
+ VkQueue queue;
+ VkCommandPool commandPool;
+ VkSubmitInfo submitInfo;
+ VkDebugReportCallbackEXT debugReportCallback;
+
+
+#define DECLARE_PROC(NAME) PFN_##NAME NAME;
+ DECLARE_PROC(vkGetInstanceProcAddr);
+ FOREACH_GLOBAL_PROC(DECLARE_PROC)
+ FOREACH_INSTANCE_PROC(DECLARE_PROC)
+ FOREACH_DEVICE_PROC(DECLARE_PROC)
+#undef DECLARE_PROC
+
+ // Renderer interface
+
+ void checkResult(VkResult result)
+ {
+ assert(result == VK_SUCCESS);
+ }
+
+ VkBool32 handleDebugMessage(
+ VkDebugReportFlagsEXT flags,
+ VkDebugReportObjectTypeEXT objType,
+ uint64_t srcObject,
+ size_t location,
+ int32_t msgCode,
+ const char* pLayerPrefix,
+ const char* pMsg)
+ {
+ char const* severity = "message";
+ if(flags & VK_DEBUG_REPORT_WARNING_BIT_EXT)
+ severity = "warning";
+ if(flags & VK_DEBUG_REPORT_ERROR_BIT_EXT)
+ severity = "error";
+
+ char buffer[1024];
+ sprintf_s(buffer,
+ "%s: %s %d: %s\n",
+ pLayerPrefix,
+ severity,
+ msgCode,
+ pMsg);
+
+ fprintf(stderr, "%s", buffer);
+ fflush(stderr);
+
+ OutputDebugStringA(buffer);
+
+ return VK_FALSE;
+ }
+
+ static VKAPI_ATTR VkBool32 VKAPI_CALL debugMessageCallback(
+ VkDebugReportFlagsEXT flags,
+ VkDebugReportObjectTypeEXT objType,
+ uint64_t srcObject,
+ size_t location,
+ int32_t msgCode,
+ const char* pLayerPrefix,
+ const char* pMsg,
+ void* pUserData)
+ {
+ return ((VKRenderer*) pUserData)->handleDebugMessage(
+ flags, objType, srcObject, location, msgCode, pLayerPrefix, pMsg);
+ }
+
+ virtual void initialize(void* inWindowHandle) override
+ {
+ char const* dynamicLibraryName = "vulkan-1.dll";
+ HMODULE vulkan = LoadLibraryA(dynamicLibraryName);
+ if(!vulkan)
+ {
+ fprintf(stderr, "error: failed load '%s'\n", dynamicLibraryName);
+ exit(1);
+ }
+
+ vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr) GetProcAddress(vulkan, "vkGetInstanceProcAddr");
+ if(!vkGetInstanceProcAddr)
+ {
+ fprintf(stderr,
+ "error: failed load symbol 'vkGetInstanceProcAddr'\n");
+ exit(1);
+ }
+
+ VkApplicationInfo applicationInfo = { VK_STRUCTURE_TYPE_APPLICATION_INFO };
+ applicationInfo.pApplicationName = "slang-render-test";
+ applicationInfo.pEngineName = "slang-render-test";
+ applicationInfo.apiVersion = VK_API_VERSION_1_0;
+
+ char const* instanceExtensions[] = {
+ VK_KHR_SURFACE_EXTENSION_NAME,
+#ifdef _WIN32
+ VK_KHR_WIN32_SURFACE_EXTENSION_NAME,
+#else
+#endif
+
+#if ENABLE_VALIDATION_LAYER
+ VK_EXT_DEBUG_REPORT_EXTENSION_NAME,
+#endif
+ };
+
+ VkInstanceCreateInfo instanceCreateInfo = { VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO };
+ instanceCreateInfo.pApplicationInfo = &applicationInfo;
+
+ instanceCreateInfo.enabledExtensionCount = sizeof(instanceExtensions) / sizeof(instanceExtensions[0]);
+ instanceCreateInfo.ppEnabledExtensionNames = &instanceExtensions[0];
+
+#if ENABLE_VALIDATION_LAYER
+
+ uint32_t layerCount = 1;
+ const char *layerNames[] = {
+ "VK_LAYER_LUNARG_standard_validation"
+ };
+
+ instanceCreateInfo.enabledLayerCount = layerCount;
+ instanceCreateInfo.ppEnabledLayerNames = layerNames;
+#endif
+
+ instance = 0;
+
+#define LOAD_INSTANCE_PROC(NAME) NAME = (PFN_##NAME) vkGetInstanceProcAddr(instance, #NAME);
+
+ FOREACH_GLOBAL_PROC(LOAD_INSTANCE_PROC);
+
+ checkResult(vkCreateInstance(
+ &instanceCreateInfo,
+ nullptr,
+ &instance));
+
+ FOREACH_INSTANCE_PROC(LOAD_INSTANCE_PROC);
+
+#undef LOAD_INSTANCE_PROC
+
+
+#if ENABLE_VALIDATION_LAYER
+ VkDebugReportFlagsEXT debugFlags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT;
+
+ VkDebugReportCallbackCreateInfoEXT debugCreateInfo = { VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT };
+ debugCreateInfo.pfnCallback = &debugMessageCallback;
+ debugCreateInfo.pUserData = this;
+ debugCreateInfo.flags = debugFlags;
+
+ checkResult(vkCreateDebugReportCallbackEXT(
+ instance, &debugCreateInfo, nullptr, &debugReportCallback));
+
+#endif
+
+ uint32_t physicalDeviceCount = 0;
+ checkResult(vkEnumeratePhysicalDevices(
+ instance, &physicalDeviceCount, nullptr));
+
+ VkPhysicalDevice* physicalDevices = (VkPhysicalDevice*)alloca(
+ physicalDeviceCount * sizeof(VkPhysicalDevice));
+ checkResult(vkEnumeratePhysicalDevices(
+ instance, &physicalDeviceCount, physicalDevices));
+
+ uint32_t selectedDeviceIndex = 0;
+ // TODO: allow override of selected device
+ physicalDevice = physicalDevices[selectedDeviceIndex];
+
+ vkGetPhysicalDeviceProperties(physicalDevice, &deviceProperties);
+ vkGetPhysicalDeviceFeatures(physicalDevice, &deviceFeatures);
+ vkGetPhysicalDeviceMemoryProperties(physicalDevice, &deviceMemoryProperties);
+
+ uint32_t queueFamilyCount = 0;
+ vkGetPhysicalDeviceQueueFamilyProperties(
+ physicalDevice, &queueFamilyCount, nullptr);
+
+ VkQueueFamilyProperties* queueFamilies = (VkQueueFamilyProperties*)alloca(
+ queueFamilyCount * sizeof(VkQueueFamilyProperties));
+ vkGetPhysicalDeviceQueueFamilyProperties(
+ physicalDevice, &queueFamilyCount, queueFamilies);
+
+ // Find a queue that can service our needs
+ VkQueueFlags reqQueueFlags =
+ VK_QUEUE_GRAPHICS_BIT
+ | VK_QUEUE_COMPUTE_BIT;
+
+ uint32_t queueFamilyIndex = uint32_t(-1);
+ for (uint32_t qq = 0; qq < queueFamilyCount; ++qq)
+ {
+ if ((queueFamilies[qq].queueFlags & reqQueueFlags) == reqQueueFlags)
+ {
+ queueFamilyIndex = qq;
+ break;
+ }
+ }
+ assert(queueFamilyIndex < queueFamilyCount);
+
+ float queuePriority = 0.0f;
+ VkDeviceQueueCreateInfo queueCreateInfo = { VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO };
+ queueCreateInfo.queueFamilyIndex = queueFamilyIndex;
+ queueCreateInfo.queueCount = 1;
+ queueCreateInfo.pQueuePriorities = &queuePriority;
+
+ char const* const deviceExtensions[] =
+ {
+ VK_KHR_SWAPCHAIN_EXTENSION_NAME,
+ };
+
+ VkDeviceCreateInfo deviceCreateInfo = { VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO };
+ deviceCreateInfo.queueCreateInfoCount = 1;
+ deviceCreateInfo.pQueueCreateInfos = &queueCreateInfo;
+ deviceCreateInfo.pEnabledFeatures = &enabledFeatures;
+
+ deviceCreateInfo.enabledExtensionCount = sizeof(deviceExtensions) / sizeof(deviceExtensions[0]);
+ deviceCreateInfo.ppEnabledExtensionNames = &deviceExtensions[0];
+
+ checkResult(vkCreateDevice(
+ physicalDevice, &deviceCreateInfo, nullptr, &device));
+
+#define LOAD_DEVICE_PROC(NAME) NAME = (PFN_##NAME) vkGetDeviceProcAddr(device, #NAME);
+ FOREACH_DEVICE_PROC(LOAD_DEVICE_PROC)
+#undef LOAD_DEVICE_PROC
+
+ // Create a command pool
+
+ VkCommandPoolCreateInfo commandPoolCreateInfo = { VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO };
+ commandPoolCreateInfo.queueFamilyIndex = queueFamilyIndex;
+ commandPoolCreateInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
+
+ checkResult(vkCreateCommandPool(
+ device, &commandPoolCreateInfo, nullptr, &commandPool));
+
+ vkGetDeviceQueue(
+ device,
+ queueFamilyIndex,
+ 0,
+ &queue);
+
+ // set up swap chain
+
+ // create command buffers
+
+ // depth/stencil?
+
+ // render pass?
+
+ // pipeline cache
+
+ // frame buffer
+
+
+
+// create semaphores for sync
+
+
+ }
+
+ float clearColor[4];
+ virtual void setClearColor(float const* color) override
+ {
+ for(int ii = 0; ii < 4; ++ii)
+ clearColor[ii] = color[ii];
+ }
+
+ virtual void clearFrame() override
+ {
+ }
+
+ virtual void presentFrame() override
+ {
+ }
+
+ virtual void captureScreenShot(char const* outputPath) override
+ {
+ }
+
+ virtual ShaderCompiler* getShaderCompiler() override
+ {
+ return this;
+ }
+
+ VkCommandBuffer getCommandBuffer()
+ {
+ VkCommandBufferAllocateInfo info = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO };
+ info.commandPool = commandPool;
+ info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
+ info.commandBufferCount = 1;
+
+ VkCommandBuffer commandBuffer;
+ checkResult(vkAllocateCommandBuffers(
+ device, &info, &commandBuffer));
+
+ return commandBuffer;
+ }
+
+ VkCommandBuffer beginCommandBuffer()
+ {
+ VkCommandBuffer commandBuffer = getCommandBuffer();
+
+ VkCommandBufferBeginInfo beginInfo = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO };
+ checkResult(vkBeginCommandBuffer(commandBuffer, &beginInfo));
+
+ return commandBuffer;
+ }
+
+ void flushCommandBuffer(VkCommandBuffer commandBuffer)
+ {
+ checkResult(vkEndCommandBuffer(commandBuffer));
+
+ VkSubmitInfo submitInfo = { VK_STRUCTURE_TYPE_SUBMIT_INFO };
+ submitInfo.commandBufferCount = 1;
+ submitInfo.pCommandBuffers = &commandBuffer;
+
+ checkResult(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE));
+ checkResult(vkQueueWaitIdle(queue));
+
+ vkFreeCommandBuffers(device, commandPool, 1, &commandBuffer);
+ }
+
+ struct BufferImpl
+ {
+ VkBuffer buffer;
+ VkDeviceMemory memory;
+ };
+
+ BufferImpl createBufferImpl(
+ size_t bufferSize,
+ VkBufferUsageFlags usage,
+ VkMemoryPropertyFlags reqMemoryProperties,
+ void const* initData = nullptr)
+ {
+ if( initData )
+ {
+ // TODO: what if we are allocating it as CPU-writable anyway?
+ usage |= VK_BUFFER_USAGE_TRANSFER_DST_BIT;
+ }
+
+ VkBufferCreateInfo bufferCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+ bufferCreateInfo.size = bufferSize;
+ bufferCreateInfo.usage = usage;
+
+ VkBuffer buffer;
+ checkResult(vkCreateBuffer(
+ device, &bufferCreateInfo, nullptr, &buffer));
+
+ VkMemoryRequirements memoryReqs = {};
+ vkGetBufferMemoryRequirements(device, buffer, &memoryReqs);
+
+ uint32_t memoryTypeIndex = getMemoryTypeIndex(
+ memoryReqs.memoryTypeBits, reqMemoryProperties);
+
+ VkMemoryPropertyFlags actualMemoryProperites = deviceMemoryProperties.memoryTypes[memoryTypeIndex].propertyFlags;
+
+ VkMemoryAllocateInfo allocateInfo = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO };
+ allocateInfo.allocationSize = memoryReqs.size;
+ allocateInfo.memoryTypeIndex = memoryTypeIndex;
+
+ VkDeviceMemory memory;
+ checkResult(vkAllocateMemory(
+ device, &allocateInfo, nullptr, &memory));
+
+ checkResult(vkBindBufferMemory(
+ device, buffer, memory, 0));
+
+ if( initData )
+ {
+ // TODO: only create staging buffer if the memory type
+ // used for the buffer doesn't let us fill things in
+ // directly.
+
+ BufferImpl staging = createBufferImpl(
+ bufferSize,
+ VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
+ VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
+
+ // Copy into staging buffer
+ void* mappedData = nullptr;
+ checkResult(vkMapMemory(device, staging.memory, 0, bufferSize, 0, &mappedData));
+ memcpy(mappedData, initData, bufferSize);
+ vkUnmapMemory(device, staging.memory);
+
+ // Copy from staging buffer to real buffer
+ VkCommandBuffer commandBuffer = beginCommandBuffer();
+
+ VkBufferCopy copyInfo = {};
+ copyInfo.size = bufferSize;
+ vkCmdCopyBuffer(
+ commandBuffer,
+ staging.buffer,
+ buffer,
+ 1,
+ &copyInfo);
+
+ flushCommandBuffer(commandBuffer);
+
+ // Now destroy the staging buffer
+ vkDestroyBuffer(device, staging.buffer, nullptr);
+ vkFreeMemory(device, staging.memory, nullptr);
+ }
+
+ BufferImpl impl;
+ impl.buffer = buffer;
+ impl.memory = memory;
+ return impl;
+ }
+
+ virtual Buffer* createBuffer(BufferDesc const& desc) override
+ {
+ size_t bufferSize = desc.size;
+
+ VkBufferUsageFlags usage = 0;
+ VkMemoryPropertyFlags reqMemoryProperties = 0;
+
+ switch( desc.flavor )
+ {
+ case BufferFlavor::Constant:
+ usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
+ reqMemoryProperties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
+ break;
+
+ case BufferFlavor::Vertex:
+ usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
+ reqMemoryProperties = 0;
+ break;
+ }
+
+ BufferImpl bufferImpl = createBufferImpl(
+ bufferSize,
+ usage,
+ reqMemoryProperties,
+ desc.initData);
+
+ BufferImpl* bufferPtr = new BufferImpl();
+ *bufferPtr = bufferImpl;
+ return (Buffer*) bufferPtr;
+ }
+
+ struct InputLayoutImpl
+ {
+ };
+
+ virtual InputLayout* createInputLayout(InputElementDesc const* inputElements, UInt inputElementCount) override
+ {
+ InputLayoutImpl* impl = new InputLayoutImpl();
+
+ // TODO: actually initialize things
+
+ return (InputLayout*) impl;
+ }
+
+ virtual void* map(Buffer* buffer, MapFlavor flavor) override
+ {
+ return nullptr;
+ }
+
+ virtual void unmap(Buffer* buffer) override
+ {
+ }
+
+ virtual void setInputLayout(InputLayout* inputLayout) override
+ {
+ }
+
+ virtual void setPrimitiveTopology(PrimitiveTopology topology) override
+ {
+ }
+
+ virtual void setVertexBuffers(UInt startSlot, UInt slotCount, Buffer* const* buffers, UInt const* strides, UInt const* offsets) override
+ {
+ }
+
+ struct ShaderProgramImpl
+ {
+ VkPipelineShaderStageCreateInfo compute;
+ VkPipelineShaderStageCreateInfo vertex;
+ VkPipelineShaderStageCreateInfo fragment;
+ };
+
+ ShaderProgramImpl* currentProgram = nullptr;
+ virtual void setShaderProgram(ShaderProgram* program) override
+ {
+ currentProgram = (ShaderProgramImpl*) program;
+ }
+
+ virtual void setConstantBuffers(UInt startSlot, UInt slotCount, Buffer* const* buffers, UInt const* offsets) override
+ {
+ }
+
+ virtual void draw(UInt vertexCount, UInt startVertex = 0) override
+ {
+ }
+
+ struct BindingImpl
+ {
+ ShaderInputType type;
+ InputBufferType bufferType; // Only valid if `type` is `Buffer`
+
+ VkImageView srv;
+ VkBufferView uav;
+ VkBuffer buffer;
+ VkSampler samplerState;
+
+ int binding = 0;
+ bool isOutput = false;
+ int bufferLength = 0;
+ };
+
+ struct BindingStateImpl
+ {
+ Slang::List<BindingImpl> bindings;
+ int numRenderTargets;
+ };
+
+ uint32_t getMemoryTypeIndex(
+ uint32_t inTypeBits,
+ VkMemoryPropertyFlags properties)
+ {
+ uint32_t typeBits = inTypeBits;
+ uint32_t typeIndex = 0;
+ while( typeBits )
+ {
+ if((deviceMemoryProperties.memoryTypes[typeIndex].propertyFlags & properties) == properties)
+ {
+ return typeIndex;
+ }
+ typeIndex++;
+ typeBits >>= 1;
+ }
+
+ assert(!"failed to find a usable memory type");
+ return uint32_t(-1);
+ }
+
+ void createInputBuffer(
+ ShaderInputLayoutEntry const& entry,
+ InputBufferDesc const& bufferDesc,
+ Slang::List<unsigned int> const& bufferData,
+ VkBuffer &bufferOut,
+ VkBufferView &uavOut,
+ VkImageView &srvOut)
+ {
+ size_t bufferSize = bufferData.Count() * sizeof(unsigned int);
+ void const* initData = bufferData.Buffer();
+
+ VkBufferUsageFlags usage = 0;
+ VkMemoryPropertyFlags reqMemoryProperties = 0;
+
+ switch( bufferDesc.type )
+ {
+ case InputBufferType::ConstantBuffer:
+ usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
+ reqMemoryProperties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
+ break;
+
+ case InputBufferType::StorageBuffer:
+ usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
+ reqMemoryProperties = 0;
+ break;
+ }
+
+ // If we are going to read back from the buffer, be sure to request
+ // the required access.
+ if(entry.isOutput)
+ {
+ usage |= VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
+ }
+
+ BufferImpl bufferImpl = createBufferImpl(
+ bufferSize,
+ usage,
+ reqMemoryProperties,
+ initData);
+
+ // TODO: need to hang onto the `memory` field so
+ // that we can release it when we are done.
+
+ bufferOut = bufferImpl.buffer;
+
+ // Fill in any views needed
+ switch( bufferDesc.type )
+ {
+ case InputBufferType::ConstantBuffer:
+ break;
+
+ case InputBufferType::StorageBuffer:
+ {
+ }
+ break;
+ }
+ }
+
+ void createInputTexture(
+ InputTextureDesc const& inputDesc,
+ VkImageView& viewOut)
+ {
+ TextureData texData;
+ generateTextureData(texData, inputDesc);
+ assert(!"unimplemented");
+ }
+
+ void createInputSampler(
+ InputSamplerDesc const& inputDesc,
+ VkSampler& stateOut)
+ {
+ assert(!"unimplemented");
+ }
+
+ virtual BindingState* createBindingState(const ShaderInputLayout & layout)
+ {
+ BindingStateImpl* bindingState = new BindingStateImpl();
+ bindingState->numRenderTargets = layout.numRenderTargets;
+ for (auto & entry : layout.entries)
+ {
+ BindingImpl binding;
+ binding.type = entry.type;
+ binding.binding = entry.hlslBinding;
+ binding.isOutput = entry.isOutput;
+ switch (entry.type)
+ {
+ case ShaderInputType::Buffer:
+ {
+ createInputBuffer(entry, entry.bufferDesc, entry.bufferData, binding.buffer, binding.uav, binding.srv);
+ binding.bufferLength = (int)(entry.bufferData.Count() * sizeof(unsigned int));
+ binding.bufferType = entry.bufferDesc.type;
+ }
+ break;
+ case ShaderInputType::Texture:
+ {
+ createInputTexture(entry.textureDesc, binding.srv);
+ }
+ break;
+ case ShaderInputType::Sampler:
+ {
+ createInputSampler(entry.samplerDesc, binding.samplerState);
+ }
+ break;
+ case ShaderInputType::CombinedTextureSampler:
+ {
+ throw "not implemented";
+ }
+ break;
+ }
+ bindingState->bindings.Add(binding);
+ }
+
+ return (BindingState*) bindingState;
+ }
+
+ BindingStateImpl* currentBindingState = nullptr;
+ virtual void setBindingState(BindingState * state)
+ {
+ currentBindingState = (BindingStateImpl*) state;
+ }
+
+ virtual void serializeOutput(BindingState* s, const char * fileName)
+ {
+ auto state = (BindingStateImpl*) s;
+
+ FILE * f = fopen(fileName, "wb");
+ int id = 0;
+ for (auto& bb: state->bindings)
+ {
+ if (bb.isOutput)
+ {
+ if (bb.buffer)
+ {
+ // create staging buffer
+ size_t bufferSize = bb.bufferLength;
+ BufferImpl staging = createBufferImpl(
+ bufferSize,
+ VK_BUFFER_USAGE_TRANSFER_DST_BIT,
+ VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
+
+ // Copy from real buffer to staging buffer
+ VkCommandBuffer commandBuffer = beginCommandBuffer();
+
+ VkBufferCopy copyInfo = {};
+ copyInfo.size = bufferSize;
+ vkCmdCopyBuffer(
+ commandBuffer,
+ bb.buffer,
+ staging.buffer,
+ 1,
+ &copyInfo);
+
+ flushCommandBuffer(commandBuffer);
+
+ // Write out the data from the buffer
+ void* mappedData = nullptr;
+ checkResult(vkMapMemory(device, staging.memory, 0, bufferSize, 0, &mappedData));
+
+ auto ptr = (unsigned int *) mappedData;
+ for (auto i = 0u; i < bufferSize / sizeof(unsigned int); i++)
+ fprintf(f, "%X\n", ptr[i]);
+
+ vkUnmapMemory(device, staging.memory);
+
+ // Now destroy the staging buffer
+ vkDestroyBuffer(device, staging.buffer, nullptr);
+ vkFreeMemory(device, staging.memory, nullptr);
+ }
+ else
+ {
+ printf("invalid output type at %d.\n", id);
+ }
+ }
+ id++;
+ }
+ fclose(f);
+
+
+ }
+
+ virtual void dispatchCompute(int x, int y, int z) override
+ {
+
+
+ // HACK: create a new pipeline for every call
+
+ // First create a pipeline layout based on what is bound
+
+ Slang::List<VkDescriptorSetLayoutBinding> bindings;
+
+ for( auto bb : currentBindingState->bindings )
+ {
+ switch( bb.type )
+ {
+ case ShaderInputType::Buffer:
+ {
+ switch(bb.bufferType)
+ {
+ case InputBufferType::StorageBuffer:
+ {
+ VkDescriptorSetLayoutBinding binding = {};
+ binding.binding = bb.binding;
+ binding.descriptorCount = 1;
+ binding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
+ binding.stageFlags = VK_SHADER_STAGE_ALL;
+
+ bindings.Add(binding);
+ }
+ break;
+
+ default:
+ // handle other cases
+ break;
+ }
+ }
+ break;
+
+ default:
+ // TODO: handle the other cases
+ break;
+ }
+ }
+
+ VkDescriptorSetLayoutCreateInfo descriptorSetLayoutInfo = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO };
+ descriptorSetLayoutInfo.bindingCount = uint32_t(bindings.Count());
+ descriptorSetLayoutInfo.pBindings = bindings.Buffer();
+
+ VkDescriptorSetLayout descriptorSetLayout = 0;
+ checkResult(vkCreateDescriptorSetLayout(
+ device, &descriptorSetLayoutInfo, nullptr, &descriptorSetLayout));
+
+ // Create a descriptor pool for allocating sets
+
+ VkDescriptorPoolSize poolSizes[] =
+ {
+ { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 128 },
+ { VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 128 },
+ { VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 128 },
+ };
+
+ VkDescriptorPoolCreateInfo descriptorPoolInfo = { VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO };
+ descriptorPoolInfo.maxSets = 128; // TODO: actually pick a size
+ descriptorPoolInfo.poolSizeCount = sizeof(poolSizes) / sizeof(poolSizes[0]);
+ descriptorPoolInfo.pPoolSizes = poolSizes;
+
+ VkDescriptorPool descriptorPool;
+ checkResult(vkCreateDescriptorPool(
+ device, &descriptorPoolInfo, nullptr, &descriptorPool));
+
+ // Create a descriptor set based on our layout
+
+ VkDescriptorSetAllocateInfo descriptorSetAllocInfo = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO };
+ descriptorSetAllocInfo.descriptorPool = descriptorPool;
+ descriptorSetAllocInfo.descriptorSetCount = 1;
+ descriptorSetAllocInfo.pSetLayouts = &descriptorSetLayout;
+
+ VkDescriptorSet descriptorSet;
+ checkResult(vkAllocateDescriptorSets(
+ device, &descriptorSetAllocInfo, &descriptorSet));
+
+ // Fill in the descritpor set, using our binding information
+ for( auto bb : currentBindingState->bindings )
+ {
+ switch( bb.type )
+ {
+ case ShaderInputType::Buffer:
+ {
+ switch(bb.bufferType)
+ {
+ case InputBufferType::StorageBuffer:
+ {
+ VkDescriptorBufferInfo bufferInfo;
+ bufferInfo.buffer = bb.buffer;
+ bufferInfo.offset = 0;
+ bufferInfo.range = bb.bufferLength;
+
+ VkWriteDescriptorSet writeInfo = { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET };
+ writeInfo.descriptorCount = 1;
+ writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
+ writeInfo.dstSet = descriptorSet;
+ writeInfo.dstBinding = bb.binding;
+ writeInfo.dstArrayElement = 0;
+ writeInfo.pBufferInfo = &bufferInfo;
+
+ vkUpdateDescriptorSets(
+ device,
+ 1,
+ &writeInfo,
+ 0,
+ nullptr);
+ }
+ break;
+
+ default:
+ // handle other cases
+ break;
+ }
+ }
+ break;
+
+ default:
+ // TODO: handle the other cases
+ break;
+ }
+ }
+
+
+ // Create a pipeline layout based on our descriptor set layout(s)
+
+ VkPipelineLayoutCreateInfo pipelineLayoutInfo = { VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO };
+ pipelineLayoutInfo.setLayoutCount = 1;
+ pipelineLayoutInfo.pSetLayouts = &descriptorSetLayout;
+
+ VkPipelineLayout pipelineLayout = 0;
+ checkResult(vkCreatePipelineLayout(
+ device, &pipelineLayoutInfo, nullptr, &pipelineLayout));
+
+ // Then create a pipeline to use that layout
+
+ VkComputePipelineCreateInfo computePipelineInfo = { VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO };
+ computePipelineInfo.stage = currentProgram->compute;
+ computePipelineInfo.layout = pipelineLayout;
+
+ VkPipelineCache pipelineCache = 0;
+
+ VkPipeline pipeline;
+ checkResult(vkCreateComputePipelines(
+ device, pipelineCache, 1, &computePipelineInfo, nullptr, &pipeline));
+
+ // Also create descriptor sets based on the given pipeline layout
+
+ VkCommandBuffer commandBuffer = beginCommandBuffer();
+
+ vkCmdBindPipeline(
+ commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline);
+
+ vkCmdBindDescriptorSets(
+ commandBuffer,
+ VK_PIPELINE_BIND_POINT_COMPUTE,
+ pipelineLayout,
+ 0, 1,
+ &descriptorSet,
+ 0,
+ nullptr);
+
+ vkCmdDispatch(commandBuffer, x, y, z);
+
+ flushCommandBuffer(commandBuffer);
+
+ vkDestroyPipeline(device, pipeline, nullptr);
+
+ // TODO: need to free up the other resources too...
+ }
+
+ // ShaderCompiler interface
+
+ VkPipelineShaderStageCreateInfo compileEntryPoint(
+ ShaderCompileRequest::EntryPoint const& entryPointRequest,
+ VkShaderStageFlagBits stage)
+ {
+ char const* dataBegin = entryPointRequest.source.dataBegin;
+ char const* dataEnd = entryPointRequest.source.dataEnd;
+
+ // We need to make a copy of the code, since the Slang compiler
+ // will free the memory after a compile request is closed.
+ size_t codeSize = dataEnd - dataBegin;
+ char* codeBegin = (char*) malloc(codeSize);
+ memcpy(codeBegin, dataBegin, codeSize);
+
+ VkShaderModuleCreateInfo moduleCreateInfo = { VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO };
+ moduleCreateInfo.pCode = (uint32_t*) codeBegin;
+ moduleCreateInfo.codeSize = codeSize;
+
+ VkShaderModule module;
+ checkResult(vkCreateShaderModule(
+ device,
+ &moduleCreateInfo,
+ nullptr,
+ &module));
+
+ VkPipelineShaderStageCreateInfo shaderStageCreateInfo = { VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO };
+ shaderStageCreateInfo.stage = stage;
+
+ shaderStageCreateInfo.module = module;
+ shaderStageCreateInfo.pName = "main";
+ return shaderStageCreateInfo;
+ }
+
+ virtual ShaderProgram* compileProgram(ShaderCompileRequest const& request) override
+ {
+ ShaderProgramImpl* impl = new ShaderProgramImpl();
+
+ if( request.computeShader.name )
+ {
+ impl->compute = compileEntryPoint(
+ request.computeShader,
+ VK_SHADER_STAGE_COMPUTE_BIT);
+ }
+ else
+ {
+ impl->vertex = compileEntryPoint(
+ request.vertexShader,
+ VK_SHADER_STAGE_VERTEX_BIT);
+
+ impl->fragment = compileEntryPoint(
+ request.fragmentShader,
+ VK_SHADER_STAGE_FRAGMENT_BIT);
+ }
+
+ return (ShaderProgram*) impl;
+ }
+};
+
+
+
+Renderer* createVKRenderer()
+{
+ return new VKRenderer();
+}
+
+} // renderer_test
diff --git a/tools/render-test/render-vk.h b/tools/render-test/render-vk.h
new file mode 100644
index 000000000..7f6d789d0
--- /dev/null
+++ b/tools/render-test/render-vk.h
@@ -0,0 +1,10 @@
+// render-vk.h
+#pragma once
+
+namespace renderer_test {
+
+class Renderer;
+
+Renderer* createVKRenderer();
+
+} // renderer_test
diff --git a/tools/render-test/render.h b/tools/render-test/render.h
index 174ba0b7b..5eb0c967d 100644
--- a/tools/render-test/render.h
+++ b/tools/render-test/render.h
@@ -16,7 +16,14 @@ struct ShaderCompileRequest
struct SourceInfo
{
char const* path;
- char const* text;
+
+ // The data may either be source text (in which
+ // case it can be assumed to be nul-terminated with
+ // `dataEnd` pointing at the terminator), or
+ // raw binary data (in which case `dataEnd` points
+ // at the end of the buffer).
+ char const* dataBegin;
+ char const* dataEnd;
};
struct EntryPoint
diff --git a/tools/render-test/slang-support.cpp b/tools/render-test/slang-support.cpp
index 9263aa41b..a75e35bd4 100644
--- a/tools/render-test/slang-support.cpp
+++ b/tools/render-test/slang-support.cpp
@@ -63,24 +63,24 @@ struct SlangShaderCompilerWrapper : public ShaderCompiler
// active in each case.
vertexTranslationUnit = spAddTranslationUnit(slangRequest, sourceLanguage, nullptr);
- spAddTranslationUnitSourceString(slangRequest, vertexTranslationUnit, request.source.path, request.source.text);
+ spAddTranslationUnitSourceString(slangRequest, vertexTranslationUnit, request.source.path, request.source.dataBegin);
spTranslationUnit_addPreprocessorDefine(slangRequest, vertexTranslationUnit, "__GLSL_VERTEX__", "1");
vertexEntryPointName = "main";
fragmentTranslationUnit = spAddTranslationUnit(slangRequest, sourceLanguage, nullptr);
- spAddTranslationUnitSourceString(slangRequest, fragmentTranslationUnit, request.source.path, request.source.text);
+ spAddTranslationUnitSourceString(slangRequest, fragmentTranslationUnit, request.source.path, request.source.dataBegin);
spTranslationUnit_addPreprocessorDefine(slangRequest, fragmentTranslationUnit, "__GLSL_FRAGMENT__", "1");
fragmentEntryPointName = "main";
computeTranslationUnit = spAddTranslationUnit(slangRequest, sourceLanguage, nullptr);
- spAddTranslationUnitSourceString(slangRequest, computeTranslationUnit, request.source.path, request.source.text);
+ spAddTranslationUnitSourceString(slangRequest, computeTranslationUnit, request.source.path, request.source.dataBegin);
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);
+ spAddTranslationUnitSourceString(slangRequest, translationUnit, request.source.path, request.source.dataBegin);
vertexTranslationUnit = translationUnit;
fragmentTranslationUnit = translationUnit;
@@ -108,8 +108,11 @@ struct SlangShaderCompilerWrapper : public ShaderCompiler
if (!compileErr)
{
ShaderCompileRequest innerRequest = request;
- char const* computeCode = spGetEntryPointSource(slangRequest, computeEntryPoint);
- innerRequest.computeShader.source.text = computeCode;
+
+ size_t codeSize = 0;
+ char const* code = (char const*) spGetEntryPointCode(slangRequest, computeEntryPoint, &codeSize);
+ innerRequest.computeShader.source.dataBegin = code;
+ innerRequest.computeShader.source.dataEnd = code + codeSize;
result = innerCompiler->compileProgram(innerRequest);
}
}
@@ -129,11 +132,17 @@ struct SlangShaderCompilerWrapper : public ShaderCompiler
{
ShaderCompileRequest innerRequest = request;
- char const* vertexCode = spGetEntryPointSource(slangRequest, vertexEntryPoint);
- char const* fragmentCode = spGetEntryPointSource(slangRequest, fragmentEntryPoint);
+ size_t vertexCodeSize = 0;
+ char const* vertexCode = (char const*) spGetEntryPointCode(slangRequest, vertexEntryPoint, &vertexCodeSize);
+
+ size_t fragmentCodeSize = 0;
+ char const* fragmentCode = (char const*) spGetEntryPointCode(slangRequest, fragmentEntryPoint, &fragmentCodeSize);
+
+ innerRequest.vertexShader.source.dataBegin = vertexCode;
+ innerRequest.vertexShader.source.dataEnd = vertexCode + vertexCodeSize;
- innerRequest.vertexShader.source.text = vertexCode;
- innerRequest.fragmentShader.source.text = fragmentCode;
+ innerRequest.fragmentShader.source.dataBegin = fragmentCode;
+ innerRequest.fragmentShader.source.dataEnd = fragmentCode + fragmentCodeSize;
result = innerCompiler->compileProgram(innerRequest);
}
diff --git a/tools/slang-test/main.cpp b/tools/slang-test/main.cpp
index 5c05cc4ce..267f62bfe 100644
--- a/tools/slang-test/main.cpp
+++ b/tools/slang-test/main.cpp
@@ -1207,6 +1207,11 @@ TestResult runSlangComputeComparisonTest(TestInput& input)
return runComputeComparisonImpl(input, "-slang -compute", input.outputStem + ".expected.txt");
}
+TestResult runSlangComputeComparisonTestEx(TestInput& input)
+{
+ return runComputeComparisonImpl(input, "", input.outputStem + ".expected.txt");
+}
+
TestResult runHLSLComputeTest(TestInput& input)
{
return runComputeComparisonImpl(input, "-hlsl-rewrite -compute", input.outputStem + ".expected.txt");
@@ -1416,6 +1421,7 @@ TestResult runTest(
{ "COMPARE_HLSL_CROSS_COMPILE_RENDER", &runHLSLCrossCompileRenderComparisonTest},
{ "COMPARE_HLSL_GLSL_RENDER", &runHLSLAndGLSLComparisonTest },
{ "COMPARE_COMPUTE", runSlangComputeComparisonTest},
+ { "COMPARE_COMPUTE_EX", runSlangComputeComparisonTestEx},
{ "HLSL_COMPUTE", runHLSLComputeTest},
{ "COMPARE_RENDER_COMPUTE", &runSlangRenderComputeComparisonTest },
@@ -1425,6 +1431,7 @@ TestResult runTest(
{ "COMPARE_HLSL_CROSS_COMPILE_RENDER", &skipTest},
{ "COMPARE_HLSL_GLSL_RENDER", &skipTest },
{ "COMPARE_COMPUTE", &skipTest},
+ { "COMPARE_COMPUTE_EX", &skipTest},
{ "HLSL_COMPUTE", &skipTest},
{ "COMPARE_RENDER_COMPUTE", &skipTest },
#endif
@@ -1735,6 +1742,9 @@ int main(
/*auto computeTestCategory = */addTestCategory("compute", fullTestCategory);
+ auto vulkanTestCategory = addTestCategory("vulkan", fullTestCategory);
+
+
// An un-categorized test will always belong to the `full` category
defaultTestCategory = fullTestCategory;
@@ -1754,6 +1764,7 @@ int main(
if( options.outputMode == kOutputMode_AppVeyor )
{
options.excludeCategories.Add(renderTestCategory, renderTestCategory);
+ options.excludeCategories.Add(vulkanTestCategory, vulkanTestCategory);
}
TestContext context = { 0 };