summaryrefslogtreecommitdiffstats
path: root/tools/render-test/main.cpp
diff options
context:
space:
mode:
authorjsmall-nvidia <jsmall@nvidia.com>2019-01-07 09:14:01 -0500
committerGitHub <noreply@github.com>2019-01-07 09:14:01 -0500
commitd155eaa92d56a4ec00109d25c8c70fe12fb96c2e (patch)
tree55355d0aa67f99727f520ee3b210c27a647a12a9 /tools/render-test/main.cpp
parentefa2c8f41aa5cd2c27990fd9b57ea0eff06976e7 (diff)
Feature/unique tool source names (#766)
* Remove AppContext. Use StdChannels to hold writers, and TestToolUtil to hold test tool specific functionality. * StdChannels -> StdWriters * getStdOut -> getOut, getStdError -> getError * Renamed main.cpp files of tools to try and stop visual studio getting confused between files - such that clicking on an error takes editor to the right location.
Diffstat (limited to 'tools/render-test/main.cpp')
-rw-r--r--tools/render-test/main.cpp679
1 files changed, 0 insertions, 679 deletions
diff --git a/tools/render-test/main.cpp b/tools/render-test/main.cpp
deleted file mode 100644
index 69874ac04..000000000
--- a/tools/render-test/main.cpp
+++ /dev/null
@@ -1,679 +0,0 @@
-// main.cpp
-
-#include "options.h"
-#include "render.h"
-#include "render-d3d11.h"
-#include "render-d3d12.h"
-#include "render-gl.h"
-#include "render-vk.h"
-
-#include "slang-support.h"
-#include "surface.h"
-#include "png-serialize-util.h"
-
-#include "shader-renderer-util.h"
-
-#include "shader-input-layout.h"
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "../../source/core/slang-test-tool-util.h"
-
-#define WIN32_LEAN_AND_MEAN
-#define NOMINMAX
-#include <Windows.h>
-#undef WIN32_LEAN_AND_MEAN
-#undef NOMINMAX
-
-#ifdef _MSC_VER
-#pragma warning(disable: 4996)
-#endif
-
-namespace renderer_test {
-
-using Slang::Result;
-
-int gWindowWidth = 1024;
-int gWindowHeight = 768;
-
-class Window: public RefObject
-{
-public:
- SlangResult initialize(int width, int height);
-
- void show();
-
- void* getHandle() const { return m_hwnd; }
-
- Window() {}
- ~Window();
-
- static LRESULT CALLBACK windowProc(HWND windowHandle,
- UINT message,
- WPARAM wParam,
- LPARAM lParam);
-
-protected:
-
- HINSTANCE m_hinst = nullptr;
- HWND m_hwnd = nullptr;
-};
-
-//
-// We use a bare-minimum window procedure to get things up and running.
-//
-
-/* static */LRESULT CALLBACK Window::windowProc(
- HWND windowHandle,
- UINT message,
- WPARAM wParam,
- LPARAM lParam)
-{
- switch (message)
- {
- case WM_CLOSE:
- PostQuitMessage(0);
- return 0;
- }
-
- return DefWindowProcW(windowHandle, message, wParam, lParam);
-}
-
-static ATOM _getWindowClassAtom(HINSTANCE hinst)
-{
- static ATOM s_windowClassAtom;
-
- if (s_windowClassAtom)
- {
- return s_windowClassAtom;
- }
- WNDCLASSEXW windowClassDesc;
- windowClassDesc.cbSize = sizeof(windowClassDesc);
- windowClassDesc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
- windowClassDesc.lpfnWndProc = &Window::windowProc;
- windowClassDesc.cbClsExtra = 0;
- windowClassDesc.cbWndExtra = 0;
- windowClassDesc.hInstance = hinst;
- windowClassDesc.hIcon = 0;
- windowClassDesc.hCursor = 0;
- windowClassDesc.hbrBackground = 0;
- windowClassDesc.lpszMenuName = 0;
- windowClassDesc.lpszClassName = L"SlangRenderTest";
- windowClassDesc.hIconSm = 0;
- s_windowClassAtom = RegisterClassExW(&windowClassDesc);
-
- return s_windowClassAtom;
-}
-
-SlangResult Window::initialize(int widthIn, int heightIn)
-{
- // Do initial window-creation stuff here, rather than in the renderer-specific files
-
- m_hinst = GetModuleHandleA(0);
-
- // First we register a window class.
- ATOM windowClassAtom = _getWindowClassAtom(m_hinst);
- if (!windowClassAtom)
- {
- fprintf(stderr, "error: failed to register window class\n");
- return SLANG_FAIL;
- }
-
- // Next, we create a window using that window class.
-
- // We will create a borderless window since our screen-capture logic in GL
- // seems to get thrown off by having to deal with a window frame.
- DWORD windowStyle = WS_POPUP;
- DWORD windowExtendedStyle = 0;
-
- RECT windowRect = { 0, 0, widthIn, heightIn };
- AdjustWindowRectEx(&windowRect, windowStyle, /*hasMenu=*/false, windowExtendedStyle);
-
- {
- auto width = windowRect.right - windowRect.left;
- auto height = windowRect.bottom - windowRect.top;
-
- LPWSTR windowName = L"Slang Render Test";
- m_hwnd = CreateWindowExW(
- windowExtendedStyle,
- (LPWSTR)windowClassAtom,
- windowName,
- windowStyle,
- 0, 0, // x, y
- width, height,
- NULL, // parent
- NULL, // menu
- m_hinst,
- NULL);
- }
- if (!m_hwnd)
- {
- fprintf(stderr, "error: failed to create window\n");
- return SLANG_FAIL;
- }
-
- return SLANG_OK;
-}
-
-
-void Window::show()
-{
- // Once initialization is all complete, we show the window...
- int showCommand = SW_SHOW;
- ShowWindow(m_hwnd, showCommand);
-}
-
-Window::~Window()
-{
- if (m_hwnd)
- {
- DestroyWindow(m_hwnd);
- }
-}
-
-//
-// For the purposes of a small example, we will define the vertex data for a
-// single triangle directly in the source file. It should be easy to extend
-// this example to load data from an external source, if desired.
-//
-
-struct Vertex
-{
- float position[3];
- float color[3];
- float uv[2];
-};
-
-static const Vertex kVertexData[] =
-{
- { { 0, 0, 0.5 }, {1, 0, 0} , {0, 0} },
- { { 0, 1, 0.5 }, {0, 0, 1} , {1, 0} },
- { { 1, 0, 0.5 }, {0, 1, 0} , {1, 1} },
-};
-static const int kVertexCount = SLANG_COUNT_OF(kVertexData);
-
-using namespace Slang;
-
-class RenderTestApp
-{
- public:
-
- // 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();
-
- BindingStateImpl* getBindingState() const { return m_bindingState; }
-
- Result writeBindingOutput(const char* fileName);
-
- Result writeScreen(const char* filename);
-
- protected:
- /// Called in initialize
- Result initializeShaders(ShaderCompiler* shaderCompiler);
-
- // variables for state to be used for rendering...
- uintptr_t m_constantBufferSize, m_computeResultBufferSize;
-
- RefPtr<Renderer> m_renderer;
-
- RefPtr<BufferResource> m_constantBuffer;
- RefPtr<InputLayout> m_inputLayout;
- RefPtr<BufferResource> m_vertexBuffer;
- RefPtr<ShaderProgram> m_shaderProgram;
- RefPtr<PipelineState> m_pipelineState;
- RefPtr<BindingStateImpl> m_bindingState;
-
- ShaderInputLayout m_shaderInputLayout; ///< The binding layout
- int m_numAddedConstantBuffers; ///< Constant buffers can be added to the binding directly. Will be added at the end.
-};
-
-// Entry point name to use for vertex/fragment shader
-static const char vertexEntryPointName[] = "vertexMain";
-static const char fragmentEntryPointName[] = "fragmentMain";
-static const char computeEntryPointName[] = "computeMain";
-
-SlangResult RenderTestApp::initialize(Renderer* renderer, ShaderCompiler* shaderCompiler)
-{
- SLANG_RETURN_ON_FAIL(initializeShaders(shaderCompiler));
-
- m_numAddedConstantBuffers = 0;
- m_renderer = renderer;
-
- // TODO(tfoley): use each API's reflection interface to query the constant-buffer size needed
- {
- m_constantBufferSize = 16 * sizeof(float);
-
- BufferResource::Desc constantBufferDesc;
- constantBufferDesc.init(m_constantBufferSize);
- constantBufferDesc.cpuAccessFlags = Resource::AccessFlag::Write;
-
- m_constantBuffer = renderer->createBufferResource(Resource::Usage::ConstantBuffer, constantBufferDesc);
- if (!m_constantBuffer)
- return SLANG_FAIL;
- }
-
- {
- //! Hack -> if doing a graphics test, add an extra binding for our dynamic constant buffer
- //
- // TODO: Should probably be more sophisticated than this - with 'dynamic' constant buffer/s binding always being specified
- // in the test file
- RefPtr<BufferResource> addedConstantBuffer;
- switch(gOptions.shaderType)
- {
- default:
- break;
-
- case Options::ShaderProgramType::Graphics:
- case Options::ShaderProgramType::GraphicsCompute:
- addedConstantBuffer = m_constantBuffer;
- m_numAddedConstantBuffers++;
- break;
- }
-
- BindingStateImpl* bindingState = nullptr;
- SLANG_RETURN_ON_FAIL(ShaderRendererUtil::createBindingState(m_shaderInputLayout, m_renderer, addedConstantBuffer, &bindingState));
- m_bindingState = bindingState;
- }
-
- // Do other initialization that doesn't depend on the source language.
-
- // Input Assembler (IA)
-
- const InputElementDesc inputElements[] = {
- { "A", 0, Format::RGB_Float32, offsetof(Vertex, position) },
- { "A", 1, Format::RGB_Float32, offsetof(Vertex, color) },
- { "A", 2, Format::RG_Float32, offsetof(Vertex, uv) },
- };
-
- m_inputLayout = renderer->createInputLayout(inputElements, SLANG_COUNT_OF(inputElements));
- if(!m_inputLayout)
- return SLANG_FAIL;
-
- BufferResource::Desc vertexBufferDesc;
- vertexBufferDesc.init(kVertexCount * sizeof(Vertex));
-
- m_vertexBuffer = renderer->createBufferResource(Resource::Usage::VertexBuffer, vertexBufferDesc, kVertexData);
- if(!m_vertexBuffer)
- return SLANG_FAIL;
-
- {
- switch(gOptions.shaderType)
- {
- default:
- assert(!"unexpected test shader type");
- return SLANG_FAIL;
-
- case Options::ShaderProgramType::Compute:
- {
- ComputePipelineStateDesc desc;
- desc.pipelineLayout = m_bindingState->pipelineLayout;
- desc.program = m_shaderProgram;
-
- m_pipelineState = renderer->createComputePipelineState(desc);
- }
- break;
-
- case Options::ShaderProgramType::Graphics:
- case Options::ShaderProgramType::GraphicsCompute:
- {
- GraphicsPipelineStateDesc desc;
- desc.pipelineLayout = m_bindingState->pipelineLayout;
- desc.program = m_shaderProgram;
- desc.inputLayout = m_inputLayout;
- desc.renderTargetCount = m_bindingState->m_numRenderTargets;
-
- m_pipelineState = renderer->createGraphicsPipelineState(desc);
- }
- break;
- }
- }
-
- return SLANG_OK;
-}
-
-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);
-
- List<char> sourceText;
- sourceText.SetSize(sourceSize + 1);
- fread(sourceText.Buffer(), sourceSize, 1, sourceFile);
- fclose(sourceFile);
- sourceText[sourceSize] = 0;
-
- switch( gOptions.shaderType )
- {
- default:
- m_shaderInputLayout.numRenderTargets = 1;
- break;
-
- case Options::ShaderProgramType::Compute:
- m_shaderInputLayout.numRenderTargets = 0;
- break;
- }
- m_shaderInputLayout.Parse(sourceText.Buffer());
-
- ShaderCompileRequest::SourceInfo sourceInfo;
- sourceInfo.path = sourcePath;
- sourceInfo.dataBegin = sourceText.Buffer();
- sourceInfo.dataEnd = sourceText.Buffer() + sourceSize;
-
- ShaderCompileRequest compileRequest;
- compileRequest.source = sourceInfo;
- if (gOptions.shaderType == Options::ShaderProgramType::Graphics || gOptions.shaderType == Options::ShaderProgramType::GraphicsCompute)
- {
- compileRequest.vertexShader.source = sourceInfo;
- compileRequest.vertexShader.name = vertexEntryPointName;
- compileRequest.fragmentShader.source = sourceInfo;
- compileRequest.fragmentShader.name = fragmentEntryPointName;
- }
- else
- {
- compileRequest.computeShader.source = sourceInfo;
- compileRequest.computeShader.name = computeEntryPointName;
- }
- compileRequest.entryPointTypeArguments = m_shaderInputLayout.globalTypeArguments;
- m_shaderProgram = shaderCompiler->compileProgram(compileRequest);
- if (!m_shaderProgram)
- {
- return SLANG_FAIL;
- }
-
- return SLANG_OK;
-}
-
-void RenderTestApp::renderFrame()
-{
- auto mappedData = m_renderer->map(m_constantBuffer, MapFlavor::WriteDiscard);
- if(mappedData)
- {
- const ProjectionStyle projectionStyle = RendererUtil::getProjectionStyle(m_renderer->getRendererType());
- RendererUtil::getIdentityProjection(projectionStyle, (float*)mappedData);
-
- m_renderer->unmap(m_constantBuffer);
- }
-
- auto pipelineType = PipelineType::Graphics;
-
- m_renderer->setPipelineState(pipelineType, m_pipelineState);
-
- m_renderer->setPrimitiveTopology(PrimitiveTopology::TriangleList);
- m_renderer->setVertexBuffer(0, m_vertexBuffer, sizeof(Vertex));
-
- m_bindingState->apply(m_renderer, pipelineType);
-
- m_renderer->draw(3);
-}
-
-void RenderTestApp::runCompute()
-{
- auto pipelineType = PipelineType::Compute;
- m_renderer->setPipelineState(pipelineType, m_pipelineState);
- m_bindingState->apply(m_renderer, pipelineType);
- m_renderer->dispatchCompute(1, 1, 1);
-}
-
-void RenderTestApp::finalize()
-{
-}
-
-Result RenderTestApp::writeBindingOutput(const char* fileName)
-{
- // Submit the work
- m_renderer->submitGpuWork();
- // Wait until everything is complete
- m_renderer->waitForGpu();
-
- FILE * f = fopen(fileName, "wb");
- if (!f)
- {
- return SLANG_FAIL;
- }
-
- for(auto binding : m_bindingState->outputBindings)
- {
- auto i = binding.entryIndex;
- const auto& layoutBinding = m_shaderInputLayout.entries[i];
-
- assert(layoutBinding.isOutput);
- {
- if (binding.resource && binding.resource->isBuffer())
- {
- BufferResource* bufferResource = static_cast<BufferResource*>(binding.resource.Ptr());
- const size_t bufferSize = bufferResource->getDesc().sizeInBytes;
-
- unsigned int* ptr = (unsigned int*)m_renderer->map(bufferResource, MapFlavor::HostRead);
- if (!ptr)
- {
- fclose(f);
- return SLANG_FAIL;
- }
-
- const int size = int(bufferSize / sizeof(unsigned int));
- for (int i = 0; i < size; ++i)
- {
- fprintf(f, "%X\n", ptr[i]);
- }
- m_renderer->unmap(bufferResource);
- }
- else
- {
- printf("invalid output type at %d.\n", int(i));
- }
- }
- }
- fclose(f);
-
- return SLANG_OK;
-}
-
-
-Result RenderTestApp::writeScreen(const char* filename)
-{
- Surface surface;
- SLANG_RETURN_ON_FAIL(m_renderer->captureScreenSurface(surface));
- return PngSerializeUtil::write(filename, surface);
-}
-
-} // namespace renderer_test
-
-SLANG_TEST_TOOL_API SlangResult innerMain(Slang::StdWriters* stdWriters, SlangSession* session, int argcIn, const char*const* argvIn)
-{
- using namespace renderer_test;
- using namespace Slang;
-
- StdWriters::setSingleton(stdWriters);
-
- // Parse command-line options
- SLANG_RETURN_ON_FAIL(parseOptions(argcIn, argvIn, StdWriters::getError()));
-
- RefPtr<renderer_test::Window> window(new renderer_test::Window);
- SLANG_RETURN_ON_FAIL(window->initialize(gWindowWidth, gWindowHeight));
-
- Slang::RefPtr<Renderer> renderer;
-
- SlangSourceLanguage nativeLanguage = SLANG_SOURCE_LANGUAGE_UNKNOWN;
- SlangCompileTarget slangTarget = SLANG_TARGET_NONE;
- SlangPassThrough slangPassThrough = SLANG_PASS_THROUGH_NONE;
- char const* profileName = "";
- switch (gOptions.rendererType)
- {
- case RendererType::DirectX11:
- renderer = createD3D11Renderer();
- slangTarget = SLANG_DXBC;
- nativeLanguage = SLANG_SOURCE_LANGUAGE_HLSL;
- slangPassThrough = SLANG_PASS_THROUGH_FXC;
- profileName = "sm_5_0";
- break;
-
- case RendererType::DirectX12:
- renderer = createD3D12Renderer();
- slangTarget = SLANG_DXBC;
- nativeLanguage = SLANG_SOURCE_LANGUAGE_HLSL;
- slangPassThrough = SLANG_PASS_THROUGH_FXC;
- profileName = "sm_5_0";
- if( gOptions.useDXIL )
- {
- slangTarget = SLANG_DXIL;
- slangPassThrough = SLANG_PASS_THROUGH_DXC;
- profileName = "sm_6_0";
- }
- break;
-
- case RendererType::OpenGl:
- renderer = createGLRenderer();
- slangTarget = SLANG_GLSL;
- nativeLanguage = SLANG_SOURCE_LANGUAGE_GLSL;
- slangPassThrough = SLANG_PASS_THROUGH_GLSLANG;
- profileName = "glsl_430";
- break;
-
- case RendererType::Vulkan:
- renderer = createVKRenderer();
- slangTarget = SLANG_SPIRV;
- nativeLanguage = SLANG_SOURCE_LANGUAGE_GLSL;
- slangPassThrough = SLANG_PASS_THROUGH_GLSLANG;
- profileName = "glsl_430";
- break;
-
- default:
- fprintf(stderr, "error: unexpected\n");
- return SLANG_FAIL;
- }
-
- if (!renderer)
- {
- fprintf(stderr, "Unable to create renderer\n");
- return SLANG_FAIL;
- }
-
- Renderer::Desc desc;
- desc.width = gWindowWidth;
- desc.height = gWindowHeight;
-
- {
- SlangResult res = renderer->initialize(desc, (HWND)window->getHandle());
- if (SLANG_FAILED(res))
- {
- fprintf(stderr, "Unable to initialize renderer\n");
- return res;
- }
- }
-
- ShaderCompiler shaderCompiler;
- shaderCompiler.renderer = renderer;
- shaderCompiler.target = slangTarget;
- shaderCompiler.profile = profileName;
- shaderCompiler.slangSession = session;
-
- switch (gOptions.inputLanguageID)
- {
- case Options::InputLanguageID::Slang:
- shaderCompiler.sourceLanguage = SLANG_SOURCE_LANGUAGE_SLANG;
- shaderCompiler.passThrough = SLANG_PASS_THROUGH_NONE;
- break;
-
- case Options::InputLanguageID::Native:
- shaderCompiler.sourceLanguage = nativeLanguage;
- shaderCompiler.passThrough = slangPassThrough;
- break;
-
- default:
- break;
- }
-
- {
- RenderTestApp app;
-
- SLANG_RETURN_ON_FAIL(app.initialize(renderer, &shaderCompiler));
-
- window->show();
-
- // ... and enter the event loop:
- for (;;)
- {
- MSG message;
-
- int result = PeekMessageW(&message, NULL, 0, 0, PM_REMOVE);
- if (result != 0)
- {
- if (message.message == WM_QUIT)
- {
- return (int)message.wParam;
- }
-
- TranslateMessage(&message);
- DispatchMessageW(&message);
- }
- else
- {
- // Whenever we don't have Windows events to process, we render a frame.
- if (gOptions.shaderType == Options::ShaderProgramType::Compute)
- {
- app.runCompute();
- }
- else
- {
- 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)
- {
- // Submit the work
- renderer->submitGpuWork();
- // Wait until everything is complete
- renderer->waitForGpu();
-
- if (gOptions.shaderType == Options::ShaderProgramType::Compute || gOptions.shaderType == Options::ShaderProgramType::GraphicsCompute)
- {
- SLANG_RETURN_ON_FAIL(app.writeBindingOutput(gOptions.outputPath));
- }
- else
- {
- SlangResult res = app.writeScreen(gOptions.outputPath);
-
- if (SLANG_FAILED(res))
- {
- fprintf(stderr, "ERROR: failed to write screen capture to file\n");
- return res;
- }
- }
- return SLANG_OK;
- }
-
- renderer->presentFrame();
- }
- }
- }
-
- return SLANG_OK;
-}
-
-
-int main(int argc, char** argv)
-{
- SlangSession* session = spCreateSession(nullptr);
- SlangResult res = innerMain(Slang::StdWriters::initDefault(), session, argc, argv);
- spDestroySession(session);
-
- return SLANG_FAILED(res) ? 1 : 0;
-}
-