summaryrefslogtreecommitdiffstats
path: root/tools/render-test
diff options
context:
space:
mode:
authorjsmall-nvidia <jsmall@nvidia.com>2018-05-04 12:00:53 -0400
committerTim Foley <tfoleyNV@users.noreply.github.com>2018-05-04 09:00:53 -0700
commitee47232fc17f31ef2bd95ca480372216a79def56 (patch)
tree75d1fdd76e2ed4e081699aaae8b6df819f181260 /tools/render-test
parent494330d4941ccaf50e07ef309fd783c2f44a492e (diff)
Use Surface for screen capture in Renderer interface (#551)
* Remove serialization of screen captures from a renderer implementation, capture now writes to a Surface. Then client code can decide to serialize (or use as needed). * Improved comment for captureScreenSurface.
Diffstat (limited to 'tools/render-test')
-rw-r--r--tools/render-test/main.cpp15
-rw-r--r--tools/render-test/render-d3d11.cpp42
-rw-r--r--tools/render-test/render-d3d12.cpp18
-rw-r--r--tools/render-test/render-gl.cpp14
-rw-r--r--tools/render-test/render-vk.cpp4
-rw-r--r--tools/render-test/render.h6
-rw-r--r--tools/render-test/surface.cpp31
-rw-r--r--tools/render-test/surface.h3
8 files changed, 83 insertions, 50 deletions
diff --git a/tools/render-test/main.cpp b/tools/render-test/main.cpp
index df9220b58..adcad42a7 100644
--- a/tools/render-test/main.cpp
+++ b/tools/render-test/main.cpp
@@ -8,6 +8,8 @@
#include "render-vk.h"
#include "slang-support.h"
+#include "surface.h"
+#include "png-serialize-util.h"
#include "shader-renderer-util.h"
@@ -68,6 +70,8 @@ class RenderTestApp
Result writeBindingOutput(const char* fileName);
+ Result writeScreen(const char* filename);
+
protected:
/// Called in initialize
Result initializeShaders(ShaderCompiler* shaderCompiler);
@@ -312,6 +316,14 @@ Result RenderTestApp::writeBindingOutput(const char* fileName)
return SLANG_OK;
}
+
+Result RenderTestApp::writeScreen(const char* filename)
+{
+ Surface surface;
+ SLANG_RETURN_ON_FAIL(m_renderer->captureScreenSurface(surface));
+ return PngSerializeUtil::write(filename, surface);
+}
+
//
// We use a bare-minimum window procedure to get things up and running.
//
@@ -504,7 +516,8 @@ SlangResult innerMain(int argc, char** argv)
}
else
{
- Result res = renderer->captureScreenShot(gOptions.outputPath);
+ Result res = app.writeScreen(gOptions.outputPath);
+
if (SLANG_FAILED(res))
{
fprintf(stderr, "ERROR: failed to write screen capture to file\n");
diff --git a/tools/render-test/render-d3d11.cpp b/tools/render-test/render-d3d11.cpp
index 96835f313..9523d37cd 100644
--- a/tools/render-test/render-d3d11.cpp
+++ b/tools/render-test/render-d3d11.cpp
@@ -8,14 +8,14 @@
#include "render.h"
#include "d3d-util.h"
+#include "surface.h"
+
// In order to use the Slang API, we need to include its header
#include <slang.h>
#include "../../source/core/slang-com-ptr.h"
-#include "png-serialize-util.h"
-
// We will be rendering with Direct3D 11, so we need to include
// the Windows and D3D11 headers
@@ -52,7 +52,7 @@ public:
virtual void presentFrame() override;
virtual TextureResource* createTextureResource(Resource::Type type, Resource::Usage initialUsage, const TextureResource::Desc& desc, const TextureResource::Data* initData) override;
virtual BufferResource* createBufferResource(Resource::Usage initialUsage, const BufferResource::Desc& bufferDesc, const void* initData) override;
- virtual SlangResult captureScreenShot(char const* outputPath) override;
+ virtual SlangResult captureScreenSurface(Surface& surfaceOut) override;
virtual InputLayout* createInputLayout( const InputElementDesc* inputElements, UInt inputElementCount) override;
virtual BindingState* createBindingState(const BindingState::Desc& desc) override;
virtual ShaderCompiler* getShaderCompiler() override;
@@ -141,7 +141,7 @@ public:
};
/// Capture a texture to a file
- static HRESULT captureTextureToFile(ID3D11Device* device, ID3D11DeviceContext* context, ID3D11Texture2D* texture, char const* outputPath);
+ static HRESULT captureTextureToSurface(ID3D11Device* device, ID3D11DeviceContext* context, ID3D11Texture2D* texture, Surface& surfaceOut);
void _applyBindingState(bool isCompute);
@@ -165,8 +165,7 @@ Renderer* createD3D11Renderer()
return new D3D11Renderer();
}
-/* static */HRESULT D3D11Renderer::captureTextureToFile(ID3D11Device* device, ID3D11DeviceContext* context,
- ID3D11Texture2D* texture, char const* outputPath)
+/* static */HRESULT D3D11Renderer::captureTextureToSurface(ID3D11Device* device, ID3D11DeviceContext* context, ID3D11Texture2D* texture, Surface& surfaceOut)
{
if (!context) return E_INVALIDARG;
if (!texture) return E_INVALIDARG;
@@ -207,23 +206,16 @@ Renderer* createD3D11Renderer()
}
// Now just read back texels from the staging textures
-
- D3D11_MAPPED_SUBRESOURCE mappedResource;
- hr = context->Map(stagingTexture, 0, D3D11_MAP_READ, 0, &mappedResource);
- if (FAILED(hr))
{
- fprintf(stderr, "ERROR: failed to map texture for read\n");
- return hr;
- }
-
- Surface surface;
- surface.setUnowned(textureDesc.Width, textureDesc.Height, Format::RGBA_Unorm_UInt8, mappedResource.RowPitch, mappedResource.pData);
+ D3D11_MAPPED_SUBRESOURCE mappedResource;
+ SLANG_RETURN_ON_FAIL(context->Map(stagingTexture, 0, D3D11_MAP_READ, 0, &mappedResource));
- Result res = PngSerializeUtil::write(outputPath, surface);
+ Result res = surfaceOut.set(textureDesc.Width, textureDesc.Height, Format::RGBA_Unorm_UInt8, mappedResource.RowPitch, mappedResource.pData, SurfaceAllocator::getMallocAllocator());
- // Make sure to unmap
- context->Unmap(stagingTexture, 0);
- return res;
+ // Make sure to unmap
+ context->Unmap(stagingTexture, 0);
+ return res;
+ }
}
// !!!!!!!!!!!!!!!!!!!!!!!!!!!! Renderer interface !!!!!!!!!!!!!!!!!!!!!!!!!!
@@ -385,15 +377,9 @@ void D3D11Renderer::presentFrame()
m_swapChain->Present(0, 0);
}
-SlangResult D3D11Renderer::captureScreenShot(const char* outputPath)
+SlangResult D3D11Renderer::captureScreenSurface(Surface& surfaceOut)
{
- HRESULT hr = captureTextureToFile(m_device, m_immediateContext, m_renderTargetTextures[0], outputPath);
- if (FAILED(hr))
- {
- fprintf(stderr, "error: could not capture screen-shot to '%s'\n", outputPath);
- SLANG_RETURN_ON_FAIL(hr);
- }
- return SLANG_OK;
+ return captureTextureToSurface(m_device, m_immediateContext, m_renderTargetTextures[0], surfaceOut);
}
ShaderCompiler* D3D11Renderer::getShaderCompiler()
diff --git a/tools/render-test/render-d3d12.cpp b/tools/render-test/render-d3d12.cpp
index d1b547f2d..a582e3feb 100644
--- a/tools/render-test/render-d3d12.cpp
+++ b/tools/render-test/render-d3d12.cpp
@@ -6,6 +6,8 @@
#include "options.h"
#include "render.h"
+#include "surface.h"
+
// In order to use the Slang API, we need to include its header
#include <slang.h>
@@ -25,8 +27,6 @@
#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"
@@ -59,7 +59,7 @@ public:
virtual void presentFrame() override;
virtual TextureResource* createTextureResource(Resource::Type type, Resource::Usage initialUsage, const TextureResource::Desc& desc, const TextureResource::Data* initData) override;
virtual BufferResource* createBufferResource(Resource::Usage initialUsage, const BufferResource::Desc& bufferDesc, const void* initData) override;
- virtual SlangResult captureScreenShot(const char* outputPath) override;
+ virtual SlangResult captureScreenSurface(Surface& surfaceOut) override;
virtual InputLayout* createInputLayout(const InputElementDesc* inputElements, UInt inputElementCount) override;
virtual BindingState* createBindingState(const BindingState::Desc& bindingStateDesc) override;
virtual ShaderCompiler* getShaderCompiler() override;
@@ -326,7 +326,7 @@ protected:
void submitGpuWorkAndWait();
void _resetCommandList();
- Result captureTextureToFile(D3D12Resource& resource, const char* outputPath);
+ Result captureTextureToSurface(D3D12Resource& resource, Surface& surfaceOut);
FrameInfo& getFrame() { return m_frameInfos[m_frameIndex]; }
const FrameInfo& getFrame() const { return m_frameInfos[m_frameIndex]; }
@@ -721,7 +721,7 @@ void D3D12Renderer::submitGpuWorkAndWait()
waitForGpu();
}
-Result D3D12Renderer::captureTextureToFile(D3D12Resource& resource, const char* outputPath)
+Result D3D12Renderer::captureTextureToSurface(D3D12Resource& resource, Surface& surfaceOut)
{
const D3D12_RESOURCE_STATES initialState = resource.getState();
@@ -794,9 +794,7 @@ Result D3D12Renderer::captureTextureToFile(D3D12Resource& resource, const char*
SLANG_RETURN_ON_FAIL(dxResource->Map(0, &readRange, reinterpret_cast<void**>(&data)));
- Surface surface;
- surface.setUnowned(int(desc.Width), int(desc.Height), Format::RGBA_Unorm_UInt8, int(rowPitch), data);
- Result res = PngSerializeUtil::write(outputPath, surface);
+ Result res = surfaceOut.set(int(desc.Width), int(desc.Height), Format::RGBA_Unorm_UInt8, int(rowPitch), data, SurfaceAllocator::getMallocAllocator());
dxResource->Unmap(0, nullptr);
return res;
@@ -1681,9 +1679,9 @@ void D3D12Renderer::presentFrame()
beginRender();
}
-SlangResult D3D12Renderer::captureScreenShot(const char* outputPath)
+SlangResult D3D12Renderer::captureScreenSurface(Surface& surfaceOut)
{
- return captureTextureToFile(*m_renderTargets[m_renderTargetIndex], outputPath);
+ return captureTextureToSurface(*m_renderTargets[m_renderTargetIndex], surfaceOut);
}
ShaderCompiler* D3D12Renderer::getShaderCompiler()
diff --git a/tools/render-test/render-gl.cpp b/tools/render-test/render-gl.cpp
index cef482798..2c4ac9ea0 100644
--- a/tools/render-test/render-gl.cpp
+++ b/tools/render-test/render-gl.cpp
@@ -12,7 +12,6 @@
#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
@@ -87,7 +86,7 @@ public:
virtual void presentFrame() override;
virtual TextureResource* createTextureResource(Resource::Type type, Resource::Usage initialUsage, const TextureResource::Desc& desc, const TextureResource::Data* initData) override;
virtual BufferResource* createBufferResource(Resource::Usage initialUsage, const BufferResource::Desc& descIn, const void* initData) override;
- virtual SlangResult captureScreenShot(char const* outputPath) override;
+ virtual SlangResult captureScreenSurface(Surface& surfaceOut) override;
virtual InputLayout* createInputLayout(const InputElementDesc* inputElements, UInt inputElementCount) override;
virtual BindingState* createBindingState(const BindingState::Desc& bindingStateDesc) override;
virtual ShaderCompiler* getShaderCompiler() override;
@@ -586,13 +585,12 @@ void GLRenderer::presentFrame()
::SwapBuffers(m_hdc);
}
-SlangResult GLRenderer::captureScreenShot(const char* outputPath)
+SlangResult GLRenderer::captureScreenSurface(Surface& surfaceOut)
{
- 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);
+ SLANG_RETURN_ON_FAIL(surfaceOut.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, surfaceOut.m_data);
+ surfaceOut.flipInplaceVertically();
+ return SLANG_OK;
}
ShaderCompiler* GLRenderer::getShaderCompiler()
diff --git a/tools/render-test/render-vk.cpp b/tools/render-test/render-vk.cpp
index 8ffb05c99..cc011a297 100644
--- a/tools/render-test/render-vk.cpp
+++ b/tools/render-test/render-vk.cpp
@@ -39,7 +39,7 @@ public:
virtual void presentFrame() override;
virtual TextureResource* createTextureResource(Resource::Type type, Resource::Usage initialUsage, const TextureResource::Desc& desc, const TextureResource::Data* initData) override;
virtual BufferResource* createBufferResource(Resource::Usage initialUsage, const BufferResource::Desc& bufferDesc, const void* initData) override;
- virtual SlangResult captureScreenShot(const char* outputPath) override;
+ virtual SlangResult captureScreenSurface(Surface& surface) override;
virtual InputLayout* createInputLayout(const InputElementDesc* inputElements, UInt inputElementCount) override;
virtual BindingState* createBindingState(const BindingState::Desc& bindingStateDesc) override;
virtual ShaderCompiler* getShaderCompiler() override;
@@ -1010,7 +1010,7 @@ void VKRenderer::presentFrame()
_beginRender();
}
-SlangResult VKRenderer::captureScreenShot(char const* outputPath)
+SlangResult VKRenderer::captureScreenSurface(Surface& surfaceOut)
{
return SLANG_FAIL;
}
diff --git a/tools/render-test/render.h b/tools/render-test/render.h
index ba76f795d..f66454712 100644
--- a/tools/render-test/render.h
+++ b/tools/render-test/render.h
@@ -15,6 +15,9 @@ namespace renderer_test {
typedef intptr_t Int;
typedef uintptr_t UInt;
+// pre declare types
+class Surface;
+
// Declare opaque type
class InputLayout: public Slang::RefObject
{
@@ -552,7 +555,8 @@ public:
/// Create a buffer resource
virtual BufferResource* createBufferResource(Resource::Usage initialUsage, const BufferResource::Desc& desc, const void* initData = nullptr) { return nullptr; }
- virtual SlangResult captureScreenShot(const char* outputPath) = 0;
+ /// Captures the back buffer and stores the result in surfaceOut. If the surface contains data - it will either be overwritten (if same size and format), or freed and a re-allocated.
+ virtual SlangResult captureScreenSurface(Surface& surfaceOut) = 0;
virtual InputLayout* createInputLayout(const InputElementDesc* inputElements, UInt inputElementCount) = 0;
virtual BindingState* createBindingState(const BindingState::Desc& desc) { return nullptr; }
diff --git a/tools/render-test/surface.cpp b/tools/render-test/surface.cpp
index 3f96052ce..4d761389a 100644
--- a/tools/render-test/surface.cpp
+++ b/tools/render-test/surface.cpp
@@ -188,4 +188,35 @@ void Surface::flipInplaceVertically()
}
}
+SlangResult Surface::set(int width, int height, Format format, int srcRowStride, const void* data, SurfaceAllocator* allocator)
+{
+ if (hasContents() && m_width == width && m_height == height && m_format == format)
+ {
+ // I can just overwrite the contents that is there
+ }
+ else
+ {
+ SLANG_RETURN_ON_FAIL(allocate(width, height, format, 0, allocator));
+ }
+
+ // Okay just need to set the contents
+
+ {
+ const size_t rowSize = calcRowSize(format, width);
+
+ const uint8_t* srcRow = (const uint8_t*)data;
+ uint8_t* dstRow = (uint8_t*)m_data;
+
+ for (int i = 0; i < m_numRows; i++)
+ {
+ ::memcpy(dstRow, srcRow, rowSize);
+
+ srcRow += srcRowStride;
+ dstRow += m_rowStrideInBytes;
+ }
+ }
+
+ return SLANG_OK;
+}
+
} // renderer_test
diff --git a/tools/render-test/surface.h b/tools/render-test/surface.h
index f5f67efc0..c7460238f 100644
--- a/tools/render-test/surface.h
+++ b/tools/render-test/surface.h
@@ -37,6 +37,9 @@ class Surface
/// Set unowned
void setUnowned(int width, int height, Format format, int strideInBytes, void* data);
+ /// Set the contents - the memory will be owned by this surface (ie will be freed by the allocator when goes out of scope or is deallocated)
+ Slang::Result set(int width, int height, Format format, int strideInBytes, const void* data, SurfaceAllocator* allocator);
+
template <typename T>
T* calcNextRow(T* ptr) const { return (T*)calcNextRow((void*)ptr); }
template <typename T>