summaryrefslogtreecommitdiff
path: root/tools/gfx
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/gfx
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/gfx')
-rw-r--r--tools/gfx/cuda/render-cuda.cpp10
-rw-r--r--tools/gfx/d3d11/render-d3d11.cpp75
-rw-r--r--tools/gfx/d3d12/render-d3d12.cpp40
-rw-r--r--tools/gfx/open-gl/render-gl.cpp39
-rw-r--r--tools/gfx/render.h5
-rw-r--r--tools/gfx/shader-cursor.cpp249
-rw-r--r--tools/gfx/shader-cursor.h123
-rw-r--r--tools/gfx/slang-gfx-helper.cpp6
-rw-r--r--tools/gfx/slang-gfx-helper.h9
-rw-r--r--tools/gfx/surface.cpp223
-rw-r--r--tools/gfx/surface.h86
-rw-r--r--tools/gfx/vulkan/render-vk.cpp39
12 files changed, 156 insertions, 748 deletions
diff --git a/tools/gfx/cuda/render-cuda.cpp b/tools/gfx/cuda/render-cuda.cpp
index bf316546e..0e4ee6c13 100644
--- a/tools/gfx/cuda/render-cuda.cpp
+++ b/tools/gfx/cuda/render-cuda.cpp
@@ -1493,10 +1493,14 @@ public:
SLANG_UNUSED(outState);
return SLANG_E_NOT_AVAILABLE;
}
- virtual SLANG_NO_THROW SlangResult SLANG_MCALL
- captureScreenSurface(Surface& surfaceOut) override
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL captureScreenSurface(
+ void* buffer, size_t* inOutBufferSize, size_t* outRowPitch, size_t* outPixelSize) override
{
- SLANG_UNUSED(surfaceOut);
+ SLANG_UNUSED(buffer);
+ SLANG_UNUSED(inOutBufferSize);
+ SLANG_UNUSED(outRowPitch);
+ SLANG_UNUSED(outPixelSize);
+
return SLANG_E_NOT_AVAILABLE;
}
virtual SLANG_NO_THROW void SLANG_MCALL
diff --git a/tools/gfx/d3d11/render-d3d11.cpp b/tools/gfx/d3d11/render-d3d11.cpp
index 8bf11c39d..4ac90f47f 100644
--- a/tools/gfx/d3d11/render-d3d11.cpp
+++ b/tools/gfx/d3d11/render-d3d11.cpp
@@ -11,8 +11,6 @@
#include "../d3d/d3d-util.h"
#include "../nvapi/nvapi-util.h"
-#include "../surface.h"
-
// In order to use the Slang API, we need to include its header
//#include <slang.h>
@@ -106,8 +104,8 @@ public:
virtual SLANG_NO_THROW Result SLANG_MCALL createComputePipelineState(
const ComputePipelineStateDesc& desc, IPipelineState** outState) override;
- virtual SLANG_NO_THROW SlangResult SLANG_MCALL
- captureScreenSurface(Surface& surfaceOut) override;
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL captureScreenSurface(
+ void* buffer, size_t* inOutBufferSize, size_t* outRowPitch, size_t* outPixelSize) override;
virtual SLANG_NO_THROW void* SLANG_MCALL map(IBufferResource* buffer, MapFlavor flavor) override;
virtual SLANG_NO_THROW void SLANG_MCALL unmap(IBufferResource* buffer) override;
@@ -491,7 +489,14 @@ public:
};
/// Capture a texture to a file
- static HRESULT captureTextureToSurface(ID3D11Device* device, ID3D11DeviceContext* context, ID3D11Texture2D* texture, Surface& surfaceOut);
+ static HRESULT captureTextureToSurface(
+ ID3D11Device* device,
+ ID3D11DeviceContext* context,
+ TextureResourceImpl* texture,
+ void* buffer,
+ size_t* inOutBufferSize,
+ size_t* outRowPitch,
+ size_t* outPixelSize);
void _flushGraphicsState();
void _flushComputeState();
@@ -569,27 +574,50 @@ D3D11Renderer::ScopeNVAPI::~ScopeNVAPI()
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!D3D11Renderer !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-/* static */HRESULT D3D11Renderer::captureTextureToSurface(ID3D11Device* device, ID3D11DeviceContext* context, ID3D11Texture2D* texture, Surface& surfaceOut)
+/* static */ HRESULT D3D11Renderer::captureTextureToSurface(
+ ID3D11Device* device,
+ ID3D11DeviceContext* context,
+ TextureResourceImpl* texture,
+ void* buffer,
+ size_t* inOutBufferSize,
+ size_t* outRowPitch,
+ size_t* outPixelSize)
{
if (!context) return E_INVALIDARG;
if (!texture) return E_INVALIDARG;
- D3D11_TEXTURE2D_DESC textureDesc;
- texture->GetDesc(&textureDesc);
-
// Don't bother supporting MSAA for right now
- if (textureDesc.SampleDesc.Count > 1)
+ if (texture->getDesc()->sampleDesc.numSamples > 1)
{
fprintf(stderr, "ERROR: cannot capture multi-sample texture\n");
return E_INVALIDARG;
}
+ size_t bytesPerPixel = sizeof(uint32_t);
+ size_t rowPitch = int(texture->getDesc()->size.width) * bytesPerPixel;
+ size_t bufferSize = rowPitch * int(texture->getDesc()->size.height);
+ if (outRowPitch)
+ *outRowPitch = rowPitch;
+ if (outPixelSize)
+ *outPixelSize = bytesPerPixel;
+ if (!buffer || *inOutBufferSize == 0)
+ {
+ *inOutBufferSize = bufferSize;
+ return S_OK;
+ }
+ if (*inOutBufferSize < bufferSize)
+ return SLANG_ERROR_INSUFFICIENT_BUFFER;
+
+ D3D11_TEXTURE2D_DESC textureDesc;
+ auto d3d11Texture = ((ID3D11Texture2D*)texture->m_resource.get());
+ d3d11Texture->GetDesc(&textureDesc);
+
HRESULT hr = S_OK;
ComPtr<ID3D11Texture2D> stagingTexture;
if (textureDesc.Usage == D3D11_USAGE_STAGING && (textureDesc.CPUAccessFlags & D3D11_CPU_ACCESS_READ))
{
- stagingTexture = texture;
+ stagingTexture = d3d11Texture;
}
else
{
@@ -606,7 +634,7 @@ D3D11Renderer::ScopeNVAPI::~ScopeNVAPI()
return hr;
}
- context->CopyResource(stagingTexture, texture);
+ context->CopyResource(stagingTexture, d3d11Texture);
}
// Now just read back texels from the staging textures
@@ -614,11 +642,16 @@ D3D11Renderer::ScopeNVAPI::~ScopeNVAPI()
D3D11_MAPPED_SUBRESOURCE mappedResource;
SLANG_RETURN_ON_FAIL(context->Map(stagingTexture, 0, D3D11_MAP_READ, 0, &mappedResource));
- Result res = surfaceOut.set(textureDesc.Width, textureDesc.Height, Format::RGBA_Unorm_UInt8, mappedResource.RowPitch, mappedResource.pData, SurfaceAllocator::getMallocAllocator());
-
+ for (size_t y = 0; y < textureDesc.Height; y++)
+ {
+ memcpy(
+ (char*)buffer + y * (*outRowPitch),
+ (char*)mappedResource.pData + y * mappedResource.RowPitch,
+ *outRowPitch);
+ }
// Make sure to unmap
context->Unmap(stagingTexture, 0);
- return res;
+ return SLANG_OK;
}
}
@@ -891,9 +924,17 @@ TextureResource::Desc D3D11Renderer::getSwapChainTextureDesc()
return desc;
}
-SlangResult D3D11Renderer::captureScreenSurface(Surface& surfaceOut)
+SlangResult D3D11Renderer::captureScreenSurface(
+ void* buffer, size_t* inOutBufferSize, size_t* outRowPitch, size_t* outPixelSize)
{
- return captureTextureToSurface(m_device, m_immediateContext, (ID3D11Texture2D*) m_primaryRenderTargetTexture->m_resource.get(), surfaceOut);
+ return captureTextureToSurface(
+ m_device,
+ m_immediateContext,
+ m_primaryRenderTargetTexture.Ptr(),
+ buffer,
+ inOutBufferSize,
+ outRowPitch,
+ outPixelSize);
}
static D3D11_BIND_FLAG _calcResourceFlag(IResource::BindFlag::Enum bindFlag)
diff --git a/tools/gfx/d3d12/render-d3d12.cpp b/tools/gfx/d3d12/render-d3d12.cpp
index 6b66c5403..3db93df50 100644
--- a/tools/gfx/d3d12/render-d3d12.cpp
+++ b/tools/gfx/d3d12/render-d3d12.cpp
@@ -7,7 +7,6 @@
#include "../renderer-shared.h"
#include "../render-graphics-common.h"
-#include "../surface.h"
#include "core/slang-basic.h"
// In order to use the Slang API, we need to include its header
@@ -112,8 +111,8 @@ public:
virtual SLANG_NO_THROW Result SLANG_MCALL createComputePipelineState(
const ComputePipelineStateDesc& desc, IPipelineState** outState) override;
- virtual SLANG_NO_THROW SlangResult SLANG_MCALL
- captureScreenSurface(Surface& surfaceOut) override;
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL captureScreenSurface(
+ void* buffer, size_t* inOutBufferSize, size_t* outRowPitch, size_t* outPixelSize) override;
virtual SLANG_NO_THROW void* SLANG_MCALL
map(IBufferResource* buffer, MapFlavor flavor) override;
@@ -648,7 +647,12 @@ protected:
void submitGpuWorkAndWait();
void _resetCommandList();
- Result captureTextureToSurface(D3D12Resource& resource, Surface& surfaceOut);
+ Result captureTextureToSurface(
+ D3D12Resource& resource,
+ void* buffer,
+ size_t* inOutBufferSize,
+ size_t* outRowPitch,
+ size_t* outPixelSize);
FrameInfo& getFrame() { return m_frameInfos[m_frameIndex]; }
const FrameInfo& getFrame() const { return m_frameInfos[m_frameIndex]; }
@@ -1063,7 +1067,12 @@ void D3D12Renderer::submitGpuWorkAndWait()
waitForGpu();
}
-Result D3D12Renderer::captureTextureToSurface(D3D12Resource& resource, Surface& surfaceOut)
+Result D3D12Renderer::captureTextureToSurface(
+ D3D12Resource& resource,
+ void* buffer,
+ size_t* inOutBufferSize,
+ size_t* outRowPitch,
+ size_t* outPixelSize)
{
const D3D12_RESOURCE_STATES initialState = resource.getState();
@@ -1079,7 +1088,17 @@ Result D3D12Renderer::captureTextureToSurface(D3D12Resource& resource, Surface&
size_t bytesPerPixel = sizeof(uint32_t);
size_t rowPitch = int(desc.Width) * bytesPerPixel;
size_t bufferSize = rowPitch * int(desc.Height);
-
+ if (outRowPitch)
+ *outRowPitch = rowPitch;
+ if (outPixelSize)
+ *outPixelSize = bytesPerPixel;
+ if (!buffer || *inOutBufferSize == 0)
+ {
+ *inOutBufferSize = bufferSize;
+ return SLANG_OK;
+ }
+ if (*inOutBufferSize < bufferSize)
+ return SLANG_ERROR_INSUFFICIENT_BUFFER;
D3D12Resource stagingResource;
{
D3D12_RESOURCE_DESC stagingDesc;
@@ -1136,10 +1155,10 @@ Result D3D12Renderer::captureTextureToSurface(D3D12Resource& resource, Surface&
SLANG_RETURN_ON_FAIL(dxResource->Map(0, &readRange, reinterpret_cast<void**>(&data)));
- Result res = surfaceOut.set(int(desc.Width), int(desc.Height), Format::RGBA_Unorm_UInt8, int(rowPitch), data, SurfaceAllocator::getMallocAllocator());
+ memcpy(buffer, data, bufferSize);
dxResource->Unmap(0, nullptr);
- return res;
+ return SLANG_OK;
}
}
@@ -1800,9 +1819,10 @@ TextureResource::Desc D3D12Renderer::getSwapChainTextureDesc()
return desc;
}
-SlangResult D3D12Renderer::captureScreenSurface(Surface& surfaceOut)
+SlangResult D3D12Renderer::captureScreenSurface(
+ void* buffer, size_t* inOutBufferSize, size_t* outRowPitch, size_t* outPixelSize)
{
- return captureTextureToSurface(*m_renderTargets[m_renderTargetIndex], surfaceOut);
+ return captureTextureToSurface(*m_renderTargets[m_renderTargetIndex], buffer, inOutBufferSize, outRowPitch, outPixelSize);
}
static D3D12_RESOURCE_STATES _calcResourceState(IResource::Usage usage)
diff --git a/tools/gfx/open-gl/render-gl.cpp b/tools/gfx/open-gl/render-gl.cpp
index 826192e8d..7ee73366b 100644
--- a/tools/gfx/open-gl/render-gl.cpp
+++ b/tools/gfx/open-gl/render-gl.cpp
@@ -13,8 +13,6 @@
#include "core/slang-secure-crt.h"
#include "external/stb/stb_image_write.h"
-#include "../surface.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...
@@ -125,8 +123,8 @@ public:
virtual SLANG_NO_THROW Result SLANG_MCALL createComputePipelineState(
const ComputePipelineStateDesc& desc, IPipelineState** outState) override;
- virtual SLANG_NO_THROW SlangResult SLANG_MCALL
- captureScreenSurface(Surface& surfaceOut) override;
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL captureScreenSurface(
+ void* buffer, size_t* inOutBufferSize, size_t* outRowPitch, size_t* outPixelSize) override;
virtual SLANG_NO_THROW void* SLANG_MCALL map(IBufferResource* buffer, MapFlavor flavor) override;
virtual SLANG_NO_THROW void SLANG_MCALL unmap(IBufferResource* buffer) override;
@@ -882,11 +880,36 @@ SLANG_NO_THROW TextureResource::Desc SLANG_MCALL GLRenderer::getSwapChainTexture
return desc;
}
-SLANG_NO_THROW Result SLANG_MCALL GLRenderer::captureScreenSurface(Surface& surfaceOut)
+SLANG_NO_THROW Result SLANG_MCALL GLRenderer::captureScreenSurface(
+ void* buffer, size_t* inOutBufferSize, size_t* outRowPitch, size_t* outPixelSize)
{
- 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();
+ size_t requiredSize = m_desc.width * m_desc.height * sizeof(uint32_t);
+ if (outRowPitch)
+ *outRowPitch = m_desc.width * sizeof(uint32_t);
+ if (outPixelSize)
+ *outPixelSize = sizeof(uint32_t);
+
+ if (!buffer || *inOutBufferSize == 0)
+ {
+ *inOutBufferSize = requiredSize;
+ return SLANG_OK;
+ }
+ if (*inOutBufferSize < requiredSize)
+ return SLANG_ERROR_INSUFFICIENT_BUFFER;
+
+ glReadPixels(0, 0, m_desc.width, m_desc.height, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
+
+ // Flip pixels vertically in-place.
+ for (int y = 0; y < m_desc.height / 2; y++)
+ {
+ for (int x = 0; x < m_desc.width; x++)
+ {
+ std::swap(
+ *((uint32_t*)buffer + y * m_desc.width + x),
+ *((uint32_t*)buffer + (m_desc.height - y - 1) * m_desc.width + x));
+ }
+ }
+
return SLANG_OK;
}
diff --git a/tools/gfx/render.h b/tools/gfx/render.h
index 0bc8692eb..8e1a5d665 100644
--- a/tools/gfx/render.h
+++ b/tools/gfx/render.h
@@ -38,9 +38,6 @@ typedef SlangResult Result;
typedef SlangInt Int;
typedef SlangUInt UInt;
-// pre declare types
-class Surface;
-
// Declare opaque type
class IInputLayout: public ISlangUnknown
{
@@ -1281,7 +1278,7 @@ public:
}
/// 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 SLANG_NO_THROW SlangResult SLANG_MCALL captureScreenSurface(Surface& surfaceOut) = 0;
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL captureScreenSurface(void* buffer, size_t *inOutBufferSize, size_t* outRowPitch, size_t* outPixelSize) = 0;
virtual SLANG_NO_THROW void* SLANG_MCALL map(IBufferResource* buffer, MapFlavor flavor) = 0;
virtual SLANG_NO_THROW void SLANG_MCALL unmap(IBufferResource* buffer) = 0;
diff --git a/tools/gfx/shader-cursor.cpp b/tools/gfx/shader-cursor.cpp
deleted file mode 100644
index 65cf2f8ac..000000000
--- a/tools/gfx/shader-cursor.cpp
+++ /dev/null
@@ -1,249 +0,0 @@
-#include "shader-cursor.h"
-
-namespace gfx
-{
-
-Result gfx::ShaderCursor::getDereferenced(ShaderCursor& outCursor) const
-{
- switch (m_typeLayout->getKind())
- {
- default:
- return SLANG_E_INVALID_ARG;
-
- case slang::TypeReflection::Kind::ConstantBuffer:
- case slang::TypeReflection::Kind::ParameterBlock:
- {
- auto subObject = m_baseObject->getObject(m_offset);
- outCursor = ShaderCursor(subObject);
- return SLANG_OK;
- }
- }
-}
-
-Result ShaderCursor::getField(Slang::UnownedStringSlice const& name, ShaderCursor& outCursor)
-{
- // If this cursor is invalid, then can't possible fetch a field.
- //
- if (!isValid())
- return SLANG_E_INVALID_ARG;
-
- // If the cursor is valid, we want to consider the type of data
- // it is referencing.
- //
- switch (m_typeLayout->getKind())
- {
- // The easy/expected case is when the value has a structure type.
- //
- case slang::TypeReflection::Kind::Struct:
- {
- // We start by looking up the index of a field matching `name`.
- //
- // If there is no such field, we have an error.
- //
- SlangInt fieldIndex = m_typeLayout->findFieldIndexByName(name.begin(), name.end());
- if (fieldIndex == -1)
- return SLANG_E_INVALID_ARG;
-
- // Once we know the index of the field being referenced,
- // we create a cursor to point at the field, based on
- // the offset information already in this cursor, plus
- // offsets derived from the field's layout.
- //
- slang::VariableLayoutReflection* fieldLayout =
- m_typeLayout->getFieldByIndex((unsigned int)fieldIndex);
- ShaderCursor fieldCursor;
-
- // The field cursorwill point into the same parent object.
- //
- fieldCursor.m_baseObject = m_baseObject;
-
- // The type being pointed to is the tyep of the field.
- //
- fieldCursor.m_typeLayout = fieldLayout->getTypeLayout();
-
- // The byte offset is the current offset plus the relative offset of the field.
- // The offset in binding ranges is computed similarly.
- //
- fieldCursor.m_offset.uniformOffset = m_offset.uniformOffset + fieldLayout->getOffset();
- fieldCursor.m_offset.bindingRangeIndex =
- m_offset.bindingRangeIndex + m_typeLayout->getFieldBindingRangeOffset(fieldIndex);
-
- // The index of the field within any binding ranges will be the same
- // as the index computed for the parent structure.
- //
- // Note: this case would arise for an array of structures with texture-type
- // fields. Suppose we have:
- //
- // struct S { Texture2D t; Texture2D u; }
- // S g[4];
- //
- // In this scenario, `g` holds two binding ranges:
- //
- // * Range #0 comprises 4 textures, representing `g[...].t`
- // * Range #1 comprises 4 textures, representing `g[...].u`
- //
- // A cursor for `g[2]` would have a `bindingRangeIndex` of zero but
- // a `bindingArrayIndex` of 2, iindicating that we could end up
- // referencing either range, but no matter what we know the index
- // is 2. Thus when we form a cursor for `g[2].u` we want to
- // apply the binding range offset to get a `bindingRangeIndex` of
- // 1, while the `bindingArrayIndex` is unmodified.
- //
- // The result is that `g[2].u` is stored in range #1 at array index 2.
- //
- fieldCursor.m_offset.bindingArrayIndex = m_offset.bindingArrayIndex;
-
- outCursor = fieldCursor;
- return SLANG_OK;
- }
- break;
-
- // In some cases the user might be trying to acess a field by name
- // from a cursor that references a constant buffer or parameter block,
- // and in these cases we want the access to Just Work.
- //
- case slang::TypeReflection::Kind::ConstantBuffer:
- case slang::TypeReflection::Kind::ParameterBlock:
- {
- // We basically need to "dereference" the current cursor
- // to go from a pointer to a constant buffer to a pointer
- // to the *contents* of the constant buffer.
- //
- ShaderCursor d = getDereferenced();
- return d.getField(name, outCursor);
- }
- break;
- }
-
- return SLANG_E_INVALID_ARG;
-}
-
-ShaderCursor ShaderCursor::getElement(Slang::Index index)
-{
- // TODO: need to auto-dereference various buffer types...
-
- if (m_typeLayout->getKind() == slang::TypeReflection::Kind::Array)
- {
- ShaderCursor elementCursor;
- elementCursor.m_baseObject = m_baseObject;
- elementCursor.m_typeLayout = m_typeLayout->getElementTypeLayout();
- elementCursor.m_offset.uniformOffset =
- m_offset.uniformOffset +
- index * m_typeLayout->getElementStride(SLANG_PARAMETER_CATEGORY_UNIFORM);
- elementCursor.m_offset.bindingRangeIndex = m_offset.bindingRangeIndex;
- elementCursor.m_offset.bindingArrayIndex =
- m_offset.bindingArrayIndex * m_typeLayout->getElementCount() + index;
- return elementCursor;
- }
-
- return ShaderCursor();
-}
-
-
-static int _peek(Slang::UnownedStringSlice const& slice)
-{
- const char* b = slice.begin();
- const char* e = slice.end();
- if (b == e)
- return -1;
- return *b;
-}
-
-static int _get(Slang::UnownedStringSlice& slice)
-{
- const char* b = slice.begin();
- const char* e = slice.end();
- if (b == e)
- return -1;
- auto result = *b++;
- slice = Slang::UnownedStringSlice(b, e);
- return result;
-}
-
-Result ShaderCursor::followPath(Slang::UnownedStringSlice const& path, ShaderCursor& ioCursor)
-{
- ShaderCursor cursor = ioCursor;
-
- enum
- {
- ALLOW_NAME = 0x1,
- ALLOW_SUBSCRIPT = 0x2,
- ALLOW_DOT = 0x4,
- };
- int state = ALLOW_NAME | ALLOW_SUBSCRIPT;
-
- Slang::UnownedStringSlice rest = path;
- for (;;)
- {
- int c = _peek(rest);
-
- if (c == -1)
- break;
- else if (c == '.')
- {
- if (!(state & ALLOW_DOT))
- return SLANG_E_INVALID_ARG;
-
- _get(rest);
- state = ALLOW_NAME;
- continue;
- }
- else if (c == '[')
- {
- if (!(state & ALLOW_SUBSCRIPT))
- return SLANG_E_INVALID_ARG;
-
- _get(rest);
- Slang::Index index = 0;
- while (_peek(rest) != ']')
- {
- int d = _get(rest);
- if (d >= '0' && d <= '9')
- {
- index = index * 10 + (d - '0');
- }
- else
- {
- return SLANG_E_INVALID_ARG;
- }
- }
-
- if (_peek(rest) != ']')
- return SLANG_E_INVALID_ARG;
- _get(rest);
-
- cursor = cursor.getElement(index);
- state = ALLOW_DOT | ALLOW_SUBSCRIPT;
- continue;
- }
- else
- {
- const char* nameBegin = rest.begin();
- for (;;)
- {
- switch (_peek(rest))
- {
- default:
- _get(rest);
- continue;
-
- case -1:
- case '.':
- case '[':
- break;
- }
- break;
- }
- char const* nameEnd = rest.begin();
- Slang::UnownedStringSlice name(nameBegin, nameEnd);
- cursor = cursor.getField(name);
- state = ALLOW_DOT | ALLOW_SUBSCRIPT;
- continue;
- }
- }
-
- ioCursor = cursor;
- return SLANG_OK;
-}
-
-} // namespace gfx
diff --git a/tools/gfx/shader-cursor.h b/tools/gfx/shader-cursor.h
deleted file mode 100644
index 82794be9a..000000000
--- a/tools/gfx/shader-cursor.h
+++ /dev/null
@@ -1,123 +0,0 @@
-#pragma once
-
-#include "tools/gfx/render.h"
-#include "core/slang-basic.h"
-
-namespace gfx
-{
-
-/// Represents a "pointer" to the storage for a shader parameter of a (dynamically) known type.
-///
-/// A `ShaderCursor` serves as a pointer-like type for things stored inside a `ShaderObject`.
-///
-/// A cursor that points to the entire content of a shader object can be formed as
-/// `ShaderCursor(someObject)`. A cursor pointing to a structure field or array element can be
-/// formed from another cursor using `getField` or `getElement` respectively.
-///
-/// Given a cursor pointing to a value of some "primitive" type, we can set or get the value
-/// using operations like `setResource`, `getResource`, etc.
-///
-/// Because type information for shader parameters is being reflected dynamically, all type
-/// checking for shader cursors occurs at runtime, and errors may occur when attempting to
-/// set a parameter using a value of an inappropriate type. As much as possible, `ShaderCursor`
-/// attempts to protect against these cases and return an error `Result` or an invalid
-/// cursor, rather than allowing operations to proceed with incorrect types.
-///
-struct ShaderCursor
-{
- IShaderObject* m_baseObject = nullptr;
- slang::TypeLayoutReflection* m_typeLayout = nullptr;
- ShaderOffset m_offset;
-
- /// Get the type (layout) of the value being pointed at by the cursor
- slang::TypeLayoutReflection* getTypeLayout() const { return m_typeLayout; }
-
- /// Is this cursor valid (that is, does it seem to point to an actual location)?
- ///
- /// This check is equivalent to checking whether a pointer is null, so it is
- /// a very weak sense of "valid." In particular, it is possible to form a
- /// `ShaderCursor` for which `isValid()` is true, but attempting to get or
- /// set the value would be an error (like dereferencing a garbage pointer).
- ///
- bool isValid() const { return m_baseObject != nullptr; }
-
- Result getDereferenced(ShaderCursor& outCursor) const;
-
- ShaderCursor getDereferenced()
- {
- ShaderCursor result;
- getDereferenced(result);
- return result;
- }
-
- /// Form a cursor pointing to the field with the given `name` within the value this cursor
- /// points at.
- ///
- /// If the operation succeeds, then the field cursor is written to `outCursor`.
- Result getField(Slang::UnownedStringSlice const& name, ShaderCursor& outCursor);
-
- ShaderCursor getField(Slang::UnownedStringSlice const& name)
- {
- ShaderCursor cursor;
- getField(name, cursor);
- return cursor;
- }
-
- ShaderCursor getField(Slang::String const& name) { return getField(name.getUnownedSlice()); }
-
- ShaderCursor getElement(Slang::Index index);
-
- static Result followPath(Slang::UnownedStringSlice const& path, ShaderCursor& ioCursor);
-
- static Result followPath(Slang::String const& path, ShaderCursor& ioCursor)
- {
- return followPath(path.getUnownedSlice(), ioCursor);
- }
-
- ShaderCursor getPath(Slang::UnownedStringSlice const& path)
- {
- ShaderCursor result(*this);
- followPath(path, result);
- return result;
- }
-
- ShaderCursor getPath(Slang::String const& path)
- {
- ShaderCursor result(*this);
- followPath(path, result);
- return result;
- }
-
- ShaderCursor() {}
-
- ShaderCursor(IShaderObject* object)
- : m_baseObject(object)
- , m_typeLayout(object->getElementTypeLayout())
- {}
-
- SlangResult setData(void const* data, size_t size)
- {
- return m_baseObject->setData(m_offset, data, size);
- }
-
- SlangResult setObject(IShaderObject* object)
- {
- return m_baseObject->setObject(m_offset, object);
- }
-
- SlangResult setResource(IResourceView* resourceView)
- {
- return m_baseObject->setResource(m_offset, resourceView);
- }
-
- SlangResult setSampler(ISamplerState* sampler)
- {
- return m_baseObject->setSampler(m_offset, sampler);
- }
-
- SlangResult setCombinedTextureSampler(IResourceView* textureView, ISamplerState* sampler)
- {
- return m_baseObject->setCombinedTextureSampler(m_offset, textureView, sampler);
- }
-};
-}
diff --git a/tools/gfx/slang-gfx-helper.cpp b/tools/gfx/slang-gfx-helper.cpp
deleted file mode 100644
index 499e462b0..000000000
--- a/tools/gfx/slang-gfx-helper.cpp
+++ /dev/null
@@ -1,6 +0,0 @@
-#include "slang-gfx-helper.h"
-#include "renderer-shared.h"
-
-namespace gfx
-{
-} // namespace gfx
diff --git a/tools/gfx/slang-gfx-helper.h b/tools/gfx/slang-gfx-helper.h
deleted file mode 100644
index 1cd3fe64c..000000000
--- a/tools/gfx/slang-gfx-helper.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#pragma once
-
-#include "render.h"
-
-namespace gfx
-{
-
-
-}
diff --git a/tools/gfx/surface.cpp b/tools/gfx/surface.cpp
deleted file mode 100644
index 636881fca..000000000
--- a/tools/gfx/surface.cpp
+++ /dev/null
@@ -1,223 +0,0 @@
-// 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/gfx/surface.h b/tools/gfx/surface.h
deleted file mode 100644
index 3e0f6f0aa..000000000
--- a/tools/gfx/surface.h
+++ /dev/null
@@ -1,86 +0,0 @@
-// 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
diff --git a/tools/gfx/vulkan/render-vk.cpp b/tools/gfx/vulkan/render-vk.cpp
index c2a1e36bf..382f12f85 100644
--- a/tools/gfx/vulkan/render-vk.cpp
+++ b/tools/gfx/vulkan/render-vk.cpp
@@ -12,8 +12,6 @@
#include "vk-device-queue.h"
#include "vk-swap-chain.h"
-#include "../surface.h"
-
// Vulkan has a different coordinate system to ogl
// http://anki3d.org/vulkan-coordinate-system/
@@ -88,7 +86,8 @@ public:
const ComputePipelineStateDesc& desc,
IPipelineState** outState) override;
- virtual SLANG_NO_THROW SlangResult SLANG_MCALL captureScreenSurface(Surface& surface) override;
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL captureScreenSurface(
+ void* buffer, size_t* inOutBufferSize, size_t* outRowPitch, size_t* outPixelSize) override;
virtual SLANG_NO_THROW void* SLANG_MCALL map(IBufferResource* buffer, MapFlavor flavor) override;
virtual SLANG_NO_THROW void SLANG_MCALL unmap(IBufferResource* buffer) override;
@@ -1439,8 +1438,13 @@ TextureResource::Desc VKRenderer::getSwapChainTextureDesc()
return desc;
}
-SlangResult VKRenderer::captureScreenSurface(Surface& surfaceOut)
+SlangResult VKRenderer::captureScreenSurface(
+ void* buffer, size_t* inOutBufferSize, size_t* outRowPitch, size_t* outPixelSize)
{
+ SLANG_UNUSED(buffer);
+ SLANG_UNUSED(inOutBufferSize);
+ SLANG_UNUSED(outRowPitch);
+ SLANG_UNUSED(outPixelSize);
return SLANG_FAIL;
}
@@ -1594,6 +1598,21 @@ void VKRenderer::_transitionImageLayout(VkImage image, VkFormat format, const Te
m_api.vkCmdPipelineBarrier(commandBuffer, sourceStage, destinationStage, 0, 0, nullptr, 0, nullptr, 1, &barrier);
}
+size_t calcRowSize(Format format, int width)
+{
+ size_t pixelSize = gfxGetFormatSize(format);
+ if (pixelSize == 0)
+ {
+ return 0;
+ }
+ return size_t(pixelSize * width);
+}
+
+size_t calcNumRows(Format format, int height)
+{
+ return (size_t)height;
+}
+
Result VKRenderer::createTextureResource(IResource::Usage initialUsage, const ITextureResource::Desc& descIn, const ITextureResource::Data* initData, ITextureResource** outResource)
{
TextureResource::Desc desc(descIn);
@@ -1704,8 +1723,8 @@ Result VKRenderer::createTextureResource(IResource::Usage initialUsage, const IT
{
const TextureResource::Size mipSize = desc.size.calcMipSize(j);
- const int rowSizeInBytes = Surface::calcRowSize(desc.format, mipSize.width);
- const int numRows = Surface::calcNumRows(desc.format, mipSize.height);
+ const int rowSizeInBytes = calcRowSize(desc.format, mipSize.width);
+ const int numRows = calcNumRows(desc.format, mipSize.height);
mipSizes.add(mipSize);
@@ -1735,8 +1754,8 @@ Result VKRenderer::createTextureResource(IResource::Usage initialUsage, const IT
const auto& mipSize = mipSizes[j];
const ptrdiff_t srcRowStride = initData->mipRowStrides[j];
- const int dstRowSizeInBytes = Surface::calcRowSize(desc.format, mipSize.width);
- const int numRows = Surface::calcNumRows(desc.format, mipSize.height);
+ const int dstRowSizeInBytes = calcRowSize(desc.format, mipSize.width);
+ const int numRows = calcNumRows(desc.format, mipSize.height);
for (int k = 0; k < mipSize.depth; k++)
{
@@ -1768,8 +1787,8 @@ Result VKRenderer::createTextureResource(IResource::Usage initialUsage, const IT
{
const auto& mipSize = mipSizes[j];
- const int rowSizeInBytes = Surface::calcRowSize(desc.format, mipSize.width);
- const int numRows = Surface::calcNumRows(desc.format, mipSize.height);
+ const int rowSizeInBytes = calcRowSize(desc.format, mipSize.width);
+ const int numRows = calcNumRows(desc.format, mipSize.height);
// https://www.khronos.org/registry/vulkan/specs/1.1-extensions/man/html/VkBufferImageCopy.html
// bufferRowLength and bufferImageHeight specify the data in buffer memory as a subregion of a larger two- or three-dimensional image,