diff options
| author | jsmall-nvidia <jsmall@nvidia.com> | 2018-03-26 15:34:01 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-03-26 15:34:01 -0400 |
| commit | 74bf38b36d9074a83a53d3baf885d8886c0b3752 (patch) | |
| tree | 31ed26ba7057c7165f33ea24b164cde10c17a0ef /tools/render-test/main.cpp | |
| parent | 5000d27d993d9ac33ef80482eb44235298d5177e (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
Diffstat (limited to 'tools/render-test/main.cpp')
| -rw-r--r-- | tools/render-test/main.cpp | 302 |
1 files changed, 160 insertions, 142 deletions
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(); } } |
