summaryrefslogtreecommitdiffstats
path: root/tools/render-test
diff options
context:
space:
mode:
authorjsmall-nvidia <jsmall@nvidia.com>2018-05-03 18:42:13 -0400
committerTim Foley <tfoleyNV@users.noreply.github.com>2018-05-03 15:42:13 -0700
commitf8472940229e8582ec9f941069fc9576bd09b94c (patch)
tree9b387a65abc42094e7a1e0687b793cb0fc5c5eaa /tools/render-test
parentc216f00f1eaff368229cb8430422972fcac801b7 (diff)
Added Surface type - as a simple value type to hold a 2d collection of pixels. (#548)
Added PngSerializeUtil allows currently for just writing Surface of RGBA format. Removes dependency on stbi_image except for in PngSerializeUtil. Removed use of gWindowWidth/Height globals - pass the height into initialize or Renderer.
Diffstat (limited to 'tools/render-test')
-rw-r--r--tools/render-test/main.cpp13
-rw-r--r--tools/render-test/options.h4
-rw-r--r--tools/render-test/png-serialize-util.cpp38
-rw-r--r--tools/render-test/png-serialize-util.h14
-rw-r--r--tools/render-test/render-d3d11.cpp39
-rw-r--r--tools/render-test/render-d3d12.cpp66
-rw-r--r--tools/render-test/render-gl.cpp59
-rw-r--r--tools/render-test/render-test.vcxproj4
-rw-r--r--tools/render-test/render-test.vcxproj.filters12
-rw-r--r--tools/render-test/render-vk.cpp8
-rw-r--r--tools/render-test/render.h7
-rw-r--r--tools/render-test/surface.cpp191
-rw-r--r--tools/render-test/surface.h83
13 files changed, 423 insertions, 115 deletions
diff --git a/tools/render-test/main.cpp b/tools/render-test/main.cpp
index 7dcb9af95..df9220b58 100644
--- a/tools/render-test/main.cpp
+++ b/tools/render-test/main.cpp
@@ -430,7 +430,11 @@ SlangResult innerMain(int argc, char** argv)
return SLANG_FAIL;
}
- SLANG_RETURN_ON_FAIL(renderer->initialize(windowHandle));
+ Renderer::Desc desc;
+ desc.width = gWindowWidth;
+ desc.height = gWindowHeight;
+
+ SLANG_RETURN_ON_FAIL(renderer->initialize(desc, windowHandle));
auto shaderCompiler = renderer->getShaderCompiler();
switch (gOptions.inputLanguageID)
@@ -500,7 +504,12 @@ SlangResult innerMain(int argc, char** argv)
}
else
{
- SLANG_RETURN_ON_FAIL(renderer->captureScreenShot(gOptions.outputPath));
+ Result res = renderer->captureScreenShot(gOptions.outputPath);
+ if (SLANG_FAILED(res))
+ {
+ fprintf(stderr, "ERROR: failed to write screen capture to file\n");
+ return res;
+ }
}
return SLANG_OK;
}
diff --git a/tools/render-test/options.h b/tools/render-test/options.h
index 56bd638ef..630c30d8a 100644
--- a/tools/render-test/options.h
+++ b/tools/render-test/options.h
@@ -51,10 +51,6 @@ struct Options
extern Options gOptions;
-extern int gWindowWidth;
-extern int gWindowHeight;
-
-
SlangResult parseOptions(int* argc, char** argv);
} // renderer_test
diff --git a/tools/render-test/png-serialize-util.cpp b/tools/render-test/png-serialize-util.cpp
new file mode 100644
index 000000000..a7f6aa83a
--- /dev/null
+++ b/tools/render-test/png-serialize-util.cpp
@@ -0,0 +1,38 @@
+// png-serialize-util.cpp
+#define _CRT_SECURE_NO_WARNINGS
+
+#include "png-serialize-util.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#define STB_IMAGE_WRITE_IMPLEMENTATION
+#include "external/stb/stb_image_write.h"
+
+namespace renderer_test {
+using namespace Slang;
+
+/* static */Slang::Result PngSerializeUtil::write(const char* filename, const Surface& surface)
+{
+ int numComps = 0;
+ switch (surface.m_format)
+ {
+ case Format::RGBA_Unorm_UInt8:
+ {
+ numComps = 4;
+ break;
+ }
+ default: break;
+ }
+
+ if (numComps <= 0)
+ {
+ return SLANG_FAIL;
+ }
+
+ int stbResult = stbi_write_png(filename, surface.m_width, surface.m_height, numComps, surface.m_data, surface.m_rowStrideInBytes);
+
+ return stbResult ? SLANG_OK : SLANG_FAIL;
+}
+
+} // renderer_test
diff --git a/tools/render-test/png-serialize-util.h b/tools/render-test/png-serialize-util.h
new file mode 100644
index 000000000..fe3b4f873
--- /dev/null
+++ b/tools/render-test/png-serialize-util.h
@@ -0,0 +1,14 @@
+// png-serialize-util.h
+#pragma once
+
+#include "surface.h"
+
+namespace renderer_test {
+
+struct PngSerializeUtil
+{
+ static Slang::Result write(const char* filename, const Surface& surface);
+
+};
+
+} // renderer_test
diff --git a/tools/render-test/render-d3d11.cpp b/tools/render-test/render-d3d11.cpp
index e2bcf1659..96835f313 100644
--- a/tools/render-test/render-d3d11.cpp
+++ b/tools/render-test/render-d3d11.cpp
@@ -1,4 +1,7 @@
// render-d3d11.cpp
+
+#define _CRT_SECURE_NO_WARNINGS
+
#include "render-d3d11.h"
#include "options.h"
@@ -11,11 +14,7 @@
#include "../../source/core/slang-com-ptr.h"
-#ifdef _MSC_VER
-#pragma warning(disable: 4996)
-#endif
-#define STB_IMAGE_WRITE_IMPLEMENTATION
-#include "external/stb/stb_image_write.h"
+#include "png-serialize-util.h"
// We will be rendering with Direct3D 11, so we need to include
// the Windows and D3D11 headers
@@ -47,7 +46,7 @@ class D3D11Renderer : public Renderer, public ShaderCompiler
{
public:
// Renderer implementation
- virtual SlangResult initialize(void* inWindowHandle) override;
+ virtual SlangResult initialize(const Desc& desc, void* inWindowHandle) override;
virtual void setClearColor(const float color[4]) override;
virtual void clearFrame() override;
virtual void presentFrame() override;
@@ -156,6 +155,8 @@ public:
RefPtr<BindingStateImpl> m_currentBindings;
+ Desc m_desc;
+
float m_clearColor[4] = { 0, 0, 0, 0 };
};
@@ -215,26 +216,22 @@ Renderer* createD3D11Renderer()
return hr;
}
- int stbResult = stbi_write_png(outputPath, textureDesc.Width, textureDesc.Height, 4,
- mappedResource.pData, mappedResource.RowPitch);
+ Surface surface;
+ surface.setUnowned(textureDesc.Width, textureDesc.Height, Format::RGBA_Unorm_UInt8, mappedResource.RowPitch, mappedResource.pData);
+
+ Result res = PngSerializeUtil::write(outputPath, surface);
// Make sure to unmap
context->Unmap(stagingTexture, 0);
-
- if (!stbResult)
- {
- fprintf(stderr, "ERROR: failed to write texture to file\n");
- return E_UNEXPECTED;
- }
-
- return S_OK;
+ return res;
}
// !!!!!!!!!!!!!!!!!!!!!!!!!!!! Renderer interface !!!!!!!!!!!!!!!!!!!!!!!!!!
-SlangResult D3D11Renderer::initialize(void* inWindowHandle)
+SlangResult D3D11Renderer::initialize(const Desc& desc, void* inWindowHandle)
{
auto windowHandle = (HWND)inWindowHandle;
+ m_desc = desc;
// Rather than statically link against D3D, we load it dynamically.
HMODULE d3dModule = LoadLibraryA("d3d11.dll");
@@ -287,8 +284,8 @@ SlangResult D3D11Renderer::initialize(void* inWindowHandle)
D3D_FEATURE_LEVEL_9_1,
};
D3D_FEATURE_LEVEL featureLevel = D3D_FEATURE_LEVEL_9_1;
- const int totalNumFeatureLevels = sizeof(featureLevels) / sizeof(featureLevels[0]);
-
+ const int totalNumFeatureLevels = SLANG_COUNT_OF(featureLevels);
+
// On a machine that does not have an up-to-date version of D3D installed,
// the `D3D11CreateDeviceAndSwapChain` call will fail with `E_INVALIDARG`
// if you ask for featuer level 11_1. The workaround is to call
@@ -360,8 +357,8 @@ SlangResult D3D11Renderer::initialize(void* inWindowHandle)
D3D11_VIEWPORT viewport;
viewport.TopLeftX = 0;
viewport.TopLeftY = 0;
- viewport.Width = (float)gWindowWidth;
- viewport.Height = (float)gWindowHeight;
+ viewport.Width = (float)desc.width;
+ viewport.Height = (float)desc.height;
viewport.MaxDepth = 1; // TODO(tfoley): use reversed depth
viewport.MinDepth = 0;
m_immediateContext->RSSetViewports(1, &viewport);
diff --git a/tools/render-test/render-d3d12.cpp b/tools/render-test/render-d3d12.cpp
index 635c6739f..d1b547f2d 100644
--- a/tools/render-test/render-d3d12.cpp
+++ b/tools/render-test/render-d3d12.cpp
@@ -1,4 +1,6 @@
// render-d3d12.cpp
+#define _CRT_SECURE_NO_WARNINGS
+
#include "render-d3d12.h"
#include "options.h"
@@ -23,19 +25,14 @@
#include "../../source/core/slang-com-ptr.h"
+#include "png-serialize-util.h"
+
#include "resource-d3d12.h"
#include "descriptor-heap-d3d12.h"
#include "circular-resource-heap-d3d12.h"
#include "d3d-util.h"
-#ifdef _MSC_VER
-#pragma warning(disable: 4996)
-#endif
-
-//#define STB_IMAGE_WRITE_IMPLEMENTATION
-#include "external/stb/stb_image_write.h"
-
// We will use the C standard library just for printing error messages.
#include <stdio.h>
@@ -56,7 +53,7 @@ class D3D12Renderer : public Renderer, public ShaderCompiler
{
public:
// Renderer implementation
- virtual SlangResult initialize(void* inWindowHandle) override;
+ virtual SlangResult initialize(const Desc& desc, void* inWindowHandle) override;
virtual void setClearColor(const float color[4]) override;
virtual void clearFrame() override;
virtual void presentFrame() override;
@@ -367,9 +364,8 @@ protected:
int m_numTargetSamples = 1; ///< The number of multi sample samples
int m_targetSampleQuality = 0; ///< The multi sample quality
- int m_windowWidth = 0;
- int m_windowHeight = 0;
-
+ Desc m_desc;
+
bool m_isInitialized = false;
D3D12_PRIMITIVE_TOPOLOGY_TYPE m_primitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
@@ -790,7 +786,6 @@ Result D3D12Renderer::captureTextureToFile(D3D12Resource& resource, const char*
// Submit the copy, and wait for copy to complete
submitGpuWorkAndWait();
- int stbResult = 0;
{
ID3D12Resource* dxResource = stagingResource;
@@ -799,17 +794,13 @@ Result D3D12Renderer::captureTextureToFile(D3D12Resource& resource, const char*
SLANG_RETURN_ON_FAIL(dxResource->Map(0, &readRange, reinterpret_cast<void**>(&data)));
- stbResult = stbi_write_png(outputPath, int(desc.Width), int(desc.Height), 4, data, int(rowPitch));
-
- dxResource->Unmap(0, nullptr);
- }
+ Surface surface;
+ surface.setUnowned(int(desc.Width), int(desc.Height), Format::RGBA_Unorm_UInt8, int(rowPitch), data);
+ Result res = PngSerializeUtil::write(outputPath, surface);
- if (!stbResult)
- {
- fprintf(stderr, "ERROR: failed to write texture to file\n");
- return SLANG_FAIL;
+ dxResource->Unmap(0, nullptr);
+ return res;
}
- return SLANG_OK;
}
Result D3D12Renderer::calcComputePipelineState(ComPtr<ID3D12RootSignature>& signatureOut, ComPtr<ID3D12PipelineState>& pipelineStateOut)
@@ -1259,7 +1250,7 @@ Result D3D12Renderer::_bindRenderState(RenderState* renderState, ID3D12GraphicsC
// !!!!!!!!!!!!!!!!!!!!!!!!!!!! Renderer interface !!!!!!!!!!!!!!!!!!!!!!!!!!
-Result D3D12Renderer::initialize(void* inWindowHandle)
+Result D3D12Renderer::initialize(const Desc& desc, void* inWindowHandle)
{
m_hwnd = (HWND)inWindowHandle;
// Rather than statically link against D3D, we load it dynamically.
@@ -1372,13 +1363,12 @@ Result D3D12Renderer::initialize(void* inWindowHandle)
m_numRenderFrames = 3;
m_numRenderTargets = 2;
- m_windowWidth = gWindowWidth;
- m_windowHeight = gWindowHeight;
-
+ m_desc = desc;
+
// set viewport
{
- m_viewport.Width = float(m_windowWidth);
- m_viewport.Height = float(m_windowHeight);
+ m_viewport.Width = float(m_desc.width);
+ m_viewport.Height = float(m_desc.height);
m_viewport.MinDepth = 0;
m_viewport.MaxDepth = 1;
m_viewport.TopLeftX = 0;
@@ -1388,8 +1378,8 @@ Result D3D12Renderer::initialize(void* inWindowHandle)
{
m_scissorRect.left = 0;
m_scissorRect.top = 0;
- m_scissorRect.right = m_windowWidth;
- m_scissorRect.bottom = m_windowHeight;
+ m_scissorRect.right = m_desc.width;
+ m_scissorRect.bottom = m_desc.height;
}
// Describe and create the command queue.
@@ -1402,8 +1392,8 @@ Result D3D12Renderer::initialize(void* inWindowHandle)
// Describe the swap chain.
DXGI_SWAP_CHAIN_DESC swapChainDesc = {};
swapChainDesc.BufferCount = m_numRenderTargets;
- swapChainDesc.BufferDesc.Width = m_windowWidth;
- swapChainDesc.BufferDesc.Height = m_windowHeight;
+ swapChainDesc.BufferDesc.Width = m_desc.width;
+ swapChainDesc.BufferDesc.Height = m_desc.height;
swapChainDesc.BufferDesc.Format = m_targetFormat;
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
@@ -1571,7 +1561,7 @@ Result D3D12Renderer::createFrameResources()
{
D3D12_RESOURCE_DESC desc = m_backBuffers[0]->getResource()->GetDesc();
- assert(desc.Width == UINT64(m_windowWidth) && desc.Height == UINT64(m_windowHeight));
+ assert(desc.Width == UINT64(m_desc.width) && desc.Height == UINT64(m_desc.height));
}
// Create the depth stencil view.
@@ -1598,8 +1588,8 @@ Result D3D12Renderer::createFrameResources()
D3D12_RESOURCE_DESC resourceDesc = {};
resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
resourceDesc.Format = resourceFormat;
- resourceDesc.Width = m_windowWidth;
- resourceDesc.Height = m_windowHeight;
+ resourceDesc.Width = m_desc.width;
+ resourceDesc.Height = m_desc.height;
resourceDesc.DepthOrArraySize = 1;
resourceDesc.MipLevels = 1;
resourceDesc.SampleDesc.Count = m_numTargetSamples;
@@ -1621,12 +1611,12 @@ Result D3D12Renderer::createFrameResources()
m_depthStencilView = m_dsvHeap->GetCPUDescriptorHandleForHeapStart();
}
- m_viewport.Width = static_cast<float>(m_windowWidth);
- m_viewport.Height = static_cast<float>(m_windowHeight);
+ m_viewport.Width = static_cast<float>(m_desc.width);
+ m_viewport.Height = static_cast<float>(m_desc.height);
m_viewport.MaxDepth = 1.0f;
- m_scissorRect.right = static_cast<LONG>(m_windowWidth);
- m_scissorRect.bottom = static_cast<LONG>(m_windowHeight);
+ m_scissorRect.right = static_cast<LONG>(m_desc.width);
+ m_scissorRect.bottom = static_cast<LONG>(m_desc.height);
return SLANG_OK;
}
diff --git a/tools/render-test/render-gl.cpp b/tools/render-test/render-gl.cpp
index b079d3f10..cef482798 100644
--- a/tools/render-test/render-gl.cpp
+++ b/tools/render-test/render-gl.cpp
@@ -11,6 +11,9 @@
#include "core/secure-crt.h"
#include "external/stb/stb_image_write.h"
+#include "surface.h"
+#include "png-serialize-util.h"
+
// TODO(tfoley): eventually we should be able to run these
// tests on non-Windows targets to confirm that cross-compilation
// at least *works* on those platforms...
@@ -78,7 +81,7 @@ class GLRenderer : public Renderer, public ShaderCompiler
public:
// Renderer implementation
- virtual SlangResult initialize(void* inWindowHandle) override;
+ virtual SlangResult initialize(const Desc& desc, void* inWindowHandle) override;
virtual void setClearColor(const float color[4]) override;
virtual void clearFrame() override;
virtual void presentFrame() override;
@@ -276,6 +279,8 @@ public:
UInt m_boundVertexStreamStrides[kMaxVertexStreams];
UInt m_boundVertexStreamOffsets[kMaxVertexStreams];
+ Desc m_desc;
+
// Declare a function pointer for each OpenGL
// extension function we need to load
#define DECLARE_GL_EXTENSION_FUNC(NAME, TYPE) TYPE NAME;
@@ -520,9 +525,10 @@ void GLRenderer::destroyBindingEntries(const BindingState::Desc& desc, const Bin
// !!!!!!!!!!!!!!!!!!!!!!!!!!!! Renderer interface !!!!!!!!!!!!!!!!!!!!!!!!!!
-SlangResult GLRenderer::initialize(void* inWindowHandle)
+SlangResult GLRenderer::initialize(const Desc& desc, void* inWindowHandle)
{
auto windowHandle = (HWND)inWindowHandle;
+ m_desc = desc;
m_hdc = ::GetDC(windowHandle);
@@ -553,7 +559,7 @@ SlangResult GLRenderer::initialize(void* inWindowHandle)
glDisable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
- glViewport(0, 0, gWindowWidth, gWindowHeight);
+ glViewport(0, 0, desc.width, desc.height);
if (glDebugMessageCallback)
{
@@ -582,48 +588,11 @@ void GLRenderer::presentFrame()
SlangResult GLRenderer::captureScreenShot(const char* outputPath)
{
- int width = gWindowWidth;
- int height = gWindowHeight;
-
- int components = 4;
- int rowStride = width*components;
-
- GLubyte* buffer = (GLubyte*)::malloc(components * width * height);
-
- glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
-
- // OpenGL's "upside down" convention bites us here, so we need
- // to flip the data in the buffer by swapping rows
- int halfHeight = height / 2;
- for (int hh = 0; hh < halfHeight; ++hh)
- {
- // Get a pointer to the row data, and a pointer
- // to the row on the "other end" of the image
- GLubyte* rowA = buffer + rowStride*hh;
- GLubyte* rowB = buffer + rowStride*(height - (hh + 1));
-
- for (int ii = 0; ii < rowStride; ++ii)
- {
- auto a = rowA[ii];
- auto b = rowB[ii];
-
- rowA[ii] = b;
- rowB[ii] = a;
- }
- }
-
- //
- int stbResult = stbi_write_png(outputPath, width, height, components, buffer, rowStride);
-
- ::free(buffer);
-
- if (!stbResult)
- {
- assert(!"unexpected");
- return SLANG_FAIL;
- }
-
- return SLANG_OK;
+ Surface surface;
+ surface.allocate(m_desc.width, m_desc.height, Format::RGBA_Unorm_UInt8, 1, SurfaceAllocator::getMallocAllocator());
+ glReadPixels(0, 0, m_desc.width, m_desc.height, GL_RGBA, GL_UNSIGNED_BYTE, surface.m_data);
+ surface.flipInplaceVertically();
+ return PngSerializeUtil::write(outputPath, surface);
}
ShaderCompiler* GLRenderer::getShaderCompiler()
diff --git a/tools/render-test/render-test.vcxproj b/tools/render-test/render-test.vcxproj
index 3fecb6879..9889ba979 100644
--- a/tools/render-test/render-test.vcxproj
+++ b/tools/render-test/render-test.vcxproj
@@ -171,6 +171,7 @@
<ClCompile Include="descriptor-heap-d3d12.cpp" />
<ClCompile Include="main.cpp" />
<ClCompile Include="options.cpp" />
+ <ClCompile Include="png-serialize-util.cpp" />
<ClCompile Include="render-d3d11.cpp" />
<ClCompile Include="render-d3d12.cpp" />
<ClCompile Include="render-gl.cpp" />
@@ -180,6 +181,7 @@
<ClCompile Include="shader-input-layout.cpp" />
<ClCompile Include="shader-renderer-util.cpp" />
<ClCompile Include="slang-support.cpp" />
+ <ClCompile Include="surface.cpp" />
<ClCompile Include="vk-api.cpp" />
<ClCompile Include="vk-device-queue.cpp" />
<ClCompile Include="vk-module.cpp" />
@@ -191,6 +193,7 @@
<ClInclude Include="d3d-util.h" />
<ClInclude Include="descriptor-heap-d3d12.h" />
<ClInclude Include="options.h" />
+ <ClInclude Include="png-serialize-util.h" />
<ClInclude Include="render-d3d11.h" />
<ClInclude Include="render-d3d12.h" />
<ClInclude Include="render-gl.h" />
@@ -200,6 +203,7 @@
<ClInclude Include="shader-input-layout.h" />
<ClInclude Include="shader-renderer-util.h" />
<ClInclude Include="slang-support.h" />
+ <ClInclude Include="surface.h" />
<ClInclude Include="vk-api.h" />
<ClInclude Include="vk-device-queue.h" />
<ClInclude Include="vk-module.h" />
diff --git a/tools/render-test/render-test.vcxproj.filters b/tools/render-test/render-test.vcxproj.filters
index 2bbf03af2..a8453035b 100644
--- a/tools/render-test/render-test.vcxproj.filters
+++ b/tools/render-test/render-test.vcxproj.filters
@@ -72,6 +72,12 @@
<ClCompile Include="vk-util.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="surface.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="png-serialize-util.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="options.h">
@@ -131,5 +137,11 @@
<ClInclude Include="vk-util.h">
<Filter>Source Files</Filter>
</ClInclude>
+ <ClInclude Include="surface.h">
+ <Filter>Source Files</Filter>
+ </ClInclude>
+ <ClInclude Include="png-serialize-util.h">
+ <Filter>Source Files</Filter>
+ </ClInclude>
</ItemGroup>
</Project> \ No newline at end of file
diff --git a/tools/render-test/render-vk.cpp b/tools/render-test/render-vk.cpp
index 9999d1e82..8ffb05c99 100644
--- a/tools/render-test/render-vk.cpp
+++ b/tools/render-test/render-vk.cpp
@@ -33,7 +33,7 @@ public:
enum { kMaxRenderTargets = 8, kMaxAttachments = kMaxRenderTargets + 1 };
// Renderer implementation
- virtual SlangResult initialize(void* inWindowHandle) override;
+ virtual SlangResult initialize(const Desc& desc, void* inWindowHandle) override;
virtual void setClearColor(const float color[4]) override;
virtual void clearFrame() override;
virtual void presentFrame() override;
@@ -254,6 +254,8 @@ public:
int m_swapChainImageIndex = -1;
float m_clearColor[4] = { 0, 0, 0, 0 };
+
+ Desc m_desc;
};
/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! VkRenderer::Buffer !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
@@ -774,11 +776,13 @@ VkPipelineShaderStageCreateInfo VKRenderer::compileEntryPoint(const ShaderCompil
// !!!!!!!!!!!!!!!!!!!!!!!!!!!! Renderer interface !!!!!!!!!!!!!!!!!!!!!!!!!!
-SlangResult VKRenderer::initialize(void* inWindowHandle)
+SlangResult VKRenderer::initialize(const Desc& desc, void* inWindowHandle)
{
SLANG_RETURN_ON_FAIL(m_module.init());
SLANG_RETURN_ON_FAIL(m_api.initGlobalProcs(m_module));
+ m_desc = desc;
+
VkApplicationInfo applicationInfo = { VK_STRUCTURE_TYPE_APPLICATION_INFO };
applicationInfo.pApplicationName = "slang-render-test";
applicationInfo.pEngineName = "slang-render-test";
diff --git a/tools/render-test/render.h b/tools/render-test/render.h
index d4385979a..ba76f795d 100644
--- a/tools/render-test/render.h
+++ b/tools/render-test/render.h
@@ -534,12 +534,13 @@ class Renderer: public Slang::RefObject
{
public:
- struct Info
+ struct Desc
{
- ProjectionStyle m_projectionStyle;
+ int width; ///< Width in pixels
+ int height; ///< height in pixels
};
- virtual SlangResult initialize(void* inWindowHandle) = 0;
+ virtual SlangResult initialize(const Desc& desc, void* inWindowHandle) = 0;
virtual void setClearColor(const float color[4]) = 0;
virtual void clearFrame() = 0;
diff --git a/tools/render-test/surface.cpp b/tools/render-test/surface.cpp
new file mode 100644
index 000000000..3f96052ce
--- /dev/null
+++ b/tools/render-test/surface.cpp
@@ -0,0 +1,191 @@
+// surface.cpp
+#include "surface.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "../../source/core/list.h"
+
+namespace renderer_test {
+using namespace Slang;
+
+class MallocSurfaceAllocator: public SurfaceAllocator
+{
+ public:
+
+ virtual Slang::Result allocate(int width, int height, Format format, int alignment, Surface& surface) override;
+ virtual void deallocate(Surface& surface) override;
+};
+
+static MallocSurfaceAllocator s_mallocSurfaceAllocator;
+
+/// Get the malloc allocator
+/* static */SurfaceAllocator* SurfaceAllocator::getMallocAllocator()
+{
+ return &s_mallocSurfaceAllocator;
+}
+
+Slang::Result MallocSurfaceAllocator::allocate(int width, int height, Format format, int alignment, Surface& surface)
+{
+ assert(surface.m_data == nullptr);
+
+ // Calculate row size
+
+ const int rowSizeInBytes = Surface::calcRowSize(format, width);
+ const int numRows = Surface::calcNumRows(format, height);
+
+ alignment = (alignment <= 0) ? int(sizeof(void*)) : alignment;
+ // It must be a power of 2
+ assert( ((alignment - 1) & alignment) == 0);
+
+ // Align rowSize
+ const int alignedRowSizeInBytes = (rowSizeInBytes + alignment - 1) & -alignment;
+
+ size_t totalSize = numRows * alignedRowSizeInBytes;
+
+ uint8_t* data = (uint8_t*)::malloc(totalSize);
+ if (!data)
+ {
+ return SLANG_E_MEM_OUT_OF_MEMORY;
+ }
+
+ surface.m_data = data;
+ surface.m_width = width;
+ surface.m_height = height;
+ surface.m_format = format;
+ surface.m_numRows = numRows;
+ surface.m_rowStrideInBytes = alignedRowSizeInBytes;
+
+ surface.m_allocator = this;
+ return SLANG_OK;
+}
+
+void MallocSurfaceAllocator::deallocate(Surface& surface)
+{
+ assert(surface.m_data);
+ // Make sure it's not an inverted, cos otherwise m_data is not the start address
+ assert(surface.m_rowStrideInBytes > 0);
+ ::free(surface.m_data);
+}
+
+// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Surface !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+/* static */int Surface::calcRowSize(Format format, int width)
+{
+ size_t pixelSize = RendererUtil::getFormatSize(format);
+ if (pixelSize == 0)
+ {
+ return 0;
+ }
+ return int(pixelSize * width);
+}
+
+/* static */int Surface::calcNumRows(Format format, int height)
+{
+ // Don't have any compressed types, so number of rows is same as the height
+ return height;
+}
+
+void Surface::init()
+{
+ m_width = 0;
+ m_height = 0;
+ m_format = Format::Unknown;
+ m_data = nullptr;
+ m_numRows = 0;
+ m_rowStrideInBytes = 0;
+ // NOTE! does not clear the allocator.
+ // If called with an allocation memory will leak!
+}
+
+Surface::~Surface()
+{
+ if (m_data && m_allocator)
+ {
+ m_allocator->deallocate(*this);
+ }
+}
+
+void Surface::deallocate()
+{
+ if (m_data && m_allocator)
+ {
+ m_allocator->deallocate(*this);
+ init();
+ }
+}
+
+Result Surface::allocate(int width, int height, Format format, int alignment, SurfaceAllocator* allocator)
+{
+ deallocate();
+ allocator = allocator ? allocator : m_allocator;
+ if (!allocator)
+ {
+ // An allocator needs to be set on the surface, or one passed in.
+ return SLANG_FAIL;
+ }
+ return allocator->allocate(width, height, format, alignment, *this);
+}
+
+void Surface::setUnowned(int width, int height, Format format, int strideInBytes, void* data)
+{
+ deallocate();
+
+ // This is unowned
+ m_allocator = nullptr;
+
+ m_width = width;
+ m_height = height;
+ m_format = format;
+ m_rowStrideInBytes = strideInBytes;
+ m_data = (uint8_t*)data;
+
+ m_numRows = Surface::calcNumRows(format, height);
+
+ const int rowSizeInBytes = Surface::calcRowSize(format, width);
+ assert((strideInBytes > 0 && rowSizeInBytes <= strideInBytes) || (strideInBytes < 0 && rowSizeInBytes <= -strideInBytes));
+}
+
+void Surface::zeroContents()
+{
+ const int rowSizeInBytes = Surface::calcRowSize(m_format, m_width);
+
+ const int stride = m_rowStrideInBytes;
+ uint8_t* dst = m_data;
+
+ for (int i = 0; i < m_numRows; i++, dst += stride)
+ {
+ ::memset(dst, 0, rowSizeInBytes);
+ }
+}
+
+void Surface::flipInplaceVertically()
+{
+ // Can only flip when m_height matches number of rows
+ assert(m_numRows == m_height);
+
+ const int rowSizeInBytes = Surface::calcRowSize(m_format, m_width);
+ if (rowSizeInBytes <= 0 || m_numRows <= 1)
+ {
+ return;
+ }
+
+ uint8_t* top = m_data;
+ uint8_t* bottom = m_data + (m_numRows - 1) * m_rowStrideInBytes;
+
+ List<uint8_t> bufferList;
+ bufferList.SetSize(rowSizeInBytes);
+ uint8_t* buffer = bufferList.Buffer();
+
+ const int stride = m_rowStrideInBytes;
+
+ const int num = m_height >> 1;
+ for (int i = 0; i < num; ++i, top += stride, bottom -= stride)
+ {
+ ::memcpy(buffer, top, rowSizeInBytes);
+ ::memcpy(top, bottom, rowSizeInBytes);
+ ::memcpy(bottom, buffer, rowSizeInBytes);
+ }
+}
+
+} // renderer_test
diff --git a/tools/render-test/surface.h b/tools/render-test/surface.h
new file mode 100644
index 000000000..f5f67efc0
--- /dev/null
+++ b/tools/render-test/surface.h
@@ -0,0 +1,83 @@
+// surface.h
+#pragma once
+
+#include "render.h"
+
+namespace renderer_test {
+
+class Surface;
+
+class SurfaceAllocator
+{
+ public:
+ virtual Slang::Result allocate(int width, int height, Format format, int alignment, Surface& surface) = 0;
+ virtual void deallocate(Surface& surface) = 0;
+
+ /// Get the malloc allocator
+ static SurfaceAllocator* getMallocAllocator();
+};
+
+class Surface
+{
+ public:
+
+ enum
+ {
+ kDefaultAlignment = sizeof(void*)
+ };
+
+ /// Allocate
+ Slang::Result allocate(int width, int height, Format format, int alignment = kDefaultAlignment, SurfaceAllocator* allocator = nullptr);
+
+ /// Deallocate contents
+ void deallocate();
+ /// Initialize contents (zero sized, no data). Note that the allocator pointer is left as is
+ void init();
+
+ /// Set unowned
+ void setUnowned(int width, int height, Format format, int strideInBytes, void* data);
+
+ template <typename T>
+ T* calcNextRow(T* ptr) const { return (T*)calcNextRow((void*)ptr); }
+ template <typename T>
+ const T* calcNextRow(const T* ptr) const { return (const T*)calcNextRow((const void*)ptr); }
+
+ void* calcNextRow(void* ptr) const { return (void*)(((uint8_t*)ptr) + m_rowStrideInBytes); }
+ const void* calcNextRow(const void* ptr) const { return (const void*)(((const uint8_t*)ptr) + m_rowStrideInBytes); }
+
+ /// Writes zero to all of the contents
+ void zeroContents();
+
+ /// Flips the contents vertically in place
+ void flipInplaceVertically();
+
+ /// True if has some contents
+ bool hasContents() const { return m_data != nullptr; }
+
+ /// Ctor
+ Surface() :
+ m_allocator(nullptr)
+ {
+ init();
+ }
+ /// Dtor
+ ~Surface();
+
+ /// Get the size of the row in bytes
+ static int calcRowSize(Format format, int width);
+ /// Calculates the number of rows
+ static int calcNumRows(Format format, int height);
+
+ int m_width;
+ int m_height;
+ Format m_format;
+
+ uint8_t* m_data; /// The data that makes up the image. If nullptr, has no data. Pointer to first 'row' of the image.
+
+ int m_numRows; ///< Total amount of rows (typically same as height, but in compressed formats may be less)
+ int m_rowStrideInBytes; ///< The number of bytes between rows
+
+ SurfaceAllocator* m_allocator; ///< Can be null if so contents is 'unowned', if set
+};
+
+} // renderer_test