summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjsmall-nvidia <jsmall@nvidia.com>2018-03-26 15:34:01 -0400
committerGitHub <noreply@github.com>2018-03-26 15:34:01 -0400
commit74bf38b36d9074a83a53d3baf885d8886c0b3752 (patch)
tree31ed26ba7057c7165f33ea24b164cde10c17a0ef
parent5000d27d993d9ac33ef80482eb44235298d5177e (diff)
Renderer resource mangement for render-test (#453)
* First pass at resource based renderer using RefObject. * Correct handling of array of buffer pointers to Dx11. * Fix bug with setting viewOut incorrectly in createInputTexture. * More support for allowing com like interfaces. * Added and tidied Slang::Result - adding interface specific results * Guid added comparison support, and made base interface IComUnknown - with lowerCamel methods
-rw-r--r--source/core/slang-com-ptr.h80
-rw-r--r--source/core/slang-result.h21
-rw-r--r--tools/render-test/main.cpp302
-rw-r--r--tools/render-test/render-d3d11.cpp401
-rw-r--r--tools/render-test/render-gl.cpp189
-rw-r--r--tools/render-test/render-vk.cpp157
-rw-r--r--tools/render-test/render.h25
7 files changed, 703 insertions, 472 deletions
diff --git a/source/core/slang-com-ptr.h b/source/core/slang-com-ptr.h
index 0b30c220c..729b6b266 100644
--- a/source/core/slang-com-ptr.h
+++ b/source/core/slang-com-ptr.h
@@ -49,13 +49,57 @@ struct Guid
uint8_t data4[8]; ///< 0, 1 = clock_seq_hi_and_reserved, clock_seq_low, followed by 'spatially unique node' (48 bits)
};
+SLANG_FORCE_INLINE bool operator==(const Guid& aIn, const Guid& bIn)
+{
+ struct GuidCompare
+ {
+ enum { kNum = sizeof(Guid) / sizeof(size_t) };
+ Guid guid;
+ size_t data[kNum];
+ };
+ const GuidCompare& a = reinterpret_cast<const GuidCompare&>(aIn);
+ const GuidCompare& b = reinterpret_cast<const GuidCompare&>(bIn);
+
+ switch (GuidCompare::kNum)
+ {
+ case 2: return ((a.data[0] ^ b.data[0]) | (a.data[1] ^ b.data[1])) == 0;
+ case 4: return ((a.data[0] ^ b.data[0]) | (a.data[1] ^ b.data[1]) | (a.data[2] ^ b.data[2]) | (a.data[3] ^ b.data[3]) ) == 0;
+ default: return false;
+ }
+}
+
+SLANG_FORCE_INLINE bool operator!=(const Guid& a, const Guid& b)
+{
+ return !(a == b);
+}
+
+// Allows for defining of a GUID that works in C++ and C which defines in a format similar to microsofts INTERFACE style
+// MIDL_INTERFACE("00000000-0000-0000-C000-00 00 00 00 00 46")
+
+#define SLANG_GUID_BYTE(x, index) ((uint8_t)(SLANG_UINT64(0x##x) >> (8 * index)))
+
+#define SLANG_MAKE_GUID(data0, data1, data2, shortTail, tail) \
+ { (uint32_t)(0x##data0), (uint16_t)(0x##data1), (uint16_t)(0x##data2), \
+ { (uint8_t)(0x##shortTail >> 8), (uint8_t)(0x##shortTail & 0xff), \
+ SLANG_GUID_BYTE(tail,5), SLANG_GUID_BYTE(tail,4), SLANG_GUID_BYTE(tail,3), SLANG_GUID_BYTE(tail,2), SLANG_GUID_BYTE(tail,1), SLANG_GUID_BYTE(tail,0) \
+ }}
+
+// Compatible with Microsoft IUnknown
+static const Guid IID_IComUnknown = SLANG_MAKE_GUID(00000000, 0000, 0000, C000, 000000000046);
+
/// ! Must be kept in sync with IUnknown
-class IForwardUnknown
+class IComUnknown
{
public:
- virtual SLANG_NO_THROW Result SLANG_MCALL QueryInterface(const Guid& iid, void* objOut) = 0;
- virtual SLANG_NO_THROW uint32_t SLANG_MCALL AddRef() = 0;
- virtual SLANG_NO_THROW uint32_t SLANG_MCALL Release() = 0;
+ virtual SLANG_NO_THROW Result SLANG_MCALL queryInterface(const Guid& iid, void* objOut) = 0;
+ virtual SLANG_NO_THROW uint32_t SLANG_MCALL addRef() = 0;
+ virtual SLANG_NO_THROW uint32_t SLANG_MCALL release() = 0;
+};
+
+// Enum to force initializing as an attach (without adding a reference)
+enum InitAttach
+{
+ INIT_ATTACH
};
template <class T>
@@ -64,15 +108,20 @@ class ComPtr
public:
typedef T Type;
typedef ComPtr ThisType;
- typedef IForwardUnknown* Ptr;
+ typedef IComUnknown* Ptr;
/// Constructors
/// Default Ctor. Sets to nullptr
SLANG_FORCE_INLINE ComPtr() :m_ptr(nullptr) {}
/// Sets, and ref counts.
- SLANG_FORCE_INLINE explicit ComPtr(T* ptr) :m_ptr(ptr) { if (ptr) ((Ptr)ptr)->AddRef(); }
+ SLANG_FORCE_INLINE explicit ComPtr(T* ptr) :m_ptr(ptr) { if (ptr) ((Ptr)ptr)->addRef(); }
/// The copy ctor
- SLANG_FORCE_INLINE ComPtr(const ThisType& rhs) : m_ptr(rhs.m_ptr) { if (m_ptr) ((Ptr)m_ptr)->AddRef(); }
+ SLANG_FORCE_INLINE ComPtr(const ThisType& rhs) : m_ptr(rhs.m_ptr) { if (m_ptr) ((Ptr)m_ptr)->addRef(); }
+
+ /// Ctor without adding to ref count.
+ SLANG_FORCE_INLINE explicit ComPtr(InitAttach, T* ptr) :m_ptr(ptr) { }
+ /// Ctor without adding to ref count
+ SLANG_FORCE_INLINE ComPtr(InitAttach, const ThisType& rhs) : m_ptr(rhs.m_ptr) { }
#ifdef SLANG_HAS_MOVE_SEMANTICS
/// Move Ctor
@@ -82,7 +131,7 @@ public:
#endif
/// Destructor releases the pointer, assuming it is set
- SLANG_FORCE_INLINE ~ComPtr() { if (m_ptr) ((Ptr)m_ptr)->Release(); }
+ SLANG_FORCE_INLINE ~ComPtr() { if (m_ptr) ((Ptr)m_ptr)->release(); }
// !!! Operators !!!
@@ -118,6 +167,7 @@ public:
protected:
/// Gets the address of the dumb pointer.
+ // Disabled: use writeRef and readRef to get a reference based on usage.
SLANG_FORCE_INLINE T** operator&();
T* m_ptr;
@@ -129,23 +179,23 @@ void ComPtr<T>::setNull()
{
if (m_ptr)
{
- ((Ptr)m_ptr)->Release();
+ ((Ptr)m_ptr)->release();
m_ptr = nullptr;
}
}
//----------------------------------------------------------------------------
-template <typename T>
+/* template <typename T>
T** ComPtr<T>::operator&()
{
assert(m_ptr == nullptr);
return &m_ptr;
-}
+} */
//----------------------------------------------------------------------------
template <typename T>
const ComPtr<T>& ComPtr<T>::operator=(const ThisType& rhs)
{
- if (rhs.m_ptr) ((Ptr)rhs.m_ptr)->AddRef();
- if (m_ptr) ((Ptr)m_ptr)->Release();
+ if (rhs.m_ptr) ((Ptr)rhs.m_ptr)->addRef();
+ if (m_ptr) ((Ptr)m_ptr)->release();
m_ptr = rhs.m_ptr;
return *this;
}
@@ -153,8 +203,8 @@ const ComPtr<T>& ComPtr<T>::operator=(const ThisType& rhs)
template <typename T>
T* ComPtr<T>::operator=(T* ptr)
{
- if (ptr) ((Ptr)ptr)->AddRef();
- if (m_ptr) ((Ptr)m_ptr)->Release();
+ if (ptr) ((Ptr)ptr)->addRef();
+ if (m_ptr) ((Ptr)m_ptr)->release();
m_ptr = ptr;
return m_ptr;
}
diff --git a/source/core/slang-result.h b/source/core/slang-result.h
index 767d2c737..348029af4 100644
--- a/source/core/slang-result.h
+++ b/source/core/slang-result.h
@@ -38,7 +38,7 @@ f is the short version of the facility name
For the common used SLANG_OK and SLANG_FAIL, the name prefix is dropped.
It is acceptable to expand 'f' to a longer name to differentiate a name
ie for a facility 'DRIVER' it might make sense to have an error of the form SLANG_E_DRIVER_OUT_OF_MEMORY
-*/
+*/
typedef int32_t SlangResult;
@@ -55,8 +55,8 @@ typedef int32_t SlangResult;
//! Get the result code for the facility
#define SLANG_GET_RESULT_CODE(r) ((int32_t)((r) & 0xffff))
-#define SLANG_MAKE_ERROR(fac, code) (SLANG_MAKE_RESULT_ID(SLANG_FACILITY_##fac, code) | 0x80000000)
-#define SLANG_MAKE_SUCCESS(fac, code) SLANG_MAKE_RESULT_ID(SLANG_FACILITY_##fac, code)
+#define SLANG_MAKE_ERROR(fac, code) (SLANG_MAKE_RESULT_ID(fac, code) | 0x80000000)
+#define SLANG_MAKE_SUCCESS(fac, code) SLANG_MAKE_RESULT_ID(fac, code)
/*************************** Facilities ************************************/
@@ -81,21 +81,24 @@ It can be useful to have a consistent short name for a facility, as used in the
/* *************************** Codes **************************************/
// Memory
-#define SLANG_E_MEM_OUT_OF_MEMORY SLANG_MAKE_ERROR(MEMORY, 1)
-#define SLANG_E_MEM_BUFFER_TOO_SMALL SLANG_MAKE_ERROR(MEMORY, 2)
+#define SLANG_E_MEM_OUT_OF_MEMORY SLANG_MAKE_ERROR(SLANG_FACILITY_MEMORY, 1)
+#define SLANG_E_MEM_BUFFER_TOO_SMALL SLANG_MAKE_ERROR(SLANG_FACILITY_MEMORY, 2)
//! SLANG_OK indicates success, and is equivalent to SLANG_MAKE_RESULT(0, GENERAL, 0)
#define SLANG_OK 0
//! SLANG_FAIL is the generic failure code - meaning a serious error occurred and the call couldn't complete
-#define SLANG_FAIL SLANG_MAKE_ERROR(GENERAL, 1)
+#define SLANG_FAIL SLANG_MAKE_ERROR(SLANG_FACILITY_GENERAL, 1)
//! Used to identify a Result that has yet to be initialized.
//! It defaults to failure such that if used incorrectly will fail, as similar in concept to using an uninitialized variable.
-#define SLANG_E_MISC_UNINITIALIZED SLANG_MAKE_ERROR(MISC, 2)
+#define SLANG_E_MISC_UNINITIALIZED SLANG_MAKE_ERROR(SLANG_FACILITY_MISC, 2)
//! Returned from an async method meaning the output is invalid (thus an error), but a result for the request is pending, and will be returned on a subsequent call with the async handle.
-#define SLANG_E_MISC_PENDING SLANG_MAKE_ERROR(MISC, 3)
+#define SLANG_E_MISC_PENDING SLANG_MAKE_ERROR(SLANG_FACILITY_MISC, 3)
//! Indicates that a handle passed in as parameter to a method is invalid.
-#define SLANG_E_MISC_INVALID_HANDLE SLANG_MAKE_ERROR(MISC, 4)
+#define SLANG_E_MISC_INVALID_HANDLE SLANG_MAKE_ERROR(SLANG_FACILITY_MISC, 4)
+
+//! Indicates that tn interface could not be found
+#define SLANG_E_INTF_NO_INTERFACE SLANG_MAKE_ERROR(SLANG_FACILITY_INTERFACE, 2)
/*! Set SLANG_HANDLE_RESULT_FAIL(x) to code to be executed whenever an error occurs, and is detected by one of the macros */
#ifndef SLANG_HANDLE_RESULT_FAIL
diff --git a/tools/render-test/main.cpp b/tools/render-test/main.cpp
index 89aa9a544..b333e57bd 100644
--- a/tools/render-test/main.cpp
+++ b/tools/render-test/main.cpp
@@ -47,109 +47,70 @@ static const Vertex kVertexData[kVertexCount] = {
{ { 1, 0, 0.5 }, {0, 1, 0} , {1, 1} },
};
+using namespace Slang;
-// Global variables for state to be used for rendering...
+class RenderTestApp
+{
+ public:
-uintptr_t gConstantBufferSize, gComputeResultBufferSize;
+ // At initialization time, we are going to load and compile our Slang shader
+ // code, and then create the API objects we need for rendering.
+ Result initialize(Renderer* renderer, ShaderCompiler* shaderCompiler);
+ void runCompute();
+ void renderFrame();
+ void finalize();
-Buffer* gConstantBuffer;
-InputLayout* gInputLayout;
-Buffer* gVertexBuffer;
-ShaderProgram* gShaderProgram;
-BindingState* gBindingState;
-ShaderInputLayout gShaderInputLayout;
+ BindingState* getBindingState() const { return m_bindingState; }
-// Entry point name to use for vertex/fragment shader
-static char const* vertexEntryPointName = "vertexMain";
-static char const* fragmentEntryPointName = "fragmentMain";
-static char const* computeEntryPointName = "computeMain";
+ protected:
+ /// Called in initialize
+ Result initializeShaders(ShaderCompiler* shaderCompiler);
-// "Profile" to use when compiling for HLSL targets
-// TODO: does this belong here?
-static char const* vertexProfileName = "vs_5_0";
-static char const* fragmentProfileName = "ps_5_0";
-static char const* computeProfileName = "cs_5_0";
+ // variables for state to be used for rendering...
+ uintptr_t m_constantBufferSize, m_computeResultBufferSize;
-SlangResult initializeShaders(
- ShaderCompiler* shaderCompiler)
-{
- // Read in the source code
- char const* sourcePath = gOptions.sourcePath;
- FILE* sourceFile = fopen(sourcePath, "rb");
- if( !sourceFile )
- {
- fprintf(stderr, "error: failed to open '%s' for reading\n", sourcePath);
- return SLANG_FAIL;
- }
- fseek(sourceFile, 0, SEEK_END);
- size_t sourceSize = ftell(sourceFile);
- fseek(sourceFile, 0, SEEK_SET);
- char* sourceText = (char*) malloc(sourceSize + 1);
- if( !sourceText )
- {
- fprintf(stderr, "error: out of memory");
- return SLANG_FAIL;
- }
- fread(sourceText, sourceSize, 1, sourceFile);
- fclose(sourceFile);
- sourceText[sourceSize] = 0;
+ RefPtr<Renderer> m_renderer;
- gShaderInputLayout.Parse(sourceText);
+ RefPtr<Buffer> m_constantBuffer;
+ RefPtr<InputLayout> m_inputLayout;
+ RefPtr<Buffer> m_vertexBuffer;
+ RefPtr<ShaderProgram> m_shaderProgram;
+ RefPtr<BindingState> m_bindingState;
- ShaderCompileRequest::SourceInfo sourceInfo;
- sourceInfo.path = sourcePath;
- sourceInfo.dataBegin = sourceText;
- sourceInfo.dataEnd = sourceText + sourceSize;
+ ShaderInputLayout m_shaderInputLayout;
- ShaderCompileRequest compileRequest;
- compileRequest.source = sourceInfo;
- if (gOptions.shaderType == ShaderProgramType::Graphics || gOptions.shaderType == ShaderProgramType::GraphicsCompute)
- {
- compileRequest.vertexShader.source = sourceInfo;
- compileRequest.vertexShader.name = vertexEntryPointName;
- compileRequest.vertexShader.profile = vertexProfileName;
- compileRequest.fragmentShader.source = sourceInfo;
- compileRequest.fragmentShader.name = fragmentEntryPointName;
- compileRequest.fragmentShader.profile = fragmentProfileName;
- }
- else
- {
- compileRequest.computeShader.source = sourceInfo;
- compileRequest.computeShader.name = computeEntryPointName;
- compileRequest.computeShader.profile = computeProfileName;
- }
- compileRequest.entryPointTypeArguments = gShaderInputLayout.globalTypeArguments;
- gShaderProgram = shaderCompiler->compileProgram(compileRequest);
- if( !gShaderProgram )
- {
- return SLANG_FAIL;
- }
+};
- return SLANG_OK;
-}
-//
-// At initialization time, we are going to load and compile our Slang shader
-// code, and then create the D3D11 API objects we need for rendering.
-//
-SlangResult initializeInner(
- Renderer* renderer,
- ShaderCompiler* shaderCompiler)
+// Entry point name to use for vertex/fragment shader
+static const char vertexEntryPointName[] = "vertexMain";
+static const char fragmentEntryPointName[] = "fragmentMain";
+static const char computeEntryPointName[] = "computeMain";
+
+// "Profile" to use when compiling for HLSL targets
+// TODO: does this belong here?
+static const char vertexProfileName[] = "vs_5_0";
+static const char fragmentProfileName[] = "ps_5_0";
+static const char computeProfileName[] = "cs_5_0";
+
+SlangResult RenderTestApp::initialize(Renderer* renderer, ShaderCompiler* shaderCompiler)
{
SLANG_RETURN_ON_FAIL(initializeShaders(shaderCompiler));
- gBindingState = renderer->createBindingState(gShaderInputLayout);
+ m_renderer = renderer;
+
+ m_bindingState = renderer->createBindingState(m_shaderInputLayout);
// Do other initialization that doesn't depend on the source language.
// TODO(tfoley): use each API's reflection interface to query the constant-buffer size needed
- gConstantBufferSize = 16 * sizeof(float);
+ m_constantBufferSize = 16 * sizeof(float);
BufferDesc constantBufferDesc;
- constantBufferDesc.size = gConstantBufferSize;
+ constantBufferDesc.size = m_constantBufferSize;
constantBufferDesc.flavor = BufferFlavor::Constant;
- gConstantBuffer = renderer->createBuffer(constantBufferDesc);
- if(!gConstantBuffer)
+ m_constantBuffer = renderer->createBuffer(constantBufferDesc);
+ if(!m_constantBuffer)
return SLANG_FAIL;
// Input Assembler (IA)
@@ -160,8 +121,8 @@ SlangResult initializeInner(
{ "A", 2, Format::RG_Float32, offsetof(Vertex, uv) },
};
- gInputLayout = renderer->createInputLayout(&inputElements[0], sizeof(inputElements)/sizeof(inputElements[0]));
- if(!gInputLayout)
+ m_inputLayout = renderer->createInputLayout(&inputElements[0], sizeof(inputElements)/sizeof(inputElements[0]));
+ if(!m_inputLayout)
return SLANG_FAIL;
BufferDesc vertexBufferDesc;
@@ -169,17 +130,73 @@ SlangResult initializeInner(
vertexBufferDesc.flavor = BufferFlavor::Vertex;
vertexBufferDesc.initData = &kVertexData[0];
- gVertexBuffer = renderer->createBuffer(vertexBufferDesc);
- if(!gVertexBuffer)
+ m_vertexBuffer = renderer->createBuffer(vertexBufferDesc);
+ if(!m_vertexBuffer)
return SLANG_FAIL;
return SLANG_OK;
}
-void renderFrameInner(
- Renderer* renderer)
+Result RenderTestApp::initializeShaders(ShaderCompiler* shaderCompiler)
+{
+ // Read in the source code
+ char const* sourcePath = gOptions.sourcePath;
+ FILE* sourceFile = fopen(sourcePath, "rb");
+ if (!sourceFile)
+ {
+ fprintf(stderr, "error: failed to open '%s' for reading\n", sourcePath);
+ return SLANG_FAIL;
+ }
+ fseek(sourceFile, 0, SEEK_END);
+ size_t sourceSize = ftell(sourceFile);
+ fseek(sourceFile, 0, SEEK_SET);
+ char* sourceText = (char*)malloc(sourceSize + 1);
+ if (!sourceText)
+ {
+ fprintf(stderr, "error: out of memory");
+ return SLANG_FAIL;
+ }
+ fread(sourceText, sourceSize, 1, sourceFile);
+ fclose(sourceFile);
+ sourceText[sourceSize] = 0;
+
+ m_shaderInputLayout.Parse(sourceText);
+
+ ShaderCompileRequest::SourceInfo sourceInfo;
+ sourceInfo.path = sourcePath;
+ sourceInfo.dataBegin = sourceText;
+ sourceInfo.dataEnd = sourceText + sourceSize;
+
+ ShaderCompileRequest compileRequest;
+ compileRequest.source = sourceInfo;
+ if (gOptions.shaderType == ShaderProgramType::Graphics || gOptions.shaderType == ShaderProgramType::GraphicsCompute)
+ {
+ compileRequest.vertexShader.source = sourceInfo;
+ compileRequest.vertexShader.name = vertexEntryPointName;
+ compileRequest.vertexShader.profile = vertexProfileName;
+ compileRequest.fragmentShader.source = sourceInfo;
+ compileRequest.fragmentShader.name = fragmentEntryPointName;
+ compileRequest.fragmentShader.profile = fragmentProfileName;
+ }
+ else
+ {
+ compileRequest.computeShader.source = sourceInfo;
+ compileRequest.computeShader.name = computeEntryPointName;
+ compileRequest.computeShader.profile = computeProfileName;
+ }
+ compileRequest.entryPointTypeArguments = m_shaderInputLayout.globalTypeArguments;
+ m_shaderProgram = shaderCompiler->compileProgram(compileRequest);
+ if (!m_shaderProgram)
+ {
+ return SLANG_FAIL;
+ }
+
+ return SLANG_OK;
+}
+
+void RenderTestApp::renderFrame()
{
- auto mappedData = renderer->map(gConstantBuffer, MapFlavor::WriteDiscard);
+ auto mappedData = m_renderer->map(m_constantBuffer, MapFlavor::WriteDiscard);
if(mappedData)
{
static const float kIdentity[] =
@@ -189,40 +206,39 @@ void renderFrameInner(
0, 0, 0, 1 };
memcpy(mappedData, kIdentity, sizeof(kIdentity));
- renderer->unmap(gConstantBuffer);
+ m_renderer->unmap(m_constantBuffer);
}
// Input Assembler (IA)
- renderer->setInputLayout(gInputLayout);
- renderer->setPrimitiveTopology(PrimitiveTopology::TriangleList);
+ m_renderer->setInputLayout(m_inputLayout);
+ m_renderer->setPrimitiveTopology(PrimitiveTopology::TriangleList);
- renderer->setVertexBuffer(0, gVertexBuffer, sizeof(Vertex));
+ m_renderer->setVertexBuffer(0, m_vertexBuffer, sizeof(Vertex));
// Vertex Shader (VS)
// Pixel Shader (PS)
- renderer->setShaderProgram(gShaderProgram);
- renderer->setConstantBuffer(0, gConstantBuffer);
- renderer->setBindingState(gBindingState);
+ m_renderer->setShaderProgram(m_shaderProgram);
+ m_renderer->setConstantBuffer(0, m_constantBuffer);
+ m_renderer->setBindingState(m_bindingState);
//
- renderer->draw(3);
+ m_renderer->draw(3);
}
-void runCompute(Renderer * renderer)
+void RenderTestApp::runCompute()
{
- renderer->setShaderProgram(gShaderProgram);
- renderer->setBindingState(gBindingState);
- renderer->dispatchCompute(1, 1, 1);
+ m_renderer->setShaderProgram(m_shaderProgram);
+ m_renderer->setBindingState(m_bindingState);
+ m_renderer->dispatchCompute(1, 1, 1);
}
-void finalize()
+void RenderTestApp::finalize()
{
}
-
//
// We use a bare-minimum window procedure to get things up and running.
//
@@ -243,7 +259,6 @@ static LRESULT CALLBACK windowProc(
return DefWindowProcW(windowHandle, message, wParam, lParam);
}
-
SlangResult innerMain(int argc, char** argv)
{
// Parse command-line options
@@ -283,7 +298,6 @@ SlangResult innerMain(int argc, char** argv)
DWORD windowStyle = WS_POPUP;
DWORD windowExtendedStyle = 0;
-
RECT windowRect = { 0, 0, gWindowWidth, gWindowHeight };
AdjustWindowRectEx(&windowRect, windowStyle, /*hasMenu=*/false, windowExtendedStyle);
@@ -308,8 +322,8 @@ SlangResult innerMain(int argc, char** argv)
return SLANG_FAIL;
}
+ Slang::RefPtr<Renderer> renderer;
- Renderer* renderer = nullptr;
SlangSourceLanguage nativeLanguage = SLANG_SOURCE_LANGUAGE_UNKNOWN;
SlangCompileTarget slangTarget = SLANG_TARGET_NONE;
switch (gOptions.rendererID)
@@ -356,53 +370,57 @@ SlangResult innerMain(int argc, char** argv)
break;
}
- SLANG_RETURN_ON_FAIL(initializeInner(renderer, shaderCompiler));
+ {
+ RenderTestApp app;
- // Once initialization is all complete, we show the window...
- ShowWindow(windowHandle, showCommand);
+ SLANG_RETURN_ON_FAIL(app.initialize(renderer, shaderCompiler));
- // ... and enter the event loop:
- for (;;)
- {
- MSG message;
+ // Once initialization is all complete, we show the window...
+ ShowWindow(windowHandle, showCommand);
- int result = PeekMessageW(&message, NULL, 0, 0, PM_REMOVE);
- if (result != 0)
+ // ... and enter the event loop:
+ for (;;)
{
- if (message.message == WM_QUIT)
- {
- return (int)message.wParam;
- }
+ MSG message;
- TranslateMessage(&message);
- DispatchMessageW(&message);
- }
- else
- {
- // Whenever we don't have Windows events to process, we render a frame.
- if (gOptions.shaderType == ShaderProgramType::Compute)
+ int result = PeekMessageW(&message, NULL, 0, 0, PM_REMOVE);
+ if (result != 0)
{
- runCompute(renderer);
- }
- else
- {
- static const float kClearColor[] = { 0.25, 0.25, 0.25, 1.0 };
- renderer->setClearColor(kClearColor);
- renderer->clearFrame();
+ if (message.message == WM_QUIT)
+ {
+ return (int)message.wParam;
+ }
- renderFrameInner(renderer);
+ TranslateMessage(&message);
+ DispatchMessageW(&message);
}
- // If we are in a mode where output is requested, we need to snapshot the back buffer here
- if (gOptions.outputPath)
+ else
{
- if (gOptions.shaderType == ShaderProgramType::Compute || gOptions.shaderType == ShaderProgramType::GraphicsCompute)
- renderer->serializeOutput(gBindingState, gOptions.outputPath);
+ // Whenever we don't have Windows events to process, we render a frame.
+ if (gOptions.shaderType == ShaderProgramType::Compute)
+ {
+ app.runCompute();
+ }
else
- SLANG_RETURN_ON_FAIL(renderer->captureScreenShot(gOptions.outputPath));
- return SLANG_OK;
+ {
+ static const float kClearColor[] = { 0.25, 0.25, 0.25, 1.0 };
+ renderer->setClearColor(kClearColor);
+ renderer->clearFrame();
+
+ app.renderFrame();
+ }
+ // If we are in a mode where output is requested, we need to snapshot the back buffer here
+ if (gOptions.outputPath)
+ {
+ if (gOptions.shaderType == ShaderProgramType::Compute || gOptions.shaderType == ShaderProgramType::GraphicsCompute)
+ renderer->serializeOutput(app.getBindingState(), gOptions.outputPath);
+ else
+ SLANG_RETURN_ON_FAIL(renderer->captureScreenShot(gOptions.outputPath));
+ return SLANG_OK;
+ }
+
+ renderer->presentFrame();
}
-
- renderer->presentFrame();
}
}
diff --git a/tools/render-test/render-d3d11.cpp b/tools/render-test/render-d3d11.cpp
index b4195c63d..35c04a79f 100644
--- a/tools/render-test/render-d3d11.cpp
+++ b/tools/render-test/render-d3d11.cpp
@@ -8,6 +8,8 @@
#include <slang.h>
+#include "../../source/core/slang-com-ptr.h"
+
#ifdef _MSC_VER
#pragma warning(disable: 4996)
#endif
@@ -70,35 +72,45 @@ public:
protected:
- struct BindingImpl
+ struct Binding
{
ShaderInputType type;
InputBufferType bufferType; // Only valid if `type` is `Buffer`
- ID3D11ShaderResourceView* srv = nullptr;
- ID3D11UnorderedAccessView* uav = nullptr;
- ID3D11Buffer* buffer = nullptr;
- ID3D11SamplerState* samplerState = nullptr;
+ ComPtr<ID3D11ShaderResourceView> srv;
+ ComPtr<ID3D11UnorderedAccessView> uav;
+ ComPtr<ID3D11Buffer> buffer;
+ ComPtr<ID3D11SamplerState> samplerState;
int binding = 0;
bool isOutput = false;
int bufferLength = 0;
};
- struct BindingStateImpl
+
+ class BindingStateImpl: public BindingState
{
- List<BindingImpl> bindings;
- int numRenderTargets = 0;
+ public:
+ List<Binding> m_bindings;
+ int m_numRenderTargets = 0;
};
- struct ShaderProgramImpl
+ class ShaderProgramImpl: public ShaderProgram
{
- ID3D11VertexShader* vertexShader = nullptr;
- ID3D11PixelShader* pixelShader = nullptr;
- ID3D11ComputeShader* computeShader = nullptr;
+ public:
+ ComPtr<ID3D11VertexShader> m_vertexShader;
+ ComPtr<ID3D11PixelShader> m_pixelShader;
+ ComPtr<ID3D11ComputeShader> m_computeShader;
};
- struct BufferImpl
+ class BufferImpl: public Buffer
{
- ID3D11Buffer* buffer = nullptr;
+ public:
+ ComPtr<ID3D11Buffer> m_buffer;
};
+ class InputLayoutImpl: public InputLayout
+ {
+ public:
+ ComPtr<ID3D11InputLayout> m_layout;
+ };
+
/// 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); }
@@ -107,29 +119,32 @@ public:
/// 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);
+ static Result compileHLSLShader(char const* sourcePath, char const* source, char const* entryPointName, char const* dxProfileName, ComPtr<ID3DBlob>& shaderBlobOut);
/// Capture a texture to a file
static HRESULT captureTextureToFile(ID3D11Device* device, ID3D11DeviceContext* context, ID3D11Texture2D* texture, char const* outputPath);
void* map(ID3D11Buffer* buffer, MapFlavor flavor);
void unmap(ID3D11Buffer* buffer);
- void createInputBuffer(InputBufferDesc& bufferDesc, List<unsigned int>& bufferData, ID3D11Buffer*& bufferOut,
- ID3D11UnorderedAccessView*& viewOut, ID3D11ShaderResourceView*& srvOut);
+ Result createInputBuffer(InputBufferDesc& bufferDesc, const List<unsigned int>& bufferData,
+ ComPtr<ID3D11Buffer>& bufferOut, ComPtr<ID3D11UnorderedAccessView>& viewOut, ComPtr<ID3D11ShaderResourceView>& srvOut);
- void createInputTexture(const InputTextureDesc& inputDesc, ID3D11ShaderResourceView*& viewOut);
+ Result createInputTexture(const InputTextureDesc& inputDesc, ComPtr<ID3D11ShaderResourceView>& viewOut);
- void createInputSampler(const InputSamplerDesc& inputDesc, ID3D11SamplerState*& stateOut);
+ Result createInputSampler(const InputSamplerDesc& inputDesc, ComPtr<ID3D11SamplerState>& stateOut);
void applyBindingState(bool isCompute);
- IDXGISwapChain* m_swapChain = nullptr;
- ID3D11Device* m_device = nullptr;
- ID3D11DeviceContext* m_immediateContext = nullptr;
- ID3D11Texture2D* m_backBufferTexture = nullptr;
- List<ID3D11RenderTargetView*> m_renderTargetViews;
- List<ID3D11Texture2D*> m_renderTargetTextures;
- BindingStateImpl* m_currentBindings = nullptr;
+ ComPtr<IDXGISwapChain> m_swapChain;
+ ComPtr<ID3D11Device> m_device;
+ ComPtr<ID3D11DeviceContext> m_immediateContext;
+ ComPtr<ID3D11Texture2D> m_backBufferTexture;
+
+ List<ComPtr<ID3D11RenderTargetView> > m_renderTargetViews;
+ List<ComPtr<ID3D11Texture2D> > m_renderTargetTextures;
+
+ RefPtr<BindingStateImpl> m_currentBindings;
+
float m_clearColor[4] = { 0, 0, 0, 0 };
};
@@ -151,7 +166,7 @@ Renderer* createD3D11Renderer()
}
}
-/* static */ID3DBlob* D3D11Renderer::compileHLSLShader(char const* sourcePath, char const* source, char const* entryPointName, char const* dxProfileName)
+/* static */Result D3D11Renderer::compileHLSLShader(char const* sourcePath, char const* source, char const* entryPointName, char const* dxProfileName, ComPtr<ID3DBlob>& shaderBlobOut)
{
// Rather than statically link against the `d3dcompile` library, we
// dynamically load it.
@@ -168,14 +183,14 @@ Renderer* createD3D11Renderer()
if (!compilerModule)
{
fprintf(stderr, "error: failed load 'd3dcompiler_47.dll'\n");
- return nullptr;
- }
+ return SLANG_FAIL;
+ }
compileFunc = (pD3DCompile)GetProcAddress(compilerModule, "D3DCompile");
if (!compileFunc)
{
fprintf(stderr, "error: failed load symbol 'D3DCompile'\n");
- return nullptr;
+ return SLANG_FAIL;
}
}
@@ -195,10 +210,11 @@ Renderer* createD3D11Renderer()
// The `D3DCompile` entry point takes a bunch of parameters, but we
// don't really need most of them for Slang-generated code.
- ID3DBlob* shaderBlob = nullptr;
- ID3DBlob* errorBlob = nullptr;
+ ComPtr<ID3DBlob> shaderBlob;
+ ComPtr<ID3DBlob> errorBlob;
+
HRESULT hr = compileFunc(source, strlen(source), sourcePath, &defines[0], nullptr, entryPointName, dxProfileName, flags, 0,
- &shaderBlob, &errorBlob);
+ shaderBlob.writeRef(), errorBlob.writeRef());
// If the HLSL-to-bytecode compilation produced any diagnostic messages
// then we will print them out (whether or not the compilation failed).
@@ -207,16 +223,12 @@ Renderer* createD3D11Renderer()
::fputs((const char*)errorBlob->GetBufferPointer(), stderr);
::fflush(stderr);
::OutputDebugStringA((const char*)errorBlob->GetBufferPointer());
-
- errorBlob->Release();
- }
-
- if (FAILED(hr))
- {
- return nullptr;
+ return SLANG_FAIL;
}
- return shaderBlob;
+ SLANG_RETURN_ON_FAIL(hr);
+ shaderBlobOut.swap(shaderBlob);
+ return SLANG_OK;
}
/* static */HRESULT D3D11Renderer::captureTextureToFile(ID3D11Device* device, ID3D11DeviceContext* context,
@@ -236,12 +248,11 @@ Renderer* createD3D11Renderer()
}
HRESULT hr = S_OK;
- ID3D11Texture2D* stagingTexture = nullptr;
-
+ ComPtr<ID3D11Texture2D> stagingTexture;
+
if (textureDesc.Usage == D3D11_USAGE_STAGING && (textureDesc.CPUAccessFlags & D3D11_CPU_ACCESS_READ))
{
stagingTexture = texture;
- stagingTexture->AddRef();
}
else
{
@@ -251,7 +262,7 @@ Renderer* createD3D11Renderer()
textureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
textureDesc.Usage = D3D11_USAGE_STAGING;
- hr = device->CreateTexture2D(&textureDesc, 0, &stagingTexture);
+ hr = device->CreateTexture2D(&textureDesc, 0, stagingTexture.writeRef());
if (FAILED(hr))
{
fprintf(stderr, "ERROR: failed to create staging texture\n");
@@ -276,7 +287,6 @@ Renderer* createD3D11Renderer()
// Make sure to unmap
context->Unmap(stagingTexture, 0);
- stagingTexture->Release();
if (!stbResult)
{
@@ -356,19 +366,19 @@ SlangResult D3D11Renderer::initialize(void* inWindowHandle)
for (int ii = 0; ii < 2; ++ii)
{
const HRESULT hr = D3D11CreateDeviceAndSwapChain_(
- NULL, // adapter (use default)
+ nullptr, // adapter (use default)
D3D_DRIVER_TYPE_REFERENCE,
//D3D_DRIVER_TYPE_HARDWARE,
- NULL, // software
+ nullptr, // software
deviceFlags,
&featureLevels[ii],
totalNumFeatureLevels - ii,
D3D11_SDK_VERSION,
&swapChainDesc,
- &m_swapChain,
- &m_device,
+ m_swapChain.writeRef(),
+ m_device.writeRef(),
&featureLevel,
- &m_immediateContext);
+ m_immediateContext.writeRef());
// Failures with `E_INVALIDARG` might be due to feature level 11_1
// not being supported.
@@ -390,27 +400,27 @@ SlangResult D3D11Renderer::initialize(void* inWindowHandle)
0x6f15aaf2, 0xd208, 0x4e89, 0x9a, 0xb4, 0x48,
0x95, 0x35, 0xd3, 0x4f, 0x9c };
- SLANG_RETURN_ON_FAIL(m_swapChain->GetBuffer(0, kIID_ID3D11Texture2D, (void**)&m_backBufferTexture));
+ SLANG_RETURN_ON_FAIL(m_swapChain->GetBuffer(0, kIID_ID3D11Texture2D, (void**)m_backBufferTexture.writeRef()));
for (int i = 0; i < 8; i++)
{
- ID3D11Texture2D* texture;
+ ComPtr<ID3D11Texture2D> texture;
D3D11_TEXTURE2D_DESC textureDesc;
m_backBufferTexture->GetDesc(&textureDesc);
- SLANG_RETURN_ON_FAIL(m_device->CreateTexture2D(&textureDesc, nullptr, &texture));
+ SLANG_RETURN_ON_FAIL(m_device->CreateTexture2D(&textureDesc, nullptr, texture.writeRef()));
- ID3D11RenderTargetView * rtv;
+ ComPtr<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(m_device->CreateRenderTargetView(texture, &rtvDesc, &rtv));
+ SLANG_RETURN_ON_FAIL(m_device->CreateRenderTargetView(texture, &rtvDesc, rtv.writeRef()));
m_renderTargetViews.Add(rtv);
m_renderTargetTextures.Add(texture);
}
- m_immediateContext->OMSetRenderTargets((UINT)m_renderTargetViews.Count(), m_renderTargetViews.Buffer(), nullptr);
+ m_immediateContext->OMSetRenderTargets((UINT)m_renderTargetViews.Count(), m_renderTargetViews.Buffer()->readRef(), nullptr);
// Similarly, we are going to set up a viewport once, and then never
// switch, since this is a simple test app.
@@ -434,9 +444,9 @@ void D3D11Renderer::setClearColor(const float color[4])
void D3D11Renderer::clearFrame()
{
for (auto i = 0u; i < m_renderTargetViews.Count(); i++)
- m_immediateContext->ClearRenderTargetView(
- m_renderTargetViews[i],
- m_clearColor);
+ {
+ m_immediateContext->ClearRenderTargetView(m_renderTargetViews[i], m_clearColor);
+ }
}
void D3D11Renderer::presentFrame()
@@ -486,13 +496,12 @@ Buffer* D3D11Renderer::createBuffer(const BufferDesc& desc)
D3D11_SUBRESOURCE_DATA subResourceData = { 0 };
subResourceData.pSysMem = desc.initData;
- ID3D11Buffer* buffer = nullptr;
- HRESULT hr = m_device->CreateBuffer(&bufferDesc, desc.initData ? &subResourceData : nullptr, &buffer);
- if (FAILED(hr)) return nullptr;
-
+ ComPtr<ID3D11Buffer> buffer;
+ SLANG_RETURN_NULL_ON_FAIL(m_device->CreateBuffer(&bufferDesc, desc.initData ? &subResourceData : nullptr, buffer.writeRef()));
+
BufferImpl* rs = new BufferImpl;
- rs->buffer = buffer;
- return (Buffer*)rs;
+ rs->m_buffer = buffer;
+ return rs;
}
InputLayout* D3D11Renderer::createInputLayout(const InputElementDesc* inputElementsIn, UInt inputElementCount)
@@ -541,20 +550,17 @@ InputLayout* D3D11Renderer::createInputLayout(const InputElementDesc* inputEleme
hlslCursor += sprintf(hlslCursor, "\n) : SV_Position { return 0; }");
- auto vertexShaderBlob = compileHLSLShader("inputLayout", hlslBuffer, "main", "vs_5_0");
- if (!vertexShaderBlob)
- return nullptr;
+ ComPtr<ID3DBlob> vertexShaderBlob;
+ SLANG_RETURN_NULL_ON_FAIL(compileHLSLShader("inputLayout", hlslBuffer, "main", "vs_5_0", vertexShaderBlob));
- ID3D11InputLayout* inputLayout = nullptr;
- HRESULT hr = m_device->CreateInputLayout(&inputElements[0], (UINT)inputElementCount, vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize(),
- &inputLayout);
+ ComPtr<ID3D11InputLayout> inputLayout;
+ SLANG_RETURN_NULL_ON_FAIL(m_device->CreateInputLayout(&inputElements[0], (UINT)inputElementCount, vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize(),
+ inputLayout.writeRef()));
- vertexShaderBlob->Release();
+ InputLayoutImpl* impl = new InputLayoutImpl;
+ impl->m_layout.swap(inputLayout);
- if (FAILED(hr))
- return nullptr;
-
- return (InputLayout*)inputLayout;
+ return impl;
}
void* D3D11Renderer::map(ID3D11Buffer* buffer, MapFlavor flavorIn)
@@ -579,16 +585,14 @@ void* D3D11Renderer::map(ID3D11Buffer* buffer, MapFlavor flavorIn)
// of the example, but we don't actually load different data
// per-frame (we always use an identity projection).
D3D11_MAPPED_SUBRESOURCE mappedSub;
- HRESULT hr = m_immediateContext->Map(buffer, 0, mapType, 0, &mappedSub);
- if (FAILED(hr))
- return nullptr;
-
+ SLANG_RETURN_NULL_ON_FAIL(m_immediateContext->Map(buffer, 0, mapType, 0, &mappedSub));
+
return mappedSub.pData;
}
void* D3D11Renderer::map(Buffer* buffer, MapFlavor flavor)
{
- return map(((BufferImpl*)buffer)->buffer, flavor);
+ return map(((BufferImpl*)buffer)->m_buffer, flavor);
}
void D3D11Renderer::unmap(ID3D11Buffer* buffer)
@@ -598,14 +602,13 @@ void D3D11Renderer::unmap(ID3D11Buffer* buffer)
void D3D11Renderer::unmap(Buffer* bufferIn)
{
- unmap(((BufferImpl*)bufferIn)->buffer);
+ unmap(((BufferImpl*)bufferIn)->m_buffer);
}
void D3D11Renderer::setInputLayout(InputLayout* inputLayoutIn)
{
- auto inputLayout = (ID3D11InputLayout*)inputLayoutIn;
-
- m_immediateContext->IASetInputLayout(inputLayout);
+ auto inputLayout = static_cast<InputLayoutImpl*>(inputLayoutIn);
+ m_immediateContext->IASetInputLayout(inputLayout->m_layout);
}
void D3D11Renderer::setPrimitiveTopology(PrimitiveTopology topology)
@@ -627,36 +630,50 @@ void D3D11Renderer::setPrimitiveTopology(PrimitiveTopology topology)
void D3D11Renderer::setVertexBuffers(UInt startSlot, UInt slotCount, Buffer*const* buffersIn, const UInt* stridesIn, const UInt* offsetsIn)
{
static const int kMaxVertexBuffers = 16;
+ assert(slotCount <= kMaxVertexBuffers);
UINT vertexStrides[kMaxVertexBuffers];
UINT vertexOffsets[kMaxVertexBuffers];
+ ID3D11Buffer* dxBuffers[kMaxVertexBuffers];
+
+ auto buffers = (BufferImpl*const*)buffersIn;
for (UInt ii = 0; ii < slotCount; ++ii)
{
vertexStrides[ii] = (UINT)stridesIn[ii];
vertexOffsets[ii] = (UINT)offsetsIn[ii];
- }
-
- auto buffers = (BufferImpl* const*)buffersIn;
+ dxBuffers[ii] = buffers[ii]->m_buffer;
+ }
- m_immediateContext->IASetVertexBuffers((UINT)startSlot, (UINT)slotCount, &(buffers[0])->buffer, &vertexStrides[0], &vertexOffsets[0]);
+ m_immediateContext->IASetVertexBuffers((UINT)startSlot, (UINT)slotCount, dxBuffers, &vertexStrides[0], &vertexOffsets[0]);
}
void D3D11Renderer::setShaderProgram(ShaderProgram* programIn)
{
auto program = (ShaderProgramImpl*)programIn;
- m_immediateContext->CSSetShader(program->computeShader, nullptr, 0);
- m_immediateContext->VSSetShader(program->vertexShader, nullptr, 0);
- m_immediateContext->PSSetShader(program->pixelShader, nullptr, 0);
+ m_immediateContext->CSSetShader(program->m_computeShader, nullptr, 0);
+ m_immediateContext->VSSetShader(program->m_vertexShader, nullptr, 0);
+ m_immediateContext->PSSetShader(program->m_pixelShader, nullptr, 0);
}
void D3D11Renderer::setConstantBuffers(UInt startSlot, UInt slotCount, Buffer*const* buffersIn, const UInt* offsetsIn)
{
+ static const int kMaxConstantBuffers = 16;
+ assert(slotCount <= kMaxConstantBuffers);
+
// TODO: actually use those offsets
auto buffers = (BufferImpl*const*)buffersIn;
- m_immediateContext->VSSetConstantBuffers((UINT)startSlot, (UINT)slotCount, &buffers[0]->buffer);
- m_immediateContext->VSSetConstantBuffers((UINT)startSlot, (UINT)slotCount, &buffers[0]->buffer);
+
+ // Copy out the actual dx buffers
+ ID3D11Buffer* dxBuffers[kMaxConstantBuffers];
+ for (int i = 0; i < slotCount; i++)
+ {
+ dxBuffers[i] = buffers[i]->m_buffer;
+ }
+
+ m_immediateContext->VSSetConstantBuffers((UINT)startSlot, (UINT)slotCount, dxBuffers);
+ m_immediateContext->VSSetConstantBuffers((UINT)startSlot, (UINT)slotCount, dxBuffers);
}
void D3D11Renderer::draw(UInt vertexCount, UInt startVertex)
@@ -669,46 +686,32 @@ ShaderProgram* D3D11Renderer::compileProgram(const ShaderCompileRequest& request
{
if (request.computeShader.name)
{
- auto computeShaderBlob = compileHLSLShader(request.computeShader.source.path, request.computeShader.source.dataBegin, request.computeShader.name, request.computeShader.profile);
- if (!computeShaderBlob)
- return nullptr;
-
- ID3D11ComputeShader* computeShader;
+ ComPtr<ID3DBlob> computeShaderBlob;
+ SLANG_RETURN_NULL_ON_FAIL(compileHLSLShader(request.computeShader.source.path, request.computeShader.source.dataBegin, request.computeShader.name, request.computeShader.profile, computeShaderBlob));
- HRESULT hr = m_device->CreateComputeShader(computeShaderBlob->GetBufferPointer(), computeShaderBlob->GetBufferSize(), nullptr, &computeShader);
-
- computeShaderBlob->Release();
-
- if (FAILED(hr)) return nullptr;
+ ComPtr<ID3D11ComputeShader> computeShader;
+ SLANG_RETURN_NULL_ON_FAIL(m_device->CreateComputeShader(computeShaderBlob->GetBufferPointer(), computeShaderBlob->GetBufferSize(), nullptr, computeShader.writeRef()));
ShaderProgramImpl* shaderProgram = new ShaderProgramImpl();
- shaderProgram->computeShader = computeShader;
- return (ShaderProgram*)shaderProgram;
+ shaderProgram->m_computeShader.swap(computeShader);
+ return shaderProgram;
}
else
{
- auto vertexShaderBlob = compileHLSLShader(request.vertexShader.source.path, request.vertexShader.source.dataBegin, request.vertexShader.name, request.vertexShader.profile);
- if (!vertexShaderBlob) return nullptr;
-
- auto fragmentShaderBlob = compileHLSLShader(request.fragmentShader.source.path, request.fragmentShader.source.dataBegin, request.fragmentShader.name, request.fragmentShader.profile);
- if (!fragmentShaderBlob) return nullptr;
+ ComPtr<ID3DBlob> vertexShaderBlob, fragmentShaderBlob;
+ SLANG_RETURN_NULL_ON_FAIL(compileHLSLShader(request.vertexShader.source.path, request.vertexShader.source.dataBegin, request.vertexShader.name, request.vertexShader.profile, vertexShaderBlob));
+ SLANG_RETURN_NULL_ON_FAIL(compileHLSLShader(request.fragmentShader.source.path, request.fragmentShader.source.dataBegin, request.fragmentShader.name, request.fragmentShader.profile, fragmentShaderBlob));
+
+ ComPtr<ID3D11VertexShader> vertexShader;
+ ComPtr<ID3D11PixelShader> pixelShader;
- ID3D11VertexShader* vertexShader;
- ID3D11PixelShader* pixelShader;
-
- HRESULT vsResult = m_device->CreateVertexShader(vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize(), nullptr, &vertexShader);
- HRESULT psResult = m_device->CreatePixelShader(fragmentShaderBlob->GetBufferPointer(), fragmentShaderBlob->GetBufferSize(), nullptr, &pixelShader);
-
- vertexShaderBlob->Release();
- fragmentShaderBlob->Release();
-
- if (FAILED(vsResult)) return nullptr;
- if (FAILED(psResult)) return nullptr;
+ SLANG_RETURN_NULL_ON_FAIL(m_device->CreateVertexShader(vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize(), nullptr, vertexShader.writeRef()));
+ SLANG_RETURN_NULL_ON_FAIL(m_device->CreatePixelShader(fragmentShaderBlob->GetBufferPointer(), fragmentShaderBlob->GetBufferSize(), nullptr, pixelShader.writeRef()));
ShaderProgramImpl* shaderProgram = new ShaderProgramImpl();
- shaderProgram->vertexShader = vertexShader;
- shaderProgram->pixelShader = pixelShader;
- return (ShaderProgram*)shaderProgram;
+ shaderProgram->m_vertexShader.swap(vertexShader);
+ shaderProgram->m_pixelShader.swap(pixelShader);
+ return shaderProgram;
}
}
@@ -718,8 +721,8 @@ void D3D11Renderer::dispatchCompute(int x, int y, int z)
m_immediateContext->Dispatch(x, y, z);
}
-void D3D11Renderer::createInputBuffer(InputBufferDesc& bufferDesc, List<unsigned int>& bufferData, ID3D11Buffer*& bufferOut,
- ID3D11UnorderedAccessView*& viewOut, ID3D11ShaderResourceView*& srvOut)
+Result D3D11Renderer::createInputBuffer(InputBufferDesc& bufferDesc, const List<unsigned int>& bufferData,
+ ComPtr<ID3D11Buffer>& bufferOut, ComPtr<ID3D11UnorderedAccessView>& viewOut, ComPtr<ID3D11ShaderResourceView>& srvOut)
{
D3D11_BUFFER_DESC desc = { 0 };
List<unsigned int> newBuffer;
@@ -748,7 +751,7 @@ void D3D11Renderer::createInputBuffer(InputBufferDesc& bufferDesc, List<unsigned
}
D3D11_SUBRESOURCE_DATA data = { 0 };
data.pSysMem = newBuffer.Buffer();
- m_device->CreateBuffer(&desc, &data, &bufferOut);
+ SLANG_RETURN_ON_FAIL(m_device->CreateBuffer(&desc, &data, bufferOut.writeRef()));
int elemSize = bufferDesc.stride <= 0 ? 1 : bufferDesc.stride;
if (bufferDesc.type == InputBufferType::StorageBuffer)
{
@@ -769,7 +772,7 @@ void D3D11Renderer::createInputBuffer(InputBufferDesc& bufferDesc, List<unsigned
viewDesc.Format = DXGI_FORMAT_R32_TYPELESS;
}
- m_device->CreateUnorderedAccessView(bufferOut, &viewDesc, &viewOut);
+ SLANG_RETURN_ON_FAIL(m_device->CreateUnorderedAccessView(bufferOut, &viewDesc, viewOut.writeRef()));
}
if (bufferDesc.type != InputBufferType::ConstantBuffer)
{
@@ -781,12 +784,22 @@ void D3D11Renderer::createInputBuffer(InputBufferDesc& bufferDesc, List<unsigned
srvDesc.Buffer.ElementOffset = 0;
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
srvDesc.Format = DXGI_FORMAT_UNKNOWN;
- m_device->CreateShaderResourceView(bufferOut, &srvDesc, &srvOut);
+
+ if (bufferDesc.stride == 0)
+ {
+ srvDesc.Format = DXGI_FORMAT_R32_FLOAT;
+ }
+
+ SLANG_RETURN_ON_FAIL(m_device->CreateShaderResourceView(bufferOut, &srvDesc, srvOut.writeRef()));
}
+
+ return SLANG_OK;
}
-void D3D11Renderer::createInputTexture(const InputTextureDesc& inputDesc, ID3D11ShaderResourceView*& viewOut)
+Result D3D11Renderer::createInputTexture(const InputTextureDesc& inputDesc, ComPtr<ID3D11ShaderResourceView>& viewOut)
{
+ ComPtr<ID3D11ShaderResourceView> view;
+
TextureData texData;
generateTextureData(texData, inputDesc);
List<D3D11_SUBRESOURCE_DATA> subRes;
@@ -816,10 +829,10 @@ void D3D11Renderer::createInputTexture(const InputTextureDesc& inputDesc, ID3D11
desc.Width = texData.textureSize;
desc.Usage = D3D11_USAGE_DEFAULT;
- ID3D11Texture1D * texture;
- m_device->CreateTexture1D(&desc, subRes.Buffer(), &texture);
- D3D11_SHADER_RESOURCE_VIEW_DESC viewDesc;
+ ComPtr<ID3D11Texture1D> texture;
+ SLANG_RETURN_ON_FAIL(m_device->CreateTexture1D(&desc, subRes.Buffer(), texture.writeRef()));
+ D3D11_SHADER_RESOURCE_VIEW_DESC viewDesc;
viewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1D;
if (inputDesc.arrayLength != 0)
viewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1DARRAY;
@@ -830,7 +843,7 @@ void D3D11Renderer::createInputTexture(const InputTextureDesc& inputDesc, ID3D11
viewDesc.Texture1DArray.MipLevels = texData.mipLevels;
viewDesc.Texture1DArray.MostDetailedMip = 0;
viewDesc.Format = desc.Format;
- m_device->CreateShaderResourceView(texture, &viewDesc, &viewOut);
+ m_device->CreateShaderResourceView(texture, &viewDesc, view.writeRef());
}
else if (inputDesc.dimension == 2)
{
@@ -871,9 +884,10 @@ void D3D11Renderer::createInputTexture(const InputTextureDesc& inputDesc, ID3D11
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
viewDesc.Format = desc.Format;
- ID3D11Texture2D * texture;
- m_device->CreateTexture2D(&desc, subRes.Buffer(), &texture);
- m_device->CreateShaderResourceView(texture, &viewDesc, &viewOut);
+
+ ComPtr<ID3D11Texture2D> texture;
+ SLANG_RETURN_ON_FAIL(m_device->CreateTexture2D(&desc, subRes.Buffer(), texture.writeRef()));
+ SLANG_RETURN_ON_FAIL(m_device->CreateShaderResourceView(texture, &viewDesc, view.writeRef()));
}
else if (inputDesc.dimension == 3)
{
@@ -889,16 +903,20 @@ void D3D11Renderer::createInputTexture(const InputTextureDesc& inputDesc, ID3D11
desc.Height = texData.textureSize;
desc.Depth = texData.textureSize;
desc.Usage = D3D11_USAGE_DEFAULT;
- ID3D11Texture3D * texture;
- m_device->CreateTexture3D(&desc, subRes.Buffer(), &texture);
+
+ ComPtr<ID3D11Texture3D> texture;
+ m_device->CreateTexture3D(&desc, subRes.Buffer(), texture.writeRef());
viewDesc.Texture3D.MipLevels = 1;
viewDesc.Texture3D.MostDetailedMip = 0;
viewDesc.Format = desc.Format;
- m_device->CreateShaderResourceView(texture, &viewDesc, &viewOut);
+ m_device->CreateShaderResourceView(texture, &viewDesc, view.writeRef());
}
+
+ viewOut.swap(view);
+ return SLANG_OK;
}
-void D3D11Renderer::createInputSampler(const InputSamplerDesc& inputDesc, ID3D11SamplerState*& stateOut)
+Result D3D11Renderer::createInputSampler(const InputSamplerDesc& inputDesc, ComPtr<ID3D11SamplerState>& stateOut)
{
D3D11_SAMPLER_DESC desc;
memset(&desc, 0, sizeof(desc));
@@ -916,16 +934,16 @@ void D3D11Renderer::createInputSampler(const InputSamplerDesc& inputDesc, ID3D11
desc.MinLOD = 0.0f;
desc.MaxLOD = 100.0f;
}
- m_device->CreateSamplerState(&desc, &stateOut);
+ return m_device->CreateSamplerState(&desc, stateOut.writeRef());
}
-BindingState * D3D11Renderer::createBindingState(const ShaderInputLayout& layout)
+BindingState* D3D11Renderer::createBindingState(const ShaderInputLayout& layout)
{
- BindingStateImpl * rs = new BindingStateImpl;
- rs->numRenderTargets = layout.numRenderTargets;
+ List<Binding> bindings;
+
for (auto & entry : layout.entries)
{
- BindingImpl rsEntry;
+ Binding rsEntry;
rsEntry.type = entry.type;
rsEntry.binding = entry.hlslBinding;
rsEntry.isOutput = entry.isOutput;
@@ -933,66 +951,73 @@ BindingState * D3D11Renderer::createBindingState(const ShaderInputLayout& layout
{
case ShaderInputType::Buffer:
{
- createInputBuffer(entry.bufferDesc, entry.bufferData, rsEntry.buffer, rsEntry.uav, rsEntry.srv);
+ SLANG_RETURN_NULL_ON_FAIL(createInputBuffer(entry.bufferDesc, entry.bufferData, rsEntry.buffer, rsEntry.uav, rsEntry.srv));
+
rsEntry.bufferLength = (int)(entry.bufferData.Count() * sizeof(unsigned int));
rsEntry.bufferType = entry.bufferDesc.type;
- }
- break;
+ break;
+ }
case ShaderInputType::Texture:
{
- createInputTexture(entry.textureDesc, rsEntry.srv);
- }
- break;
+ SLANG_RETURN_NULL_ON_FAIL(createInputTexture(entry.textureDesc, rsEntry.srv));
+ break;
+ }
case ShaderInputType::Sampler:
{
- createInputSampler(entry.samplerDesc, rsEntry.samplerState);
- }
- break;
+ SLANG_RETURN_NULL_ON_FAIL(createInputSampler(entry.samplerDesc, rsEntry.samplerState));
+ break;
+ }
case ShaderInputType::CombinedTextureSampler:
{
- throw "not implemented";
- }
- break;
+ assert(!"Not implemented");
+ //throw "not implemented";
+ return nullptr;
+ break;
+ }
}
- rs->bindings.Add(rsEntry);
+ bindings.Add(rsEntry);
}
- return (BindingState*)rs;
+ BindingStateImpl* rs = new BindingStateImpl;
+ rs->m_numRenderTargets = layout.numRenderTargets;
+ rs->m_bindings.SwapWith(bindings);
+
+ return rs;
}
void D3D11Renderer::applyBindingState(bool isCompute)
{
- auto context = m_immediateContext;
- for (auto & binding : m_currentBindings->bindings)
+ auto context = m_immediateContext.get();
+ for (auto & binding : m_currentBindings->m_bindings)
{
if (binding.type == ShaderInputType::Buffer)
{
if (binding.bufferType == InputBufferType::ConstantBuffer)
{
if (isCompute)
- context->CSSetConstantBuffers(binding.binding, 1, &binding.buffer);
+ context->CSSetConstantBuffers(binding.binding, 1, binding.buffer.readRef());
else
{
- context->VSSetConstantBuffers(binding.binding, 1, &binding.buffer);
- context->PSSetConstantBuffers(binding.binding, 1, &binding.buffer);
+ context->VSSetConstantBuffers(binding.binding, 1, binding.buffer.readRef());
+ context->PSSetConstantBuffers(binding.binding, 1, binding.buffer.readRef());
}
}
else if (binding.uav)
{
if (isCompute)
- context->CSSetUnorderedAccessViews(binding.binding, 1, &binding.uav, nullptr);
+ context->CSSetUnorderedAccessViews(binding.binding, 1, binding.uav.readRef(), nullptr);
else
- context->OMSetRenderTargetsAndUnorderedAccessViews(m_currentBindings->numRenderTargets,
- m_renderTargetViews.Buffer(), nullptr, binding.binding, 1, &binding.uav, nullptr);
+ context->OMSetRenderTargetsAndUnorderedAccessViews(m_currentBindings->m_numRenderTargets,
+ m_renderTargetViews.Buffer()->readRef(), nullptr, binding.binding, 1, binding.uav.readRef(), nullptr);
}
else
{
if (isCompute)
- context->CSSetShaderResources(binding.binding, 1, &binding.srv);
+ context->CSSetShaderResources(binding.binding, 1, binding.srv.readRef());
else
{
- context->PSSetShaderResources(binding.binding, 1, &binding.srv);
- context->VSSetShaderResources(binding.binding, 1, &binding.srv);
+ context->PSSetShaderResources(binding.binding, 1, binding.srv.readRef());
+ context->VSSetShaderResources(binding.binding, 1, binding.srv.readRef());
}
}
}
@@ -1001,30 +1026,30 @@ void D3D11Renderer::applyBindingState(bool isCompute)
if (binding.uav)
{
if (isCompute)
- context->CSSetUnorderedAccessViews(binding.binding, 1, &binding.uav, nullptr);
+ context->CSSetUnorderedAccessViews(binding.binding, 1, binding.uav.readRef(), nullptr);
else
context->OMSetRenderTargetsAndUnorderedAccessViews(D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL,
- nullptr, nullptr, binding.binding, 1, &binding.uav, nullptr);
+ nullptr, nullptr, binding.binding, 1, binding.uav.readRef(), nullptr);
}
else
{
if (isCompute)
- context->CSSetShaderResources(binding.binding, 1, &binding.srv);
+ context->CSSetShaderResources(binding.binding, 1, binding.srv.readRef());
else
{
- context->PSSetShaderResources(binding.binding, 1, &binding.srv);
- context->VSSetShaderResources(binding.binding, 1, &binding.srv);
+ context->PSSetShaderResources(binding.binding, 1, binding.srv.readRef());
+ context->VSSetShaderResources(binding.binding, 1, binding.srv.readRef());
}
}
}
else if (binding.type == ShaderInputType::Sampler)
{
if (isCompute)
- context->CSSetSamplers(binding.binding, 1, &binding.samplerState);
+ context->CSSetSamplers(binding.binding, 1, binding.samplerState.readRef());
else
{
- context->PSSetSamplers(binding.binding, 1, &binding.samplerState);
- context->VSSetSamplers(binding.binding, 1, &binding.samplerState);
+ context->PSSetSamplers(binding.binding, 1, binding.samplerState.readRef());
+ context->VSSetSamplers(binding.binding, 1, binding.samplerState.readRef());
}
}
else
@@ -1034,22 +1059,23 @@ void D3D11Renderer::applyBindingState(bool isCompute)
void D3D11Renderer::setBindingState(BindingState* state)
{
- m_currentBindings = (BindingStateImpl*)state;
+ m_currentBindings = static_cast<BindingStateImpl*>(state);
}
-void D3D11Renderer::serializeOutput(BindingState* state, const char* fileName)
+void D3D11Renderer::serializeOutput(BindingState* stateIn, const char* fileName)
{
- auto bindingState = (BindingStateImpl*)state;
+ auto bindingState = static_cast<BindingStateImpl*>(stateIn);
FILE * f = fopen(fileName, "wb");
int id = 0;
- for (auto & binding : bindingState->bindings)
+ for (auto & binding : bindingState->m_bindings)
{
if (binding.isOutput)
{
if (binding.buffer)
{
// create staging buffer
- ID3D11Buffer* stageBuf;
+ ComPtr<ID3D11Buffer> stageBuf;
+
D3D11_BUFFER_DESC bufDesc;
memset(&bufDesc, 0, sizeof(bufDesc));
bufDesc.BindFlags = 0;
@@ -1057,14 +1083,13 @@ void D3D11Renderer::serializeOutput(BindingState* state, const char* fileName)
bufDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
bufDesc.Usage = D3D11_USAGE_STAGING;
- m_device->CreateBuffer(&bufDesc, nullptr, &stageBuf);
+ SLANG_RETURN_VOID_ON_FAIL(m_device->CreateBuffer(&bufDesc, nullptr, stageBuf.writeRef()));
m_immediateContext->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
{
diff --git a/tools/render-test/render-gl.cpp b/tools/render-test/render-gl.cpp
index 9c77fe7ba..37745d93b 100644
--- a/tools/render-test/render-gl.cpp
+++ b/tools/render-test/render-gl.cpp
@@ -51,7 +51,8 @@
F(glGenBuffers, PFNGLGENBUFFERSPROC) \
F(glBindBuffer, PFNGLBINDBUFFERPROC) \
F(glBufferData, PFNGLBUFFERDATAPROC) \
- F(glMapBuffer, PFNGLMAPBUFFERPROC) \
+ F(glDeleteBuffers, PFNGLDELETEBUFFERSPROC) \
+ F(glMapBuffer, PFNGLMAPBUFFERPROC) \
F(glUnmapBuffer, PFNGLUNMAPBUFFERPROC) \
F(glUseProgram, PFNGLUSEPROGRAMPROC) \
F(glBindBufferBase, PFNGLBINDBUFFERBASEPROC) \
@@ -62,6 +63,7 @@
F(glDispatchCompute, PFNGLDISPATCHCOMPUTEPROC) \
F(glActiveTexture, PFNGLACTIVETEXTUREPROC) \
F(glCreateSamplers, PFNGLCREATESAMPLERSPROC) \
+ F(glDeleteSamplers, PFNGLDELETESAMPLERSPROC) \
F(glBindSampler, PFNGLBINDSAMPLERPROC) \
F(glTexImage3D, PFNGLTEXIMAGE3DPROC) \
F(glSamplerParameteri, PFNGLSAMPLERPARAMETERIPROC) \
@@ -120,13 +122,33 @@ public:
GLsizei offset;
};
- struct InputLayoutImpl
+ class InputLayoutImpl: public InputLayout
{
- VertexAttributeDesc attributes[kMaxVertexStreams];
- UInt attributeCount = 0;
+ public:
+ VertexAttributeDesc m_attributes[kMaxVertexStreams];
+ UInt m_attributeCount = 0;
};
- struct BindingEntryImpl
+ class BufferImpl: public Buffer
+ {
+ public:
+ BufferImpl(GLRenderer* renderer, GLuint id):
+ m_renderer(renderer),
+ m_id(id)
+ {}
+ ~BufferImpl()
+ {
+ if (m_renderer)
+ {
+ m_renderer->glDeleteBuffers(1, &m_id);
+ }
+ }
+
+ GLRenderer* m_renderer;
+ GLuint m_id;
+ };
+
+ struct BindingEntry
{
ShaderInputType type;
GLuint handle;
@@ -135,18 +157,56 @@ public:
int bufferSize;
bool isOutput = false;
};
- struct BindingStateImpl
- {
- List<BindingEntryImpl> entries;
+ class BindingStateImpl: public BindingState
+ {
+ public:
+ BindingStateImpl(GLRenderer* renderer):
+ m_renderer(renderer)
+ {
+ }
+
+ ~BindingStateImpl()
+ {
+ if (m_renderer)
+ {
+ m_renderer->destroyBindingEntries(m_entries.Buffer(), int(m_entries.Count()));
+ }
+ }
+
+ GLRenderer* m_renderer;
+ List<BindingEntry> m_entries;
};
+ class ShaderProgramImpl : public ShaderProgram
+ {
+ public:
+ ShaderProgramImpl(GLRenderer* renderer, GLuint id):
+ m_renderer(renderer),
+ m_id(id)
+ {
+ }
+ ~ShaderProgramImpl()
+ {
+ if (m_renderer)
+ {
+ m_renderer->glDeleteProgram(m_id);
+ }
+ }
+
+ GLuint m_id;
+ GLRenderer* m_renderer;
+ };
+
+ void destroyBindingEntry(const BindingEntry& entry);
+ void destroyBindingEntries(const BindingEntry* entries, int numEntries);
+
void bindBufferImpl(int target, UInt startSlot, UInt slotCount, Buffer*const* buffers, const UInt* offsets);
void flushStateForDraw();
GLuint loadShader(GLenum stage, char const* source);
- void createInputBuffer(BindingEntryImpl& rs, InputBufferDesc bufDesc, List<unsigned int>& bufferData);
+ void createInputBuffer(BindingEntry& rs, InputBufferDesc bufDesc, List<unsigned int>& bufferData);
void debugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message);
- void createInputTexture(BindingEntryImpl& rs, InputTextureDesc texDesc, InputSamplerDesc samplerDesc);
- void createInputSampler(BindingEntryImpl& rs, InputSamplerDesc samplerDesc);
+ void createInputTexture(BindingEntry& rs, InputTextureDesc texDesc, InputSamplerDesc samplerDesc);
+ void createInputSampler(BindingEntry& rs, InputSamplerDesc samplerDesc);
static void APIENTRY staticDebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, const void* userParam);
static VertexAttributeFormat getVertexAttributeFormat(Format format);
@@ -155,7 +215,9 @@ public:
HGLRC m_glContext;
float m_clearColor[4] = { 0, 0, 0, 0 };
- InputLayoutImpl* m_boundInputLayout = nullptr;
+ RefPtr<ShaderProgramImpl> m_boundShaderProgram;
+ RefPtr<InputLayoutImpl> m_boundInputLayout;
+
GLenum m_boundPrimitiveTopology = GL_TRIANGLES;
GLuint m_boundVertexStreamBuffers[kMaxVertexStreams];
UInt m_boundVertexStreamStrides[kMaxVertexStreams];
@@ -214,9 +276,9 @@ void GLRenderer::bindBufferImpl(int target, UInt startSlot, UInt slotCount, Buff
{
UInt slot = startSlot + ii;
- Buffer* buffer = buffers[ii];
- GLuint bufferID = (GLuint)(uintptr_t)buffer;
-
+ BufferImpl* buffer = static_cast<BufferImpl*>(buffers[ii]);
+ GLuint bufferID = buffer ? buffer->m_id : 0;
+
assert(!offsets || !offsets[ii]);
glBindBufferBase(target, (GLuint)slot, bufferID);
@@ -225,11 +287,11 @@ void GLRenderer::bindBufferImpl(int target, UInt startSlot, UInt slotCount, Buff
void GLRenderer::flushStateForDraw()
{
- auto layout = m_boundInputLayout;
- auto attrCount = layout->attributeCount;
+ auto layout = m_boundInputLayout.Ptr();
+ auto attrCount = layout->m_attributeCount;
for (UInt ii = 0; ii < attrCount; ++ii)
{
- auto& attr = layout->attributes[ii];
+ auto& attr = layout->m_attributes[ii];
auto streamIndex = attr.streamIndex;
@@ -362,7 +424,39 @@ GLuint GLRenderer::loadShader(GLenum stage, const char* source)
return shaderID;
}
-void GLRenderer::createInputBuffer(BindingEntryImpl& rs, InputBufferDesc bufDesc, List<unsigned int>& bufferData)
+void GLRenderer::destroyBindingEntry(const BindingEntry& entry)
+{
+ switch (entry.type)
+ {
+ case ShaderInputType::Buffer:
+ {
+ glDeleteBuffers(1, &entry.handle);
+ break;
+ }
+ case ShaderInputType::Texture:
+ case ShaderInputType::CombinedTextureSampler:
+ {
+ glDeleteTextures(1, &entry.handle);
+ break;
+ }
+ case ShaderInputType::Sampler:
+ {
+ glDeleteSamplers(1, &entry.handle);
+ break;
+ }
+ default: break;
+ }
+}
+
+void GLRenderer::destroyBindingEntries(const BindingEntry* entries, int numEntries)
+{
+ for (int i = 0; i < numEntries; ++i)
+ {
+ destroyBindingEntry(entries[i]);
+ }
+}
+
+void GLRenderer::createInputBuffer(BindingEntry& rs, InputBufferDesc bufDesc, List<unsigned int>& bufferData)
{
rs.bindTarget = (bufDesc.type == InputBufferType::StorageBuffer ? GL_SHADER_STORAGE_BUFFER : GL_UNIFORM_BUFFER);
glGenBuffers(1, &rs.handle);
@@ -371,8 +465,7 @@ void GLRenderer::createInputBuffer(BindingEntryImpl& rs, InputBufferDesc bufDesc
glBindBuffer(rs.bindTarget, 0);
}
-
-void GLRenderer::createInputTexture(BindingEntryImpl& rs, InputTextureDesc texDesc, InputSamplerDesc samplerDesc)
+void GLRenderer::createInputTexture(BindingEntry& rs, InputTextureDesc texDesc, InputSamplerDesc samplerDesc)
{
TextureData texData;
generateTextureData(texData, texDesc);
@@ -386,11 +479,13 @@ void GLRenderer::createInputTexture(BindingEntryImpl& rs, InputTextureDesc texDe
glBindTexture(rs.bindTarget, rs.handle);
int slice = 0;
for (int i = 0; i < texData.arraySize; i++)
+ {
for (int j = 0; j < texData.mipLevels; j++)
{
glTexImage2D(rs.bindTarget, j, GL_RGBA8, texData.textureSize, i, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData.dataBuffer[slice].Buffer());
slice++;
}
+ }
}
else
{
@@ -458,7 +553,7 @@ void GLRenderer::createInputTexture(BindingEntryImpl& rs, InputTextureDesc texDe
}
}
-void GLRenderer::createInputSampler(BindingEntryImpl& rs, InputSamplerDesc samplerDesc)
+void GLRenderer::createInputSampler(BindingEntry& rs, InputSamplerDesc samplerDesc)
{
glCreateSamplers(1, &rs.handle);
glSamplerParameteri(rs.handle, GL_TEXTURE_WRAP_S, GL_REPEAT);
@@ -608,18 +703,18 @@ Buffer* GLRenderer::createBuffer(const BufferDesc& desc)
glBufferData(target, desc.size, desc.initData, usage);
- return (Buffer*)(uintptr_t)bufferID;
+ return new BufferImpl(this, bufferID);
}
InputLayout* GLRenderer::createInputLayout(const InputElementDesc* inputElements, UInt inputElementCount)
{
InputLayoutImpl* inputLayout = new InputLayoutImpl;
- inputLayout->attributeCount = inputElementCount;
+ inputLayout->m_attributeCount = inputElementCount;
for (UInt ii = 0; ii < inputElementCount; ++ii)
{
auto& inputAttr = inputElements[ii];
- auto& glAttr = inputLayout->attributes[ii];
+ auto& glAttr = inputLayout->m_attributes[ii];
glAttr.streamIndex = 0;
glAttr.format = getVertexAttributeFormat(inputAttr.format);
@@ -629,8 +724,10 @@ InputLayout* GLRenderer::createInputLayout(const InputElementDesc* inputElements
return (InputLayout*)inputLayout;
}
-void* GLRenderer::map(Buffer* buffer, MapFlavor flavor)
+void* GLRenderer::map(Buffer* bufferIn, MapFlavor flavor)
{
+ BufferImpl* buffer = static_cast<BufferImpl*>(bufferIn);
+
GLenum target = GL_UNIFORM_BUFFER;
GLuint access = 0;
@@ -645,23 +742,23 @@ void* GLRenderer::map(Buffer* buffer, MapFlavor flavor)
break;
}
- auto bufferID = (GLuint)(uintptr_t)buffer;
+ auto bufferID = buffer ? buffer->m_id : 0;
glBindBuffer(target, bufferID);
return glMapBuffer(target, access);
}
-void GLRenderer::unmap(Buffer* buffer)
+void GLRenderer::unmap(Buffer* bufferIn)
{
+ BufferImpl* buffer = static_cast<BufferImpl*>(bufferIn);
GLenum target = GL_UNIFORM_BUFFER;
-
- auto bufferID = (GLuint)(uintptr_t)buffer;
+ auto bufferID = buffer ? buffer->m_id : 0;
glUnmapBuffer(target);
}
void GLRenderer::setInputLayout(InputLayout* inputLayout)
{
- m_boundInputLayout = (InputLayoutImpl*)inputLayout;
+ m_boundInputLayout = static_cast<InputLayoutImpl*>(inputLayout);
}
void GLRenderer::setPrimitiveTopology(PrimitiveTopology topology)
@@ -684,19 +781,21 @@ void GLRenderer::setVertexBuffers(UInt startSlot, UInt slotCount, Buffer*const*
{
UInt slot = startSlot + ii;
- Buffer* buffer = buffers[ii];
- GLuint bufferID = (GLuint)(uintptr_t)buffer;
-
+ BufferImpl* buffer = static_cast<BufferImpl*>(buffers[ii]);
+ GLuint bufferID = buffer ? buffer->m_id : 0;
+
m_boundVertexStreamBuffers[slot] = bufferID;
m_boundVertexStreamStrides[slot] = strides[ii];
m_boundVertexStreamOffsets[slot] = offsets[ii];
}
}
-void GLRenderer::setShaderProgram(ShaderProgram* program)
+void GLRenderer::setShaderProgram(ShaderProgram* programIn)
{
- GLuint programID = (GLuint)(uintptr_t)program;
- glUseProgram(programID);
+ ShaderProgramImpl* program = static_cast<ShaderProgramImpl*>(programIn);
+ m_boundShaderProgram = program;
+ GLuint programID = program ? program->m_id : 0;
+ glUseProgram(programID);
}
void GLRenderer::setConstantBuffers(UInt startSlot, UInt slotCount, Buffer*const* buffers, const UInt* offsets)
@@ -718,10 +817,10 @@ void GLRenderer::dispatchCompute(int x, int y, int z)
BindingState* GLRenderer::createBindingState(const ShaderInputLayout& layout)
{
- BindingStateImpl* rs = new BindingStateImpl;
+ BindingStateImpl* state = new BindingStateImpl(this);
for (auto & entry : layout.entries)
{
- BindingEntryImpl rsEntry;
+ BindingEntry rsEntry;
rsEntry.isOutput = entry.isOutput;
rsEntry.binding = entry.glslBinding;
rsEntry.type = entry.type;
@@ -740,15 +839,15 @@ BindingState* GLRenderer::createBindingState(const ShaderInputLayout& layout)
createInputSampler(rsEntry, entry.samplerDesc);
break;
}
- rs->entries.Add(rsEntry);
+ state->m_entries.Add(rsEntry);
}
- return (BindingState*)rs;
+ return state;
}
void GLRenderer::setBindingState(BindingState* stateIn)
{
- BindingStateImpl* state = (BindingStateImpl*)stateIn;
- for (auto & entry : state->entries)
+ BindingStateImpl* state = static_cast<BindingStateImpl*>(stateIn);
+ for (auto & entry : state->m_entries)
{
switch (entry.type)
{
@@ -773,7 +872,7 @@ void GLRenderer::serializeOutput(BindingState* stateIn, const char* fileName)
BindingStateImpl * state = (BindingStateImpl*)stateIn;
FILE * f;
fopen_s(&f, fileName, "wt");
- for (auto & entry : state->entries)
+ for (auto & entry : state->m_entries)
{
if (entry.isOutput)
{
@@ -837,7 +936,7 @@ ShaderProgram* GLRenderer::compileProgram(const ShaderCompileRequest& request)
return nullptr;
}
- return (ShaderProgram*)(uintptr_t)programID;
+ return new ShaderProgramImpl(this, programID);
}
diff --git a/tools/render-test/render-vk.cpp b/tools/render-test/render-vk.cpp
index ff22c91ea..bb177a88a 100644
--- a/tools/render-test/render-vk.cpp
+++ b/tools/render-test/render-vk.cpp
@@ -4,6 +4,8 @@
#include "options.h"
#include "render.h"
+#include "../../source/core/smart-pointer.h"
+
#ifdef _WIN32
#define VK_USE_PLATFORM_WIN32_KHR 1
#endif
@@ -75,6 +77,7 @@
namespace renderer_test {
+using namespace Slang;
#define RETURN_ON_VK_FAIL(x) { VkResult _vkRes = x; if (_vkRes != VK_SUCCESS) { SLANG_RETURN_ON_FAIL(toSlangResult(_vkRes)); }}
@@ -108,20 +111,45 @@ public:
protected:
- struct BufferImpl
+ class BufferImpl: public Buffer
{
- VkBuffer buffer;
- VkDeviceMemory memory;
+ public:
+
+ BufferImpl(VKRenderer* renderer, VkBuffer buffer, VkDeviceMemory memory):
+ m_renderer(renderer),
+ m_buffer(buffer),
+ m_memory(memory)
+ {
+ assert(renderer);
+ }
+
+ ~BufferImpl()
+ {
+ // Now destroy the staging buffer
+ if (m_renderer)
+ {
+ m_renderer->vkDestroyBuffer(m_renderer->m_device, m_buffer, nullptr);
+ m_renderer->vkFreeMemory(m_renderer->m_device, m_memory, nullptr);
+ }
+ }
+
+ VKRenderer* m_renderer;
+ VkBuffer m_buffer;
+ VkDeviceMemory m_memory;
};
- struct ShaderProgramImpl
+ class ShaderProgramImpl: public ShaderProgram
{
- VkPipelineShaderStageCreateInfo compute;
- VkPipelineShaderStageCreateInfo vertex;
- VkPipelineShaderStageCreateInfo fragment;
+ public:
+
+ VkPipelineShaderStageCreateInfo m_compute;
+ VkPipelineShaderStageCreateInfo m_vertex;
+ VkPipelineShaderStageCreateInfo m_fragment;
+
+ List<char> m_buffers[2]; //< To keep storage of code in scope
};
- struct BindingImpl
+ struct Binding
{
ShaderInputType type;
InputBufferType bufferType; // Only valid if `type` is `Buffer`
@@ -136,19 +164,28 @@ public:
int bufferLength = 0;
};
- struct BindingStateImpl
+ class BindingStateImpl: public BindingState
{
- Slang::List<BindingImpl> bindings;
- int numRenderTargets;
+ public:
+ BindingStateImpl(VKRenderer* renderer):
+ m_renderer(renderer),
+ m_numRenderTargets(0)
+ {
+ }
+
+ VKRenderer* m_renderer;
+ List<Binding> m_bindings;
+ int m_numRenderTargets;
};
- struct InputLayoutImpl
+ class InputLayoutImpl: public InputLayout
{
+ public:
};
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, const void* initData = nullptr);
+ BufferImpl* createBufferImpl(size_t bufferSize, VkBufferUsageFlags usage, VkMemoryPropertyFlags reqMemoryProperties, const void* initData = nullptr);
VkCommandBuffer getCommandBuffer();
VkCommandBuffer beginCommandBuffer();
@@ -156,7 +193,7 @@ public:
uint32_t getMemoryTypeIndex(uint32_t inTypeBits, VkMemoryPropertyFlags properties);
- VkPipelineShaderStageCreateInfo compileEntryPoint(const ShaderCompileRequest::EntryPoint& entryPointRequest, VkShaderStageFlagBits stage);
+ VkPipelineShaderStageCreateInfo compileEntryPoint(const ShaderCompileRequest::EntryPoint& entryPointRequest, VkShaderStageFlagBits stage, List<char>& bufferOut);
void createInputTexture(const InputTextureDesc& inputDesc, VkImageView& viewOut);
void createInputSampler(const InputSamplerDesc& inputDesc, VkSampler& stateOut);
@@ -179,8 +216,8 @@ public:
VkSubmitInfo m_submitInfo;
VkDebugReportCallbackEXT m_debugReportCallback;
- BindingStateImpl* m_currentBindingState = nullptr;
- ShaderProgramImpl* m_currentProgram = nullptr;
+ RefPtr<BindingStateImpl> m_currentBindingState;
+ RefPtr<ShaderProgramImpl> m_currentProgram;
float m_clearColor[4] = { 0, 0, 0, 0 };;
@@ -276,7 +313,7 @@ void VKRenderer::flushCommandBuffer(VkCommandBuffer commandBuffer)
vkFreeCommandBuffers(m_device, m_commandPool, 1, &commandBuffer);
}
-VKRenderer::BufferImpl VKRenderer::createBufferImpl(size_t bufferSize, VkBufferUsageFlags usage, VkMemoryPropertyFlags reqMemoryProperties, const void* initData)
+VKRenderer::BufferImpl* VKRenderer::createBufferImpl(size_t bufferSize, VkBufferUsageFlags usage, VkMemoryPropertyFlags reqMemoryProperties, const void* initData)
{
if (initData)
{
@@ -313,33 +350,26 @@ VKRenderer::BufferImpl VKRenderer::createBufferImpl(size_t bufferSize, VkBufferU
// used for the buffer doesn't let us fill things in
// directly.
- BufferImpl staging = createBufferImpl(bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
+ RefPtr<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(m_device, staging.memory, 0, bufferSize, 0, &mappedData));
+ checkResult(vkMapMemory(m_device, staging->m_memory, 0, bufferSize, 0, &mappedData));
memcpy(mappedData, initData, bufferSize);
- vkUnmapMemory(m_device, staging.memory);
+ vkUnmapMemory(m_device, staging->m_memory);
// Copy from staging buffer to real buffer
VkCommandBuffer commandBuffer = beginCommandBuffer();
VkBufferCopy copyInfo = {};
copyInfo.size = bufferSize;
- vkCmdCopyBuffer(commandBuffer, staging.buffer, buffer, 1, &copyInfo);
+ vkCmdCopyBuffer(commandBuffer, staging->m_buffer, buffer, 1, &copyInfo);
flushCommandBuffer(commandBuffer);
-
- // Now destroy the staging buffer
- vkDestroyBuffer(m_device, staging.buffer, nullptr);
- vkFreeMemory(m_device, staging.memory, nullptr);
}
- BufferImpl impl;
- impl.buffer = buffer;
- impl.memory = memory;
- return impl;
+ return new BufferImpl(this, buffer, memory);
}
uint32_t VKRenderer::getMemoryTypeIndex(uint32_t inTypeBits, VkMemoryPropertyFlags properties)
@@ -401,12 +431,13 @@ void VKRenderer::createInputBuffer(const ShaderInputLayoutEntry& entry, const In
usage |= VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
}
- BufferImpl bufferImpl = createBufferImpl(bufferSize, usage, reqMemoryProperties, initData);
+ RefPtr<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;
+ // Set the m_renderer to null to stop any destruction as bufferImpl leaves scope
+ bufferImpl->m_renderer = nullptr;
+ bufferOut = bufferImpl->m_buffer;
// Fill in any views needed
switch (bufferDesc.type)
@@ -421,7 +452,7 @@ void VKRenderer::createInputBuffer(const ShaderInputLayoutEntry& entry, const In
}
}
-VkPipelineShaderStageCreateInfo VKRenderer::compileEntryPoint(const ShaderCompileRequest::EntryPoint& entryPointRequest, VkShaderStageFlagBits stage)
+VkPipelineShaderStageCreateInfo VKRenderer::compileEntryPoint(const ShaderCompileRequest::EntryPoint& entryPointRequest, VkShaderStageFlagBits stage, List<char>& bufferOut)
{
char const* dataBegin = entryPointRequest.source.dataBegin;
char const* dataEnd = entryPointRequest.source.dataEnd;
@@ -429,9 +460,11 @@ VkPipelineShaderStageCreateInfo VKRenderer::compileEntryPoint(const ShaderCompil
// 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);
+ bufferOut.InsertRange(0, dataBegin, codeSize);
+
+ char* codeBegin = bufferOut.Buffer();
+
VkShaderModuleCreateInfo moduleCreateInfo = { VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO };
moduleCreateInfo.pCode = (uint32_t*)codeBegin;
moduleCreateInfo.codeSize = codeSize;
@@ -661,15 +694,7 @@ Buffer* VKRenderer::createBuffer(const BufferDesc& desc)
break;
}
- BufferImpl bufferImpl = createBufferImpl(
- bufferSize,
- usage,
- reqMemoryProperties,
- desc.initData);
-
- BufferImpl* bufferPtr = new BufferImpl();
- *bufferPtr = bufferImpl;
- return (Buffer*)bufferPtr;
+ return createBufferImpl(bufferSize, usage, reqMemoryProperties, desc.initData);
}
InputLayout* VKRenderer::createInputLayout(const InputElementDesc* inputElements, UInt inputElementCount)
@@ -717,11 +742,11 @@ void VKRenderer::draw(UInt vertexCount, UInt startVertex = 0)
BindingState* VKRenderer::createBindingState(const ShaderInputLayout& layout)
{
- BindingStateImpl* bindingState = new BindingStateImpl;
- bindingState->numRenderTargets = layout.numRenderTargets;
+ BindingStateImpl* bindingState = new BindingStateImpl(this);
+ bindingState->m_numRenderTargets = layout.numRenderTargets;
for (auto & entry : layout.entries)
{
- BindingImpl binding;
+ Binding binding;
binding.type = entry.type;
binding.binding = entry.hlslBinding;
binding.isOutput = entry.isOutput;
@@ -750,24 +775,24 @@ BindingState* VKRenderer::createBindingState(const ShaderInputLayout& layout)
break;
}
}
- bindingState->bindings.Add(binding);
+ bindingState->m_bindings.Add(binding);
}
- return (BindingState*)bindingState;
+ return bindingState;
}
void VKRenderer::setBindingState(BindingState* state)
{
- m_currentBindingState = (BindingStateImpl*)state;
+ m_currentBindingState = static_cast<BindingStateImpl*>(state);
}
void VKRenderer::serializeOutput(BindingState* s, const char* fileName)
{
- auto state = (BindingStateImpl*)s;
+ auto state = static_cast<BindingStateImpl*>(s);
FILE * f = fopen(fileName, "wb");
int id = 0;
- for (auto& bb : state->bindings)
+ for (auto& bb : state->m_bindings)
{
if (bb.isOutput)
{
@@ -775,31 +800,27 @@ void VKRenderer::serializeOutput(BindingState* s, const char* fileName)
{
// 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);
+ RefPtr<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);
+ vkCmdCopyBuffer(commandBuffer, bb.buffer, staging->m_buffer, 1, &copyInfo);
flushCommandBuffer(commandBuffer);
// Write out the data from the buffer
void* mappedData = nullptr;
- checkResult(vkMapMemory(m_device, staging.memory, 0, bufferSize, 0, &mappedData));
+ checkResult(vkMapMemory(m_device, staging->m_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(m_device, staging.memory);
-
- // Now destroy the staging buffer
- vkDestroyBuffer(m_device, staging.buffer, nullptr);
- vkFreeMemory(m_device, staging.memory, nullptr);
+ vkUnmapMemory(m_device, staging->m_memory);
}
else
{
@@ -819,7 +840,7 @@ void VKRenderer::dispatchCompute(int x, int y, int z)
Slang::List<VkDescriptorSetLayoutBinding> bindings;
- for (auto bb : m_currentBindingState->bindings)
+ for (auto bb : m_currentBindingState->m_bindings)
{
switch (bb.type)
{
@@ -887,7 +908,7 @@ void VKRenderer::dispatchCompute(int x, int y, int z)
checkResult(vkAllocateDescriptorSets(m_device, &descriptorSetAllocInfo, &descriptorSet));
// Fill in the descritpor set, using our binding information
- for (auto bb : m_currentBindingState->bindings)
+ for (auto bb : m_currentBindingState->m_bindings)
{
switch (bb.type)
{
@@ -939,7 +960,7 @@ void VKRenderer::dispatchCompute(int x, int y, int z)
// Then create a pipeline to use that layout
VkComputePipelineCreateInfo computePipelineInfo = { VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO };
- computePipelineInfo.stage = m_currentProgram->compute;
+ computePipelineInfo.stage = m_currentProgram->m_compute;
computePipelineInfo.layout = pipelineLayout;
VkPipelineCache pipelineCache = 0;
@@ -977,14 +998,14 @@ ShaderProgram* VKRenderer::compileProgram(const ShaderCompileRequest & request)
ShaderProgramImpl* impl = new ShaderProgramImpl;
if (request.computeShader.name)
{
- impl->compute = compileEntryPoint(request.computeShader, VK_SHADER_STAGE_COMPUTE_BIT);
+ impl->m_compute = compileEntryPoint(request.computeShader, VK_SHADER_STAGE_COMPUTE_BIT, impl->m_buffers[0]);
}
else
{
- impl->vertex = compileEntryPoint(request.vertexShader, VK_SHADER_STAGE_VERTEX_BIT);
- impl->fragment = compileEntryPoint(request.fragmentShader, VK_SHADER_STAGE_FRAGMENT_BIT);
+ impl->m_vertex = compileEntryPoint(request.vertexShader, VK_SHADER_STAGE_VERTEX_BIT, impl->m_buffers[0]);
+ impl->m_fragment = compileEntryPoint(request.fragmentShader, VK_SHADER_STAGE_FRAGMENT_BIT, impl->m_buffers[1]);
}
- return (ShaderProgram*)impl;
+ return impl;
}
} // renderer_test
diff --git a/tools/render-test/render.h b/tools/render-test/render.h
index 08d364b05..7484f0f3d 100644
--- a/tools/render-test/render.h
+++ b/tools/render-test/render.h
@@ -6,14 +6,29 @@
#include "shader-input-layout.h"
#include "../../source/core/slang-result.h"
+#include "../../source/core/smart-pointer.h"
namespace renderer_test {
// Declare opaque type
-struct Buffer;
-struct InputLayout;
-struct ShaderProgram;
-struct BindingState;
+class Buffer: public Slang::RefObject
+{
+ public:
+};
+class InputLayout: public Slang::RefObject
+{
+ public:
+};
+
+class ShaderProgram: public Slang::RefObject
+{
+ public:
+};
+
+class BindingState: public Slang::RefObject
+{
+ public:
+};
struct ShaderCompileRequest
{
@@ -91,7 +106,7 @@ enum class PrimitiveTopology
TriangleList,
};
-class Renderer
+class Renderer: public Slang::RefObject
{
public:
virtual SlangResult initialize(void* inWindowHandle) = 0;