summaryrefslogtreecommitdiffstats
path: root/tools/render-test
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2021-01-17 22:00:49 -0800
committerGitHub <noreply@github.com>2021-01-17 22:00:49 -0800
commit1296c7bb55b14db24308f31cacdda7f7a71fc937 (patch)
tree935ebf1e829361a17f98f5ead3460998719acf42 /tools/render-test
parent2a5d5b32348c33aac7ca62aa9a4c2bb7cff8e08a (diff)
Make `gfx` compile to a DLL. (#1660)
* Make `gfx` compile to a DLL. * Fix cuda * Fix cuda build * Bug gl screen capture bug.
Diffstat (limited to 'tools/render-test')
-rw-r--r--tools/render-test/render-test-main.cpp19
-rw-r--r--tools/render-test/surface.cpp223
-rw-r--r--tools/render-test/surface.h86
3 files changed, 326 insertions, 2 deletions
diff --git a/tools/render-test/render-test-main.cpp b/tools/render-test/render-test-main.cpp
index 89bb25871..184373f0c 100644
--- a/tools/render-test/render-test-main.cpp
+++ b/tools/render-test/render-test-main.cpp
@@ -4,7 +4,7 @@
#include "options.h"
#include "render.h"
-#include "shader-cursor.h"
+#include "tools/gfx-util/shader-cursor.h"
#include "slang-support.h"
#include "surface.h"
#include "png-serialize-util.h"
@@ -827,8 +827,23 @@ Result ShaderObjectRenderTestApp::writeBindingOutput(BindRoot* bindRoot, const c
Result RenderTestApp::writeScreen(const char* filename)
{
+ size_t rowPitch, bufferSize, pixelSize;
+ List<uint8_t> buffer;
+
+ SLANG_RETURN_ON_FAIL(m_renderer->captureScreenSurface(nullptr, &bufferSize, &rowPitch, &pixelSize));
+ buffer.setCount(bufferSize);
+ SLANG_RETURN_ON_FAIL(
+ m_renderer->captureScreenSurface(buffer.getBuffer(), &bufferSize, &rowPitch, &pixelSize));
+
Surface surface;
- SLANG_RETURN_ON_FAIL(m_renderer->captureScreenSurface(surface));
+ size_t width = rowPitch / pixelSize;
+ size_t height = bufferSize / rowPitch;
+ surface.setUnowned(
+ width,
+ height,
+ gfx::Format::RGBA_Unorm_UInt8,
+ rowPitch,
+ buffer.getBuffer());
return PngSerializeUtil::write(filename, surface);
}
diff --git a/tools/render-test/surface.cpp b/tools/render-test/surface.cpp
new file mode 100644
index 000000000..636881fca
--- /dev/null
+++ b/tools/render-test/surface.cpp
@@ -0,0 +1,223 @@
+// surface.cpp
+#include "surface.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "../../source/core/slang-list.h"
+
+namespace gfx {
+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_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 = gfxGetFormatSize(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.setCount(rowSizeInBytes);
+ uint8_t* buffer = bufferList.getBuffer();
+
+ 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);
+ }
+}
+
+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
new file mode 100644
index 000000000..3e0f6f0aa
--- /dev/null
+++ b/tools/render-test/surface.h
@@ -0,0 +1,86 @@
+// surface.h
+#pragma once
+
+#include "render.h"
+
+namespace gfx {
+
+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);
+
+ /// 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>
+ 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