1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
|
#pragma once
#include "slang-gfx.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;
ShaderObjectContainerType m_containerType = ShaderObjectContainerType::None;
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() const
{
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(const char* nameBegin, const char* nameEnd, ShaderCursor& outCursor) const;
ShaderCursor getField(const char* name) const
{
ShaderCursor cursor;
getField(name, nullptr, cursor);
return cursor;
}
ShaderCursor getElement(SlangInt index) const;
static Result followPath(const char* path, ShaderCursor& ioCursor);
ShaderCursor getPath(const char* path) const
{
ShaderCursor result(*this);
followPath(path, result);
return result;
}
ShaderCursor() {}
ShaderCursor(IShaderObject* object)
: m_baseObject(object)
, m_typeLayout(object->getElementTypeLayout())
, m_containerType(object->getContainerType())
{}
SlangResult setData(void const* data, size_t size) const
{
return m_baseObject->setData(m_offset, data, size);
}
template <typename T>
SlangResult setData(T const& data) const
{
return setData(&data, sizeof(data));
}
SlangResult setObject(IShaderObject* object) const
{
return m_baseObject->setObject(m_offset, object);
}
SlangResult setSpecializationArgs(const slang::SpecializationArg* args, uint32_t count) const
{
return m_baseObject->setSpecializationArgs(m_offset, args, count);
}
SlangResult setResource(IResourceView* resourceView) const
{
return m_baseObject->setResource(m_offset, resourceView);
}
SlangResult setSampler(ISamplerState* sampler) const
{
return m_baseObject->setSampler(m_offset, sampler);
}
SlangResult setCombinedTextureSampler(IResourceView* textureView, ISamplerState* sampler) const
{
return m_baseObject->setCombinedTextureSampler(m_offset, textureView, sampler);
}
/// Produce a cursor to the field with the given `name`.
///
/// This is a convenience wrapper around `getField()`.
ShaderCursor operator[](const char* name) const
{
return getField(name);
}
/// Produce a cursor to the element or field with the given `index`.
///
/// This is a convenience wrapper around `getElement()`.
ShaderCursor operator[](int64_t index) const { return getElement((SlangInt)index); }
ShaderCursor operator[](uint64_t index) const { return getElement((SlangInt)index); }
ShaderCursor operator[](int32_t index) const { return getElement((SlangInt)index); }
ShaderCursor operator[](uint32_t index) const { return getElement((SlangInt)index); }
ShaderCursor operator[](int16_t index) const { return getElement((SlangInt)index); }
ShaderCursor operator[](uint16_t index) const { return getElement((SlangInt)index); }
ShaderCursor operator[](int8_t index) const { return getElement((SlangInt)index); }
ShaderCursor operator[](uint8_t index) const { return getElement((SlangInt)index); }
};
}
|