summaryrefslogtreecommitdiff
path: root/tools/render-test
diff options
context:
space:
mode:
authorjsmall-nvidia <jsmall@nvidia.com>2018-03-21 14:28:43 -0400
committerTim Foley <tfoleyNV@users.noreply.github.com>2018-03-21 11:28:43 -0700
commitd421988f91d0d6fda78b9aea4cba763f9c662ffe (patch)
tree4207ebec4a744f67df540388133033753cffa359 /tools/render-test
parent98b8e0c809ceab84cee25389e54f3f37d220d95e (diff)
First pass impls on ComPtr and reorganise Renderer (#450)
* Fixed some small typos in api-users-guide.md * Fix some small typos in slang-test/main.cpp, render-test/render-d3d11.cpp * Remove exit() calls from test code. Added Slang::Result, which works in the same way as COM HRESULT. * FIx bug introduced when moving to Slang::Result - handling E_INVALIDARG on Dx11. * Fix the testing of feature levels on Dx11 renderer. * First attempt at README.md for slang-test. * Tidied up the slang-test README.md file. * Fix some small typos in tools/slang-test/main.cpp * Fix spaces -> tabs problems. Fix some small types. * Refactor Renderer implementations such that: * Class definition does not contain long implementation/s * Removed unused globals * Ordered implementation after class definition * Made renderer specific classes child classes, and use Impl postfix to differentiate * Converted tabs into spaces * First pass at Slang::ComPtr. Added slang-defines.h which sets up some fairly commonly used defines such as SLANG_FORCE_INLINE, compiler detection, os detection, and some other cross platform features.
Diffstat (limited to 'tools/render-test')
-rw-r--r--tools/render-test/render-d3d11.cpp1508
-rw-r--r--tools/render-test/render-d3d12.cpp421
-rw-r--r--tools/render-test/render-gl.cpp1109
-rw-r--r--tools/render-test/render-vk.cpp1398
-rw-r--r--tools/render-test/render.h42
5 files changed, 2248 insertions, 2230 deletions
diff --git a/tools/render-test/render-d3d11.cpp b/tools/render-test/render-d3d11.cpp
index ba8d9e46d..dc86e2e44 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"
@@ -40,61 +40,124 @@ using namespace Slang;
namespace renderer_test {
-struct D3DBinding
-{
- ShaderInputType type;
- InputBufferType bufferType; // Only valid if `type` is `Buffer`
- ID3D11ShaderResourceView * srv = nullptr;
- ID3D11UnorderedAccessView * uav = nullptr;
- ID3D11Buffer * buffer = nullptr;
- ID3D11SamplerState * samplerState = nullptr;
- int binding = 0;
- bool isOutput = false;
- int bufferLength = 0;
-};
-struct D3DBindingState
+//static char const* vertexEntryPointName = "vertexMain";
+//static char const* fragmentEntryPointName = "fragmentMain";
+
+//static char const* vertexProfileName = "vs_4_0";
+//static char const* fragmentProfileName = "ps_4_0";
+
+class D3D11Renderer : public Renderer, public ShaderCompiler
{
- List<D3DBinding> bindings;
- int numRenderTargets = 0;
-};
+public:
+ // Renderer implementation
+ virtual SlangResult initialize(void* inWindowHandle) override;
+ virtual void setClearColor(float const* color) override;
+ virtual void clearFrame() override;
+ virtual void presentFrame() override;
+ virtual SlangResult captureScreenShot(char const* outputPath) override;
+ virtual void serializeOutput(BindingState* state, const char * fileName) override;
+ virtual Buffer* createBuffer(BufferDesc const& desc) override;
+ virtual InputLayout* createInputLayout(InputElementDesc const* inputElements, UInt inputElementCount) override;
+ virtual BindingState * createBindingState(const ShaderInputLayout& layout) override;
+ virtual ShaderCompiler* getShaderCompiler() override;
+ virtual void* map(Buffer* buffer, MapFlavor flavor) override;
+ virtual void unmap(Buffer* buffer) override;
+ virtual void setInputLayout(InputLayout* inputLayout) override;
+ virtual void setPrimitiveTopology(PrimitiveTopology topology) override;
+ virtual void setBindingState(BindingState * state);
+ 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;
+
+ // ShaderCompiler implementation
+ virtual ShaderProgram* compileProgram(ShaderCompileRequest const& request) override;
-//
+ protected:
+ struct BindingImpl
+ {
+ ShaderInputType type;
+ InputBufferType bufferType; // Only valid if `type` is `Buffer`
+ ID3D11ShaderResourceView * srv = nullptr;
+ ID3D11UnorderedAccessView * uav = nullptr;
+ ID3D11Buffer * buffer = nullptr;
+ ID3D11SamplerState * samplerState = nullptr;
+ int binding = 0;
+ bool isOutput = false;
+ int bufferLength = 0;
+ };
+ struct BindingStateImpl
+ {
+ List<BindingImpl> bindings;
+ int numRenderTargets = 0;
+ };
+ struct ShaderProgramImpl
+ {
+ ID3D11VertexShader* dxVertexShader = nullptr;
+ ID3D11PixelShader* dxPixelShader = nullptr;
+ ID3D11ComputeShader* dxComputeShader = nullptr;
+ };
-//
+ struct BufferImpl
+ {
+ ID3D11Buffer* buffer = nullptr;
+ };
-// Global variabels for the various D3D11 API objects to be used for rendering
-ID3D11Buffer* dxConstantBuffer;
-ID3D11InputLayout* dxInputLayout;
-ID3D11Buffer* dxVertexBuffer;
-ID3D11VertexShader* dxVertexShader;
-ID3D11PixelShader* dxPixelShader;
+ /// Calculate size taking into account alignment. Alignment must be a power of 2
+ static UInt calcAligned(UInt size, UInt alignment) { return (size + alignment - 1) & ~(alignment - 1); }
+
+ static DXGI_FORMAT getMapFormat(Format format);
-// 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);
+ /// The Slang compiler currently generates HLSL source, so we'll need a utility
+ /// routine (defined later) to translate that into D3D11 shader bytecode.
+ /// Definition of the HLSL-to-bytecode compilation logic.
+ static ID3DBlob* compileHLSLShader(char const* sourcePath, char const* source, char const* entryPointName, char const* dxProfileName);
+ /// Capture a texture to a file
+ static HRESULT captureTextureToFile(ID3D11Device* dxDevice, ID3D11DeviceContext* dxContext, ID3D11Texture2D* dxTexture, char const* outputPath);
-static char const* vertexEntryPointName = "vertexMain";
-static char const* fragmentEntryPointName = "fragmentMain";
+ void* map(ID3D11Buffer * buffer, MapFlavor flavor);
+ void unmap(ID3D11Buffer * buffer);
-static char const* vertexProfileName = "vs_4_0";
-static char const* fragmentProfileName = "ps_4_0";
+ void createInputBuffer(InputBufferDesc & bufferDesc, List<unsigned int> & bufferData, ID3D11Buffer * &bufferOut,
+ ID3D11UnorderedAccessView * &viewOut, ID3D11ShaderResourceView * &srvOut);
-ID3DBlob* gVertexShaderBlob;
-ID3DBlob* gPixelShaderBlob;
+ void createInputTexture(const InputTextureDesc & inputDesc, ID3D11ShaderResourceView * &viewOut);
-//
-// Definition of the HLSL-to-bytecode compilation logic.
-//
-ID3DBlob* compileHLSLShader(
- char const* sourcePath,
- char const* source,
- char const* entryPointName,
- char const* dxProfileName )
+ void createInputSampler(const InputSamplerDesc & inputDesc, ID3D11SamplerState * & stateOut);
+
+ void applyBindingState(bool isCompute);
+
+ IDXGISwapChain* dxSwapChain = nullptr;
+ ID3D11Device* dxDevice = nullptr;
+ ID3D11DeviceContext* dxImmediateContext = nullptr;
+ ID3D11Texture2D* dxBackBufferTexture = nullptr;
+ List<ID3D11RenderTargetView*> dxRenderTargetViews;
+ List<ID3D11Texture2D*> dxRenderTargetTextures;
+ BindingStateImpl* currentBindings = nullptr;
+ float clearColor[4] = { 0, 0, 0, 0 };
+};
+
+Renderer* createD3D11Renderer()
+{
+ return new D3D11Renderer();
+}
+
+/* static */DXGI_FORMAT D3D11Renderer::getMapFormat(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;
+ }
+}
+
+/* static */ID3DBlob* D3D11Renderer::compileHLSLShader(char const* sourcePath, char const* source, char const* entryPointName, char const* dxProfileName)
{
// Rather than statically link against the `d3dcompile` library, we
// dynamically load it.
@@ -104,21 +167,21 @@ ID3DBlob* compileHLSLShader(
// on-the-fly like this
//
static pD3DCompile D3DCompile_ = nullptr;
- if( !D3DCompile_ )
+ if (!D3DCompile_)
{
// TODO(tfoley): maybe want to search for one of a few versions of the DLL
HMODULE d3dcompiler = LoadLibraryA("d3dcompiler_47.dll");
- if(!d3dcompiler)
+ if (!d3dcompiler)
{
fprintf(stderr, "error: failed load 'd3dcompiler_47.dll'\n");
return nullptr;
}
D3DCompile_ = (pD3DCompile)GetProcAddress(d3dcompiler, "D3DCompile");
- if( !D3DCompile_ )
+ if (!D3DCompile_)
{
fprintf(stderr, "error: failed load symbol 'D3DCompile'\n");
- return nullptr;
+ return nullptr;
}
}
@@ -155,7 +218,7 @@ ID3DBlob* compileHLSLShader(
// If the HLSL-to-bytecode compilation produced any diagnostic messages
// then we will print them out (whether or not the compilation failed).
- if( dxErrorBlob )
+ if (dxErrorBlob)
{
fputs(
(char const*)dxErrorBlob->GetBufferPointer(),
@@ -168,7 +231,7 @@ ID3DBlob* compileHLSLShader(
dxErrorBlob->Release();
}
- if( FAILED(hr) )
+ if (FAILED(hr))
{
return nullptr;
}
@@ -176,34 +239,26 @@ ID3DBlob* compileHLSLShader(
return dxShaderBlob;
}
-
-
-
-// Capture a texture to a file
-
-static HRESULT captureTextureToFile(
- ID3D11Device* dxDevice,
- ID3D11DeviceContext* dxContext,
- ID3D11Texture2D* dxTexture,
- char const* outputPath)
+/* static */HRESULT D3D11Renderer::captureTextureToFile(ID3D11Device* dxDevice, ID3D11DeviceContext* dxContext,
+ ID3D11Texture2D* dxTexture, char const* outputPath)
{
- if(!dxContext) return E_INVALIDARG;
- if(!dxTexture) return E_INVALIDARG;
+ if (!dxContext) return E_INVALIDARG;
+ if (!dxTexture) return E_INVALIDARG;
D3D11_TEXTURE2D_DESC dxTextureDesc;
dxTexture->GetDesc(&dxTextureDesc);
// Don't bother supporting MSAA for right now
- if( dxTextureDesc.SampleDesc.Count > 1 )
+ if (dxTextureDesc.SampleDesc.Count > 1)
{
- fprintf(stderr, "ERROR: cannot capture multisample texture\n");
+ fprintf(stderr, "ERROR: cannot capture multi-sample texture\n");
return E_INVALIDARG;
}
HRESULT hr = S_OK;
ID3D11Texture2D* dxStagingTexture = nullptr;
- if( dxTextureDesc.Usage == D3D11_USAGE_STAGING && (dxTextureDesc.CPUAccessFlags & D3D11_CPU_ACCESS_READ) )
+ if (dxTextureDesc.Usage == D3D11_USAGE_STAGING && (dxTextureDesc.CPUAccessFlags & D3D11_CPU_ACCESS_READ))
{
dxStagingTexture = dxTexture;
dxStagingTexture->AddRef();
@@ -217,12 +272,12 @@ static HRESULT captureTextureToFile(
dxTextureDesc.Usage = D3D11_USAGE_STAGING;
hr = dxDevice->CreateTexture2D(&dxTextureDesc, 0, &dxStagingTexture);
- if( FAILED(hr) )
+ if (FAILED(hr))
{
fprintf(stderr, "ERROR: failed to create staging texture\n");
return hr;
}
-
+
dxContext->CopyResource(dxStagingTexture, dxTexture);
}
@@ -230,240 +285,215 @@ static HRESULT captureTextureToFile(
D3D11_MAPPED_SUBRESOURCE dxMappedResource;
hr = dxContext->Map(dxStagingTexture, 0, D3D11_MAP_READ, 0, &dxMappedResource);
- if( FAILED(hr) )
+ if (FAILED(hr))
{
fprintf(stderr, "ERROR: failed to map texture for read\n");
return hr;
}
- int stbResult = stbi_write_png(
- outputPath,
- dxTextureDesc.Width,
- dxTextureDesc.Height,
- 4,
- dxMappedResource.pData,
- dxMappedResource.RowPitch);
- if( !stbResult )
+ int stbResult = stbi_write_png(outputPath, dxTextureDesc.Width, dxTextureDesc.Height, 4,
+ dxMappedResource.pData, dxMappedResource.RowPitch);
+
+ // Make sure to unmap
+ dxContext->Unmap(dxStagingTexture, 0);
+ dxStagingTexture->Release();
+
+ if (!stbResult)
{
fprintf(stderr, "ERROR: failed to write texture to file\n");
return E_UNEXPECTED;
}
- dxContext->Unmap(dxStagingTexture, 0);
-
- dxStagingTexture->Release();
-
return S_OK;
}
-//
+// !!!!!!!!!!!!!!!!!!!!!!!!!!!! Renderer interface !!!!!!!!!!!!!!!!!!!!!!!!!!
-class D3D11Renderer : public Renderer, public ShaderCompiler
+SlangResult D3D11Renderer::initialize(void* inWindowHandle)
{
-public:
- IDXGISwapChain* dxSwapChain = nullptr;
- ID3D11Device* dxDevice = nullptr;
- ID3D11DeviceContext* dxImmediateContext = nullptr;
- ID3D11Texture2D* dxBackBufferTexture = nullptr;
- List<ID3D11RenderTargetView*> dxRenderTargetViews;
- List<ID3D11Texture2D *> dxRenderTargetTextures;
- D3DBindingState * currentBindings = nullptr;
- virtual SlangResult initialize(void* inWindowHandle) override
+ auto windowHandle = (HWND)inWindowHandle;
+ // Rather than statically link against D3D, we load it dynamically.
+
+ HMODULE d3d11 = LoadLibraryA("d3d11.dll");
+ if (!d3d11)
{
- auto windowHandle = (HWND) inWindowHandle;
- // Rather than statically link against D3D, we load it dynamically.
+ fprintf(stderr, "error: failed load 'd3d11.dll'\n");
+ return SLANG_FAIL;
+ }
- HMODULE d3d11 = LoadLibraryA("d3d11.dll");
- if(!d3d11)
- {
- fprintf(stderr, "error: failed load 'd3d11.dll'\n");
- return SLANG_FAIL;
- }
+ PFN_D3D11_CREATE_DEVICE_AND_SWAP_CHAIN D3D11CreateDeviceAndSwapChain_ =
+ (PFN_D3D11_CREATE_DEVICE_AND_SWAP_CHAIN)GetProcAddress(d3d11, "D3D11CreateDeviceAndSwapChain");
+ if (!D3D11CreateDeviceAndSwapChain_)
+ {
+ fprintf(stderr,
+ "error: failed load symbol 'D3D11CreateDeviceAndSwapChain'\n");
+ return SLANG_FAIL;
+ }
- PFN_D3D11_CREATE_DEVICE_AND_SWAP_CHAIN D3D11CreateDeviceAndSwapChain_ =
- (PFN_D3D11_CREATE_DEVICE_AND_SWAP_CHAIN)GetProcAddress(d3d11, "D3D11CreateDeviceAndSwapChain");
- if(!D3D11CreateDeviceAndSwapChain_)
- {
- fprintf(stderr,
- "error: failed load symbol 'D3D11CreateDeviceAndSwapChain'\n");
- return SLANG_FAIL;
- }
+ // We create our device in debug mode, just so that we can check that the
+ // example doesn't trigger warnings.
+ UINT deviceFlags = 0;
+ deviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
+
+
+ // Our swap chain uses RGBA8 with sRGB, with double buffering.
+
+ DXGI_SWAP_CHAIN_DESC dxSwapChainDesc = { 0 };
+ dxSwapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
+
+ // Note(tfoley): Disabling sRGB for DX back buffer for now, so that we
+ // can get consistent output with OpenGL, where setting up sRGB will
+ // probably be more involved.
+ // dxSwapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
+ dxSwapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+
+ dxSwapChainDesc.SampleDesc.Count = 1;
+ dxSwapChainDesc.SampleDesc.Quality = 0;
+ dxSwapChainDesc.BufferCount = 2;
+ dxSwapChainDesc.OutputWindow = windowHandle;
+ dxSwapChainDesc.Windowed = TRUE;
+ dxSwapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
+ dxSwapChainDesc.Flags = 0;
+
+ // We will ask for the highest feature level that can be supported.
+ D3D_FEATURE_LEVEL featureLevels[] = {
+ D3D_FEATURE_LEVEL_11_1,
+ D3D_FEATURE_LEVEL_11_0,
+ D3D_FEATURE_LEVEL_10_1,
+ D3D_FEATURE_LEVEL_10_0,
+ D3D_FEATURE_LEVEL_9_3,
+ D3D_FEATURE_LEVEL_9_2,
+ D3D_FEATURE_LEVEL_9_1,
+ };
+ D3D_FEATURE_LEVEL dxFeatureLevel = D3D_FEATURE_LEVEL_9_1;
+ const int totalNumFeatureLevels = sizeof(featureLevels) / sizeof(featureLevels[0]);
+
+ // On a machine that does not have an up-to-date version of D3D installed,
+ // the `D3D11CreateDeviceAndSwapChain` call will fail with `E_INVALIDARG`
+ // if you ask for featuer level 11_1. The workaround is to call
+ // `D3D11CreateDeviceAndSwapChain` up to twice: the first time with 11_1
+ // at the start of the list of requested feature levels, and the second
+ // time without it.
- // We create our device in debug mode, just so that we can check that the
- // example doesn't trigger warnings.
- UINT deviceFlags = 0;
- deviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
-
-
- // Our swap chain uses RGBA8 with sRGB, with double buffering.
-
- DXGI_SWAP_CHAIN_DESC dxSwapChainDesc = { 0 };
- dxSwapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
-
- // Note(tfoley): Disabling sRGB for DX back buffer for now, so that we
- // can get consistent output with OpenGL, where setting up sRGB will
- // probably be more involved.
-// dxSwapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
- dxSwapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
-
- dxSwapChainDesc.SampleDesc.Count = 1;
- dxSwapChainDesc.SampleDesc.Quality = 0;
- dxSwapChainDesc.BufferCount = 2;
- dxSwapChainDesc.OutputWindow = windowHandle;
- dxSwapChainDesc.Windowed = TRUE;
- dxSwapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
- dxSwapChainDesc.Flags = 0;
-
- // We will ask for the highest feature level that can be supported.
- D3D_FEATURE_LEVEL featureLevels[] = {
- D3D_FEATURE_LEVEL_11_1,
- D3D_FEATURE_LEVEL_11_0,
- D3D_FEATURE_LEVEL_10_1,
- D3D_FEATURE_LEVEL_10_0,
- D3D_FEATURE_LEVEL_9_3,
- D3D_FEATURE_LEVEL_9_2,
- D3D_FEATURE_LEVEL_9_1,
- };
- D3D_FEATURE_LEVEL dxFeatureLevel = D3D_FEATURE_LEVEL_9_1;
- const int totalNumFeatureLevels = sizeof(featureLevels) / sizeof(featureLevels[0]);
-
- // On a machine that does not have an up-to-date version of D3D installed,
- // the `D3D11CreateDeviceAndSwapChain` call will fail with `E_INVALIDARG`
- // if you ask for featuer level 11_1. The workaround is to call
- // `D3D11CreateDeviceAndSwapChain` up to twice: the first time with 11_1
- // at the start of the list of requested feature levels, and the second
- // time without it.
-
- for( int ii = 0; ii < 2; ++ii )
+ for (int ii = 0; ii < 2; ++ii)
+ {
+ const HRESULT hr = D3D11CreateDeviceAndSwapChain_(
+ NULL, // adapter (use default)
+ D3D_DRIVER_TYPE_REFERENCE,
+ //D3D_DRIVER_TYPE_HARDWARE,
+ NULL, // software
+ deviceFlags,
+ &featureLevels[ii],
+ totalNumFeatureLevels - ii,
+ D3D11_SDK_VERSION,
+ &dxSwapChainDesc,
+ &dxSwapChain,
+ &dxDevice,
+ &dxFeatureLevel,
+ &dxImmediateContext);
+
+ // Failures with `E_INVALIDARG` might be due to feature level 11_1
+ // not being supported.
+ if (hr == E_INVALIDARG)
{
- const HRESULT hr = D3D11CreateDeviceAndSwapChain_(
- NULL, // adapter (use default)
- D3D_DRIVER_TYPE_REFERENCE,
- //D3D_DRIVER_TYPE_HARDWARE,
- NULL, // software
- deviceFlags,
- &featureLevels[ii],
- totalNumFeatureLevels - ii,
- D3D11_SDK_VERSION,
- &dxSwapChainDesc,
- &dxSwapChain,
- &dxDevice,
- &dxFeatureLevel,
- &dxImmediateContext);
-
- // Failures with `E_INVALIDARG` might be due to feature level 11_1
- // not being supported.
- if (hr == E_INVALIDARG)
- {
- continue;
- }
-
- // Other failures are real, though.
- SLANG_RETURN_ON_FAIL(hr);
- // We must have a swap chain
- break;
+ continue;
}
-
- // After we've created the swap chain, we can request a pointer to the
- // back buffer as a D3D11 texture, and create a render-target view from it.
- static const IID kIID_ID3D11Texture2D = {
- 0x6f15aaf2, 0xd208, 0x4e89, 0x9a, 0xb4, 0x48,
- 0x95, 0x35, 0xd3, 0x4f, 0x9c };
+ // Other failures are real, though.
+ SLANG_RETURN_ON_FAIL(hr);
+ // We must have a swap chain
+ break;
+ }
- SLANG_RETURN_ON_FAIL(dxSwapChain->GetBuffer(0, kIID_ID3D11Texture2D, (void**)&dxBackBufferTexture));
+ // After we've created the swap chain, we can request a pointer to the
+ // back buffer as a D3D11 texture, and create a render-target view from it.
- for (int i = 0; i < 8; i++)
- {
- ID3D11Texture2D* texture;
- D3D11_TEXTURE2D_DESC textureDesc;
- dxBackBufferTexture->GetDesc(&textureDesc);
- SLANG_RETURN_ON_FAIL(dxDevice->CreateTexture2D(&textureDesc, nullptr, &texture));
-
- ID3D11RenderTargetView * rtv;
- D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
- rtvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
- rtvDesc.Texture2D.MipSlice = 0;
- rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
- SLANG_RETURN_ON_FAIL(dxDevice->CreateRenderTargetView(texture, &rtvDesc, &rtv));
-
- dxRenderTargetViews.Add(rtv);
- dxRenderTargetTextures.Add(texture);
- }
+ static const IID kIID_ID3D11Texture2D = {
+ 0x6f15aaf2, 0xd208, 0x4e89, 0x9a, 0xb4, 0x48,
+ 0x95, 0x35, 0xd3, 0x4f, 0x9c };
- dxImmediateContext->OMSetRenderTargets((UINT)dxRenderTargetViews.Count(), dxRenderTargetViews.Buffer(), nullptr);
-
- // Similarly, we are going to set up a viewport once, and then never
- // switch, since this is a simple test app.
- D3D11_VIEWPORT dxViewport;
- dxViewport.TopLeftX = 0;
- dxViewport.TopLeftY = 0;
- dxViewport.Width = (float) gWindowWidth;
- dxViewport.Height = (float) gWindowHeight;
- dxViewport.MaxDepth = 1; // TODO(tfoley): use reversed depth
- dxViewport.MinDepth = 0;
- dxImmediateContext->RSSetViewports(1, &dxViewport);
-
- return SLANG_OK;
- }
+ SLANG_RETURN_ON_FAIL(dxSwapChain->GetBuffer(0, kIID_ID3D11Texture2D, (void**)&dxBackBufferTexture));
- float clearColor[4] = { 0, 0, 0, 0 };
- virtual void setClearColor(float const* color) override
+ for (int i = 0; i < 8; i++)
{
- memcpy(clearColor, color, sizeof(clearColor));
+ ID3D11Texture2D* texture;
+ D3D11_TEXTURE2D_DESC textureDesc;
+ dxBackBufferTexture->GetDesc(&textureDesc);
+ SLANG_RETURN_ON_FAIL(dxDevice->CreateTexture2D(&textureDesc, nullptr, &texture));
+
+ ID3D11RenderTargetView * rtv;
+ D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+ rtvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+ rtvDesc.Texture2D.MipSlice = 0;
+ rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
+ SLANG_RETURN_ON_FAIL(dxDevice->CreateRenderTargetView(texture, &rtvDesc, &rtv));
+
+ dxRenderTargetViews.Add(rtv);
+ dxRenderTargetTextures.Add(texture);
}
- virtual void clearFrame() override
- {
- for (auto i = 0u; i < dxRenderTargetViews.Count(); i++)
- dxImmediateContext->ClearRenderTargetView(
- dxRenderTargetViews[i],
- clearColor);
- }
+ dxImmediateContext->OMSetRenderTargets((UINT)dxRenderTargetViews.Count(), dxRenderTargetViews.Buffer(), nullptr);
- virtual void presentFrame() override
- {
- dxImmediateContext->CopyResource(dxBackBufferTexture, dxRenderTargetTextures[0]);
- dxSwapChain->Present(0, 0);
- }
+ // Similarly, we are going to set up a viewport once, and then never
+ // switch, since this is a simple test app.
+ D3D11_VIEWPORT dxViewport;
+ dxViewport.TopLeftX = 0;
+ dxViewport.TopLeftY = 0;
+ dxViewport.Width = (float)gWindowWidth;
+ dxViewport.Height = (float)gWindowHeight;
+ dxViewport.MaxDepth = 1; // TODO(tfoley): use reversed depth
+ dxViewport.MinDepth = 0;
+ dxImmediateContext->RSSetViewports(1, &dxViewport);
- virtual SlangResult captureScreenShot(char const* outputPath) override
- {
- HRESULT hr = captureTextureToFile(
- dxDevice,
- dxImmediateContext,
- dxRenderTargetTextures[0],
- outputPath);
- if( FAILED(hr) )
- {
- fprintf(stderr, "error: could not capture screenshot to '%s'\n", outputPath);
- SLANG_RETURN_ON_FAIL(hr);
- }
- return SLANG_OK;
- }
+ return SLANG_OK;
+}
- virtual ShaderCompiler* getShaderCompiler() override
- {
- return this;
- }
+void D3D11Renderer::setClearColor(float const* color)
+{
+ memcpy(clearColor, color, sizeof(clearColor));
+}
- struct D3DBuffer
- {
- ID3D11Buffer * buffer = nullptr;
- };
+void D3D11Renderer::clearFrame()
+{
+ for (auto i = 0u; i < dxRenderTargetViews.Count(); i++)
+ dxImmediateContext->ClearRenderTargetView(
+ dxRenderTargetViews[i],
+ clearColor);
+}
+
+void D3D11Renderer::presentFrame()
+{
+ dxImmediateContext->CopyResource(dxBackBufferTexture, dxRenderTargetTextures[0]);
+ dxSwapChain->Present(0, 0);
+}
- UInt RoundUpToAlignment(UInt size, UInt alignment)
+SlangResult D3D11Renderer::captureScreenShot(char const* outputPath)
+{
+ HRESULT hr = captureTextureToFile(
+ dxDevice,
+ dxImmediateContext,
+ dxRenderTargetTextures[0],
+ outputPath);
+ if (FAILED(hr))
{
- return ((size + alignment - 1) / alignment) * alignment;
+ fprintf(stderr, "error: could not capture screen-shot to '%s'\n", outputPath);
+ SLANG_RETURN_ON_FAIL(hr);
}
+ return SLANG_OK;
+}
- virtual Buffer* createBuffer(BufferDesc const& desc) override
- {
- D3D11_BUFFER_DESC dxBufferDesc = { 0 };
- dxBufferDesc.ByteWidth = (UINT)RoundUpToAlignment(desc.size, 256);
+ShaderCompiler* D3D11Renderer::getShaderCompiler()
+{
+ return this;
+}
- switch( desc.flavor )
- {
+Buffer* D3D11Renderer::createBuffer(BufferDesc const& desc)
+{
+ D3D11_BUFFER_DESC dxBufferDesc = { 0 };
+ dxBufferDesc.ByteWidth = (UINT)calcAligned(desc.size, 256);
+
+ switch (desc.flavor)
+ {
case BufferFlavor::Constant:
dxBufferDesc.Usage = D3D11_USAGE_DYNAMIC;
dxBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
@@ -477,64 +507,47 @@ public:
break;
default:
return nullptr;
- }
+ }
- D3D11_SUBRESOURCE_DATA dxInitData = { 0 };
- dxInitData.pSysMem = desc.initData;
+ D3D11_SUBRESOURCE_DATA dxInitData = { 0 };
+ dxInitData.pSysMem = desc.initData;
+ ID3D11Buffer* dxBuffer = nullptr;
+ HRESULT hr = dxDevice->CreateBuffer(&dxBufferDesc, desc.initData ? &dxInitData : nullptr, &dxBuffer);
+ if (FAILED(hr)) return nullptr;
- ID3D11Buffer* dxBuffer = nullptr;
- HRESULT hr = dxDevice->CreateBuffer(
- &dxBufferDesc,
- desc.initData ? &dxInitData : nullptr,
- &dxBuffer);
- if(FAILED(hr)) return nullptr;
+ BufferImpl* rs = new BufferImpl;
+ rs->buffer = dxBuffer;
+ return (Buffer*)rs;
+}
- D3DBuffer * rs = new D3DBuffer();
- rs->buffer = dxBuffer;
- return (Buffer*) rs;
- }
+InputLayout* D3D11Renderer::createInputLayout(InputElementDesc const* inputElements, UInt inputElementCount)
+{
+ D3D11_INPUT_ELEMENT_DESC dxInputElements[16] = {};
- static DXGI_FORMAT mapFormat(Format format)
+ char hlslBuffer[1024];
+ char* hlslCursor = &hlslBuffer[0];
+
+ hlslCursor += sprintf(hlslCursor, "float4 main(\n");
+
+ for (UInt ii = 0; ii < inputElementCount; ++ii)
{
- switch( format )
+ dxInputElements[ii].SemanticName = inputElements[ii].semanticName;
+ dxInputElements[ii].SemanticIndex = (UINT)inputElements[ii].semanticIndex;
+ dxInputElements[ii].Format = getMapFormat(inputElements[ii].format);
+ dxInputElements[ii].InputSlot = 0;
+ dxInputElements[ii].AlignedByteOffset = (UINT)inputElements[ii].offset;
+ dxInputElements[ii].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
+ dxInputElements[ii].InstanceDataStepRate = 0;
+
+ if (ii != 0)
{
- case Format::RGB_Float32:
- return DXGI_FORMAT_R32G32B32_FLOAT;
- case Format::RG_Float32:
- return DXGI_FORMAT_R32G32_FLOAT;
- default:
- return DXGI_FORMAT_UNKNOWN;
+ hlslCursor += sprintf(hlslCursor, ",\n");
}
- }
-
- virtual InputLayout* createInputLayout(InputElementDesc const* inputElements, UInt inputElementCount) override
- {
- D3D11_INPUT_ELEMENT_DESC dxInputElements[16] = {};
-
- char hlslBuffer[1024];
- char* hlslCursor = &hlslBuffer[0];
-
- hlslCursor += sprintf(hlslCursor, "float4 main(\n");
- for( UInt ii = 0; ii < inputElementCount; ++ii )
+ char const* typeName = "Unknown";
+ switch (inputElements[ii].format)
{
- dxInputElements[ii].SemanticName = inputElements[ii].semanticName;
- dxInputElements[ii].SemanticIndex = (UINT) inputElements[ii].semanticIndex;
- dxInputElements[ii].Format = mapFormat(inputElements[ii].format);
- dxInputElements[ii].InputSlot = 0;
- dxInputElements[ii].AlignedByteOffset = (UINT) inputElements[ii].offset;
- dxInputElements[ii].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
- dxInputElements[ii].InstanceDataStepRate = 0;
-
- if(ii != 0)
- {
- hlslCursor+= sprintf(hlslCursor, ",\n");
- }
-
- char const* typeName = "Unknown";
- switch(inputElements[ii].format)
- {
case Format::RGB_Float32:
typeName = "float3";
break;
@@ -543,46 +556,46 @@ public:
break;
default:
return nullptr;
- }
-
- hlslCursor+= sprintf(hlslCursor, "%s a%d : %s%d",
- typeName,
- (int) ii,
- inputElements[ii].semanticName,
- (int) inputElements[ii].semanticIndex);
}
- hlslCursor += sprintf(hlslCursor, "\n) : SV_Position { return 0; }");
+ hlslCursor += sprintf(hlslCursor, "%s a%d : %s%d",
+ typeName,
+ (int)ii,
+ inputElements[ii].semanticName,
+ (int)inputElements[ii].semanticIndex);
+ }
- auto dxVertexShaderBlob = compileHLSLShader("inputLayout", hlslBuffer, "main", "vs_5_0");
- if(!dxVertexShaderBlob)
- return nullptr;
+ hlslCursor += sprintf(hlslCursor, "\n) : SV_Position { return 0; }");
- ID3D11InputLayout* dxInputLayout = nullptr;
- HRESULT hr = dxDevice->CreateInputLayout(
- &dxInputElements[0],
- (UINT) inputElementCount,
- dxVertexShaderBlob->GetBufferPointer(),
- dxVertexShaderBlob->GetBufferSize(),
- &dxInputLayout);
+ auto dxVertexShaderBlob = compileHLSLShader("inputLayout", hlslBuffer, "main", "vs_5_0");
+ if (!dxVertexShaderBlob)
+ return nullptr;
- dxVertexShaderBlob->Release();
+ ID3D11InputLayout* dxInputLayout = nullptr;
+ HRESULT hr = dxDevice->CreateInputLayout(
+ &dxInputElements[0],
+ (UINT)inputElementCount,
+ dxVertexShaderBlob->GetBufferPointer(),
+ dxVertexShaderBlob->GetBufferSize(),
+ &dxInputLayout);
- if(FAILED(hr))
- return nullptr;
+ dxVertexShaderBlob->Release();
- return (InputLayout*) dxInputLayout;
- }
+ if (FAILED(hr))
+ return nullptr;
- void* map(ID3D11Buffer * buffer, MapFlavor flavor)
- {
- auto dxContext = dxImmediateContext;
+ return (InputLayout*)dxInputLayout;
+}
- auto dxBuffer = buffer;
+void* D3D11Renderer::map(ID3D11Buffer * buffer, MapFlavor flavor)
+{
+ auto dxContext = dxImmediateContext;
- D3D11_MAP dxMapFlavor;
- switch (flavor)
- {
+ auto dxBuffer = buffer;
+
+ D3D11_MAP dxMapFlavor;
+ switch (flavor)
+ {
case MapFlavor::WriteDiscard:
dxMapFlavor = D3D11_MAP_WRITE_DISCARD;
break;
@@ -594,395 +607,380 @@ public:
break;
default:
return nullptr;
- }
+ }
- // We update our constant buffer per-frame, just for the purposes
- // of the example, but we don't actually load different data
- // per-frame (we always use an identity projection).
- D3D11_MAPPED_SUBRESOURCE dxMapped;
- HRESULT hr = dxContext->Map(dxBuffer, 0, dxMapFlavor, 0, &dxMapped);
- if (FAILED(hr))
- return nullptr;
+ // We update our constant buffer per-frame, just for the purposes
+ // of the example, but we don't actually load different data
+ // per-frame (we always use an identity projection).
+ D3D11_MAPPED_SUBRESOURCE dxMapped;
+ HRESULT hr = dxContext->Map(dxBuffer, 0, dxMapFlavor, 0, &dxMapped);
+ if (FAILED(hr))
+ return nullptr;
- return dxMapped.pData;
- }
+ return dxMapped.pData;
+}
- virtual void* map(Buffer* buffer, MapFlavor flavor) override
- {
- return map(((D3DBuffer*)buffer)->buffer, flavor);
- }
+void* D3D11Renderer::map(Buffer* buffer, MapFlavor flavor)
+{
+ return map(((BufferImpl*)buffer)->buffer, flavor);
+}
- void unmap(ID3D11Buffer * buffer)
- {
- auto dxContext = dxImmediateContext;
- dxContext->Unmap(buffer, 0);
- }
+void D3D11Renderer::unmap(ID3D11Buffer * buffer)
+{
+ auto dxContext = dxImmediateContext;
+ dxContext->Unmap(buffer, 0);
+}
- virtual void unmap(Buffer* buffer) override
- {
- auto dxBuffer = ((D3DBuffer*)buffer)->buffer;
- unmap(dxBuffer);
- }
+void D3D11Renderer::unmap(Buffer* buffer)
+{
+ auto dxBuffer = ((BufferImpl*)buffer)->buffer;
+ unmap(dxBuffer);
+}
- virtual void setInputLayout(InputLayout* inputLayout) override
- {
- auto dxContext = dxImmediateContext;
- auto dxInputLayout = (ID3D11InputLayout*) inputLayout;
+void D3D11Renderer::setInputLayout(InputLayout* inputLayout)
+{
+ auto dxContext = dxImmediateContext;
+ auto dxInputLayout = (ID3D11InputLayout*)inputLayout;
- dxContext->IASetInputLayout(dxInputLayout);
- }
+ dxContext->IASetInputLayout(dxInputLayout);
+}
- virtual void setPrimitiveTopology(PrimitiveTopology topology) override
- {
- auto dxContext = dxImmediateContext;
+void D3D11Renderer::setPrimitiveTopology(PrimitiveTopology topology)
+{
+ auto dxContext = dxImmediateContext;
- D3D11_PRIMITIVE_TOPOLOGY dxTopology;
- switch( topology )
- {
+ D3D11_PRIMITIVE_TOPOLOGY dxTopology;
+ switch (topology)
+ {
case PrimitiveTopology::TriangleList:
dxTopology = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
break;
default:
return;
- }
-
- dxContext->IASetPrimitiveTopology(dxTopology);
}
- virtual void setVertexBuffers(UInt startSlot, UInt slotCount, Buffer* const* buffers, UInt const* strides, UInt const* offsets) override
- {
- auto dxContext = dxImmediateContext;
-
- static const int kMaxVertexBuffers = 16;
-
- UINT dxVertexStrides[kMaxVertexBuffers];
- UINT dxVertexOffsets[kMaxVertexBuffers];
+ dxContext->IASetPrimitiveTopology(dxTopology);
+}
- for( UInt ii = 0; ii < slotCount; ++ii )
- {
- dxVertexStrides[ii] = (UINT) strides[ii];
- dxVertexOffsets[ii] = (UINT) offsets[ii];
- }
+void D3D11Renderer::setVertexBuffers(UInt startSlot, UInt slotCount, Buffer* const* buffers, UInt const* strides, UInt const* offsets)
+{
+ auto dxContext = dxImmediateContext;
- auto dxVertexBuffers = (D3DBuffer* const*) buffers;
+ static const int kMaxVertexBuffers = 16;
- dxContext->IASetVertexBuffers(
- (UINT) startSlot,
- (UINT) slotCount, &(dxVertexBuffers[0])->buffer, &dxVertexStrides[0], &dxVertexOffsets[0]);
- }
+ UINT dxVertexStrides[kMaxVertexBuffers];
+ UINT dxVertexOffsets[kMaxVertexBuffers];
- virtual void setShaderProgram(ShaderProgram* inProgram) override
+ for (UInt ii = 0; ii < slotCount; ++ii)
{
- 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);
+ dxVertexStrides[ii] = (UINT)strides[ii];
+ dxVertexOffsets[ii] = (UINT)offsets[ii];
}
- virtual void setConstantBuffers(UInt startSlot, UInt slotCount, Buffer* const* buffers, UInt const* offsets) override
- {
- auto dxContext = dxImmediateContext;
+ auto dxVertexBuffers = (BufferImpl* const*)buffers;
- // TODO: actually use those offsets
+ dxContext->IASetVertexBuffers(
+ (UINT)startSlot,
+ (UINT)slotCount, &(dxVertexBuffers[0])->buffer, &dxVertexStrides[0], &dxVertexOffsets[0]);
+}
- auto dxConstantBuffers = (D3DBuffer* const*) buffers;
- dxContext->VSSetConstantBuffers(
- (UINT) startSlot, (UINT) slotCount, &dxConstantBuffers[0]->buffer);
- dxContext->VSSetConstantBuffers(
- (UINT) startSlot, (UINT) slotCount, &dxConstantBuffers[0]->buffer);
- }
+void D3D11Renderer::setShaderProgram(ShaderProgram* inProgram)
+{
+ auto dxContext = dxImmediateContext;
- virtual void draw(UInt vertexCount, UInt startVertex) override
- {
- auto dxContext = dxImmediateContext;
- applyBindingState(false);
- dxContext->Draw((UINT) vertexCount, (UINT) startVertex);
- }
+ auto program = (ShaderProgramImpl*)inProgram;
+ dxContext->CSSetShader(program->dxComputeShader, nullptr, 0);
+ dxContext->VSSetShader(program->dxVertexShader, nullptr, 0);
+ dxContext->PSSetShader(program->dxPixelShader, nullptr, 0);
+}
+void D3D11Renderer::setConstantBuffers(UInt startSlot, UInt slotCount, Buffer* const* buffers, UInt const* offsets)
+{
+ auto dxContext = dxImmediateContext;
- // ShaderCompiler interface
+ // TODO: actually use those offsets
- struct D3D11ShaderProgram
- {
- ID3D11VertexShader* dxVertexShader = nullptr;
- ID3D11PixelShader* dxPixelShader = nullptr;
- ID3D11ComputeShader* dxComputeShader = nullptr;
- };
+ auto dxConstantBuffers = (BufferImpl* const*)buffers;
+ dxContext->VSSetConstantBuffers((UINT)startSlot, (UINT)slotCount, &dxConstantBuffers[0]->buffer);
+ dxContext->VSSetConstantBuffers((UINT)startSlot, (UINT)slotCount, &dxConstantBuffers[0]->buffer);
+}
+
+void D3D11Renderer::draw(UInt vertexCount, UInt startVertex)
+{
+ auto dxContext = dxImmediateContext;
+ applyBindingState(false);
+ dxContext->Draw((UINT)vertexCount, (UINT)startVertex);
+}
- virtual ShaderProgram* compileProgram(ShaderCompileRequest const& request) override
+ShaderProgram* D3D11Renderer::compileProgram(ShaderCompileRequest const& request)
+{
+ if (request.computeShader.name)
{
- if (request.computeShader.name)
- {
- auto dxComputeShaderBlob = compileHLSLShader(request.computeShader.source.path, request.computeShader.source.dataBegin, request.computeShader.name, request.computeShader.profile);
- if (!dxComputeShaderBlob)
- return nullptr;
+ auto dxComputeShaderBlob = compileHLSLShader(request.computeShader.source.path, request.computeShader.source.dataBegin, request.computeShader.name, request.computeShader.profile);
+ if (!dxComputeShaderBlob)
+ return nullptr;
- ID3D11ComputeShader* dxComputeShader;
+ ID3D11ComputeShader* dxComputeShader;
- HRESULT csResult = dxDevice->CreateComputeShader(dxComputeShaderBlob->GetBufferPointer(), dxComputeShaderBlob->GetBufferSize(), nullptr, &dxComputeShader);
+ HRESULT csResult = dxDevice->CreateComputeShader(dxComputeShaderBlob->GetBufferPointer(), dxComputeShaderBlob->GetBufferSize(), nullptr, &dxComputeShader);
- dxComputeShaderBlob->Release();
+ dxComputeShaderBlob->Release();
- if (FAILED(csResult)) return nullptr;
+ if (FAILED(csResult)) return nullptr;
- D3D11ShaderProgram* shaderProgram = new D3D11ShaderProgram();
- shaderProgram->dxComputeShader = dxComputeShader;
- return (ShaderProgram*)shaderProgram;
- }
- else
- {
- auto dxVertexShaderBlob = compileHLSLShader(request.vertexShader.source.path, request.vertexShader.source.dataBegin, request.vertexShader.name, request.vertexShader.profile);
- if (!dxVertexShaderBlob) return nullptr;
+ ShaderProgramImpl* shaderProgram = new ShaderProgramImpl();
+ shaderProgram->dxComputeShader = dxComputeShader;
+ return (ShaderProgram*)shaderProgram;
+ }
+ else
+ {
+ 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.dataBegin, request.fragmentShader.name, request.fragmentShader.profile);
- if (!dxFragmentShaderBlob) return nullptr;
+ auto dxFragmentShaderBlob = compileHLSLShader(request.fragmentShader.source.path, request.fragmentShader.source.dataBegin, request.fragmentShader.name, request.fragmentShader.profile);
+ if (!dxFragmentShaderBlob) return nullptr;
- ID3D11VertexShader* dxVertexShader;
- ID3D11PixelShader* dxPixelShader;
+ ID3D11VertexShader* dxVertexShader;
+ ID3D11PixelShader* dxPixelShader;
- HRESULT vsResult = dxDevice->CreateVertexShader(dxVertexShaderBlob->GetBufferPointer(), dxVertexShaderBlob->GetBufferSize(), nullptr, &dxVertexShader);
- HRESULT psResult = dxDevice->CreatePixelShader(dxFragmentShaderBlob->GetBufferPointer(), dxFragmentShaderBlob->GetBufferSize(), nullptr, &dxPixelShader);
+ HRESULT vsResult = dxDevice->CreateVertexShader(dxVertexShaderBlob->GetBufferPointer(), dxVertexShaderBlob->GetBufferSize(), nullptr, &dxVertexShader);
+ HRESULT psResult = dxDevice->CreatePixelShader(dxFragmentShaderBlob->GetBufferPointer(), dxFragmentShaderBlob->GetBufferSize(), nullptr, &dxPixelShader);
- dxVertexShaderBlob->Release();
- dxFragmentShaderBlob->Release();
+ dxVertexShaderBlob->Release();
+ dxFragmentShaderBlob->Release();
- if (FAILED(vsResult)) return nullptr;
- if (FAILED(psResult)) return nullptr;
+ if (FAILED(vsResult)) return nullptr;
+ if (FAILED(psResult)) return nullptr;
- D3D11ShaderProgram* shaderProgram = new D3D11ShaderProgram();
- shaderProgram->dxVertexShader = dxVertexShader;
- shaderProgram->dxPixelShader = dxPixelShader;
- return (ShaderProgram*)shaderProgram;
- }
+ ShaderProgramImpl* shaderProgram = new ShaderProgramImpl();
+ shaderProgram->dxVertexShader = dxVertexShader;
+ shaderProgram->dxPixelShader = dxPixelShader;
+ return (ShaderProgram*)shaderProgram;
}
+}
+
+void D3D11Renderer::dispatchCompute(int x, int y, int z)
+{
+ auto dxContext = dxImmediateContext;
+ applyBindingState(true);
+ dxContext->Dispatch(x, y, z);
+}
- virtual void dispatchCompute(int x, int y, int z) override
- {
- auto dxContext = dxImmediateContext;
- applyBindingState(true);
- dxContext->Dispatch(x, y, z);
- }
-
- void createInputBuffer(
- InputBufferDesc & bufferDesc,
- List<unsigned int> & bufferData,
- ID3D11Buffer * &bufferOut,
- ID3D11UnorderedAccessView * &viewOut,
- ID3D11ShaderResourceView * &srvOut)
+void D3D11Renderer::createInputBuffer(InputBufferDesc & bufferDesc, List<unsigned int> & bufferData, ID3D11Buffer * &bufferOut,
+ ID3D11UnorderedAccessView * &viewOut, ID3D11ShaderResourceView * &srvOut)
+{
+ auto dxContext = dxImmediateContext;
+ D3D11_BUFFER_DESC desc = { 0 };
+ List<unsigned int> newBuffer;
+ desc.ByteWidth = (UINT)calcAligned((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)
{
- auto dxContext = dxImmediateContext;
- D3D11_BUFFER_DESC desc = {0};
- 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;
+ desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
+ }
+ else
+ {
+ desc.Usage = D3D11_USAGE_DEFAULT;
+ desc.BindFlags = D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_SHADER_RESOURCE;
+ if (bufferDesc.stride != 0)
{
- desc.Usage = D3D11_USAGE_DEFAULT;
- desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
+ desc.StructureByteStride = bufferDesc.stride;
+ desc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED;
}
else
{
- desc.Usage = D3D11_USAGE_DEFAULT;
- desc.BindFlags = D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_SHADER_RESOURCE;
- if (bufferDesc.stride != 0)
- {
- desc.StructureByteStride = bufferDesc.stride;
- desc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED;
- }
- else
- {
- desc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS;
- }
+ desc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS;
}
- D3D11_SUBRESOURCE_DATA data = {0};
- data.pSysMem = newBuffer.Buffer();
- dxDevice->CreateBuffer(&desc, &data, &bufferOut);
- int elemSize = bufferDesc.stride <= 0 ? 1 : bufferDesc.stride;
- if (bufferDesc.type == InputBufferType::StorageBuffer)
+ }
+ D3D11_SUBRESOURCE_DATA data = { 0 };
+ data.pSysMem = newBuffer.Buffer();
+ dxDevice->CreateBuffer(&desc, &data, &bufferOut);
+ int elemSize = bufferDesc.stride <= 0 ? 1 : bufferDesc.stride;
+ if (bufferDesc.type == InputBufferType::StorageBuffer)
+ {
+ D3D11_UNORDERED_ACCESS_VIEW_DESC viewDesc;
+ memset(&viewDesc, 0, sizeof(viewDesc));
+ viewDesc.Buffer.FirstElement = 0;
+ viewDesc.Buffer.NumElements = (UINT)(bufferData.Count() * sizeof(unsigned int) / elemSize);
+ viewDesc.Buffer.Flags = 0;
+ viewDesc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
+ viewDesc.Format = DXGI_FORMAT_UNKNOWN;
+
+ if (bufferDesc.stride == 0)
{
- D3D11_UNORDERED_ACCESS_VIEW_DESC viewDesc;
- memset(&viewDesc, 0, sizeof(viewDesc));
- viewDesc.Buffer.FirstElement = 0;
- viewDesc.Buffer.NumElements = (UINT)(bufferData.Count() * sizeof(unsigned int) / elemSize);
- viewDesc.Buffer.Flags = 0;
- viewDesc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
- viewDesc.Format = DXGI_FORMAT_UNKNOWN;
-
- if( bufferDesc.stride == 0 )
- {
- // TODO: are there UAV cases we need to handle that are neither
- // raw nor structured? RWBuffer<T> would be one...
+ // TODO: are there UAV cases we need to handle that are neither
+ // raw nor structured? RWBuffer<T> would be one...
- viewDesc.Buffer.Flags |= D3D11_BUFFER_UAV_FLAG_RAW;
- viewDesc.Format = DXGI_FORMAT_R32_TYPELESS;
- }
-
- dxDevice->CreateUnorderedAccessView(bufferOut, &viewDesc, &viewOut);
- }
- if (bufferDesc.type != InputBufferType::ConstantBuffer)
- {
- D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
- memset(&srvDesc, 0, sizeof(srvDesc));
- srvDesc.Buffer.FirstElement = 0;
- srvDesc.Buffer.ElementWidth = elemSize;
- srvDesc.Buffer.NumElements = (UINT)(bufferData.Count() * sizeof(unsigned int) / elemSize);
- srvDesc.Buffer.ElementOffset = 0;
- srvDesc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
- srvDesc.Format = DXGI_FORMAT_UNKNOWN;
- dxDevice->CreateShaderResourceView(bufferOut, &srvDesc, &srvOut);
+ viewDesc.Buffer.Flags |= D3D11_BUFFER_UAV_FLAG_RAW;
+ viewDesc.Format = DXGI_FORMAT_R32_TYPELESS;
}
+
+ dxDevice->CreateUnorderedAccessView(bufferOut, &viewDesc, &viewOut);
}
+ if (bufferDesc.type != InputBufferType::ConstantBuffer)
+ {
+ D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
+ memset(&srvDesc, 0, sizeof(srvDesc));
+ srvDesc.Buffer.FirstElement = 0;
+ srvDesc.Buffer.ElementWidth = elemSize;
+ srvDesc.Buffer.NumElements = (UINT)(bufferData.Count() * sizeof(unsigned int) / elemSize);
+ srvDesc.Buffer.ElementOffset = 0;
+ srvDesc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
+ srvDesc.Format = DXGI_FORMAT_UNKNOWN;
+ dxDevice->CreateShaderResourceView(bufferOut, &srvDesc, &srvOut);
+ }
+}
- void createInputTexture(const InputTextureDesc & inputDesc, ID3D11ShaderResourceView * &viewOut)
+void D3D11Renderer::createInputTexture(const InputTextureDesc & inputDesc, ID3D11ShaderResourceView * &viewOut)
+{
+ TextureData texData;
+ generateTextureData(texData, inputDesc);
+ List<D3D11_SUBRESOURCE_DATA> subRes;
+ for (int i = 0; i < texData.arraySize; i++)
{
- TextureData texData;
- generateTextureData(texData, inputDesc);
- List<D3D11_SUBRESOURCE_DATA> subRes;
- for (int i = 0; i < texData.arraySize; i++)
- {
- int slice = 0;
- for (int j = 0; j < texData.mipLevels; j++)
- {
- int size = texData.textureSize >> j;
- D3D11_SUBRESOURCE_DATA res;
- res.pSysMem = texData.dataBuffer[slice].Buffer();
- res.SysMemPitch = sizeof(unsigned int) * size;
- res.SysMemSlicePitch = sizeof(unsigned int) * size * size;
- subRes.Add(res);
- slice++;
- }
- }
- if (inputDesc.dimension == 1)
- {
- D3D11_TEXTURE1D_DESC desc = { 0 };
- desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
- desc.CPUAccessFlags = 0;
- desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
- desc.MiscFlags = 0;
- desc.MipLevels = texData.mipLevels;
- desc.ArraySize = texData.arraySize;
- desc.Width = texData.textureSize;
- desc.Usage = D3D11_USAGE_DEFAULT;
-
- ID3D11Texture1D * texture;
- dxDevice->CreateTexture1D(&desc, subRes.Buffer(), &texture);
- D3D11_SHADER_RESOURCE_VIEW_DESC viewDesc;
-
- viewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1D;
- if (inputDesc.arrayLength != 0)
- viewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1DARRAY;
- viewDesc.Texture1D.MipLevels = texData.mipLevels;
- viewDesc.Texture1D.MostDetailedMip = 0;
- viewDesc.Texture1DArray.ArraySize = texData.arraySize;
- viewDesc.Texture1DArray.FirstArraySlice = 0;
- viewDesc.Texture1DArray.MipLevels = texData.mipLevels;
- viewDesc.Texture1DArray.MostDetailedMip = 0;
- viewDesc.Format = desc.Format;
- dxDevice->CreateShaderResourceView(texture, &viewDesc, &viewOut);
- }
- else if (inputDesc.dimension == 2)
- {
- D3D11_SHADER_RESOURCE_VIEW_DESC viewDesc;
- D3D11_TEXTURE2D_DESC desc = { 0 };
- desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
- desc.CPUAccessFlags = 0;
- desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
- desc.MiscFlags = 0;
- desc.MipLevels = texData.mipLevels;
- desc.ArraySize = texData.arraySize;
- if (inputDesc.isCube)
- {
- desc.MiscFlags |= D3D11_RESOURCE_MISC_TEXTURECUBE;
- viewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
- viewDesc.TextureCube.MipLevels = texData.mipLevels;
- viewDesc.TextureCube.MostDetailedMip = 0;
- viewDesc.TextureCubeArray.MipLevels = texData.mipLevels;
- viewDesc.TextureCubeArray.MostDetailedMip = 0;
- viewDesc.TextureCubeArray.First2DArrayFace = 0;
- viewDesc.TextureCubeArray.NumCubes = inputDesc.arrayLength;
- }
- else
- {
- viewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
- viewDesc.Texture2D.MipLevels = texData.mipLevels;
- viewDesc.Texture2D.MostDetailedMip = 0;
- viewDesc.Texture2DArray.ArraySize = texData.arraySize;
- viewDesc.Texture2DArray.FirstArraySlice = 0;
- viewDesc.Texture2DArray.MipLevels = texData.mipLevels;
- viewDesc.Texture2DArray.MostDetailedMip = 0;
- }
- if (inputDesc.arrayLength != 0)
- viewDesc.ViewDimension = (D3D11_SRV_DIMENSION)(int)(viewDesc.ViewDimension + 1);
- desc.Width = texData.textureSize;
- desc.Height = texData.textureSize;
- desc.Usage = D3D11_USAGE_DEFAULT;
- desc.SampleDesc.Count = 1;
- desc.SampleDesc.Quality = 0;
- viewDesc.Format = desc.Format;
- ID3D11Texture2D * texture;
- dxDevice->CreateTexture2D(&desc, subRes.Buffer(), &texture);
- dxDevice->CreateShaderResourceView(texture, &viewDesc, &viewOut);
- }
- else if (inputDesc.dimension == 3)
+ int slice = 0;
+ for (int j = 0; j < texData.mipLevels; j++)
{
- D3D11_SHADER_RESOURCE_VIEW_DESC viewDesc;
- D3D11_TEXTURE3D_DESC desc = { 0 };
- desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
- desc.CPUAccessFlags = 0;
- desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
- desc.MiscFlags = 0;
- desc.MipLevels = 1;
- viewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
- desc.Width = texData.textureSize;
- desc.Height = texData.textureSize;
- desc.Depth = texData.textureSize;
- desc.Usage = D3D11_USAGE_DEFAULT;
- ID3D11Texture3D * texture;
- dxDevice->CreateTexture3D(&desc, subRes.Buffer(), &texture);
- viewDesc.Texture3D.MipLevels = 1;
- viewDesc.Texture3D.MostDetailedMip = 0;
- viewDesc.Format = desc.Format;
- dxDevice->CreateShaderResourceView(texture, &viewDesc, &viewOut);
+ int size = texData.textureSize >> j;
+ D3D11_SUBRESOURCE_DATA res;
+ res.pSysMem = texData.dataBuffer[slice].Buffer();
+ res.SysMemPitch = sizeof(unsigned int) * size;
+ res.SysMemSlicePitch = sizeof(unsigned int) * size * size;
+ subRes.Add(res);
+ slice++;
}
}
-
- void createInputSampler(const InputSamplerDesc & inputDesc, ID3D11SamplerState * & stateOut)
+ if (inputDesc.dimension == 1)
+ {
+ D3D11_TEXTURE1D_DESC desc = { 0 };
+ desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
+ desc.CPUAccessFlags = 0;
+ desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+ desc.MiscFlags = 0;
+ desc.MipLevels = texData.mipLevels;
+ desc.ArraySize = texData.arraySize;
+ desc.Width = texData.textureSize;
+ desc.Usage = D3D11_USAGE_DEFAULT;
+
+ ID3D11Texture1D * texture;
+ dxDevice->CreateTexture1D(&desc, subRes.Buffer(), &texture);
+ D3D11_SHADER_RESOURCE_VIEW_DESC viewDesc;
+
+ viewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1D;
+ if (inputDesc.arrayLength != 0)
+ viewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1DARRAY;
+ viewDesc.Texture1D.MipLevels = texData.mipLevels;
+ viewDesc.Texture1D.MostDetailedMip = 0;
+ viewDesc.Texture1DArray.ArraySize = texData.arraySize;
+ viewDesc.Texture1DArray.FirstArraySlice = 0;
+ viewDesc.Texture1DArray.MipLevels = texData.mipLevels;
+ viewDesc.Texture1DArray.MostDetailedMip = 0;
+ viewDesc.Format = desc.Format;
+ dxDevice->CreateShaderResourceView(texture, &viewDesc, &viewOut);
+ }
+ else if (inputDesc.dimension == 2)
{
- D3D11_SAMPLER_DESC desc;
- memset(&desc, 0, sizeof(desc));
- desc.AddressU = desc.AddressV = desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
- if (inputDesc.isCompareSampler)
+ D3D11_SHADER_RESOURCE_VIEW_DESC viewDesc;
+ D3D11_TEXTURE2D_DESC desc = { 0 };
+ desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
+ desc.CPUAccessFlags = 0;
+ desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+ desc.MiscFlags = 0;
+ desc.MipLevels = texData.mipLevels;
+ desc.ArraySize = texData.arraySize;
+ if (inputDesc.isCube)
{
- desc.ComparisonFunc = D3D11_COMPARISON_LESS_EQUAL;
- desc.Filter = D3D11_FILTER_MIN_LINEAR_MAG_MIP_POINT;
- desc.MinLOD = desc.MaxLOD = 0.0f;
+ desc.MiscFlags |= D3D11_RESOURCE_MISC_TEXTURECUBE;
+ viewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
+ viewDesc.TextureCube.MipLevels = texData.mipLevels;
+ viewDesc.TextureCube.MostDetailedMip = 0;
+ viewDesc.TextureCubeArray.MipLevels = texData.mipLevels;
+ viewDesc.TextureCubeArray.MostDetailedMip = 0;
+ viewDesc.TextureCubeArray.First2DArrayFace = 0;
+ viewDesc.TextureCubeArray.NumCubes = inputDesc.arrayLength;
}
else
{
- desc.Filter = D3D11_FILTER_ANISOTROPIC;
- desc.MaxAnisotropy = 8;
- desc.MinLOD = 0.0f;
- desc.MaxLOD = 100.0f;
+ viewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
+ viewDesc.Texture2D.MipLevels = texData.mipLevels;
+ viewDesc.Texture2D.MostDetailedMip = 0;
+ viewDesc.Texture2DArray.ArraySize = texData.arraySize;
+ viewDesc.Texture2DArray.FirstArraySlice = 0;
+ viewDesc.Texture2DArray.MipLevels = texData.mipLevels;
+ viewDesc.Texture2DArray.MostDetailedMip = 0;
}
- dxDevice->CreateSamplerState(&desc, &stateOut);
+ if (inputDesc.arrayLength != 0)
+ viewDesc.ViewDimension = (D3D11_SRV_DIMENSION)(int)(viewDesc.ViewDimension + 1);
+ desc.Width = texData.textureSize;
+ desc.Height = texData.textureSize;
+ desc.Usage = D3D11_USAGE_DEFAULT;
+ desc.SampleDesc.Count = 1;
+ desc.SampleDesc.Quality = 0;
+ viewDesc.Format = desc.Format;
+ ID3D11Texture2D * texture;
+ dxDevice->CreateTexture2D(&desc, subRes.Buffer(), &texture);
+ dxDevice->CreateShaderResourceView(texture, &viewDesc, &viewOut);
+ }
+ else if (inputDesc.dimension == 3)
+ {
+ D3D11_SHADER_RESOURCE_VIEW_DESC viewDesc;
+ D3D11_TEXTURE3D_DESC desc = { 0 };
+ desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
+ desc.CPUAccessFlags = 0;
+ desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+ desc.MiscFlags = 0;
+ desc.MipLevels = 1;
+ viewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
+ desc.Width = texData.textureSize;
+ desc.Height = texData.textureSize;
+ desc.Depth = texData.textureSize;
+ desc.Usage = D3D11_USAGE_DEFAULT;
+ ID3D11Texture3D * texture;
+ dxDevice->CreateTexture3D(&desc, subRes.Buffer(), &texture);
+ viewDesc.Texture3D.MipLevels = 1;
+ viewDesc.Texture3D.MostDetailedMip = 0;
+ viewDesc.Format = desc.Format;
+ dxDevice->CreateShaderResourceView(texture, &viewDesc, &viewOut);
+ }
+}
+
+void D3D11Renderer::createInputSampler(const InputSamplerDesc & inputDesc, ID3D11SamplerState * & stateOut)
+{
+ D3D11_SAMPLER_DESC desc;
+ memset(&desc, 0, sizeof(desc));
+ desc.AddressU = desc.AddressV = desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
+ if (inputDesc.isCompareSampler)
+ {
+ desc.ComparisonFunc = D3D11_COMPARISON_LESS_EQUAL;
+ desc.Filter = D3D11_FILTER_MIN_LINEAR_MAG_MIP_POINT;
+ desc.MinLOD = desc.MaxLOD = 0.0f;
+ }
+ else
+ {
+ desc.Filter = D3D11_FILTER_ANISOTROPIC;
+ desc.MaxAnisotropy = 8;
+ desc.MinLOD = 0.0f;
+ desc.MaxLOD = 100.0f;
}
- virtual BindingState * createBindingState(const ShaderInputLayout & layout)
+ dxDevice->CreateSamplerState(&desc, &stateOut);
+}
+
+BindingState * D3D11Renderer::createBindingState(const ShaderInputLayout& layout)
+{
+ BindingStateImpl * rs = new BindingStateImpl();
+ rs->numRenderTargets = layout.numRenderTargets;
+ for (auto & entry : layout.entries)
{
- D3DBindingState * rs = new D3DBindingState();
- rs->numRenderTargets = layout.numRenderTargets;
- for (auto & entry : layout.entries)
+ BindingImpl rsEntry;
+ rsEntry.type = entry.type;
+ rsEntry.binding = entry.hlslBinding;
+ rsEntry.isOutput = entry.isOutput;
+ switch (entry.type)
{
- D3DBinding rsEntry;
- rsEntry.type = entry.type;
- rsEntry.binding = entry.hlslBinding;
- rsEntry.isOutput = entry.isOutput;
- switch (entry.type)
- {
case ShaderInputType::Buffer:
{
createInputBuffer(entry.bufferDesc, entry.bufferData, rsEntry.buffer, rsEntry.uav, rsEntry.srv);
@@ -1005,133 +1003,127 @@ public:
throw "not implemented";
}
break;
- }
- rs->bindings.Add(rsEntry);
}
-
- return (BindingState*)rs;
+ rs->bindings.Add(rsEntry);
}
- void applyBindingState(bool isCompute)
+ return (BindingState*)rs;
+}
+
+void D3D11Renderer::applyBindingState(bool isCompute)
+{
+ auto dxContext = dxImmediateContext;
+ for (auto & binding : currentBindings->bindings)
{
- auto dxContext = dxImmediateContext;
- for (auto & binding : currentBindings->bindings)
+ if (binding.type == ShaderInputType::Buffer)
{
- if (binding.type == ShaderInputType::Buffer)
+ if (binding.bufferType == InputBufferType::ConstantBuffer)
{
- if (binding.bufferType == InputBufferType::ConstantBuffer)
- {
- if (isCompute)
- dxContext->CSSetConstantBuffers(binding.binding, 1, &binding.buffer);
- else
- {
- dxContext->VSSetConstantBuffers(binding.binding, 1, &binding.buffer);
- dxContext->PSSetConstantBuffers(binding.binding, 1, &binding.buffer);
- }
- }
- else if (binding.uav)
- {
- if (isCompute)
- dxContext->CSSetUnorderedAccessViews(binding.binding, 1, &binding.uav, nullptr);
- else
- dxContext->OMSetRenderTargetsAndUnorderedAccessViews(currentBindings->numRenderTargets,
- dxRenderTargetViews.Buffer(), nullptr, binding.binding, 1, &binding.uav, nullptr);
- }
+ if (isCompute)
+ dxContext->CSSetConstantBuffers(binding.binding, 1, &binding.buffer);
else
{
- if (isCompute)
- dxContext->CSSetShaderResources(binding.binding, 1, &binding.srv);
- else
- {
- dxContext->PSSetShaderResources(binding.binding, 1, &binding.srv);
- dxContext->VSSetShaderResources(binding.binding, 1, &binding.srv);
- }
+ dxContext->VSSetConstantBuffers(binding.binding, 1, &binding.buffer);
+ dxContext->PSSetConstantBuffers(binding.binding, 1, &binding.buffer);
}
}
- else if (binding.type == ShaderInputType::Texture)
+ else if (binding.uav)
{
- if (binding.uav)
- {
- if (isCompute)
- dxContext->CSSetUnorderedAccessViews(binding.binding, 1, &binding.uav, nullptr);
- else
- dxContext->OMSetRenderTargetsAndUnorderedAccessViews(D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL,
- nullptr, nullptr, binding.binding, 1, &binding.uav, nullptr);
- }
+ if (isCompute)
+ dxContext->CSSetUnorderedAccessViews(binding.binding, 1, &binding.uav, nullptr);
+ else
+ dxContext->OMSetRenderTargetsAndUnorderedAccessViews(currentBindings->numRenderTargets,
+ dxRenderTargetViews.Buffer(), nullptr, binding.binding, 1, &binding.uav, nullptr);
+ }
+ else
+ {
+ if (isCompute)
+ dxContext->CSSetShaderResources(binding.binding, 1, &binding.srv);
else
{
- if (isCompute)
- dxContext->CSSetShaderResources(binding.binding, 1, &binding.srv);
- else
- {
- dxContext->PSSetShaderResources(binding.binding, 1, &binding.srv);
- dxContext->VSSetShaderResources(binding.binding, 1, &binding.srv);
- }
+ dxContext->PSSetShaderResources(binding.binding, 1, &binding.srv);
+ dxContext->VSSetShaderResources(binding.binding, 1, &binding.srv);
}
}
- else if (binding.type == ShaderInputType::Sampler)
+ }
+ else if (binding.type == ShaderInputType::Texture)
+ {
+ if (binding.uav)
+ {
+ if (isCompute)
+ dxContext->CSSetUnorderedAccessViews(binding.binding, 1, &binding.uav, nullptr);
+ else
+ dxContext->OMSetRenderTargetsAndUnorderedAccessViews(D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL,
+ nullptr, nullptr, binding.binding, 1, &binding.uav, nullptr);
+ }
+ else
{
if (isCompute)
- dxContext->CSSetSamplers(binding.binding, 1, &binding.samplerState);
+ dxContext->CSSetShaderResources(binding.binding, 1, &binding.srv);
else
{
- dxContext->PSSetSamplers(binding.binding, 1, &binding.samplerState);
- dxContext->VSSetSamplers(binding.binding, 1, &binding.samplerState);
+ dxContext->PSSetShaderResources(binding.binding, 1, &binding.srv);
+ dxContext->VSSetShaderResources(binding.binding, 1, &binding.srv);
}
}
+ }
+ else if (binding.type == ShaderInputType::Sampler)
+ {
+ if (isCompute)
+ dxContext->CSSetSamplers(binding.binding, 1, &binding.samplerState);
else
- throw "not implemented";
+ {
+ dxContext->PSSetSamplers(binding.binding, 1, &binding.samplerState);
+ dxContext->VSSetSamplers(binding.binding, 1, &binding.samplerState);
+ }
}
+ else
+ throw "not implemented";
}
+}
- virtual void setBindingState(BindingState * state)
- {
- auto dxBindingState = (D3DBindingState*) state;
- currentBindings = dxBindingState;
- }
+void D3D11Renderer::setBindingState(BindingState* state)
+{
+ auto dxBindingState = (BindingStateImpl*)state;
+ currentBindings = dxBindingState;
+}
- virtual void serializeOutput(BindingState* state, const char * fileName)
+void D3D11Renderer::serializeOutput(BindingState* state, const char* fileName)
+{
+ auto dxContext = dxImmediateContext;
+ auto dxBindingState = (BindingStateImpl*)state;
+ FILE * f = fopen(fileName, "wb");
+ int id = 0;
+ for (auto & binding : dxBindingState->bindings)
{
- auto dxContext = dxImmediateContext;
- auto dxBindingState = (D3DBindingState*)state;
- FILE * f = fopen(fileName, "wb");
- int id = 0;
- for (auto & binding : dxBindingState->bindings)
+ if (binding.isOutput)
{
- if (binding.isOutput)
+ if (binding.buffer)
{
- if (binding.buffer)
- {
- // create staging buffer
- ID3D11Buffer* stageBuf;
- D3D11_BUFFER_DESC bufDesc;
- memset(&bufDesc, 0, sizeof(bufDesc));
- bufDesc.BindFlags = 0;
- bufDesc.ByteWidth = (UINT)RoundUpToAlignment(binding.bufferLength, 256);
- bufDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
- bufDesc.Usage = D3D11_USAGE_STAGING;
- dxDevice->CreateBuffer(&bufDesc, nullptr, &stageBuf);
- dxContext->CopyResource(stageBuf, binding.buffer);
- auto ptr = (unsigned int *)map(stageBuf, MapFlavor::HostRead);
- for (auto i = 0u; i < binding.bufferLength / sizeof(unsigned int); i++)
- fprintf(f, "%X\n", ptr[i]);
- unmap(stageBuf);
- stageBuf->Release();
- }
- else
- {
- printf("invalid output type at %d.\n", id);
- }
+ // create staging buffer
+ ID3D11Buffer* stageBuf;
+ D3D11_BUFFER_DESC bufDesc;
+ memset(&bufDesc, 0, sizeof(bufDesc));
+ bufDesc.BindFlags = 0;
+ bufDesc.ByteWidth = (UINT)calcAligned(binding.bufferLength, 256);
+ bufDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
+ bufDesc.Usage = D3D11_USAGE_STAGING;
+ dxDevice->CreateBuffer(&bufDesc, nullptr, &stageBuf);
+ dxContext->CopyResource(stageBuf, binding.buffer);
+ auto ptr = (unsigned int *)map(stageBuf, MapFlavor::HostRead);
+ for (auto i = 0u; i < binding.bufferLength / sizeof(unsigned int); i++)
+ fprintf(f, "%X\n", ptr[i]);
+ unmap(stageBuf);
+ stageBuf->Release();
+ }
+ else
+ {
+ printf("invalid output type at %d.\n", id);
}
- id++;
}
- fclose(f);
+ id++;
}
-};
-
-Renderer* createD3D11Renderer()
-{
- return new D3D11Renderer();
+ fclose(f);
}
} // renderer_test
diff --git a/tools/render-test/render-d3d12.cpp b/tools/render-test/render-d3d12.cpp
index f0b0eb478..d481d7084 100644
--- a/tools/render-test/render-d3d12.cpp
+++ b/tools/render-test/render-d3d12.cpp
@@ -1,4 +1,4 @@
-// render-d3d12.cpp
+// render-d3d12.cpp
#include "render-d3d12.h"
#include "options.h"
@@ -46,279 +46,300 @@ ID3DBlob* compileHLSLShader(
char const* entryPointName,
char const* dxProfileName);
-static char const* vertexProfileName = "vs_4_0";
-static char const* fragmentProfileName = "ps_4_0";
+//static char const* vertexProfileName = "vs_4_0";
+//static char const* fragmentProfileName = "ps_4_0";
//
-
class D3D12Renderer : public Renderer, public ShaderCompiler
{
public:
- IDXGISwapChain* dxSwapChain = nullptr;
+ // Renderer implementation
+ virtual SlangResult initialize(void* inWindowHandle) override;
+ virtual void setClearColor(float const* color) override;
+ virtual void clearFrame() override;
+ virtual void presentFrame() override;
+ virtual SlangResult captureScreenShot(char const* outputPath) override;
+ virtual void serializeOutput(BindingState* state, const char * fileName) override;
+ virtual Buffer* createBuffer(BufferDesc const& desc) override;
+ virtual InputLayout* createInputLayout(InputElementDesc const* inputElements, UInt inputElementCount) override;
+ virtual BindingState * createBindingState(const ShaderInputLayout & layout) override;
+ virtual ShaderCompiler* getShaderCompiler() override;
+ virtual void* map(Buffer* buffer, MapFlavor flavor) override;
+ virtual void unmap(Buffer* buffer) override;
+ virtual void setInputLayout(InputLayout* inputLayout) override;
+ virtual void setPrimitiveTopology(PrimitiveTopology topology) override;
+ virtual void setBindingState(BindingState * state);
+ 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;
+
+ // ShaderCompiler implementation
+ virtual ShaderProgram* compileProgram(ShaderCompileRequest const& request) override;
+
+ protected:
+ PROC loadProc(HMODULE module, char const* name);
+ static DXGI_FORMAT mapFormat(Format format);
+ float clearColor[4] = { 0, 0, 0, 0 };
+ IDXGISwapChain* dxSwapChain = nullptr;
ID3D12Device* dxDevice = nullptr;
+};
+
+Renderer* createD3D12Renderer()
+{
+ return new D3D12Renderer;
+}
- virtual PROC loadProc(
- HMODULE module,
- char const* name)
+PROC D3D12Renderer::loadProc(HMODULE module, char const* name)
+{
+ PROC proc = ::GetProcAddress(module, name);
+ if (!proc)
{
- PROC proc = GetProcAddress(module, name);
- if( !proc )
- {
- fprintf(stderr,
- "error: failed load symbol '%s'\n", name);
- return nullptr;
- }
- return proc;
+ fprintf(stderr, "error: failed load symbol '%s'\n", name);
+ return nullptr;
}
+ return proc;
+}
- virtual SlangResult initialize(void* inWindowHandle) override
+/* static */DXGI_FORMAT D3D12Renderer::mapFormat(Format format)
+{
+ switch (format)
{
- auto windowHandle = (HWND) inWindowHandle;
- // Rather than statically link against D3D, we load it dynamically.
+ case Format::RGB_Float32:
+ return DXGI_FORMAT_R32G32B32_FLOAT;
+ case Format::RG_Float32:
+ return DXGI_FORMAT_R32G32_FLOAT;
+ default:
+ return DXGI_FORMAT_UNKNOWN;
+ }
+}
- HMODULE d3d12 = LoadLibraryA("d3d12.dll");
- if(!d3d12)
- {
- fprintf(stderr, "error: failed load 'd3d12.dll'\n");
- return SLANG_FAIL;
- }
+// !!!!!!!!!!!!!!!!!!!!!!!!!!!! Renderer interface !!!!!!!!!!!!!!!!!!!!!!!!!!
+
+SlangResult D3D12Renderer::initialize(void* inWindowHandle)
+{
+ 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");
+ return SLANG_FAIL;
+ }
#define LOAD_PROC(TYPE, NAME) \
TYPE NAME##_ = (TYPE) loadProc(d3d12, #NAME); \
- if (NAME##_ == nullptr) return SLANG_FAIL;
+ if (NAME##_ == nullptr) return SLANG_FAIL;
- UINT dxgiFactoryFlags = 0;
+ UINT dxgiFactoryFlags = 0;
#if ENABLE_DEBUG_LAYER
- LOAD_PROC(PFN_D3D12_GET_DEBUG_INTERFACE, D3D12GetDebugInterface);
+ LOAD_PROC(PFN_D3D12_GET_DEBUG_INTERFACE, D3D12GetDebugInterface);
- ID3D12Debug* debugController;
- if(SUCCEEDED(D3D12GetDebugInterface_(IID_PPV_ARGS(&debugController))))
- {
- debugController->EnableDebugLayer();
- dxgiFactoryFlags |= DXGI_CREATE_FACTORY_DEBUG;
- }
+ 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);
+ typedef HRESULT(WINAPI *PFN_DXGI_CREATE_FACTORY_2)(UINT Flags, REFIID riid, _COM_Outptr_ void **ppFactory);
- IDXGIFactory4* dxgiFactory;
- SLANG_RETURN_ON_FAIL(CreateDXGIFactory2_(dxgiFactoryFlags, IID_PPV_ARGS(&dxgiFactory)));
+ LOAD_PROC(PFN_DXGI_CREATE_FACTORY_2, CreateDXGIFactory2);
- D3D_FEATURE_LEVEL featureLevel = D3D_FEATURE_LEVEL_11_0;
+ IDXGIFactory4* dxgiFactory;
+ SLANG_RETURN_ON_FAIL(CreateDXGIFactory2_(dxgiFactoryFlags, IID_PPV_ARGS(&dxgiFactory)));
- // Search for an adapter that meets our requirements
- IDXGIAdapter* adapter = nullptr;
+ D3D_FEATURE_LEVEL featureLevel = D3D_FEATURE_LEVEL_11_0;
- LOAD_PROC(PFN_D3D12_CREATE_DEVICE, D3D12CreateDevice);
+ // Search for an adapter that meets our requirements
+ IDXGIAdapter* adapter = nullptr;
- UINT adapterCounter = 0;
- for(;;)
+ 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)
{
- 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();
+ // TODO: may want to allow software driver as fallback
}
-
- if(!adapter)
+ else if (SUCCEEDED(D3D12CreateDevice_(candidateAdapter, featureLevel, IID_PPV_ARGS(&dxDevice))))
{
- // Couldn't find an adapter
- return SLANG_FAIL;
+ // We found one!
+ adapter = candidateAdapter;
+ break;
}
- // Command Queue
- D3D12_COMMAND_QUEUE_DESC queueDesc = {};
- queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
+ candidateAdapter->Release();
+ }
- ID3D12CommandQueue* commandQueue;
- SLANG_RETURN_ON_FAIL(dxDevice->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&commandQueue)));
+ if (!adapter)
+ {
+ // Couldn't find an adapter
+ return SLANG_FAIL;
+ }
- // Swap Chain
- UINT frameCount = 2; // TODO: configure
+ // Command Queue
+ D3D12_COMMAND_QUEUE_DESC queueDesc = {};
+ queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
- 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;
+ ID3D12CommandQueue* commandQueue;
+ SLANG_RETURN_ON_FAIL(dxDevice->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&commandQueue)));
- IDXGISwapChain1* swapChain;
- SLANG_RETURN_ON_FAIL(dxgiFactory->CreateSwapChainForHwnd(
- commandQueue,
- windowHandle,
- &swapChainDesc,
- nullptr,
- nullptr,
- &swapChain));
+ // Swap Chain
+ UINT frameCount = 2; // TODO: configure
- // Is this needed?
- dxgiFactory->MakeWindowAssociation(windowHandle, DXGI_MWA_NO_ALT_ENTER);
+ 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;
- IDXGISwapChain3* swapChainEx;
- SLANG_RETURN_ON_FAIL(swapChain->QueryInterface(IID_PPV_ARGS(&swapChainEx)));
+ IDXGISwapChain1* swapChain;
+ SLANG_RETURN_ON_FAIL(dxgiFactory->CreateSwapChainForHwnd(commandQueue, windowHandle, &swapChainDesc, nullptr, nullptr, &swapChain));
- UINT frameIndex = swapChainEx->GetCurrentBackBufferIndex();
+ // Is this needed?
+ dxgiFactory->MakeWindowAssociation(windowHandle, DXGI_MWA_NO_ALT_ENTER);
- // Descriptor heaps
+ IDXGISwapChain3* swapChainEx;
+ SLANG_RETURN_ON_FAIL(swapChain->QueryInterface(IID_PPV_ARGS(&swapChainEx)));
- D3D12_DESCRIPTOR_HEAP_DESC rtvHeapDesc = {};
- rtvHeapDesc.NumDescriptors = frameCount;
- rtvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
+ UINT frameIndex = swapChainEx->GetCurrentBackBufferIndex();
- ID3D12DescriptorHeap* rtvHeap;
- SLANG_RETURN_ON_FAIL(dxDevice->CreateDescriptorHeap(&rtvHeapDesc, IID_PPV_ARGS(&rtvHeap)));
+ // Descriptor heaps
- UINT rtvDescriptorSize = dxDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
+ D3D12_DESCRIPTOR_HEAP_DESC rtvHeapDesc = {};
+ rtvHeapDesc.NumDescriptors = frameCount;
+ rtvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
- D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = rtvHeap->GetCPUDescriptorHandleForHeapStart();
+ ID3D12DescriptorHeap* rtvHeap;
+ SLANG_RETURN_ON_FAIL(dxDevice->CreateDescriptorHeap(&rtvHeapDesc, IID_PPV_ARGS(&rtvHeap)));
- // Create per-frame RTVs
- ID3D12Resource* backBufferResources[2];
- for( UINT ff = 0; ff < frameCount; ++ff )
- {
- SLANG_RETURN_ON_FAIL(swapChainEx->GetBuffer(ff, IID_PPV_ARGS(&backBufferResources[ff])));
- dxDevice->CreateRenderTargetView(backBufferResources[ff], nullptr, rtvHandle);
- rtvHandle.ptr += rtvDescriptorSize;
- }
+ UINT rtvDescriptorSize = dxDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
- ID3D12CommandAllocator* commandAllocator;
- SLANG_RETURN_ON_FAIL(dxDevice->CreateCommandAllocator( D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&commandAllocator)));
- return SLANG_OK;
- }
+ D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = rtvHeap->GetCPUDescriptorHandleForHeapStart();
- float clearColor[4] = { 0, 0, 0, 0 };
- virtual void setClearColor(float const* color) override
+ // Create per-frame RTVs
+ ID3D12Resource* backBufferResources[2];
+ for (UINT ff = 0; ff < frameCount; ++ff)
{
- memcpy(clearColor, color, sizeof(clearColor));
+ SLANG_RETURN_ON_FAIL(swapChainEx->GetBuffer(ff, IID_PPV_ARGS(&backBufferResources[ff])));
+ dxDevice->CreateRenderTargetView(backBufferResources[ff], nullptr, rtvHandle);
+ rtvHandle.ptr += rtvDescriptorSize;
}
- virtual void clearFrame() override
- {
- }
+ ID3D12CommandAllocator* commandAllocator;
+ SLANG_RETURN_ON_FAIL(dxDevice->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&commandAllocator)));
+ return SLANG_OK;
+}
- virtual void presentFrame() override
- {
- }
+void D3D12Renderer::setClearColor(float const* color)
+{
+ memcpy(clearColor, color, sizeof(clearColor));
+}
- virtual SlangResult captureScreenShot(char const* outputPath) override
- {
- return SLANG_FAIL;
- }
+void D3D12Renderer::clearFrame()
+{
+}
- virtual ShaderCompiler* getShaderCompiler() override
- {
- return this;
- }
+void D3D12Renderer::presentFrame()
+{
+}
- virtual Buffer* createBuffer(BufferDesc const& desc) override
- {
- return nullptr;
- }
+SlangResult D3D12Renderer::captureScreenShot(char const* outputPath)
+{
+ return SLANG_FAIL;
+}
- 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;
- }
- }
+ShaderCompiler* D3D12Renderer::getShaderCompiler()
+{
+ return this;
+}
- virtual InputLayout* createInputLayout(InputElementDesc const* inputElements, UInt inputElementCount) override
- {
- return nullptr;
- }
+Buffer* D3D12Renderer::createBuffer(BufferDesc const& desc)
+{
+ return nullptr;
+}
- virtual void* map(Buffer* buffer, MapFlavor flavor) override
- {
- return nullptr;
- }
- virtual void unmap(Buffer* buffer) override
- {
- }
+InputLayout* D3D12Renderer::createInputLayout(InputElementDesc const* inputElements, UInt inputElementCount)
+{
+ return nullptr;
+}
- virtual void setInputLayout(InputLayout* inputLayout) override
- {
- }
+void* D3D12Renderer::map(Buffer* buffer, MapFlavor flavor)
+{
+ return nullptr;
+}
- virtual void setPrimitiveTopology(PrimitiveTopology topology) override
- {
- }
+void D3D12Renderer::unmap(Buffer* buffer)
+{
+}
- virtual void setVertexBuffers(UInt startSlot, UInt slotCount, Buffer* const* buffers, UInt const* strides, UInt const* offsets) override
- {
- }
+void D3D12Renderer::setInputLayout(InputLayout* inputLayout)
+{
+}
- virtual void setShaderProgram(ShaderProgram* inProgram) override
- {
- }
+void D3D12Renderer::setPrimitiveTopology(PrimitiveTopology topology)
+{
+}
- virtual void setConstantBuffers(UInt startSlot, UInt slotCount, Buffer* const* buffers, UInt const* offsets) override
- {
- }
+void D3D12Renderer::setVertexBuffers(UInt startSlot, UInt slotCount, Buffer* const* buffers, UInt const* strides, UInt const* offsets)
+{
+}
- virtual void draw(UInt vertexCount, UInt startVertex) override
- {
- }
+void D3D12Renderer::setShaderProgram(ShaderProgram* inProgram)
+{
+}
+void D3D12Renderer::setConstantBuffers(UInt startSlot, UInt slotCount, Buffer* const* buffers, UInt const* offsets)
+{
+}
- virtual void dispatchCompute(int x, int y, int z) override
- {
- }
+void D3D12Renderer::draw(UInt vertexCount, UInt startVertex)
+{
+}
- virtual BindingState * createBindingState(const ShaderInputLayout & layout)
- {
- return nullptr;
- }
- virtual void setBindingState(BindingState * state)
- {
- }
+void D3D12Renderer::dispatchCompute(int x, int y, int z)
+{
+}
- virtual void serializeOutput(BindingState* state, const char * fileName)
- {
- }
+BindingState* D3D12Renderer::createBindingState(const ShaderInputLayout & layout)
+{
+ return nullptr;
+}
- // ShaderCompiler interface
+void D3D12Renderer::setBindingState(BindingState * state)
+{
+}
- virtual ShaderProgram* compileProgram(ShaderCompileRequest const& request) override
- {
- return nullptr;
- }
+void D3D12Renderer::serializeOutput(BindingState* state, const char * fileName)
+{
+}
-};
+// ShaderCompiler interface
-Renderer* createD3D12Renderer()
+ShaderProgram* D3D12Renderer::compileProgram(ShaderCompileRequest const& request)
{
- return new D3D12Renderer();
+ return nullptr;
}
} // renderer_test
+
diff --git a/tools/render-test/render-gl.cpp b/tools/render-test/render-gl.cpp
index c2195f4f0..7f6e401e5 100644
--- a/tools/render-test/render-gl.cpp
+++ b/tools/render-test/render-gl.cpp
@@ -59,8 +59,8 @@
F(glEnableVertexAttribArray, PFNGLENABLEVERTEXATTRIBARRAYPROC) \
F(glDisableVertexAttribArray, PFNGLDISABLEVERTEXATTRIBARRAYPROC) \
F(glDebugMessageCallback, PFNGLDEBUGMESSAGECALLBACKPROC) \
- F(glDispatchCompute, PFNGLDISPATCHCOMPUTEPROC) \
- F(glActiveTexture, PFNGLACTIVETEXTUREPROC) \
+ F(glDispatchCompute, PFNGLDISPATCHCOMPUTEPROC) \
+ F(glActiveTexture, PFNGLACTIVETEXTUREPROC) \
F(glCreateSamplers, PFNGLCREATESAMPLERSPROC) \
F(glBindSampler, PFNGLBINDSAMPLERPROC) \
F(glTexImage3D, PFNGLTEXIMAGE3DPROC) \
@@ -74,189 +74,37 @@ namespace renderer_test {
class GLRenderer : public Renderer, public ShaderCompiler
{
public:
- HDC deviceContext;
- HGLRC glContext;
-
- // Declre a function pointer for each OpenGL
- // extension function we need to load
-
-#define DECLARE_GL_EXTENSION_FUNC(NAME, TYPE) TYPE NAME;
- MAP_GL_EXTENSION_FUNCS(DECLARE_GL_EXTENSION_FUNC)
-#undef DECLARE_GL_EXTENSION_FUNC
-
- // Renderer interface
-
- virtual SlangResult initialize(void* inWindowHandle) override
- {
- auto windowHandle = (HWND) inWindowHandle;
-
- deviceContext = GetDC(windowHandle);
-
- PIXELFORMATDESCRIPTOR pixelFormatDesc = { sizeof(PIXELFORMATDESCRIPTOR) };
- pixelFormatDesc.nVersion = 1;
- pixelFormatDesc.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
- pixelFormatDesc.iPixelType = PFD_TYPE_RGBA;
- pixelFormatDesc.cColorBits = 32;
- pixelFormatDesc.cDepthBits = 24;
- pixelFormatDesc.cStencilBits = 8;
- pixelFormatDesc.iLayerType = PFD_MAIN_PLANE;
-
- int pixelFormatIndex = ChoosePixelFormat(deviceContext, &pixelFormatDesc);
- SetPixelFormat(deviceContext, pixelFormatIndex, &pixelFormatDesc);
-
- glContext = wglCreateContext(deviceContext);
- wglMakeCurrent(deviceContext, glContext);
-
- auto renderer = glGetString(GL_RENDERER);
- auto extensions = glGetString(GL_EXTENSIONS);
-
- // Load ech of our etension functions by name
-
- #define LOAD_GL_EXTENSION_FUNC(NAME, TYPE) NAME = (TYPE) wglGetProcAddress(#NAME);
- MAP_GL_EXTENSION_FUNCS(LOAD_GL_EXTENSION_FUNC)
- #undef LOAD_GL_EXTENSION_FUNC
-
-
- glDisable(GL_DEPTH_TEST);
- glDisable(GL_CULL_FACE);
-
- glViewport(0, 0, gWindowWidth, gWindowHeight);
-
- if (glDebugMessageCallback)
- {
- glEnable(GL_DEBUG_OUTPUT);
- glDebugMessageCallback(staticDebugCallback, this);
- }
-
- return SLANG_OK;
- }
-
- void debugCallback(
- GLenum source,
- GLenum type,
- GLuint id,
- GLenum severity,
- GLsizei length,
- GLchar const* message)
- {
- OutputDebugStringA("GL: ");
- OutputDebugStringA(message);
- OutputDebugStringA("\n");
-
- switch (type)
- {
- case GL_DEBUG_TYPE_ERROR:
- break;
-
- default:
- break;
- }
- }
-
- static void APIENTRY staticDebugCallback(
- GLenum source,
- GLenum type,
- GLuint id,
- GLenum severity,
- GLsizei length,
- GLchar const* message,
- void const* userParam)
- {
- ((GLRenderer*) userParam)->debugCallback(
- source, type, id, severity, length, message);
- }
-
- float clearColor[4] = { 0, 0, 0, 0 };
- virtual void setClearColor(float const* color) override
- {
- glClearColor(color[0], color[1], color[2], color[3]);
- }
-
- virtual void clearFrame() override
- {
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
- }
-
- virtual void presentFrame() override
- {
- glFlush();
- SwapBuffers(deviceContext);
- }
-
- virtual SlangResult captureScreenShot(char const* outputPath) override
- {
- int width = gWindowWidth;
- int height = gWindowHeight;
-
- int components = 4;
- int rowStride = width*components;
-
- GLubyte* buffer = (GLubyte*)::malloc(components * width * height);
-
- glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
-
- // OpenGL's "upside down" convention bites us here, so we need
- // to flip the data in the buffer by swapping rows
- int halfHeight = height / 2;
- for (int hh = 0; hh < halfHeight; ++hh)
- {
- // Get a pointer to the row data, and a pointer
- // to the row on the "other end" of the image
- GLubyte* rowA = buffer + rowStride*hh;
- GLubyte* rowB = buffer + rowStride*(height - (hh + 1));
-
- for (int ii = 0; ii < rowStride; ++ii)
- {
- auto a = rowA[ii];
- auto b = rowB[ii];
-
- rowA[ii] = b;
- rowB[ii] = a;
- }
- }
-
- //
-
- int stbResult = stbi_write_png(
- outputPath,
- width,
- height,
- components,
- buffer,
- rowStride);
-
- ::free(buffer);
-
- if( !stbResult )
- {
- assert(!"unexpected");
- return SLANG_FAIL;
- }
-
- return SLANG_OK;
- }
-
- virtual ShaderCompiler* getShaderCompiler() override
- {
- return this;
- }
-
- virtual Buffer* createBuffer(BufferDesc const& desc) override
+
+ // Renderer implementation
+ virtual SlangResult initialize(void* inWindowHandle) override;
+ virtual void setClearColor(float const* color) override;
+ virtual void clearFrame() override;
+ virtual void presentFrame() override;
+ virtual SlangResult captureScreenShot(char const* outputPath) override;
+ virtual void serializeOutput(BindingState* state, const char * fileName) override;
+ virtual Buffer* createBuffer(BufferDesc const& desc) override;
+ virtual InputLayout* createInputLayout(InputElementDesc const* inputElements, UInt inputElementCount) override;
+ virtual BindingState * createBindingState(const ShaderInputLayout & layout) override;
+ virtual ShaderCompiler* getShaderCompiler() override;
+ virtual void* map(Buffer* buffer, MapFlavor flavor) override;
+ virtual void unmap(Buffer* buffer) override;
+ virtual void setInputLayout(InputLayout* inputLayout) override;
+ virtual void setPrimitiveTopology(PrimitiveTopology topology) override;
+ virtual void setBindingState(BindingState * state);
+ 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;
+
+ // ShaderCompiler implementation
+ virtual ShaderProgram* compileProgram(ShaderCompileRequest const& request) override;
+
+ protected:
+ enum
{
- // TODO: should derive target from desc...
- GLenum target = GL_UNIFORM_BUFFER;
-
- // TODO: should derive from desc...
- GLenum usage = GL_DYNAMIC_DRAW;
-
- GLuint bufferID = 0;
- glGenBuffers(1, &bufferID);
- glBindBuffer(target, bufferID);
-
- glBufferData(target, desc.size, desc.initData, usage);
-
- return (Buffer*)(uintptr_t)bufferID;
- }
+ kMaxVertexStreams = 16,
+ };
struct VertexAttributeFormat
{
@@ -272,290 +120,185 @@ public:
GLsizei offset;
};
- enum
- {
- kMaxVertexStreams = 16,
- };
-
struct InputLayoutImpl
{
VertexAttributeDesc attributes[kMaxVertexStreams];
UInt attributeCount = 0;
};
- static VertexAttributeFormat getVertexAttributeFormat(
- Format format)
+ struct BindingEntryImpl
{
- switch (format)
- {
- default: assert(!"unexpected"); return VertexAttributeFormat();
-
- #define CASE(NAME, COUNT, TYPE, NORMALIZED) \
- case Format::NAME: do { VertexAttributeFormat result = {COUNT, TYPE, NORMALIZED}; return result; } while (0)
-
- CASE(RGB_Float32, 3, GL_FLOAT, GL_FALSE);
- CASE(RG_Float32, 2, GL_FLOAT, GL_FALSE);
-
- #undef CASE
-
- }
- }
-
- virtual InputLayout* createInputLayout(InputElementDesc const* inputElements, UInt inputElementCount) override
- {
- InputLayoutImpl* inputLayout = new InputLayoutImpl();
-
- inputLayout->attributeCount = inputElementCount;
- for (UInt ii = 0; ii < inputElementCount; ++ii)
- {
- auto& inputAttr = inputElements[ii];
- auto& glAttr = inputLayout->attributes[ii];
-
- glAttr.streamIndex = 0;
- glAttr.format = getVertexAttributeFormat(inputAttr.format);
- glAttr.offset = (GLsizei) inputAttr.offset;
- }
-
- return (InputLayout*)inputLayout;
- }
-
- virtual void* map(Buffer* buffer, MapFlavor flavor) override
+ ShaderInputType type;
+ GLuint handle;
+ List<int> binding;
+ int bindTarget;
+ int bufferSize;
+ bool isOutput = false;
+ };
+ struct BindingStateImpl
{
- GLenum target = GL_UNIFORM_BUFFER;
-
- GLuint access = 0;
- 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;
- glBindBuffer(target, bufferID);
-
- return glMapBuffer(target, access);
- }
+ List<BindingEntryImpl> entries;
+ };
- virtual void unmap(Buffer* buffer) override
- {
- GLenum target = GL_UNIFORM_BUFFER;
+ void bindBufferImpl(int target, UInt startSlot, UInt slotCount, Buffer* const* buffers, UInt const* offsets);
+ void flushStateForDraw();
+ GLuint loadShader(GLenum stage, char const* source);
+ void createInputBuffer(BindingEntryImpl& rs, InputBufferDesc bufDesc, List<unsigned int>& bufferData);
+ void debugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, GLchar const* message);
+ void createInputTexture(BindingEntryImpl& rs, InputTextureDesc texDesc, InputSamplerDesc samplerDesc);
+ void createInputSampler(BindingEntryImpl& rs, InputSamplerDesc samplerDesc);
- auto bufferID = (GLuint)(uintptr_t)buffer;
- glUnmapBuffer(target);
- }
+ static void APIENTRY staticDebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, GLchar const* message, void const* userParam);
+ static VertexAttributeFormat getVertexAttributeFormat(Format format);
InputLayoutImpl* boundInputLayout = nullptr;
- virtual void setInputLayout(InputLayout* inputLayout) override
- {
- boundInputLayout = (InputLayoutImpl*) inputLayout;
- }
-
GLenum boundPrimitiveTopology = GL_TRIANGLES;
- virtual void setPrimitiveTopology(PrimitiveTopology topology) override
- {
- GLenum glTopology = 0;
- switch (topology)
- {
- #define CASE(NAME, VALUE) case PrimitiveTopology::NAME: glTopology = VALUE; break
-
- CASE(TriangleList, GL_TRIANGLES);
-
- #undef CASE
- }
- boundPrimitiveTopology = glTopology;
- }
-
+ HDC deviceContext;
+ HGLRC glContext;
+ float clearColor[4] = { 0, 0, 0, 0 };
GLuint boundVertexStreamBuffers[kMaxVertexStreams];
UInt boundVertexStreamStrides[kMaxVertexStreams];
UInt boundVertexStreamOffsets[kMaxVertexStreams];
- virtual void setVertexBuffers(UInt startSlot, UInt slotCount, Buffer* const* buffers, UInt const* strides, UInt const* offsets) override
- {
- for (UInt ii = 0; ii < slotCount; ++ii)
- {
- UInt slot = startSlot + ii;
+ // Declare a function pointer for each OpenGL
+ // extension function we need to load
+#define DECLARE_GL_EXTENSION_FUNC(NAME, TYPE) TYPE NAME;
+ MAP_GL_EXTENSION_FUNCS(DECLARE_GL_EXTENSION_FUNC)
+#undef DECLARE_GL_EXTENSION_FUNC
+};
- Buffer* buffer = buffers[ii];
- GLuint bufferID = (GLuint)(uintptr_t)buffer;
+Renderer* createGLRenderer()
+{
+ return new GLRenderer();
+}
- boundVertexStreamBuffers[slot] = bufferID;
- boundVertexStreamStrides[slot] = strides[ii];
- boundVertexStreamOffsets[slot] = offsets[ii];
- }
- }
+void GLRenderer::debugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, GLchar const* message)
+{
+ ::OutputDebugStringA("GL: ");
+ ::OutputDebugStringA(message);
+ ::OutputDebugStringA("\n");
- virtual void setShaderProgram(ShaderProgram* program) override
+ switch (type)
{
- GLuint programID = (GLuint)(uintptr_t)program;
- glUseProgram(programID);
+ case GL_DEBUG_TYPE_ERROR:
+ break;
+ default:
+ break;
}
+}
- 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;
+/* static */void APIENTRY GLRenderer::staticDebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, GLchar const* message, void const* userParam)
+{
+ ((GLRenderer*)userParam)->debugCallback(source, type, id, severity, length, message);
+}
- assert(!offsets || !offsets[ii]);
+/* static */GLRenderer::VertexAttributeFormat GLRenderer::getVertexAttributeFormat(Format format)
+{
+ switch (format)
+ {
+ default: assert(!"unexpected"); return VertexAttributeFormat();
- glBindBufferBase(target, (GLuint)slot, bufferID);
- }
- }
+#define CASE(NAME, COUNT, TYPE, NORMALIZED) \
+ case Format::NAME: do { VertexAttributeFormat result = {COUNT, TYPE, NORMALIZED}; return result; } while (0)
- virtual void setConstantBuffers(UInt startSlot, UInt slotCount, Buffer* const* buffers, UInt const* offsets) override
- {
- bindBufferImpl(GL_UNIFORM_BUFFER, startSlot, slotCount, buffers, offsets);
+ CASE(RGB_Float32, 3, GL_FLOAT, GL_FALSE);
+ CASE(RG_Float32, 2, GL_FLOAT, GL_FALSE);
+#undef CASE
}
+}
- void flushStateForDraw()
+void GLRenderer::bindBufferImpl(int target, UInt startSlot, UInt slotCount, Buffer* const* buffers, UInt const* offsets)
+{
+ for (UInt ii = 0; ii < slotCount; ++ii)
{
- auto layout = this->boundInputLayout;
- auto attrCount = layout->attributeCount;
- for (UInt ii = 0; ii < attrCount; ++ii)
- {
- auto& attr = layout->attributes[ii];
-
- auto streamIndex = attr.streamIndex;
+ UInt slot = startSlot + ii;
- glBindBuffer(GL_ARRAY_BUFFER, boundVertexStreamBuffers[streamIndex]);
+ Buffer* buffer = buffers[ii];
+ GLuint bufferID = (GLuint)(uintptr_t)buffer;
- glVertexAttribPointer(
- (GLuint) ii,
- attr.format.componentCount,
- attr.format.componentType,
- attr.format.normalized,
- (GLsizei) boundVertexStreamStrides[streamIndex],
- (GLvoid*)(attr.offset + boundVertexStreamOffsets[streamIndex]));
+ assert(!offsets || !offsets[ii]);
- glEnableVertexAttribArray((GLuint)ii);
- }
- for (UInt ii = attrCount; ii < kMaxVertexStreams; ++ii)
- {
- glDisableVertexAttribArray((GLuint)ii);
- }
+ glBindBufferBase(target, (GLuint)slot, bufferID);
}
+}
- virtual void draw(UInt vertexCount, UInt startVertex = 0) override
- {
- flushStateForDraw();
-
- glDrawArrays(boundPrimitiveTopology, (GLint) startVertex, (GLsizei) vertexCount);
- }
-
- // ShaderCompiler interface
-
- virtual ShaderProgram* compileProgram(ShaderCompileRequest const& request) override
+void GLRenderer::flushStateForDraw()
+{
+ auto layout = this->boundInputLayout;
+ auto attrCount = layout->attributeCount;
+ for (UInt ii = 0; ii < attrCount; ++ii)
{
- auto programID = glCreateProgram();
- if (request.computeShader.name)
- {
- auto computeShaderID = loadShader(GL_COMPUTE_SHADER, request.computeShader.source.dataBegin);
-
- glAttachShader(programID, computeShaderID);
-
-
- glLinkProgram(programID);
-
- glDeleteShader(computeShaderID);
- }
- else
- {
- 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);
+ auto& attr = layout->attributes[ii];
+ auto streamIndex = attr.streamIndex;
- glLinkProgram(programID);
+ glBindBuffer(GL_ARRAY_BUFFER, boundVertexStreamBuffers[streamIndex]);
- glDeleteShader(vertexShaderID);
- glDeleteShader(fragmentShaderID);
- }
- GLint success = GL_FALSE;
- glGetProgramiv(programID, GL_LINK_STATUS, &success);
- if( !success )
- {
- int maxSize = 0;
- glGetProgramiv(programID, GL_INFO_LOG_LENGTH, &maxSize);
-
- auto infoBuffer = (char*)::malloc(maxSize);
-
- int infoSize = 0;
- glGetProgramInfoLog(programID, maxSize, &infoSize, infoBuffer);
- if( infoSize > 0 )
- {
- fprintf(stderr, "%s", infoBuffer);
- OutputDebugStringA(infoBuffer);
- }
-
- ::free(infoBuffer);
+ glVertexAttribPointer(
+ (GLuint)ii,
+ attr.format.componentCount,
+ attr.format.componentType,
+ attr.format.normalized,
+ (GLsizei)boundVertexStreamStrides[streamIndex],
+ (GLvoid*)(attr.offset + boundVertexStreamOffsets[streamIndex]));
- glDeleteProgram(programID);
- return nullptr;
- }
-
- return (ShaderProgram*) (uintptr_t) programID;
+ glEnableVertexAttribArray((GLuint)ii);
}
-
- GLuint loadShader(GLenum stage, char const* source)
+ for (UInt ii = attrCount; ii < kMaxVertexStreams; ++ii)
{
+ glDisableVertexAttribArray((GLuint)ii);
+ }
+}
- // GLSL in monumentally stupid. It officially requires the `#version` directive
- // to be the first thing in the file, which wouldn't be so bad but the API
- // doesn't provide a way to pass a `#define` into your shader other than by
- // prepending it to the whole thing.
- //
- // We are going to solve this problem by doing some surgery on the source
- // that was passed in.
-
- char const* sourceBegin = source;
- char const* sourceEnd = source + strlen(source);
-
- // Look for a version directive in the user-provided source.
- char const* versionBegin = strstr(source, "#version");
- char const* versionEnd = nullptr;
- if( versionBegin )
+GLuint GLRenderer::loadShader(GLenum stage, char const* source)
+{
+ // GLSL is monumentally stupid. It officially requires the `#version` directive
+ // to be the first thing in the file, which wouldn't be so bad but the API
+ // doesn't provide a way to pass a `#define` into your shader other than by
+ // prepending it to the whole thing.
+ //
+ // We are going to solve this problem by doing some surgery on the source
+ // that was passed in.
+
+ char const* sourceBegin = source;
+ char const* sourceEnd = source + strlen(source);
+
+ // Look for a version directive in the user-provided source.
+ char const* versionBegin = strstr(source, "#version");
+ char const* versionEnd = nullptr;
+ if (versionBegin)
+ {
+ // If we found a directive, then scan for the end-of-line
+ // after it, and use that to specify the slice.
+ versionEnd = strchr(versionBegin, '\n');
+ if (!versionEnd)
{
- // If we found a directive, then scan for the end-of-line
- // after it, and use that to specify the slice.
- versionEnd = strchr(versionBegin, '\n');
- if( !versionEnd )
- {
- versionEnd = sourceEnd;
- }
- else
- {
- versionEnd = versionEnd + 1;
- }
+ versionEnd = sourceEnd;
}
else
{
- // If we didn't find a directive, then treat it as being
- // a zero-byte slice at the start of the string
- versionBegin = sourceBegin;
- versionEnd = sourceBegin;
+ versionEnd = versionEnd + 1;
}
+ }
+ else
+ {
+ // If we didn't find a directive, then treat it as being
+ // a zero-byte slice at the start of the string
+ versionBegin = sourceBegin;
+ versionEnd = sourceBegin;
+ }
- enum { kMaxSourceStringCount = 16 };
- GLchar const* sourceStrings[kMaxSourceStringCount];
- GLint sourceStringLengths[kMaxSourceStringCount];
+ enum { kMaxSourceStringCount = 16 };
+ GLchar const* sourceStrings[kMaxSourceStringCount];
+ GLint sourceStringLengths[kMaxSourceStringCount];
- int sourceStringCount = 0;
+ int sourceStringCount = 0;
- char const* stagePrelude = "\n";
- switch (stage)
- {
+ char const* stagePrelude = "\n";
+ switch (stage)
+ {
#define CASE(NAME) case GL_##NAME##_SHADER: stagePrelude = "#define __GLSL_" #NAME "__ 1\n"; break
CASE(VERTEX);
@@ -566,11 +309,11 @@ public:
CASE(COMPUTE);
#undef CASE
- }
+ }
- char const* prelude =
- "#define __GLSL__ 1\n"
- ;
+ char const* prelude =
+ "#define __GLSL__ 1\n"
+ ;
#define ADD_SOURCE_STRING_SPAN(BEGIN, END) \
sourceStrings[sourceStringCount] = BEGIN; \
@@ -582,79 +325,61 @@ public:
sourceStringLengths[sourceStringCount++] = GLint(strlen(BEGIN)) \
/* end */
- ADD_SOURCE_STRING_SPAN(versionBegin, versionEnd);
- ADD_SOURCE_STRING(stagePrelude);
- ADD_SOURCE_STRING(prelude);
- ADD_SOURCE_STRING_SPAN(sourceBegin, versionBegin);
- ADD_SOURCE_STRING_SPAN(versionEnd, sourceEnd);
-
- auto shaderID = glCreateShader(stage);
- glShaderSource(
- shaderID,
- sourceStringCount,
- &sourceStrings[0],
- &sourceStringLengths[0]);
- glCompileShader(shaderID);
-
- GLint success = GL_FALSE;
- glGetShaderiv(shaderID, GL_COMPILE_STATUS, &success);
- if( !success )
- {
- int maxSize = 0;
- glGetShaderiv(shaderID, GL_INFO_LOG_LENGTH, &maxSize);
+ ADD_SOURCE_STRING_SPAN(versionBegin, versionEnd);
+ ADD_SOURCE_STRING(stagePrelude);
+ ADD_SOURCE_STRING(prelude);
+ ADD_SOURCE_STRING_SPAN(sourceBegin, versionBegin);
+ ADD_SOURCE_STRING_SPAN(versionEnd, sourceEnd);
- auto infoBuffer = (char*) malloc(maxSize);
+ auto shaderID = glCreateShader(stage);
+ glShaderSource(
+ shaderID,
+ sourceStringCount,
+ &sourceStrings[0],
+ &sourceStringLengths[0]);
+ glCompileShader(shaderID);
- int infoSize = 0;
- glGetShaderInfoLog(shaderID, maxSize, &infoSize, infoBuffer);
- if( infoSize > 0 )
- {
- fprintf(stderr, "%s", infoBuffer);
- OutputDebugStringA(infoBuffer);
- }
+ GLint success = GL_FALSE;
+ glGetShaderiv(shaderID, GL_COMPILE_STATUS, &success);
+ if (!success)
+ {
+ int maxSize = 0;
+ glGetShaderiv(shaderID, GL_INFO_LOG_LENGTH, &maxSize);
+
+ auto infoBuffer = (char*)malloc(maxSize);
- glDeleteShader(shaderID);
- return 0;
+ int infoSize = 0;
+ glGetShaderInfoLog(shaderID, maxSize, &infoSize, infoBuffer);
+ if (infoSize > 0)
+ {
+ fprintf(stderr, "%s", infoBuffer);
+ OutputDebugStringA(infoBuffer);
}
- return shaderID;
- }
+ glDeleteShader(shaderID);
+ return 0;
+ }
- virtual void dispatchCompute(int x, int y, int z) override
- {
- glDispatchCompute(x, y, z);
- }
+ return shaderID;
+}
- struct GLBindingEntry
- {
- ShaderInputType type;
- GLuint handle;
- List<int> binding;
- int bindTarget;
- int bufferSize;
- bool isOutput = false;
- };
- struct GLBindingState
- {
- List<GLBindingEntry> entries;
- };
+void GLRenderer::createInputBuffer(BindingEntryImpl& rs, InputBufferDesc bufDesc, List<unsigned int>& bufferData)
+{
+ rs.bindTarget = (bufDesc.type == InputBufferType::StorageBuffer ? GL_SHADER_STORAGE_BUFFER : GL_UNIFORM_BUFFER);
+ glGenBuffers(1, &rs.handle);
+ glBindBuffer(rs.bindTarget, rs.handle);
+ glBufferData(rs.bindTarget, bufferData.Count() * sizeof(unsigned int), bufferData.Buffer(), GL_STATIC_READ);
+ glBindBuffer(rs.bindTarget, 0);
+}
- void createInputBuffer(GLBindingEntry & rs, InputBufferDesc bufDesc, List<unsigned int> & bufferData)
- {
- rs.bindTarget = (bufDesc.type == InputBufferType::StorageBuffer ? GL_SHADER_STORAGE_BUFFER : GL_UNIFORM_BUFFER);
- glGenBuffers(1, &rs.handle);
- glBindBuffer(rs.bindTarget, rs.handle);
- glBufferData(rs.bindTarget, bufferData.Count() * sizeof(unsigned int), bufferData.Buffer(), GL_STATIC_READ);
- glBindBuffer(rs.bindTarget, 0);
- }
- void createInputTexture(GLBindingEntry & rs, InputTextureDesc texDesc, InputSamplerDesc samplerDesc)
+void GLRenderer::createInputTexture(BindingEntryImpl& rs, InputTextureDesc texDesc, InputSamplerDesc samplerDesc)
+{
+ TextureData texData;
+ generateTextureData(texData, texDesc);
+ glGenTextures(1, &rs.handle);
+ switch (texDesc.dimension)
{
- TextureData texData;
- generateTextureData(texData, texDesc);
- glGenTextures(1, &rs.handle);
- switch (texDesc.dimension)
- {
case 1:
if (texDesc.arrayLength > 0)
{
@@ -714,59 +439,295 @@ public:
for (int i = 0; i < texData.mipLevels; i++)
glTexImage3D(rs.bindTarget, i, GL_RGBA8, texData.textureSize, texData.textureSize, texData.textureSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData.dataBuffer[i].Buffer());
break;
- }
- glTexParameteri(rs.bindTarget, GL_TEXTURE_WRAP_S, GL_REPEAT);
- glTexParameteri(rs.bindTarget, GL_TEXTURE_WRAP_T, GL_REPEAT);
- glTexParameteri(rs.bindTarget, GL_TEXTURE_WRAP_R, GL_REPEAT);
+ }
+ glTexParameteri(rs.bindTarget, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameteri(rs.bindTarget, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ glTexParameteri(rs.bindTarget, GL_TEXTURE_WRAP_R, GL_REPEAT);
- if (samplerDesc.isCompareSampler)
- {
- glTexParameteri(rs.bindTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
- glTexParameteri(rs.bindTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameterf(rs.bindTarget, GL_TEXTURE_MAX_ANISOTROPY_EXT, 8.0f);
- }
- else
- {
- glTexParameteri(rs.bindTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(rs.bindTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(rs.bindTarget, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
- glTexParameteri(rs.bindTarget, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
- }
+ if (samplerDesc.isCompareSampler)
+ {
+ glTexParameteri(rs.bindTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+ glTexParameteri(rs.bindTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameterf(rs.bindTarget, GL_TEXTURE_MAX_ANISOTROPY_EXT, 8.0f);
+ }
+ else
+ {
+ glTexParameteri(rs.bindTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(rs.bindTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(rs.bindTarget, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
+ glTexParameteri(rs.bindTarget, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
}
+}
- void createInputSampler(GLBindingEntry & rs, InputSamplerDesc samplerDesc)
+void GLRenderer::createInputSampler(BindingEntryImpl& rs, InputSamplerDesc samplerDesc)
+{
+ glCreateSamplers(1, &rs.handle);
+ glSamplerParameteri(rs.handle, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glSamplerParameteri(rs.handle, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ glSamplerParameteri(rs.handle, GL_TEXTURE_WRAP_R, GL_REPEAT);
+
+ if (samplerDesc.isCompareSampler)
+ {
+ glSamplerParameteri(rs.handle, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+ glSamplerParameteri(rs.handle, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glSamplerParameteri(rs.handle, GL_TEXTURE_MAX_ANISOTROPY_EXT, 8);
+ }
+ else
{
- glCreateSamplers(1, &rs.handle);
- glSamplerParameteri(rs.handle, GL_TEXTURE_WRAP_S, GL_REPEAT);
- glSamplerParameteri(rs.handle, GL_TEXTURE_WRAP_T, GL_REPEAT);
- glSamplerParameteri(rs.handle, GL_TEXTURE_WRAP_R, GL_REPEAT);
+ glSamplerParameteri(rs.handle, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glSamplerParameteri(rs.handle, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glSamplerParameteri(rs.handle, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
+ glSamplerParameteri(rs.handle, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
+ }
+}
- if (samplerDesc.isCompareSampler)
- {
- glSamplerParameteri(rs.handle, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
- glSamplerParameteri(rs.handle, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glSamplerParameteri(rs.handle, GL_TEXTURE_MAX_ANISOTROPY_EXT, 8);
- }
- else
+
+// !!!!!!!!!!!!!!!!!!!!!!!!!!!! Renderer interface !!!!!!!!!!!!!!!!!!!!!!!!!!
+
+SlangResult GLRenderer::initialize(void* inWindowHandle)
+{
+ auto windowHandle = (HWND)inWindowHandle;
+
+ deviceContext = ::GetDC(windowHandle);
+
+ PIXELFORMATDESCRIPTOR pixelFormatDesc = { sizeof(PIXELFORMATDESCRIPTOR) };
+ pixelFormatDesc.nVersion = 1;
+ pixelFormatDesc.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
+ pixelFormatDesc.iPixelType = PFD_TYPE_RGBA;
+ pixelFormatDesc.cColorBits = 32;
+ pixelFormatDesc.cDepthBits = 24;
+ pixelFormatDesc.cStencilBits = 8;
+ pixelFormatDesc.iLayerType = PFD_MAIN_PLANE;
+
+ int pixelFormatIndex = ChoosePixelFormat(deviceContext, &pixelFormatDesc);
+ SetPixelFormat(deviceContext, pixelFormatIndex, &pixelFormatDesc);
+
+ glContext = wglCreateContext(deviceContext);
+ wglMakeCurrent(deviceContext, glContext);
+
+ auto renderer = glGetString(GL_RENDERER);
+ auto extensions = glGetString(GL_EXTENSIONS);
+
+ // Load each of our extension functions by name
+
+#define LOAD_GL_EXTENSION_FUNC(NAME, TYPE) NAME = (TYPE) wglGetProcAddress(#NAME);
+ MAP_GL_EXTENSION_FUNCS(LOAD_GL_EXTENSION_FUNC)
+#undef LOAD_GL_EXTENSION_FUNC
+
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_CULL_FACE);
+
+ glViewport(0, 0, gWindowWidth, gWindowHeight);
+
+ if (glDebugMessageCallback)
+ {
+ glEnable(GL_DEBUG_OUTPUT);
+ glDebugMessageCallback(staticDebugCallback, this);
+ }
+
+ return SLANG_OK;
+}
+
+void GLRenderer::setClearColor(float const* color)
+{
+ glClearColor(color[0], color[1], color[2], color[3]);
+}
+
+void GLRenderer::clearFrame()
+{
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+}
+
+void GLRenderer::presentFrame()
+{
+ glFlush();
+ ::SwapBuffers(deviceContext);
+}
+
+SlangResult GLRenderer::captureScreenShot(char const* outputPath)
+{
+ int width = gWindowWidth;
+ int height = gWindowHeight;
+
+ int components = 4;
+ int rowStride = width*components;
+
+ GLubyte* buffer = (GLubyte*)::malloc(components * width * height);
+
+ glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
+
+ // OpenGL's "upside down" convention bites us here, so we need
+ // to flip the data in the buffer by swapping rows
+ int halfHeight = height / 2;
+ for (int hh = 0; hh < halfHeight; ++hh)
+ {
+ // Get a pointer to the row data, and a pointer
+ // to the row on the "other end" of the image
+ GLubyte* rowA = buffer + rowStride*hh;
+ GLubyte* rowB = buffer + rowStride*(height - (hh + 1));
+
+ for (int ii = 0; ii < rowStride; ++ii)
{
- glSamplerParameteri(rs.handle, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glSamplerParameteri(rs.handle, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glSamplerParameteri(rs.handle, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
- glSamplerParameteri(rs.handle, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
+ auto a = rowA[ii];
+ auto b = rowB[ii];
+
+ rowA[ii] = b;
+ rowB[ii] = a;
}
}
- virtual BindingState * createBindingState(const ShaderInputLayout & layout)
+ //
+ int stbResult = stbi_write_png(outputPath, width, height, components, buffer, rowStride);
+
+ ::free(buffer);
+
+ if (!stbResult)
+ {
+ assert(!"unexpected");
+ return SLANG_FAIL;
+ }
+
+ return SLANG_OK;
+}
+
+ShaderCompiler* GLRenderer::getShaderCompiler()
+{
+ return this;
+}
+
+Buffer* GLRenderer::createBuffer(BufferDesc const& desc)
+{
+ // TODO: should derive target from desc...
+ GLenum target = GL_UNIFORM_BUFFER;
+
+ // TODO: should derive from desc...
+ GLenum usage = GL_DYNAMIC_DRAW;
+
+ GLuint bufferID = 0;
+ glGenBuffers(1, &bufferID);
+ glBindBuffer(target, bufferID);
+
+ glBufferData(target, desc.size, desc.initData, usage);
+
+ return (Buffer*)(uintptr_t)bufferID;
+}
+
+InputLayout* GLRenderer::createInputLayout(InputElementDesc const* inputElements, UInt inputElementCount)
+{
+ InputLayoutImpl* inputLayout = new InputLayoutImpl();
+
+ inputLayout->attributeCount = inputElementCount;
+ for (UInt ii = 0; ii < inputElementCount; ++ii)
+ {
+ auto& inputAttr = inputElements[ii];
+ auto& glAttr = inputLayout->attributes[ii];
+
+ glAttr.streamIndex = 0;
+ glAttr.format = getVertexAttributeFormat(inputAttr.format);
+ glAttr.offset = (GLsizei)inputAttr.offset;
+ }
+
+ return (InputLayout*)inputLayout;
+}
+
+void* GLRenderer::map(Buffer* buffer, MapFlavor flavor)
+{
+ GLenum target = GL_UNIFORM_BUFFER;
+
+ GLuint access = 0;
+ 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;
+ glBindBuffer(target, bufferID);
+
+ return glMapBuffer(target, access);
+}
+
+void GLRenderer::unmap(Buffer* buffer)
+{
+ GLenum target = GL_UNIFORM_BUFFER;
+
+ auto bufferID = (GLuint)(uintptr_t)buffer;
+ glUnmapBuffer(target);
+}
+
+void GLRenderer::setInputLayout(InputLayout* inputLayout)
+{
+ boundInputLayout = (InputLayoutImpl*)inputLayout;
+}
+
+void GLRenderer::setPrimitiveTopology(PrimitiveTopology topology)
+{
+ GLenum glTopology = 0;
+ switch (topology)
+ {
+#define CASE(NAME, VALUE) case PrimitiveTopology::NAME: glTopology = VALUE; break
+
+ CASE(TriangleList, GL_TRIANGLES);
+
+#undef CASE
+ }
+ boundPrimitiveTopology = glTopology;
+}
+
+void GLRenderer::setVertexBuffers(UInt startSlot, UInt slotCount, Buffer* const* buffers, UInt const* strides, UInt const* offsets)
+{
+ for (UInt ii = 0; ii < slotCount; ++ii)
{
- GLBindingState * rs = new GLBindingState();
- for (auto & entry : layout.entries)
+ UInt slot = startSlot + ii;
+
+ Buffer* buffer = buffers[ii];
+ GLuint bufferID = (GLuint)(uintptr_t)buffer;
+
+ boundVertexStreamBuffers[slot] = bufferID;
+ boundVertexStreamStrides[slot] = strides[ii];
+ boundVertexStreamOffsets[slot] = offsets[ii];
+ }
+}
+
+void GLRenderer::setShaderProgram(ShaderProgram* program)
+{
+ GLuint programID = (GLuint)(uintptr_t)program;
+ glUseProgram(programID);
+}
+
+void GLRenderer::setConstantBuffers(UInt startSlot, UInt slotCount, Buffer* const* buffers, UInt const* offsets)
+{
+ bindBufferImpl(GL_UNIFORM_BUFFER, startSlot, slotCount, buffers, offsets);
+}
+
+void GLRenderer::draw(UInt vertexCount, UInt startVertex = 0)
+{
+ flushStateForDraw();
+
+ glDrawArrays(boundPrimitiveTopology, (GLint)startVertex, (GLsizei)vertexCount);
+}
+
+void GLRenderer::dispatchCompute(int x, int y, int z)
+{
+ glDispatchCompute(x, y, z);
+}
+
+BindingState* GLRenderer::createBindingState(const ShaderInputLayout & layout)
+{
+ BindingStateImpl * rs = new BindingStateImpl();
+ for (auto & entry : layout.entries)
+ {
+ BindingEntryImpl rsEntry;
+ rsEntry.isOutput = entry.isOutput;
+ rsEntry.binding = entry.glslBinding;
+ rsEntry.type = entry.type;
+ switch (entry.type)
{
- GLBindingEntry rsEntry;
- rsEntry.isOutput = entry.isOutput;
- rsEntry.binding = entry.glslBinding;
- rsEntry.type = entry.type;
- switch (entry.type)
- {
case ShaderInputType::Buffer:
createInputBuffer(rsEntry, entry.bufferDesc, entry.bufferData);
break;
@@ -779,19 +740,19 @@ public:
case ShaderInputType::Sampler:
createInputSampler(rsEntry, entry.samplerDesc);
break;
- }
- rs->entries.Add(rsEntry);
}
- return (BindingState*)rs;
+ rs->entries.Add(rsEntry);
}
+ return (BindingState*)rs;
+}
- virtual void setBindingState(BindingState * state)
+void GLRenderer::setBindingState(BindingState * state)
+{
+ BindingStateImpl * glState = (BindingStateImpl*)state;
+ for (auto & entry : glState->entries)
{
- GLBindingState * glState = (GLBindingState*)state;
- for (auto & entry : glState->entries)
+ switch (entry.type)
{
- switch (entry.type)
- {
case ShaderInputType::Buffer:
glBindBufferBase(entry.bindTarget, entry.binding[0], entry.handle);
break;
@@ -804,35 +765,81 @@ public:
glActiveTexture(GL_TEXTURE0 + entry.binding[0]);
glBindTexture(entry.bindTarget, entry.handle);
break;
- }
}
}
+}
- virtual void serializeOutput(BindingState* state, const char * fileName)
+void GLRenderer::serializeOutput(BindingState* state, const char * fileName)
+{
+ BindingStateImpl * glState = (BindingStateImpl*)state;
+ FILE * f;
+ fopen_s(&f, fileName, "wt");
+ for (auto & entry : glState->entries)
{
- GLBindingState * glState = (GLBindingState*)state;
- FILE * f;
- fopen_s(&f, fileName, "wt");
- for (auto & entry : glState->entries)
+ if (entry.isOutput)
{
- if (entry.isOutput)
- {
- glBindBuffer(entry.bindTarget, entry.handle);
- auto ptr = (unsigned int *)glMapBuffer(entry.bindTarget, GL_READ_ONLY);
- for (auto i = 0u; i < entry.bufferSize / sizeof(unsigned int); i++)
- fprintf(f, "%X\n", ptr[i]);
- glUnmapBuffer(entry.bindTarget);
- }
+ glBindBuffer(entry.bindTarget, entry.handle);
+ auto ptr = (unsigned int *)glMapBuffer(entry.bindTarget, GL_READ_ONLY);
+ for (auto i = 0u; i < entry.bufferSize / sizeof(unsigned int); i++)
+ fprintf(f, "%X\n", ptr[i]);
+ glUnmapBuffer(entry.bindTarget);
}
- fclose(f);
}
-};
+ fclose(f);
+}
+// ShaderCompiler interface
-Renderer* createGLRenderer()
+ShaderProgram* GLRenderer::compileProgram(ShaderCompileRequest const& request)
{
- return new GLRenderer();
+ auto programID = glCreateProgram();
+ if (request.computeShader.name)
+ {
+ auto computeShaderID = loadShader(GL_COMPUTE_SHADER, request.computeShader.source.dataBegin);
+ glAttachShader(programID, computeShaderID);
+ glLinkProgram(programID);
+ glDeleteShader(computeShaderID);
+ }
+ else
+ {
+ 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);
+
+
+ glLinkProgram(programID);
+
+ glDeleteShader(vertexShaderID);
+ glDeleteShader(fragmentShaderID);
+ }
+ GLint success = GL_FALSE;
+ glGetProgramiv(programID, GL_LINK_STATUS, &success);
+ if (!success)
+ {
+ int maxSize = 0;
+ glGetProgramiv(programID, GL_INFO_LOG_LENGTH, &maxSize);
+
+ auto infoBuffer = (char*)::malloc(maxSize);
+
+ int infoSize = 0;
+ glGetProgramInfoLog(programID, maxSize, &infoSize, infoBuffer);
+ if (infoSize > 0)
+ {
+ fprintf(stderr, "%s", infoBuffer);
+ OutputDebugStringA(infoBuffer);
+ }
+
+ ::free(infoBuffer);
+
+ glDeleteProgram(programID);
+ return nullptr;
+ }
+
+ return (ShaderProgram*)(uintptr_t)programID;
}
+
} // renderer_test
diff --git a/tools/render-test/render-vk.cpp b/tools/render-test/render-vk.cpp
index 1f8e11aa6..2c74c8883 100644
--- a/tools/render-test/render-vk.cpp
+++ b/tools/render-test/render-vk.cpp
@@ -81,6 +81,92 @@ namespace renderer_test {
class VKRenderer : public Renderer, public ShaderCompiler
{
public:
+ // Renderer implementation
+ virtual SlangResult initialize(void* inWindowHandle) override;
+ virtual void setClearColor(float const* color) override;
+ virtual void clearFrame() override;
+ virtual void presentFrame() override;
+ virtual SlangResult captureScreenShot(char const* outputPath) override;
+ virtual void serializeOutput(BindingState* state, const char * fileName) override;
+ virtual Buffer* createBuffer(BufferDesc const& desc) override;
+ virtual InputLayout* createInputLayout(InputElementDesc const* inputElements, UInt inputElementCount) override;
+ virtual BindingState * createBindingState(const ShaderInputLayout & layout) override;
+ virtual ShaderCompiler* getShaderCompiler() override;
+ virtual void* map(Buffer* buffer, MapFlavor flavor) override;
+ virtual void unmap(Buffer* buffer) override;
+ virtual void setInputLayout(InputLayout* inputLayout) override;
+ virtual void setPrimitiveTopology(PrimitiveTopology topology) override;
+ virtual void setBindingState(BindingState * state);
+ 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;
+
+ // ShaderCompiler implementation
+ virtual ShaderProgram* compileProgram(ShaderCompileRequest const& request) override;
+
+ protected:
+
+ struct BufferImpl
+ {
+ VkBuffer buffer;
+ VkDeviceMemory memory;
+ };
+
+ struct ShaderProgramImpl
+ {
+ VkPipelineShaderStageCreateInfo compute;
+ VkPipelineShaderStageCreateInfo vertex;
+ VkPipelineShaderStageCreateInfo fragment;
+ };
+
+ 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;
+ };
+
+ struct InputLayoutImpl
+ {
+ };
+
+ VkBool32 handleDebugMessage(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objType, uint64_t srcObject,
+ size_t location, int32_t msgCode, const char* pLayerPrefix, const char* pMsg);
+ BufferImpl createBufferImpl(size_t bufferSize, VkBufferUsageFlags usage, VkMemoryPropertyFlags reqMemoryProperties, void const* initData = nullptr);
+
+ VkCommandBuffer getCommandBuffer();
+ VkCommandBuffer beginCommandBuffer();
+ void flushCommandBuffer(VkCommandBuffer commandBuffer);
+
+ uint32_t getMemoryTypeIndex(uint32_t inTypeBits, VkMemoryPropertyFlags properties);
+
+ VkPipelineShaderStageCreateInfo compileEntryPoint(const ShaderCompileRequest::EntryPoint& entryPointRequest, VkShaderStageFlagBits stage);
+
+ void createInputTexture(const InputTextureDesc& inputDesc, VkImageView& viewOut);
+ void createInputSampler(const InputSamplerDesc& inputDesc, VkSampler& stateOut);
+ void createInputBuffer(const ShaderInputLayoutEntry& entry, const InputBufferDesc& bufferDesc, const Slang::List<unsigned int>& bufferData,
+ VkBuffer& bufferOut, VkBufferView& uavOut, VkImageView& srvOut);
+
+ static SlangResult toSlangResult(VkResult res);
+ static void checkResult(VkResult result);
+ 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);
VkInstance instance;
VkPhysicalDevice physicalDevice;
@@ -94,6 +180,10 @@ public:
VkSubmitInfo submitInfo;
VkDebugReportCallbackEXT debugReportCallback;
+ BindingStateImpl* currentBindingState = nullptr;
+ ShaderProgramImpl* currentProgram = nullptr;
+
+ float clearColor[4];
#define DECLARE_PROC(NAME) PFN_##NAME NAME;
DECLARE_PROC(vkGetInstanceProcAddr);
@@ -101,605 +191,555 @@ public:
FOREACH_INSTANCE_PROC(DECLARE_PROC)
FOREACH_DEVICE_PROC(DECLARE_PROC)
#undef DECLARE_PROC
+
+};
- // Renderer interface
-
- static SlangResult toSlangResult(VkResult res)
- {
- return (res == VK_SUCCESS) ? SLANG_OK : SLANG_FAIL;
- }
- 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;
- }
+Renderer* createVKRenderer()
+{
+ return new VKRenderer();
+}
- 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);
- }
+/* static */SlangResult VKRenderer::toSlangResult(VkResult res)
+{
+ return (res == VK_SUCCESS) ? SLANG_OK : SLANG_FAIL;
+}
- virtual SlangResult initialize(void* inWindowHandle) override
- {
- char const* dynamicLibraryName = "vulkan-1.dll";
- HMODULE vulkan = LoadLibraryA(dynamicLibraryName);
- if(!vulkan)
- {
- fprintf(stderr, "error: failed load '%s'\n", dynamicLibraryName);
- return SLANG_FAIL;
- }
+void VKRenderer::checkResult(VkResult result)
+{
+ assert(result == VK_SUCCESS);
+}
- vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr) GetProcAddress(vulkan, "vkGetInstanceProcAddr");
- if(!vkGetInstanceProcAddr)
- {
- fprintf(stderr, "error: failed load symbol 'vkGetInstanceProcAddr'\n");
- return SLANG_FAIL;
- }
+VkBool32 VKRenderer::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;
+}
- VkApplicationInfo applicationInfo = { VK_STRUCTURE_TYPE_APPLICATION_INFO };
- applicationInfo.pApplicationName = "slang-render-test";
- applicationInfo.pEngineName = "slang-render-test";
- applicationInfo.apiVersion = VK_API_VERSION_1_0;
+/* static */VKAPI_ATTR VkBool32 VKAPI_CALL VKRenderer::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);
+}
- char const* instanceExtensions[] = {
- VK_KHR_SURFACE_EXTENSION_NAME,
-#ifdef _WIN32
- VK_KHR_WIN32_SURFACE_EXTENSION_NAME,
-#else
-#endif
+VkCommandBuffer VKRenderer::getCommandBuffer()
+{
+ VkCommandBufferAllocateInfo info = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO };
+ info.commandPool = commandPool;
+ info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
+ info.commandBufferCount = 1;
-#if ENABLE_VALIDATION_LAYER
- VK_EXT_DEBUG_REPORT_EXTENSION_NAME,
-#endif
- };
+ VkCommandBuffer commandBuffer;
+ checkResult(vkAllocateCommandBuffers(
+ device, &info, &commandBuffer));
- VkInstanceCreateInfo instanceCreateInfo = { VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO };
- instanceCreateInfo.pApplicationInfo = &applicationInfo;
+ return commandBuffer;
+}
- instanceCreateInfo.enabledExtensionCount = sizeof(instanceExtensions) / sizeof(instanceExtensions[0]);
- instanceCreateInfo.ppEnabledExtensionNames = &instanceExtensions[0];
+VkCommandBuffer VKRenderer::beginCommandBuffer()
+{
+ VkCommandBuffer commandBuffer = getCommandBuffer();
-#if ENABLE_VALIDATION_LAYER
+ VkCommandBufferBeginInfo beginInfo = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO };
+ checkResult(vkBeginCommandBuffer(commandBuffer, &beginInfo));
- uint32_t layerCount = 1;
- const char *layerNames[] = {
- "VK_LAYER_LUNARG_standard_validation"
- };
+ return commandBuffer;
+}
- instanceCreateInfo.enabledLayerCount = layerCount;
- instanceCreateInfo.ppEnabledLayerNames = layerNames;
-#endif
+void VKRenderer::flushCommandBuffer(VkCommandBuffer commandBuffer)
+{
+ checkResult(vkEndCommandBuffer(commandBuffer));
- instance = 0;
+ VkSubmitInfo submitInfo = { VK_STRUCTURE_TYPE_SUBMIT_INFO };
+ submitInfo.commandBufferCount = 1;
+ submitInfo.pCommandBuffers = &commandBuffer;
-#define LOAD_INSTANCE_PROC(NAME) NAME = (PFN_##NAME) vkGetInstanceProcAddr(instance, #NAME);
+ checkResult(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE));
+ checkResult(vkQueueWaitIdle(queue));
- FOREACH_GLOBAL_PROC(LOAD_INSTANCE_PROC);
+ vkFreeCommandBuffers(device, commandPool, 1, &commandBuffer);
+}
- RETURN_ON_VK_FAIL(vkCreateInstance(&instanceCreateInfo, nullptr, &instance));
+VKRenderer::BufferImpl VKRenderer::createBufferImpl(size_t bufferSize, VkBufferUsageFlags usage, VkMemoryPropertyFlags reqMemoryProperties, void const* initData)
+{
+ if (initData)
+ {
+ // TODO: what if we are allocating it as CPU-writable anyway?
+ usage |= VK_BUFFER_USAGE_TRANSFER_DST_BIT;
+ }
- FOREACH_INSTANCE_PROC(LOAD_INSTANCE_PROC);
+ VkBufferCreateInfo bufferCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+ bufferCreateInfo.size = bufferSize;
+ bufferCreateInfo.usage = usage;
-#undef LOAD_INSTANCE_PROC
+ VkBuffer buffer;
+ checkResult(vkCreateBuffer(
+ device, &bufferCreateInfo, nullptr, &buffer));
+ VkMemoryRequirements memoryReqs = {};
+ vkGetBufferMemoryRequirements(device, buffer, &memoryReqs);
-#if ENABLE_VALIDATION_LAYER
- VkDebugReportFlagsEXT debugFlags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT;
+ uint32_t memoryTypeIndex = getMemoryTypeIndex(
+ memoryReqs.memoryTypeBits, reqMemoryProperties);
- VkDebugReportCallbackCreateInfoEXT debugCreateInfo = { VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT };
- debugCreateInfo.pfnCallback = &debugMessageCallback;
- debugCreateInfo.pUserData = this;
- debugCreateInfo.flags = debugFlags;
+ VkMemoryPropertyFlags actualMemoryProperites = deviceMemoryProperties.memoryTypes[memoryTypeIndex].propertyFlags;
- RETURN_ON_VK_FAIL(vkCreateDebugReportCallbackEXT(instance, &debugCreateInfo, nullptr, &debugReportCallback));
+ VkMemoryAllocateInfo allocateInfo = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO };
+ allocateInfo.allocationSize = memoryReqs.size;
+ allocateInfo.memoryTypeIndex = memoryTypeIndex;
-#endif
+ VkDeviceMemory memory;
+ checkResult(vkAllocateMemory(
+ device, &allocateInfo, nullptr, &memory));
- uint32_t physicalDeviceCount = 0;
- RETURN_ON_VK_FAIL(vkEnumeratePhysicalDevices(instance, &physicalDeviceCount, nullptr));
+ checkResult(vkBindBufferMemory(
+ device, buffer, memory, 0));
- VkPhysicalDevice* physicalDevices = (VkPhysicalDevice*)alloca(
- physicalDeviceCount * sizeof(VkPhysicalDevice));
- RETURN_ON_VK_FAIL(vkEnumeratePhysicalDevices(
- instance, &physicalDeviceCount, physicalDevices));
+ if (initData)
+ {
+ // TODO: only create staging buffer if the memory type
+ // used for the buffer doesn't let us fill things in
+ // directly.
- uint32_t selectedDeviceIndex = 0;
- // TODO: allow override of selected device
- physicalDevice = physicalDevices[selectedDeviceIndex];
+ BufferImpl staging = createBufferImpl(bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
+ VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
- vkGetPhysicalDeviceProperties(physicalDevice, &deviceProperties);
- vkGetPhysicalDeviceFeatures(physicalDevice, &deviceFeatures);
- vkGetPhysicalDeviceMemoryProperties(physicalDevice, &deviceMemoryProperties);
+ // Copy into staging buffer
+ void* mappedData = nullptr;
+ checkResult(vkMapMemory(device, staging.memory, 0, bufferSize, 0, &mappedData));
+ memcpy(mappedData, initData, bufferSize);
+ vkUnmapMemory(device, staging.memory);
- uint32_t queueFamilyCount = 0;
- vkGetPhysicalDeviceQueueFamilyProperties(
- physicalDevice, &queueFamilyCount, nullptr);
+ // Copy from staging buffer to real buffer
+ VkCommandBuffer commandBuffer = beginCommandBuffer();
- VkQueueFamilyProperties* queueFamilies = (VkQueueFamilyProperties*)alloca(
- queueFamilyCount * sizeof(VkQueueFamilyProperties));
- vkGetPhysicalDeviceQueueFamilyProperties(
- physicalDevice, &queueFamilyCount, queueFamilies);
+ VkBufferCopy copyInfo = {};
+ copyInfo.size = bufferSize;
+ vkCmdCopyBuffer(commandBuffer, staging.buffer, buffer, 1, &copyInfo);
- // Find a queue that can service our needs
- VkQueueFlags reqQueueFlags =
- VK_QUEUE_GRAPHICS_BIT
- | VK_QUEUE_COMPUTE_BIT;
+ flushCommandBuffer(commandBuffer);
- 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);
+ // Now destroy the staging buffer
+ vkDestroyBuffer(device, staging.buffer, nullptr);
+ vkFreeMemory(device, staging.memory, nullptr);
+ }
- float queuePriority = 0.0f;
- VkDeviceQueueCreateInfo queueCreateInfo = { VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO };
- queueCreateInfo.queueFamilyIndex = queueFamilyIndex;
- queueCreateInfo.queueCount = 1;
- queueCreateInfo.pQueuePriorities = &queuePriority;
+ BufferImpl impl;
+ impl.buffer = buffer;
+ impl.memory = memory;
+ return impl;
+}
- char const* const deviceExtensions[] =
+uint32_t VKRenderer::getMemoryTypeIndex(uint32_t inTypeBits, VkMemoryPropertyFlags properties)
+{
+ uint32_t typeBits = inTypeBits;
+ uint32_t typeIndex = 0;
+ while (typeBits)
+ {
+ if ((deviceMemoryProperties.memoryTypes[typeIndex].propertyFlags & properties) == properties)
{
- VK_KHR_SWAPCHAIN_EXTENSION_NAME,
- };
+ return typeIndex;
+ }
+ typeIndex++;
+ typeBits >>= 1;
+ }
- VkDeviceCreateInfo deviceCreateInfo = { VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO };
- deviceCreateInfo.queueCreateInfoCount = 1;
- deviceCreateInfo.pQueueCreateInfos = &queueCreateInfo;
- deviceCreateInfo.pEnabledFeatures = &enabledFeatures;
+ assert(!"failed to find a usable memory type");
+ return uint32_t(-1);
+}
- deviceCreateInfo.enabledExtensionCount = sizeof(deviceExtensions) / sizeof(deviceExtensions[0]);
- deviceCreateInfo.ppEnabledExtensionNames = &deviceExtensions[0];
+void VKRenderer::createInputTexture(const InputTextureDesc& inputDesc, VkImageView& viewOut)
+{
+ TextureData texData;
+ generateTextureData(texData, inputDesc);
+ assert(!"unimplemented");
+}
- RETURN_ON_VK_FAIL(vkCreateDevice(
- physicalDevice, &deviceCreateInfo, nullptr, &device));
+void VKRenderer::createInputSampler(const InputSamplerDesc& inputDesc, VkSampler& stateOut)
+{
+ assert(!"unimplemented");
+}
-#define LOAD_DEVICE_PROC(NAME) NAME = (PFN_##NAME) vkGetDeviceProcAddr(device, #NAME);
- FOREACH_DEVICE_PROC(LOAD_DEVICE_PROC)
-#undef LOAD_DEVICE_PROC
+void VKRenderer::createInputBuffer(const ShaderInputLayoutEntry& entry, const InputBufferDesc& bufferDesc, const Slang::List<unsigned int>& bufferData,
+ VkBuffer& bufferOut, VkBufferView& uavOut, VkImageView& srvOut)
+{
+ size_t bufferSize = bufferData.Count() * sizeof(unsigned int);
+ void const* initData = bufferData.Buffer();
- // Create a command pool
+ VkBufferUsageFlags usage = 0;
+ VkMemoryPropertyFlags reqMemoryProperties = 0;
- VkCommandPoolCreateInfo commandPoolCreateInfo = { VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO };
- commandPoolCreateInfo.queueFamilyIndex = queueFamilyIndex;
- commandPoolCreateInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
+ 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;
- RETURN_ON_VK_FAIL(vkCreateCommandPool(
- device, &commandPoolCreateInfo, nullptr, &commandPool));
+ case InputBufferType::StorageBuffer:
+ usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
+ reqMemoryProperties = 0;
+ break;
+ }
- vkGetDeviceQueue(
- device,
- queueFamilyIndex,
- 0,
- &queue);
+ // 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;
+ }
- // set up swap chain
+ 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;
- // create command buffers
+ // Fill in any views needed
+ switch (bufferDesc.type)
+ {
+ case InputBufferType::ConstantBuffer:
+ break;
- // depth/stencil?
+ case InputBufferType::StorageBuffer:
+ {
+ }
+ break;
+ }
+}
- // render pass?
+VkPipelineShaderStageCreateInfo VKRenderer::compileEntryPoint(const ShaderCompileRequest::EntryPoint& entryPointRequest, VkShaderStageFlagBits stage)
+{
+ char const* dataBegin = entryPointRequest.source.dataBegin;
+ char const* dataEnd = entryPointRequest.source.dataEnd;
- // pipeline cache
+ // 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);
- // frame buffer
+ 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));
+ //::free(codeBegin);
- // create semaphores for sync
+ VkPipelineShaderStageCreateInfo shaderStageCreateInfo = { VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO };
+ shaderStageCreateInfo.stage = stage;
- return SLANG_OK;
- }
+ shaderStageCreateInfo.module = module;
+ shaderStageCreateInfo.pName = "main";
+ return shaderStageCreateInfo;
+}
- float clearColor[4];
- virtual void setClearColor(float const* color) override
- {
- for(int ii = 0; ii < 4; ++ii)
- clearColor[ii] = color[ii];
- }
+// !!!!!!!!!!!!!!!!!!!!!!!!!!!! Renderer interface !!!!!!!!!!!!!!!!!!!!!!!!!!
- virtual void clearFrame() override
+SlangResult VKRenderer::initialize(void* inWindowHandle)
+{
+ char const* dynamicLibraryName = "vulkan-1.dll";
+ HMODULE vulkan = LoadLibraryA(dynamicLibraryName);
+ if (!vulkan)
{
+ fprintf(stderr, "error: failed load '%s'\n", dynamicLibraryName);
+ return SLANG_FAIL;
}
- virtual void presentFrame() override
+ vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)GetProcAddress(vulkan, "vkGetInstanceProcAddr");
+ if (!vkGetInstanceProcAddr)
{
+ fprintf(stderr, "error: failed load symbol 'vkGetInstanceProcAddr'\n");
+ return SLANG_FAIL;
}
- virtual SlangResult captureScreenShot(char const* outputPath) override
- {
- return SLANG_FAIL;
- }
+ VkApplicationInfo applicationInfo = { VK_STRUCTURE_TYPE_APPLICATION_INFO };
+ applicationInfo.pApplicationName = "slang-render-test";
+ applicationInfo.pEngineName = "slang-render-test";
+ applicationInfo.apiVersion = VK_API_VERSION_1_0;
- virtual ShaderCompiler* getShaderCompiler() override
- {
- return this;
- }
+ char const* instanceExtensions[] = {
+ VK_KHR_SURFACE_EXTENSION_NAME,
+#ifdef _WIN32
+ VK_KHR_WIN32_SURFACE_EXTENSION_NAME,
+#else
+#endif
- VkCommandBuffer getCommandBuffer()
- {
- VkCommandBufferAllocateInfo info = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO };
- info.commandPool = commandPool;
- info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
- info.commandBufferCount = 1;
+#if ENABLE_VALIDATION_LAYER
+ VK_EXT_DEBUG_REPORT_EXTENSION_NAME,
+#endif
+ };
- VkCommandBuffer commandBuffer;
- checkResult(vkAllocateCommandBuffers(
- device, &info, &commandBuffer));
+ VkInstanceCreateInfo instanceCreateInfo = { VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO };
+ instanceCreateInfo.pApplicationInfo = &applicationInfo;
- return commandBuffer;
- }
+ instanceCreateInfo.enabledExtensionCount = sizeof(instanceExtensions) / sizeof(instanceExtensions[0]);
+ instanceCreateInfo.ppEnabledExtensionNames = &instanceExtensions[0];
- VkCommandBuffer beginCommandBuffer()
- {
- VkCommandBuffer commandBuffer = getCommandBuffer();
+#if ENABLE_VALIDATION_LAYER
- VkCommandBufferBeginInfo beginInfo = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO };
- checkResult(vkBeginCommandBuffer(commandBuffer, &beginInfo));
+ uint32_t layerCount = 1;
+ const char *layerNames[] = {
+ "VK_LAYER_LUNARG_standard_validation"
+ };
- return commandBuffer;
- }
+ instanceCreateInfo.enabledLayerCount = layerCount;
+ instanceCreateInfo.ppEnabledLayerNames = layerNames;
+#endif
- void flushCommandBuffer(VkCommandBuffer commandBuffer)
- {
- checkResult(vkEndCommandBuffer(commandBuffer));
+ instance = 0;
- VkSubmitInfo submitInfo = { VK_STRUCTURE_TYPE_SUBMIT_INFO };
- submitInfo.commandBufferCount = 1;
- submitInfo.pCommandBuffers = &commandBuffer;
+#define LOAD_INSTANCE_PROC(NAME) NAME = (PFN_##NAME) vkGetInstanceProcAddr(instance, #NAME);
- checkResult(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE));
- checkResult(vkQueueWaitIdle(queue));
+ FOREACH_GLOBAL_PROC(LOAD_INSTANCE_PROC);
- vkFreeCommandBuffers(device, commandPool, 1, &commandBuffer);
- }
+ RETURN_ON_VK_FAIL(vkCreateInstance(&instanceCreateInfo, nullptr, &instance));
- struct BufferImpl
- {
- VkBuffer buffer;
- VkDeviceMemory memory;
- };
+ FOREACH_INSTANCE_PROC(LOAD_INSTANCE_PROC);
- 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;
- }
+#undef LOAD_INSTANCE_PROC
- VkBufferCreateInfo bufferCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
- bufferCreateInfo.size = bufferSize;
- bufferCreateInfo.usage = usage;
- VkBuffer buffer;
- checkResult(vkCreateBuffer(
- device, &bufferCreateInfo, nullptr, &buffer));
+#if ENABLE_VALIDATION_LAYER
+ VkDebugReportFlagsEXT debugFlags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT;
- VkMemoryRequirements memoryReqs = {};
- vkGetBufferMemoryRequirements(device, buffer, &memoryReqs);
+ VkDebugReportCallbackCreateInfoEXT debugCreateInfo = { VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT };
+ debugCreateInfo.pfnCallback = &debugMessageCallback;
+ debugCreateInfo.pUserData = this;
+ debugCreateInfo.flags = debugFlags;
- uint32_t memoryTypeIndex = getMemoryTypeIndex(
- memoryReqs.memoryTypeBits, reqMemoryProperties);
+ RETURN_ON_VK_FAIL(vkCreateDebugReportCallbackEXT(instance, &debugCreateInfo, nullptr, &debugReportCallback));
- VkMemoryPropertyFlags actualMemoryProperites = deviceMemoryProperties.memoryTypes[memoryTypeIndex].propertyFlags;
+#endif
- VkMemoryAllocateInfo allocateInfo = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO };
- allocateInfo.allocationSize = memoryReqs.size;
- allocateInfo.memoryTypeIndex = memoryTypeIndex;
+ uint32_t physicalDeviceCount = 0;
+ RETURN_ON_VK_FAIL(vkEnumeratePhysicalDevices(instance, &physicalDeviceCount, nullptr));
- VkDeviceMemory memory;
- checkResult(vkAllocateMemory(
- device, &allocateInfo, nullptr, &memory));
+ VkPhysicalDevice* physicalDevices = (VkPhysicalDevice*)alloca(
+ physicalDeviceCount * sizeof(VkPhysicalDevice));
+ RETURN_ON_VK_FAIL(vkEnumeratePhysicalDevices(
+ instance, &physicalDeviceCount, physicalDevices));
- checkResult(vkBindBufferMemory(
- device, buffer, memory, 0));
+ uint32_t selectedDeviceIndex = 0;
+ // TODO: allow override of selected device
+ physicalDevice = physicalDevices[selectedDeviceIndex];
- 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);
- }
+ vkGetPhysicalDeviceProperties(physicalDevice, &deviceProperties);
+ vkGetPhysicalDeviceFeatures(physicalDevice, &deviceFeatures);
+ vkGetPhysicalDeviceMemoryProperties(physicalDevice, &deviceMemoryProperties);
- BufferImpl impl;
- impl.buffer = buffer;
- impl.memory = memory;
- return impl;
- }
+ uint32_t queueFamilyCount = 0;
+ vkGetPhysicalDeviceQueueFamilyProperties(
+ physicalDevice, &queueFamilyCount, nullptr);
- virtual Buffer* createBuffer(BufferDesc const& desc) override
- {
- size_t bufferSize = desc.size;
+ VkQueueFamilyProperties* queueFamilies = (VkQueueFamilyProperties*)alloca(
+ queueFamilyCount * sizeof(VkQueueFamilyProperties));
+ vkGetPhysicalDeviceQueueFamilyProperties(
+ physicalDevice, &queueFamilyCount, queueFamilies);
- VkBufferUsageFlags usage = 0;
- VkMemoryPropertyFlags reqMemoryProperties = 0;
+ // Find a queue that can service our needs
+ VkQueueFlags reqQueueFlags = VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT;
- switch( desc.flavor )
+ uint32_t queueFamilyIndex = uint32_t(-1);
+ for (uint32_t qq = 0; qq < queueFamilyCount; ++qq)
+ {
+ if ((queueFamilies[qq].queueFlags & reqQueueFlags) == reqQueueFlags)
{
- 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;
+ queueFamilyIndex = qq;
break;
}
-
- BufferImpl bufferImpl = createBufferImpl(
- bufferSize,
- usage,
- reqMemoryProperties,
- desc.initData);
-
- BufferImpl* bufferPtr = new BufferImpl();
- *bufferPtr = bufferImpl;
- return (Buffer*) bufferPtr;
}
+ assert(queueFamilyIndex < queueFamilyCount);
- struct InputLayoutImpl
+ 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,
};
- virtual InputLayout* createInputLayout(InputElementDesc const* inputElements, UInt inputElementCount) override
- {
- InputLayoutImpl* impl = new InputLayoutImpl();
+ VkDeviceCreateInfo deviceCreateInfo = { VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO };
+ deviceCreateInfo.queueCreateInfoCount = 1;
+ deviceCreateInfo.pQueueCreateInfos = &queueCreateInfo;
+ deviceCreateInfo.pEnabledFeatures = &enabledFeatures;
- // TODO: actually initialize things
+ deviceCreateInfo.enabledExtensionCount = sizeof(deviceExtensions) / sizeof(deviceExtensions[0]);
+ deviceCreateInfo.ppEnabledExtensionNames = &deviceExtensions[0];
- return (InputLayout*) impl;
- }
+ RETURN_ON_VK_FAIL(vkCreateDevice(
+ physicalDevice, &deviceCreateInfo, nullptr, &device));
- virtual void* map(Buffer* buffer, MapFlavor flavor) override
- {
- return nullptr;
- }
+#define LOAD_DEVICE_PROC(NAME) NAME = (PFN_##NAME) vkGetDeviceProcAddr(device, #NAME);
+ FOREACH_DEVICE_PROC(LOAD_DEVICE_PROC)
+#undef LOAD_DEVICE_PROC
- virtual void unmap(Buffer* buffer) override
- {
- }
+ // Create a command pool
- virtual void setInputLayout(InputLayout* inputLayout) override
- {
- }
+ VkCommandPoolCreateInfo commandPoolCreateInfo = { VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO };
+ commandPoolCreateInfo.queueFamilyIndex = queueFamilyIndex;
+ commandPoolCreateInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
- virtual void setPrimitiveTopology(PrimitiveTopology topology) override
- {
- }
+ RETURN_ON_VK_FAIL(vkCreateCommandPool(
+ device, &commandPoolCreateInfo, nullptr, &commandPool));
- virtual void setVertexBuffers(UInt startSlot, UInt slotCount, Buffer* const* buffers, UInt const* strides, UInt const* offsets) override
- {
- }
+ vkGetDeviceQueue(device, queueFamilyIndex, 0, &queue);
- struct ShaderProgramImpl
- {
- VkPipelineShaderStageCreateInfo compute;
- VkPipelineShaderStageCreateInfo vertex;
- VkPipelineShaderStageCreateInfo fragment;
- };
+ // set up swap chain
- 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
- {
- }
+ // create command buffers
- struct BindingImpl
- {
- ShaderInputType type;
- InputBufferType bufferType; // Only valid if `type` is `Buffer`
+ // depth/stencil?
- VkImageView srv;
- VkBufferView uav;
- VkBuffer buffer;
- VkSampler samplerState;
+ // render pass?
- int binding = 0;
- bool isOutput = false;
- int bufferLength = 0;
- };
+ // pipeline cache
- struct BindingStateImpl
- {
- Slang::List<BindingImpl> bindings;
- int numRenderTargets;
- };
+ // frame buffer
- 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();
+ // create semaphores for sync
+
+ return SLANG_OK;
+}
- VkBufferUsageFlags usage = 0;
- VkMemoryPropertyFlags reqMemoryProperties = 0;
+void VKRenderer::setClearColor(float const* color)
+{
+ for (int ii = 0; ii < 4; ++ii)
+ clearColor[ii] = color[ii];
+}
- switch( bufferDesc.type )
- {
- case InputBufferType::ConstantBuffer:
+void VKRenderer::clearFrame()
+{
+}
+
+void VKRenderer::presentFrame()
+{
+}
+
+SlangResult VKRenderer::captureScreenShot(char const* outputPath)
+{
+ return SLANG_FAIL;
+}
+
+ShaderCompiler* VKRenderer::getShaderCompiler()
+{
+ return this;
+}
+
+Buffer* VKRenderer::createBuffer(BufferDesc const& desc)
+{
+ 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 InputBufferType::StorageBuffer:
- usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
+ case BufferFlavor::Vertex:
+ usage = VK_BUFFER_USAGE_VERTEX_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,
+ desc.initData);
- BufferImpl bufferImpl = createBufferImpl(
- bufferSize,
- usage,
- reqMemoryProperties,
- initData);
+ BufferImpl* bufferPtr = new BufferImpl();
+ *bufferPtr = bufferImpl;
+ return (Buffer*)bufferPtr;
+}
- // TODO: need to hang onto the `memory` field so
- // that we can release it when we are done.
+InputLayout* VKRenderer::createInputLayout(InputElementDesc const* inputElements, UInt inputElementCount)
+{
+ InputLayoutImpl* impl = new InputLayoutImpl;
- bufferOut = bufferImpl.buffer;
+ // TODO: actually initialize things
- // Fill in any views needed
- switch( bufferDesc.type )
- {
- case InputBufferType::ConstantBuffer:
- break;
+ return (InputLayout*)impl;
+}
- case InputBufferType::StorageBuffer:
- {
- }
- break;
- }
- }
+void* VKRenderer::map(Buffer* buffer, MapFlavor flavor)
+{
+ return nullptr;
+}
- void createInputTexture(
- InputTextureDesc const& inputDesc,
- VkImageView& viewOut)
- {
- TextureData texData;
- generateTextureData(texData, inputDesc);
- assert(!"unimplemented");
- }
+void VKRenderer::unmap(Buffer* buffer)
+{
+}
- void createInputSampler(
- InputSamplerDesc const& inputDesc,
- VkSampler& stateOut)
- {
- assert(!"unimplemented");
- }
+void VKRenderer::setInputLayout(InputLayout* inputLayout)
+{
+}
+
+void VKRenderer::setPrimitiveTopology(PrimitiveTopology topology)
+{
+}
- virtual BindingState* createBindingState(const ShaderInputLayout & layout)
+void VKRenderer::setVertexBuffers(UInt startSlot, UInt slotCount, Buffer* const* buffers, UInt const* strides, UInt const* offsets)
+{
+}
+
+void VKRenderer::setShaderProgram(ShaderProgram* program)
+{
+ currentProgram = (ShaderProgramImpl*)program;
+}
+
+void VKRenderer::setConstantBuffers(UInt startSlot, UInt slotCount, Buffer* const* buffers, UInt const* offsets)
+{
+}
+
+void VKRenderer::draw(UInt vertexCount, UInt startVertex = 0)
+{
+}
+
+BindingState* VKRenderer::createBindingState(const ShaderInputLayout& layout)
+{
+ BindingStateImpl* bindingState = new BindingStateImpl;
+ bindingState->numRenderTargets = layout.numRenderTargets;
+ for (auto & entry : layout.entries)
{
- 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)
{
- 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);
@@ -710,328 +750,276 @@ public:
case ShaderInputType::Texture:
{
createInputTexture(entry.textureDesc, binding.srv);
+ break;
}
- break;
case ShaderInputType::Sampler:
{
createInputSampler(entry.samplerDesc, binding.samplerState);
+ break;
}
- break;
case ShaderInputType::CombinedTextureSampler:
{
throw "not implemented";
+ break;
}
- break;
- }
- bindingState->bindings.Add(binding);
}
-
- return (BindingState*) bindingState;
+ bindingState->bindings.Add(binding);
}
- BindingStateImpl* currentBindingState = nullptr;
- virtual void setBindingState(BindingState * state)
- {
- currentBindingState = (BindingStateImpl*) state;
- }
+ return (BindingState*)bindingState;
+}
- virtual void serializeOutput(BindingState* s, const char * fileName)
- {
- auto state = (BindingStateImpl*) s;
+void VKRenderer::setBindingState(BindingState * state)
+{
+ currentBindingState = (BindingStateImpl*)state;
+}
+
+void VKRenderer::serializeOutput(BindingState* s, const char * fileName)
+{
+ auto state = (BindingStateImpl*)s;
- FILE * f = fopen(fileName, "wb");
- int id = 0;
- for (auto& bb: state->bindings)
+ FILE * f = fopen(fileName, "wb");
+ int id = 0;
+ for (auto& bb : state->bindings)
+ {
+ if (bb.isOutput)
{
- if (bb.isOutput)
+ if (bb.buffer)
{
- 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);
- }
+ // 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);
-
-
+ id++;
}
+ fclose(f);
+}
- virtual void dispatchCompute(int x, int y, int z) override
- {
-
-
- // HACK: create a new pipeline for every call
+void VKRenderer::dispatchCompute(int x, int y, int z)
+{
+ // HACK: create a new pipeline for every call
- // First create a pipeline layout based on what is bound
+ // First create a pipeline layout based on what is bound
- Slang::List<VkDescriptorSetLayoutBinding> bindings;
+ Slang::List<VkDescriptorSetLayoutBinding> bindings;
- for( auto bb : currentBindingState->bindings )
+ for (auto bb : currentBindingState->bindings)
+ {
+ switch (bb.type)
{
- switch( bb.type )
- {
case ShaderInputType::Buffer:
+ {
+ switch (bb.bufferType)
{
- 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;
+ {
+ 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;
+ }
+ 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();
+ 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));
+ VkDescriptorSetLayout descriptorSetLayout = 0;
+ checkResult(vkCreateDescriptorSetLayout(
+ device, &descriptorSetLayoutInfo, nullptr, &descriptorSetLayout));
- // Create a descriptor pool for allocating sets
+ // 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 },
- };
+ 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;
+ 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));
+ VkDescriptorPool descriptorPool;
+ checkResult(vkCreateDescriptorPool(
+ device, &descriptorPoolInfo, nullptr, &descriptorPool));
- // Create a descriptor set based on our layout
+ // 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;
+ 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));
+ VkDescriptorSet descriptorSet;
+ checkResult(vkAllocateDescriptorSets(
+ device, &descriptorSetAllocInfo, &descriptorSet));
- // Fill in the descritpor set, using our binding information
- for( auto bb : currentBindingState->bindings )
+ // Fill in the descritpor set, using our binding information
+ for (auto bb : currentBindingState->bindings)
+ {
+ switch (bb.type)
{
- switch( bb.type )
- {
case ShaderInputType::Buffer:
+ {
+ switch (bb.bufferType)
{
- 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;
+ {
+ 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;
+ }
+ break;
default:
// TODO: handle the other cases
break;
- }
}
+ }
- // Create a pipeline layout based on our descriptor set layout(s)
+ // 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;
+ VkPipelineLayoutCreateInfo pipelineLayoutInfo = { VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO };
+ pipelineLayoutInfo.setLayoutCount = 1;
+ pipelineLayoutInfo.pSetLayouts = &descriptorSetLayout;
- VkPipelineLayout pipelineLayout = 0;
- checkResult(vkCreatePipelineLayout(
- device, &pipelineLayoutInfo, nullptr, &pipelineLayout));
+ VkPipelineLayout pipelineLayout = 0;
+ checkResult(vkCreatePipelineLayout(
+ device, &pipelineLayoutInfo, nullptr, &pipelineLayout));
- // Then create a pipeline to use that layout
+ // Then create a pipeline to use that layout
- VkComputePipelineCreateInfo computePipelineInfo = { VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO };
- computePipelineInfo.stage = currentProgram->compute;
- computePipelineInfo.layout = pipelineLayout;
+ VkComputePipelineCreateInfo computePipelineInfo = { VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO };
+ computePipelineInfo.stage = currentProgram->compute;
+ computePipelineInfo.layout = pipelineLayout;
- VkPipelineCache pipelineCache = 0;
+ VkPipelineCache pipelineCache = 0;
- VkPipeline pipeline;
- checkResult(vkCreateComputePipelines(
- device, pipelineCache, 1, &computePipelineInfo, nullptr, &pipeline));
+ VkPipeline pipeline;
+ checkResult(vkCreateComputePipelines(
+ device, pipelineCache, 1, &computePipelineInfo, nullptr, &pipeline));
- // Also create descriptor sets based on the given pipeline layout
+ // Also create descriptor sets based on the given pipeline layout
- VkCommandBuffer commandBuffer = beginCommandBuffer();
+ VkCommandBuffer commandBuffer = beginCommandBuffer();
- vkCmdBindPipeline(
- commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline);
+ vkCmdBindPipeline(
+ commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline);
- vkCmdBindDescriptorSets(
- commandBuffer,
- VK_PIPELINE_BIND_POINT_COMPUTE,
- pipelineLayout,
- 0, 1,
- &descriptorSet,
- 0,
- nullptr);
+ vkCmdBindDescriptorSets(
+ commandBuffer,
+ VK_PIPELINE_BIND_POINT_COMPUTE,
+ pipelineLayout,
+ 0, 1,
+ &descriptorSet,
+ 0,
+ nullptr);
- vkCmdDispatch(commandBuffer, x, y, z);
+ vkCmdDispatch(commandBuffer, x, y, z);
- flushCommandBuffer(commandBuffer);
+ flushCommandBuffer(commandBuffer);
- vkDestroyPipeline(device, pipeline, nullptr);
+ vkDestroyPipeline(device, pipeline, nullptr);
- // TODO: need to free up the other resources too...
- }
+ // TODO: need to free up the other resources too...
+}
- // ShaderCompiler interface
- VkPipelineShaderStageCreateInfo compileEntryPoint(
- ShaderCompileRequest::EntryPoint const& entryPointRequest,
- VkShaderStageFlagBits stage)
+
+// ShaderCompiler interface
+ShaderProgram* VKRenderer::compileProgram(const ShaderCompileRequest & request)
+{
+ ShaderProgramImpl* impl = new ShaderProgramImpl;
+ if (request.computeShader.name)
{
- 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;
+ impl->compute = compileEntryPoint(request.computeShader, VK_SHADER_STAGE_COMPUTE_BIT);
}
-
- virtual ShaderProgram* compileProgram(ShaderCompileRequest const& request) override
+ else
{
- 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;
+ impl->vertex = compileEntryPoint(request.vertexShader, VK_SHADER_STAGE_VERTEX_BIT);
+ impl->fragment = compileEntryPoint(request.fragmentShader, VK_SHADER_STAGE_FRAGMENT_BIT);
}
-};
-
-
-
-Renderer* createVKRenderer()
-{
- return new VKRenderer();
+ return (ShaderProgram*)impl;
}
+
} // renderer_test
diff --git a/tools/render-test/render.h b/tools/render-test/render.h
index 902067d62..bc63caa77 100644
--- a/tools/render-test/render.h
+++ b/tools/render-test/render.h
@@ -9,10 +9,12 @@
namespace renderer_test {
-typedef struct Buffer Buffer;
-typedef struct InputLayout InputLayout;
-typedef struct ShaderProgram ShaderProgram;
-typedef struct BindingState BindingState;
+// Declare opaque type
+struct Buffer;
+struct InputLayout;
+struct ShaderProgram;
+struct BindingState;
+
struct ShaderCompileRequest
{
struct SourceInfo
@@ -39,7 +41,7 @@ struct ShaderCompileRequest
SourceInfo source;
EntryPoint vertexShader;
EntryPoint fragmentShader;
- EntryPoint computeShader;
+ EntryPoint computeShader;
Slang::List<Slang::String> entryPointTypeArguments;
};
@@ -79,8 +81,8 @@ struct InputElementDesc
enum class MapFlavor
{
- HostRead,
- HostWrite,
+ HostRead,
+ HostWrite,
WriteDiscard,
};
@@ -115,20 +117,28 @@ public:
virtual void setBindingState(BindingState * state) = 0;
virtual void setVertexBuffers(UInt startSlot, UInt slotCount, Buffer* const* buffers, UInt const* strides, UInt const* offsets) = 0;
- inline void setVertexBuffer(UInt slot, Buffer* buffer, UInt stride, UInt offset = 0)
- {
- setVertexBuffers(slot, 1, &buffer, &stride, &offset);
- }
+ inline void setVertexBuffer(UInt slot, Buffer* buffer, UInt stride, UInt offset = 0);
virtual void setShaderProgram(ShaderProgram* program) = 0;
virtual void setConstantBuffers(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 setConstantBuffer(UInt slot, Buffer* buffer, UInt offset = 0);
+
virtual void draw(UInt vertexCount, UInt startVertex = 0) = 0;
- virtual void dispatchCompute(int x, int y, int z) = 0;
+ virtual void dispatchCompute(int x, int y, int z) = 0;
};
+
+// ----------------------------------------------------------------------------------------
+inline void Renderer::setVertexBuffer(UInt slot, Buffer* buffer, UInt stride, UInt offset)
+{
+ setVertexBuffers(slot, 1, &buffer, &stride, &offset);
+}
+// ----------------------------------------------------------------------------------------
+inline void Renderer::setConstantBuffer(UInt slot, Buffer* buffer, UInt offset)
+{
+ setConstantBuffers(slot, 1, &buffer, &offset);
+}
+
+
} // renderer_test