summaryrefslogtreecommitdiffstats
path: root/source/slang/parameter-binding.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/slang/parameter-binding.cpp')
-rw-r--r--source/slang/parameter-binding.cpp105
1 files changed, 90 insertions, 15 deletions
diff --git a/source/slang/parameter-binding.cpp b/source/slang/parameter-binding.cpp
index 4378cb06b..e0cc26f2b 100644
--- a/source/slang/parameter-binding.cpp
+++ b/source/slang/parameter-binding.cpp
@@ -288,8 +288,34 @@ struct LayoutSemanticInfo
// TODO: need to deal with component-granularity binding...
};
+static bool isDigit(char c)
+{
+ return (c >= '0') && (c <= '9');
+}
+
+/// Given a string that specifies a name and index (e.g., `COLOR0`),
+/// split it into slices for the name part and the index part.
+static void splitNameAndIndex(
+ String const& text,
+ UnownedStringSlice& outName,
+ UnownedStringSlice& outDigits)
+{
+ char const* nameBegin = text.begin();
+ char const* digitsEnd = text.end();
+
+ char const* nameEnd = digitsEnd;
+ while( nameEnd != nameBegin && isDigit(*(nameEnd - 1)) )
+ {
+ nameEnd--;
+ }
+ char const* digitsBegin = nameEnd;
+
+ outName = UnownedStringSlice(nameBegin, nameEnd);
+ outDigits = UnownedStringSlice(digitsBegin, digitsEnd);
+}
+
LayoutSemanticInfo ExtractLayoutSemanticInfo(
- ParameterBindingContext* /*context*/,
+ ParameterBindingContext* context,
HLSLLayoutSemantic* semantic)
{
LayoutSemanticInfo info;
@@ -297,12 +323,31 @@ LayoutSemanticInfo ExtractLayoutSemanticInfo(
info.index = 0;
info.kind = LayoutResourceKind::None;
- auto registerName = semantic->registerName.Content;
+ String registerName = semantic->registerName.Content;
if (registerName.Length() == 0)
return info;
+ // The register name is expected to be in the form:
+ //
+ // identifier-char+ digit+
+ //
+ // where the identifier characters name a "register class"
+ // and the digits identify a register index within that class.
+ //
+ // We are going to split the string the user gave us
+ // into these constituent parts:
+ //
+ UnownedStringSlice registerClassName;
+ UnownedStringSlice registerIndexDigits;
+ splitNameAndIndex(registerName, registerClassName, registerIndexDigits);
+
+ // All of the register classes we support are single ASCII characters,
+ // so we really just care about the first byte, but we want to be
+ // careful and only look at it if the register class name is one
+ // byte long.
+ char registerClassChar = registerClassName.size() == 1 ? *registerClassName.begin() : 0;
LayoutResourceKind kind = LayoutResourceKind::None;
- switch (registerName[0])
+ switch (registerClassChar)
{
case 'b':
kind = LayoutResourceKind::ConstantBuffer;
@@ -321,29 +366,59 @@ LayoutSemanticInfo ExtractLayoutSemanticInfo(
break;
default:
- // TODO: issue an error here!
+ getSink(context)->diagnose(semantic->registerName, Diagnostics::unknownRegisterClass, registerClassName);
return info;
}
- // TODO: need to parse and handle `space` binding
- int space = 0;
+ // For a `register` semantic, the register index is not optional (unlike
+ // how it works for varying input/output semantics).
+ if( registerIndexDigits.size() == 0 )
+ {
+ getSink(context)->diagnose(semantic->registerName, Diagnostics::expectedARegisterIndex, registerClassName);
+ }
UInt index = 0;
- for (UInt ii = 1; ii < registerName.Length(); ++ii)
+ for(auto c : registerIndexDigits)
{
- int c = registerName[ii];
- if (c >= '0' && c <= '9')
- {
- index = index * 10 + (c - '0');
- }
- else
+ SLANG_ASSERT(isDigit(c));
+ index = index * 10 + (c - '0');
+ }
+
+
+ UInt space = 0;
+ if( auto registerSemantic = dynamic_cast<HLSLRegisterSemantic*>(semantic) )
+ {
+ auto const& spaceName = registerSemantic->spaceName.Content;
+ if(spaceName.Length() != 0)
{
- // TODO: issue an error here!
- return info;
+ UnownedStringSlice spaceSpelling;
+ UnownedStringSlice spaceDigits;
+ splitNameAndIndex(spaceName, spaceSpelling, spaceDigits);
+
+ if( spaceSpelling != UnownedTerminatedStringSlice("space") )
+ {
+ getSink(context)->diagnose(semantic->registerName, Diagnostics::expectedSpace, spaceSpelling);
+ }
+ else if( spaceDigits.size() == 0 )
+ {
+ getSink(context)->diagnose(semantic->registerName, Diagnostics::expectedSpaceIndex);
+ }
+ else
+ {
+ for(auto c : spaceDigits)
+ {
+ SLANG_ASSERT(isDigit(c));
+ space = space * 10 + (c - '0');
+ }
+ }
}
}
// TODO: handle component mask part of things...
+ if( semantic->componentMask.Content.Length() != 0 )
+ {
+ getSink(context)->diagnose(semantic->componentMask, Diagnostics::componentMaskNotSupported);
+ }
info.kind = kind;
info.index = (int) index;