summaryrefslogtreecommitdiffstats
path: root/tools/gfx-util/shader-cursor.cpp
diff options
context:
space:
mode:
authorGangzheng Tong <tonggangzheng@gmail.com>2025-07-08 23:44:56 -0700
committerGitHub <noreply@github.com>2025-07-09 06:44:56 +0000
commit43d0c2100ef1a5df4b54525e50eb29fe7c39ec16 (patch)
tree25ec4fb9c726115f90bdaa9878f2f4ca372ad0a6 /tools/gfx-util/shader-cursor.cpp
parent00746bf09047cdf01c19dac513a532bcf3ed3ea3 (diff)
Convert gfx unit tests and examples to use slang-rhi (#7577)
* Port first gfx unit test to slang-rhi * port triangle example to use slang-rhi * port platform-test to slang-rhi * Update platform-test to throttle mouse move events * port gpu-printing example to use slang-rhi * port model-viewer example to use slang-rhi * port ray-tracing example to use slang-rhi * port ray-tracing pipeline example to use slang-rhi * port reflection parameter blocks example to use slang-rhi * port shader-object example to use slang-rhi * port shader-toy example to use slang-rhi * Port most of tests to slang-rhi * port link-time-constant-array-size to use slang-rhi * Fix tests and find matching tests in slang-rhi * port autodiff-texture * remove gfx target; port nv-aftermath-example * update include path for shader-cursor.h * Disabled 2 more ported tests * fix build error * remove gfx test * put slang-rhi (static-lib) before slang (shared) * format code (#7621) Co-authored-by: slangbot <186143334+slangbot@users.noreply.github.com> * add debug callback * format code (#7649) Co-authored-by: slangbot <186143334+slangbot@users.noreply.github.com> * Address review comments; revert back to use SLANG_CHECK_MSG --------- Co-authored-by: slangbot <ellieh+slangbot@nvidia.com> Co-authored-by: slangbot <186143334+slangbot@users.noreply.github.com>
Diffstat (limited to 'tools/gfx-util/shader-cursor.cpp')
-rw-r--r--tools/gfx-util/shader-cursor.cpp379
1 files changed, 0 insertions, 379 deletions
diff --git a/tools/gfx-util/shader-cursor.cpp b/tools/gfx-util/shader-cursor.cpp
deleted file mode 100644
index 80d674768..000000000
--- a/tools/gfx-util/shader-cursor.cpp
+++ /dev/null
@@ -1,379 +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;
- }
- }
-}
-
-ShaderCursor ShaderCursor::getExplicitCounter() const
-{
- // Similar to getField below
-
- // The alternative to handling this here would be to augment IResourceView
- // with a `getCounterResourceView()`, and set that also in `setResource`
- if (const auto counterVarLayout = m_typeLayout->getExplicitCounter())
- {
- ShaderCursor counterCursor;
-
- // The counter cursor will point into the same parent object.
- counterCursor.m_baseObject = m_baseObject;
-
- // The type being pointed to is the type of the field.
- counterCursor.m_typeLayout = counterVarLayout->getTypeLayout();
-
- // The byte offset is the current offset plus the relative offset of the counter.
- // The offset in binding ranges is computed similarly.
- counterCursor.m_offset.uniformOffset =
- m_offset.uniformOffset + SlangInt(counterVarLayout->getOffset());
- counterCursor.m_offset.bindingRangeIndex =
- m_offset.bindingRangeIndex +
- GfxIndex(m_typeLayout->getExplicitCounterBindingRangeOffset());
-
- // The index of the counter 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 structured buffers
- //
- // AppendStructuredBuffer g[4];
- //
- // In this scenario, `g` holds two binding ranges:
- //
- // * Range #0 comprises 4 element buffers, representing `g[...].elements`
- // * Range #1 comprises 4 counter buffers, representing `g[...].counter`
- //
- // A cursor for `g[2]` would have a `bindingRangeIndex` of zero but
- // a `bindingArrayIndex` of 2, indicating 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].counter` 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].counter` is stored in range #1 at array index 2.
- //
- counterCursor.m_offset.bindingArrayIndex = m_offset.bindingArrayIndex;
-
- return counterCursor;
- }
- // Otherwise, return an invalid cursor
- return ShaderCursor{};
-}
-
-Result ShaderCursor::getField(const char* name, const char* nameEnd, ShaderCursor& outCursor) const
-{
- // 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, nameEnd);
- if (fieldIndex == -1)
- break;
-
- // 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 +
- (GfxIndex)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, nameEnd, outCursor);
- }
- break;
- }
-
- // If a cursor is pointing at a root shader object (created for a
- // program), then we will also iterate over the entry point shader
- // objects attached to it and look for a matching parameter name
- // on them.
- //
- // This is a bit of "do what I mean" logic and could potentially
- // lead to problems if there could be multiple entry points with
- // the same parameter name.
- //
- // TODO: figure out whether we should support this long-term.
- //
- auto entryPointCount = (GfxIndex)m_baseObject->getEntryPointCount();
- for (GfxIndex e = 0; e < entryPointCount; ++e)
- {
- ComPtr<IShaderObject> entryPoint;
- m_baseObject->getEntryPoint(e, entryPoint.writeRef());
-
- ShaderCursor entryPointCursor(entryPoint);
-
- auto result = entryPointCursor.getField(name, nameEnd, outCursor);
- if (SLANG_SUCCEEDED(result))
- return result;
- }
-
- return SLANG_E_INVALID_ARG;
-}
-
-ShaderCursor ShaderCursor::getElement(GfxIndex index) const
-{
- if (m_containerType != ShaderObjectContainerType::None)
- {
- ShaderCursor elementCursor;
- elementCursor.m_baseObject = m_baseObject;
- elementCursor.m_typeLayout = m_typeLayout->getElementTypeLayout();
- elementCursor.m_containerType = m_containerType;
- elementCursor.m_offset.uniformOffset = index * m_typeLayout->getStride();
- elementCursor.m_offset.bindingRangeIndex = 0;
- elementCursor.m_offset.bindingArrayIndex = index;
- return elementCursor;
- }
-
- switch (m_typeLayout->getKind())
- {
- case 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 * (GfxCount)m_typeLayout->getElementCount() + index;
- return elementCursor;
- }
- break;
-
- case slang::TypeReflection::Kind::Struct:
- {
- // The logic here is similar to `getField()` except that we don't
- // need to look up the field index based on a name first.
- //
- auto fieldIndex = index;
- slang::VariableLayoutReflection* fieldLayout =
- m_typeLayout->getFieldByIndex((unsigned int)fieldIndex);
- if (!fieldLayout)
- return ShaderCursor();
-
- ShaderCursor fieldCursor;
- fieldCursor.m_baseObject = m_baseObject;
- fieldCursor.m_typeLayout = fieldLayout->getTypeLayout();
- fieldCursor.m_offset.uniformOffset = m_offset.uniformOffset + fieldLayout->getOffset();
- fieldCursor.m_offset.bindingRangeIndex =
- m_offset.bindingRangeIndex +
- (GfxIndex)m_typeLayout->getFieldBindingRangeOffset(fieldIndex);
- fieldCursor.m_offset.bindingArrayIndex = m_offset.bindingArrayIndex;
-
- return fieldCursor;
- }
- break;
-
- case slang::TypeReflection::Kind::Vector:
- case slang::TypeReflection::Kind::Matrix:
- {
- ShaderCursor fieldCursor;
- fieldCursor.m_baseObject = m_baseObject;
- fieldCursor.m_typeLayout = m_typeLayout->getElementTypeLayout();
- fieldCursor.m_offset.uniformOffset =
- m_offset.uniformOffset +
- m_typeLayout->getElementStride(SLANG_PARAMETER_CATEGORY_UNIFORM) * index;
- fieldCursor.m_offset.bindingRangeIndex = m_offset.bindingRangeIndex;
- fieldCursor.m_offset.bindingArrayIndex = m_offset.bindingArrayIndex;
- return fieldCursor;
- }
- break;
- }
-
- return ShaderCursor();
-}
-
-
-static int _peek(const char* slice)
-{
- const char* b = slice;
- if (!b || !*b)
- return -1;
- return *b;
-}
-
-static int _get(const char*& slice)
-{
- const char* b = slice;
- if (!b || !*b)
- return -1;
- auto result = *b++;
- slice = b;
- return result;
-}
-
-Result ShaderCursor::followPath(const char* path, ShaderCursor& ioCursor)
-{
- ShaderCursor cursor = ioCursor;
-
- enum
- {
- ALLOW_NAME = 0x1,
- ALLOW_SUBSCRIPT = 0x2,
- ALLOW_DOT = 0x4,
- };
- int state = ALLOW_NAME | ALLOW_SUBSCRIPT;
-
- const char* 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);
- GfxCount 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;
- for (;;)
- {
- switch (_peek(rest))
- {
- default:
- _get(rest);
- continue;
-
- case -1:
- case '.':
- case '[':
- break;
- }
- break;
- }
- char const* nameEnd = rest;
- ShaderCursor newCursor;
- cursor.getField(nameBegin, nameEnd, newCursor);
- cursor = newCursor;
- state = ALLOW_DOT | ALLOW_SUBSCRIPT;
- continue;
- }
- }
-
- ioCursor = cursor;
- return SLANG_OK;
-}
-
-} // namespace gfx