diff options
Diffstat (limited to 'tools/render-test/shader-input-layout.cpp')
| -rw-r--r-- | tools/render-test/shader-input-layout.cpp | 2396 |
1 files changed, 1245 insertions, 1151 deletions
diff --git a/tools/render-test/shader-input-layout.cpp b/tools/render-test/shader-input-layout.cpp index 013e86c37..e2cf25809 100644 --- a/tools/render-test/shader-input-layout.cpp +++ b/tools/render-test/shader-input-layout.cpp @@ -2,6 +2,7 @@ #define _CRT_SECURE_NO_WARNINGS 1 #include "shader-input-layout.h" + #include "core/slang-token-reader.h" #include "core/slang-type-text-util.h" @@ -9,7 +10,7 @@ namespace renderer_test { - using namespace Slang; +using namespace Slang; // clang-format off #define SLANG_SCALAR_TYPES(x) \ @@ -19,1177 +20,1229 @@ namespace renderer_test // clang-format on - Format _getFormatFromName(const UnownedStringSlice& slice) +Format _getFormatFromName(const UnownedStringSlice& slice) +{ + for (int i = 0; i < int(Format::_Count); ++i) { - for (int i = 0; i < int(Format::_Count); ++i) + const FormatInfo& info = getFormatInfo(Format(i)); + if (slice == info.name) { - const FormatInfo& info = getFormatInfo(Format(i)); - if (slice == info.name) - { - return Format(i); - } + return Format(i); } - return Format::Unknown; } + return Format::Unknown; +} - struct TypeInfo - { - UnownedStringSlice name; - SlangScalarType type; - }; +struct TypeInfo +{ + UnownedStringSlice name; + SlangScalarType type; +}; -#define SLANG_SCALAR_TYPE_INFO(name, value) { UnownedStringSlice::fromLiteral(name), SLANG_SCALAR_TYPE_##value }, - static const TypeInfo g_scalarTypeInfos[] = - { - SLANG_SCALAR_TYPES(SLANG_SCALAR_TYPE_INFO) - }; +#define SLANG_SCALAR_TYPE_INFO(name, value) \ + {UnownedStringSlice::fromLiteral(name), SLANG_SCALAR_TYPE_##value}, +static const TypeInfo g_scalarTypeInfos[] = {SLANG_SCALAR_TYPES(SLANG_SCALAR_TYPE_INFO)}; #undef SLANG_SCALAR_TYPES #undef SLANG_SCALAR_TYPE_INFO - static SlangScalarType _getScalarType(const UnownedStringSlice& slice) +static SlangScalarType _getScalarType(const UnownedStringSlice& slice) +{ + for (const auto& info : g_scalarTypeInfos) { - for (const auto& info : g_scalarTypeInfos) + if (info.name == slice) { - if (info.name == slice) - { - return info.type; - } + return info.type; } - return SLANG_SCALAR_TYPE_NONE; } + return SLANG_SCALAR_TYPE_NONE; +} - void ShaderInputLayout::AggVal::addField(ShaderInputLayout::Field const& field) - { - fields.add(field); - } +void ShaderInputLayout::AggVal::addField(ShaderInputLayout::Field const& field) +{ + fields.add(field); +} - void ShaderInputLayout::ArrayVal::addField(ShaderInputLayout::Field const& field) +void ShaderInputLayout::ArrayVal::addField(ShaderInputLayout::Field const& field) +{ + vals.add(field.val); +} + +class ShaderInputLayoutFormatException : public Exception +{ +public: + ShaderInputLayoutFormatException(String message) + : Exception(message) { - vals.add(field.val); } +}; - class ShaderInputLayoutFormatException : public Exception - { - public: - ShaderInputLayoutFormatException(String message) - : Exception(message) - {} - }; +struct ShaderInputLayoutParser +{ + ShaderInputLayout* layout; + RandomGenerator* rand; - struct ShaderInputLayoutParser + ShaderInputLayoutParser(ShaderInputLayout* layout, RandomGenerator* rand) + : layout(layout), rand(rand) { - ShaderInputLayout* layout; - RandomGenerator* rand; - - ShaderInputLayoutParser(ShaderInputLayout* layout, RandomGenerator* rand) - : layout(layout) - , rand(rand) - {} + } - RefPtr<ShaderInputLayout::ParentVal> parentVal; - List<RefPtr<ShaderInputLayout::ParentVal>> parentValStack; + RefPtr<ShaderInputLayout::ParentVal> parentVal; + List<RefPtr<ShaderInputLayout::ParentVal>> parentValStack; - SlangResult parseOption(Misc::TokenReader& parser, String const& word, ShaderInputLayout::TextureVal* val) + SlangResult parseOption( + Misc::TokenReader& parser, + String const& word, + ShaderInputLayout::TextureVal* val) + { + if (word == "depth") { - if (word == "depth") - { - val->textureDesc.isDepthTexture = true; - } - else if (word == "arrayLength") - { - parser.Read("="); - val->textureDesc.arrayLength = parser.ReadInt(); - } - else if (word == "size") - { - parser.Read("="); - auto size = parser.ReadInt(); - val->textureDesc.size = size; - } - else if (word == "content") - { - parser.Read("="); - auto contentWord = parser.ReadWord(); - if (contentWord == "zero") - val->textureDesc.content = InputTextureContent::Zero; - else if (contentWord == "one") - val->textureDesc.content = InputTextureContent::One; - else if (contentWord == "chessboard") - val->textureDesc.content = InputTextureContent::ChessBoard; - else - val->textureDesc.content = InputTextureContent::Gradient; - } - else if (word == "sampleCount") - { - parser.Read("="); - auto contentWord = parser.ReadWord(); - if(contentWord == "one") - val->textureDesc.sampleCount = InputTextureSampleCount::One; - else if(contentWord == "two") - val->textureDesc.sampleCount = InputTextureSampleCount::Two; - else if(contentWord == "four") - val->textureDesc.sampleCount = InputTextureSampleCount::Four; - else if(contentWord == "eight") - val->textureDesc.sampleCount = InputTextureSampleCount::Eight; - else if(contentWord == "sixteen") - val->textureDesc.sampleCount = InputTextureSampleCount::Sixteen; - else if(contentWord == "thirtyTwo") - val->textureDesc.sampleCount = InputTextureSampleCount::ThirtyTwo; - else if(contentWord == "sixtyFour") - val->textureDesc.sampleCount = InputTextureSampleCount::SixtyFour; - } - else if(word == "mipMaps") - { - parser.Read("="); - val->textureDesc.mipMapCount = int(parser.ReadInt()); - } - else if(word == "format") - { - val->textureDesc.format = parseFormatOption(parser); - - if (val->textureDesc.format == Format::Unknown) - { - return SLANG_FAIL; - } - } - else - { - return SLANG_FAIL; - } - return SLANG_OK; + val->textureDesc.isDepthTexture = true; } - - SlangResult parseOption(Misc::TokenReader& parser, String const& word, ShaderInputLayout::SamplerVal* val) + else if (word == "arrayLength") { - if (word == "depthCompare") - { - val->samplerDesc.isCompareSampler = true; - } + parser.Read("="); + val->textureDesc.arrayLength = parser.ReadInt(); + } + else if (word == "size") + { + parser.Read("="); + auto size = parser.ReadInt(); + val->textureDesc.size = size; + } + else if (word == "content") + { + parser.Read("="); + auto contentWord = parser.ReadWord(); + if (contentWord == "zero") + val->textureDesc.content = InputTextureContent::Zero; + else if (contentWord == "one") + val->textureDesc.content = InputTextureContent::One; + else if (contentWord == "chessboard") + val->textureDesc.content = InputTextureContent::ChessBoard; else + val->textureDesc.content = InputTextureContent::Gradient; + } + else if (word == "sampleCount") + { + parser.Read("="); + auto contentWord = parser.ReadWord(); + if (contentWord == "one") + val->textureDesc.sampleCount = InputTextureSampleCount::One; + else if (contentWord == "two") + val->textureDesc.sampleCount = InputTextureSampleCount::Two; + else if (contentWord == "four") + val->textureDesc.sampleCount = InputTextureSampleCount::Four; + else if (contentWord == "eight") + val->textureDesc.sampleCount = InputTextureSampleCount::Eight; + else if (contentWord == "sixteen") + val->textureDesc.sampleCount = InputTextureSampleCount::Sixteen; + else if (contentWord == "thirtyTwo") + val->textureDesc.sampleCount = InputTextureSampleCount::ThirtyTwo; + else if (contentWord == "sixtyFour") + val->textureDesc.sampleCount = InputTextureSampleCount::SixtyFour; + } + else if (word == "mipMaps") + { + parser.Read("="); + val->textureDesc.mipMapCount = int(parser.ReadInt()); + } + else if (word == "format") + { + val->textureDesc.format = parseFormatOption(parser); + + if (val->textureDesc.format == Format::Unknown) { return SLANG_FAIL; } - return SLANG_OK; } + else + { + return SLANG_FAIL; + } + return SLANG_OK; + } - - SlangResult parseOption(Misc::TokenReader& parser, String const& word, ShaderInputLayout::CombinedTextureSamplerVal* val) + SlangResult parseOption( + Misc::TokenReader& parser, + String const& word, + ShaderInputLayout::SamplerVal* val) + { + if (word == "depthCompare") + { + val->samplerDesc.isCompareSampler = true; + } + else { - auto result = parseOption(parser, word, val->textureVal); - if(SLANG_SUCCEEDED(result)) return result; + return SLANG_FAIL; + } + return SLANG_OK; + } + - result = parseOption(parser, word, val->samplerVal); + SlangResult parseOption( + Misc::TokenReader& parser, + String const& word, + ShaderInputLayout::CombinedTextureSamplerVal* val) + { + auto result = parseOption(parser, word, val->textureVal); + if (SLANG_SUCCEEDED(result)) return result; - } - SlangResult parseOption(Misc::TokenReader& parser, String const& word, ShaderInputLayout::DataValBase* val) + result = parseOption(parser, word, val->samplerVal); + return result; + } + + SlangResult parseOption( + Misc::TokenReader& parser, + String const& word, + ShaderInputLayout::DataValBase* val) + { + if (word == "data") { - if (word == "data") - { - parser.Read("="); + parser.Read("="); - parser.Read("["); - uint32_t offset = 0; - while (!parser.IsEnd() && !parser.LookAhead("]")) + parser.Read("["); + uint32_t offset = 0; + while (!parser.IsEnd() && !parser.LookAhead("]")) + { + bool negate = false; + if (parser.NextToken().Type == Misc::TokenType::OpSub) { - bool negate = false; - if(parser.NextToken().Type == Misc::TokenType::OpSub) - { - parser.ReadToken(); - negate = true; - } + parser.ReadToken(); + negate = true; + } - if (parser.NextToken().Type == Misc::TokenType::IntLiteral) - { - uint32_t value = parser.ReadUInt(); - if(negate) value = uint32_t(-int32_t(value)); - val->bufferData.add(value); - } - else - { - auto floatNum = parser.ReadFloat(); - if(negate) floatNum = -floatNum; - val->bufferData.add(*(unsigned int*)&floatNum); - } - offset += 4; + if (parser.NextToken().Type == Misc::TokenType::IntLiteral) + { + uint32_t value = parser.ReadUInt(); + if (negate) + value = uint32_t(-int32_t(value)); + val->bufferData.add(value); } - parser.Read("]"); - } - else - { - return SLANG_FAIL; + else + { + auto floatNum = parser.ReadFloat(); + if (negate) + floatNum = -floatNum; + val->bufferData.add(*(unsigned int*)&floatNum); + } + offset += 4; } - return SLANG_OK; + parser.Read("]"); } + else + { + return SLANG_FAIL; + } + return SLANG_OK; + } - SlangResult parseOption(Misc::TokenReader& parser, String const& word, ShaderInputLayout::BufferVal* val) + SlangResult parseOption( + Misc::TokenReader& parser, + String const& word, + ShaderInputLayout::BufferVal* val) + { + if (word == "stride") { - if (word == "stride") - { - parser.Read("="); - val->bufferDesc.stride = parser.ReadInt(); - } - else if (word == "count") - { - parser.Read("="); - val->bufferDesc.elementCount = parser.ReadInt(); - } - else if (word == "counter") - { - parser.Read("="); - val->bufferDesc.counter = parser.ReadInt(); - } - else if (word == "random") - { - parser.Read("("); - // Read the type - String type = parser.ReadWord(); - SlangScalarType scalarType = _getScalarType(type.getUnownedSlice()); - if (scalarType == SLANG_SCALAR_TYPE_NONE) + parser.Read("="); + val->bufferDesc.stride = parser.ReadInt(); + } + else if (word == "count") + { + parser.Read("="); + val->bufferDesc.elementCount = parser.ReadInt(); + } + else if (word == "counter") + { + parser.Read("="); + val->bufferDesc.counter = parser.ReadInt(); + } + else if (word == "random") + { + parser.Read("("); + // Read the type + String type = parser.ReadWord(); + SlangScalarType scalarType = _getScalarType(type.getUnownedSlice()); + if (scalarType == SLANG_SCALAR_TYPE_NONE) + { + StringBuilder scalarTypeNames; + for (const auto& info : g_scalarTypeInfos) { - StringBuilder scalarTypeNames; - for (const auto& info : g_scalarTypeInfos) + if (scalarTypeNames.getLength() != 0) { - if (scalarTypeNames.getLength() != 0) - { - scalarTypeNames << ", "; - } - scalarTypeNames << info.name; + scalarTypeNames << ", "; } - - throw ShaderInputLayoutFormatException(StringBuilder() << "Expecting " << scalarTypeNames << " " << parser.NextToken().Position.Line); + scalarTypeNames << info.name; } - parser.Read(","); - const int size = int(parser.ReadUInt()); + throw ShaderInputLayoutFormatException( + StringBuilder() + << "Expecting " << scalarTypeNames << " " << parser.NextToken().Position.Line); + } + + parser.Read(","); + const int size = int(parser.ReadUInt()); - switch (scalarType) + switch (scalarType) + { + case SLANG_SCALAR_TYPE_INT32: { - case SLANG_SCALAR_TYPE_INT32: - { - bool hasRange = false; + bool hasRange = false; + + int32_t minValue = -0x7fffffff - 1; + int32_t maxValue = 0x7fffffff; - int32_t minValue = -0x7fffffff - 1; - int32_t maxValue = 0x7fffffff; + if (parser.LookAhead(",")) + { + hasRange = true; + parser.ReadToken(); + minValue = parser.ReadInt(); if (parser.LookAhead(",")) { - hasRange = true; parser.ReadToken(); - minValue = parser.ReadInt(); - - if (parser.LookAhead(",")) - { - parser.ReadToken(); - maxValue = parser.ReadInt(); - } + maxValue = parser.ReadInt(); } - SLANG_ASSERT(minValue <= maxValue); - maxValue = (maxValue >= minValue) ? maxValue : minValue; + } + SLANG_ASSERT(minValue <= maxValue); + maxValue = (maxValue >= minValue) ? maxValue : minValue; - // Generate the data - val->bufferData.setCount(size); + // Generate the data + val->bufferData.setCount(size); - int32_t* dst = (int32_t*)val->bufferData.getBuffer(); - for (int i = 0; i < size; ++i) - { - dst[i] = hasRange ? rand->nextInt32InRange(minValue, maxValue) : rand->nextInt32(); - } - break; + int32_t* dst = (int32_t*)val->bufferData.getBuffer(); + for (int i = 0; i < size; ++i) + { + dst[i] = hasRange ? rand->nextInt32InRange(minValue, maxValue) + : rand->nextInt32(); } - case SLANG_SCALAR_TYPE_UINT32: + break; + } + case SLANG_SCALAR_TYPE_UINT32: + { + bool hasRange = false; + uint32_t minValue = 0; + uint32_t maxValue = 0xffffffff; + + if (parser.LookAhead(",")) { - bool hasRange = false; - uint32_t minValue = 0; - uint32_t maxValue = 0xffffffff; + parser.ReadToken(); + minValue = parser.ReadUInt(); + + hasRange = true; if (parser.LookAhead(",")) { parser.ReadToken(); - minValue = parser.ReadUInt(); - - hasRange = true; - - if (parser.LookAhead(",")) - { - parser.ReadToken(); - maxValue = parser.ReadUInt(); - } + maxValue = parser.ReadUInt(); } + } - SLANG_ASSERT(minValue <= maxValue); - maxValue = (maxValue >= minValue) ? maxValue : minValue; + SLANG_ASSERT(minValue <= maxValue); + maxValue = (maxValue >= minValue) ? maxValue : minValue; - // Generate the data - val->bufferData.setCount(size); + // Generate the data + val->bufferData.setCount(size); - uint32_t* dst = (uint32_t*)val->bufferData.getBuffer(); - for (int i = 0; i < size; ++i) - { - dst[i] = hasRange ? rand->nextUInt32InRange(minValue, maxValue) : rand->nextUInt32(); - } - - break; + uint32_t* dst = (uint32_t*)val->bufferData.getBuffer(); + for (int i = 0; i < size; ++i) + { + dst[i] = hasRange ? rand->nextUInt32InRange(minValue, maxValue) + : rand->nextUInt32(); } - case SLANG_SCALAR_TYPE_FLOAT32: + + break; + } + case SLANG_SCALAR_TYPE_FLOAT32: + { + float minValue = -1.0f; + float maxValue = 1.0f; + + if (parser.LookAhead(",")) { - float minValue = -1.0f; - float maxValue = 1.0f; - + parser.ReadToken(); + minValue = parser.ReadFloat(); + if (parser.LookAhead(",")) { parser.ReadToken(); - minValue = parser.ReadFloat(); - - if (parser.LookAhead(",")) - { - parser.ReadToken(); - maxValue = parser.ReadFloat(); - } + maxValue = parser.ReadFloat(); } + } - SLANG_ASSERT(minValue <= maxValue); - maxValue = (maxValue >= minValue) ? maxValue : minValue; + SLANG_ASSERT(minValue <= maxValue); + maxValue = (maxValue >= minValue) ? maxValue : minValue; - // Generate the data - val->bufferData.setCount(size); + // Generate the data + val->bufferData.setCount(size); - float* dst = (float*)val->bufferData.getBuffer(); - for (int i = 0; i < size; ++i) - { - dst[i] = (rand->nextUnitFloat32() * (maxValue - minValue)) + minValue; - } - break; + float* dst = (float*)val->bufferData.getBuffer(); + for (int i = 0; i < size; ++i) + { + dst[i] = (rand->nextUnitFloat32() * (maxValue - minValue)) + minValue; } + break; } + } - // Read the range + // Read the range - parser.Read(")"); - } - else if(word == "format") - { - val->bufferDesc.format = parseFormatOption(parser); - } - else - { - return parseOption(parser, word, static_cast<ShaderInputLayout::DataValBase*>(val)); - } - return SLANG_OK; + parser.Read(")"); } - - SlangResult parseOption(Misc::TokenReader& parser, String const& word, ShaderInputLayout::ObjectVal* val) + else if (word == "format") { - if( word == "type" ) - { - parser.Read("="); - val->typeName = parser.ReadWord(); - } - else - { - return SLANG_FAIL; - } - return SLANG_OK; + val->bufferDesc.format = parseFormatOption(parser); + } + else + { + return parseOption(parser, word, static_cast<ShaderInputLayout::DataValBase*>(val)); } + return SLANG_OK; + } - Format parseFormatOption(Misc::TokenReader& parser) + SlangResult parseOption( + Misc::TokenReader& parser, + String const& word, + ShaderInputLayout::ObjectVal* val) + { + if (word == "type") { parser.Read("="); - auto formatWord = parser.ReadWord(); - - return _getFormatFromName(formatWord.getUnownedSlice()); + val->typeName = parser.ReadWord(); } + else + { + return SLANG_FAIL; + } + return SLANG_OK; + } - template<typename T> - void maybeParseOptions(Misc::TokenReader& parser, T* val) + Format parseFormatOption(Misc::TokenReader& parser) + { + parser.Read("="); + auto formatWord = parser.ReadWord(); + + return _getFormatFromName(formatWord.getUnownedSlice()); + } + + template<typename T> + void maybeParseOptions(Misc::TokenReader& parser, T* val) + { + // parse options + if (parser.LookAhead("(")) { - // parse options - if (parser.LookAhead("(")) + parser.Read("("); + while (!parser.IsEnd() && !parser.LookAhead(")")) { - parser.Read("("); - while (!parser.IsEnd() && !parser.LookAhead(")")) + auto word = parser.ReadWord(); + if (SLANG_FAILED(parseOption(parser, word, val))) { - auto word = parser.ReadWord(); - if( SLANG_FAILED(parseOption(parser, word, val)) ) - { - throw ShaderInputLayoutFormatException(String("Unsupported option '") + word + String("' at line ") + String(parser.NextToken().Position.Line)); - } - - if (parser.LookAhead(",")) - parser.Read(","); - else - break; + throw ShaderInputLayoutFormatException( + String("Unsupported option '") + word + String("' at line ") + + String(parser.NextToken().Position.Line)); } - parser.Read(")"); + + if (parser.LookAhead(",")) + parser.Read(","); + else + break; } + parser.Read(")"); } + } - RefPtr<ShaderInputLayout::Val> parseNumericValExpr(Misc::TokenReader& parser, bool negate = false) + RefPtr<ShaderInputLayout::Val> parseNumericValExpr( + Misc::TokenReader& parser, + bool negate = false) + { + switch (parser.NextToken().Type) { - switch(parser.NextToken().Type) + case Misc::TokenType::IntLiteral: { - case Misc::TokenType::IntLiteral: - { - RefPtr<ShaderInputLayout::DataVal> val = new ShaderInputLayout::DataVal; - - uint32_t value = parser.ReadUInt(); - if(negate) value = uint32_t(-int32_t(value)); - val->bufferData.add(value); + RefPtr<ShaderInputLayout::DataVal> val = new ShaderInputLayout::DataVal; - return val; - } - break; + uint32_t value = parser.ReadUInt(); + if (negate) + value = uint32_t(-int32_t(value)); + val->bufferData.add(value); - case Misc::TokenType::DoubleLiteral: - { - RefPtr<ShaderInputLayout::DataVal> val = new ShaderInputLayout::DataVal; + return val; + } + break; - float floatValue = parser.ReadFloat(); - if(negate) floatValue = -floatValue; + case Misc::TokenType::DoubleLiteral: + { + RefPtr<ShaderInputLayout::DataVal> val = new ShaderInputLayout::DataVal; - uint32_t value = 0; - memcpy(&value, &floatValue, sizeof(floatValue)); - val->bufferData.add(value); + float floatValue = parser.ReadFloat(); + if (negate) + floatValue = -floatValue; - return val; - } - break; + uint32_t value = 0; + memcpy(&value, &floatValue, sizeof(floatValue)); + val->bufferData.add(value); - default: - throw ShaderInputLayoutFormatException(String("Expected a numeric literal but found '") + parser.NextToken().Content + String("' at line") + String(parser.NextToken().Position.Line)); + return val; } + break; + + default: + throw ShaderInputLayoutFormatException( + String("Expected a numeric literal but found '") + parser.NextToken().Content + + String("' at line") + String(parser.NextToken().Position.Line)); } + } - String parseTypeName(Misc::TokenReader& parser) + String parseTypeName(Misc::TokenReader& parser) + { + String typeName = parser.ReadWord(); + if (parser.AdvanceIf("<")) { - String typeName = parser.ReadWord(); - if (parser.AdvanceIf("<")) + StringBuilder sb; + sb << typeName << "<"; + for (;;) { - StringBuilder sb; - sb << typeName << "<"; - for (;;) - { - if (parser.LookAhead(Misc::TokenType::IntLiteral)) - sb << parser.ReadInt(); - else - sb << parseTypeName(parser); - if (!parser.AdvanceIf(",")) - break; - sb << ","; - } - sb << ">"; - parser.Read(">"); - return sb.produceString(); + if (parser.LookAhead(Misc::TokenType::IntLiteral)) + sb << parser.ReadInt(); + else + sb << parseTypeName(parser); + if (!parser.AdvanceIf(",")) + break; + sb << ","; } - return typeName; + sb << ">"; + parser.Read(">"); + return sb.produceString(); } + return typeName; + } - RefPtr<ShaderInputLayout::Val> parseValExpr(Misc::TokenReader& parser) - { - typedef Misc::TokenType TokenType; + RefPtr<ShaderInputLayout::Val> parseValExpr(Misc::TokenReader& parser) + { + typedef Misc::TokenType TokenType; - switch(parser.NextToken().Type) + switch (parser.NextToken().Type) + { + case TokenType::OpSub: { - case TokenType::OpSub: - { - parser.ReadToken(); - return parseNumericValExpr(parser, true); - } - break; - - case TokenType::IntLiteral: - case TokenType::DoubleLiteral: - return parseNumericValExpr(parser); - - case TokenType::LBrace: - { - // aggregate - parser.ReadToken(); - RefPtr<ShaderInputLayout::AggVal> val = new ShaderInputLayout::AggVal; - - while( !parser.IsEnd() && !parser.LookAhead(TokenType::RBrace) ) - { - ShaderInputLayout::Field field; - - if( parser.LookAhead(TokenType::Identifier) && parser.NextToken(1).Type == TokenType::Colon ) - { - field.name = parser.ReadWord(); - parser.Read(TokenType::Colon); - } - - field.val = parseValExpr(parser); - - val->fields.add(field); - - if(parser.LookAhead(TokenType::RBrace)) - break; - - parser.Read(TokenType::Comma); - } - parser.Read(TokenType::RBrace); + parser.ReadToken(); + return parseNumericValExpr(parser, true); + } + break; + case TokenType::IntLiteral: + case TokenType::DoubleLiteral: return parseNumericValExpr(parser); - return val; - } - break; + case TokenType::LBrace: + { + // aggregate + parser.ReadToken(); + RefPtr<ShaderInputLayout::AggVal> val = new ShaderInputLayout::AggVal; - case TokenType::LBracket: + while (!parser.IsEnd() && !parser.LookAhead(TokenType::RBrace)) { - // array - parser.ReadToken(); - RefPtr<ShaderInputLayout::ArrayVal> val = new ShaderInputLayout::ArrayVal; + ShaderInputLayout::Field field; - while( !parser.IsEnd() && !parser.LookAhead(TokenType::RBracket) ) + if (parser.LookAhead(TokenType::Identifier) && + parser.NextToken(1).Type == TokenType::Colon) { - val->vals.add(parseValExpr(parser)); - - if(parser.LookAhead(TokenType::RBracket)) - break; - - parser.Read(TokenType::Comma); + field.name = parser.ReadWord(); + parser.Read(TokenType::Colon); } - parser.Read(TokenType::RBracket); - - return val; - } - break; - case TokenType::Identifier: - { - if( parser.AdvanceIf("new") ) - { - RefPtr<ShaderInputLayout::ObjectVal> val = new ShaderInputLayout::ObjectVal; + field.val = parseValExpr(parser); - if( parser.NextToken().Type == TokenType::Identifier ) - { - val->typeName = parseTypeName(parser); - } + val->fields.add(field); - val->contentVal = parseValExpr(parser); - return val; - } - else if( parser.AdvanceIf("out") ) - { - auto val = parseValExpr(parser); - val->isOutput = true; - return val; - } - else if (parser.AdvanceIf("specialize")) - { - RefPtr<ShaderInputLayout::SpecializeVal> val = - new ShaderInputLayout::SpecializeVal(); + if (parser.LookAhead(TokenType::RBrace)) + break; - parser.Read(Misc::TokenType::LParent); - while (!parser.IsEnd() && - parser.NextToken().Type != Misc::TokenType::RParent) - { - val->typeArgs.add(parseTypeName(parser)); - if (!parser.AdvanceIf(",")) - break; - } - parser.Read(Misc::TokenType::RParent); - val->contentVal = parseValExpr(parser); - return val; - } - else if (parser.AdvanceIf("dynamic")) - { - RefPtr<ShaderInputLayout::SpecializeVal> val = - new ShaderInputLayout::SpecializeVal(); - val->typeArgs.add("__Dynamic"); - val->contentVal = parseValExpr(parser); - return val; - } - else - { - // We assume that any other word is introducing one of the other - // cases for a parse-able value. - return parseVal(parser); - } + parser.Read(TokenType::Comma); } - break; + parser.Read(TokenType::RBrace); - default: - throw ShaderInputLayoutFormatException(String("Unexpected '") + parser.NextToken().Content + String("' at line") + String(parser.NextToken().Position.Line)); - } - } - RefPtr<ShaderInputLayout::Val> parseVal(Misc::TokenReader& parser) - { - auto word = parser.NextToken().Content; - if (parser.AdvanceIf("begin_array")) - { - RefPtr<ShaderInputLayout::ArrayVal> val = new ShaderInputLayout::ArrayVal; - pushParentVal(val); return val; } - else if (parser.AdvanceIf("begin_object")) - { - RefPtr<ShaderInputLayout::ObjectVal> val = new ShaderInputLayout::ObjectVal; - maybeParseOptions(parser, val.Ptr()); - - RefPtr<ShaderInputLayout::AggVal> contentVal = new ShaderInputLayout::AggVal; - val->contentVal = contentVal; - pushParentVal(contentVal); + break; - return val; - } - else if (parser.AdvanceIf("uniform")) + case TokenType::LBracket: { - RefPtr<ShaderInputLayout::DataVal> val = new ShaderInputLayout::DataVal; - maybeParseOptions(parser, val.Ptr()); - return val; - } - else if (parser.AdvanceIf("cbuffer")) - { - // A `cbuffer` is basically just an object where the content of - // the object is being provided by `uniform` data instead. + // array + parser.ReadToken(); + RefPtr<ShaderInputLayout::ArrayVal> val = new ShaderInputLayout::ArrayVal; - RefPtr<ShaderInputLayout::ObjectVal> objVal = new ShaderInputLayout::ObjectVal; + while (!parser.IsEnd() && !parser.LookAhead(TokenType::RBracket)) + { + val->vals.add(parseValExpr(parser)); - RefPtr<ShaderInputLayout::DataVal> dataVal = new ShaderInputLayout::DataVal; - maybeParseOptions(parser, dataVal.Ptr()); + if (parser.LookAhead(TokenType::RBracket)) + break; - objVal->contentVal = dataVal; + parser.Read(TokenType::Comma); + } + parser.Read(TokenType::RBracket); - return objVal; - } - else if (parser.AdvanceIf("ubuffer")) - { - RefPtr<ShaderInputLayout::BufferVal> val = new ShaderInputLayout::BufferVal; - val->bufferDesc.type = InputBufferType::StorageBuffer; - maybeParseOptions(parser, val.Ptr()); - return val; - } - else if (parser.AdvanceIf("Texture1D")) - { - RefPtr<ShaderInputLayout::TextureVal> val = new ShaderInputLayout::TextureVal; - val->textureDesc.dimension = 1; - maybeParseOptions(parser, val.Ptr()); - return val; - } - else if (parser.AdvanceIf("RWTextureBuffer")) - { - RefPtr<ShaderInputLayout::BufferVal> val = new ShaderInputLayout::BufferVal; - val->bufferDesc.type = InputBufferType::StorageBuffer; - maybeParseOptions(parser, val.Ptr()); - return val; - } - else if (parser.AdvanceIf("Texture2D")) - { - RefPtr<ShaderInputLayout::TextureVal> val = new ShaderInputLayout::TextureVal; - val->textureDesc.dimension = 2; - maybeParseOptions(parser, val.Ptr()); - return val; - } - else if (parser.AdvanceIf("Texture3D")) - { - RefPtr<ShaderInputLayout::TextureVal> val = new ShaderInputLayout::TextureVal; - val->textureDesc.dimension = 3; - maybeParseOptions(parser, val.Ptr()); - return val; - } - else if (parser.AdvanceIf("TextureCube")) - { - RefPtr<ShaderInputLayout::TextureVal> val = new ShaderInputLayout::TextureVal; - val->textureDesc.dimension = 2; - val->textureDesc.isCube = true; - maybeParseOptions(parser, val.Ptr()); - return val; - } - else if (parser.AdvanceIf("RWTexture1D")) - { - RefPtr<ShaderInputLayout::TextureVal> val = new ShaderInputLayout::TextureVal; - val->textureDesc.dimension = 1; - val->textureDesc.isRWTexture = true; - maybeParseOptions(parser, val.Ptr()); - return val; - } - else if (parser.AdvanceIf("RWTexture2D")) - { - RefPtr<ShaderInputLayout::TextureVal> val = new ShaderInputLayout::TextureVal; - val->textureDesc.dimension = 2; - val->textureDesc.isRWTexture = true; - maybeParseOptions(parser, val.Ptr()); - return val; - } - else if (parser.AdvanceIf("RWTexture3D")) - { - RefPtr<ShaderInputLayout::TextureVal> val = new ShaderInputLayout::TextureVal; - val->textureDesc.dimension = 3; - val->textureDesc.isRWTexture = true; - maybeParseOptions(parser, val.Ptr()); return val; } - else if (parser.AdvanceIf("RWTextureCube")) - { - RefPtr<ShaderInputLayout::TextureVal> val = new ShaderInputLayout::TextureVal; - val->textureDesc.dimension = 2; - val->textureDesc.isCube = true; - val->textureDesc.isRWTexture = true; - maybeParseOptions(parser, val.Ptr()); - return val; - } - else if (parser.AdvanceIf("Sampler")) - { - RefPtr<ShaderInputLayout::SamplerVal> val = new ShaderInputLayout::SamplerVal; - maybeParseOptions(parser, val.Ptr()); - return val; - } - else if (parser.AdvanceIf("TextureSampler1D")) - { - RefPtr<ShaderInputLayout::CombinedTextureSamplerVal> val = new ShaderInputLayout::CombinedTextureSamplerVal; - val->textureVal = new ShaderInputLayout::TextureVal; - val->samplerVal = new ShaderInputLayout::SamplerVal; - val->textureVal->textureDesc.dimension = 1; - maybeParseOptions(parser, val.Ptr()); - return val; - } - else if (parser.AdvanceIf("TextureSampler2D")) - { - RefPtr<ShaderInputLayout::CombinedTextureSamplerVal> val = new ShaderInputLayout::CombinedTextureSamplerVal; - val->textureVal = new ShaderInputLayout::TextureVal; - val->samplerVal = new ShaderInputLayout::SamplerVal; - val->textureVal->textureDesc.dimension = 2; - maybeParseOptions(parser, val.Ptr()); - return val; - } - else if (parser.AdvanceIf("TextureSampler3D")) - { - RefPtr<ShaderInputLayout::CombinedTextureSamplerVal> val = new ShaderInputLayout::CombinedTextureSamplerVal; - val->textureVal = new ShaderInputLayout::TextureVal; - val->samplerVal = new ShaderInputLayout::SamplerVal; - val->textureVal->textureDesc.dimension = 3; - maybeParseOptions(parser, val.Ptr()); - return val; - } - else if (parser.AdvanceIf("TextureSamplerCube")) - { - RefPtr<ShaderInputLayout::CombinedTextureSamplerVal> val = new ShaderInputLayout::CombinedTextureSamplerVal; - val->textureVal = new ShaderInputLayout::TextureVal; - val->samplerVal = new ShaderInputLayout::SamplerVal; - val->textureVal->textureDesc.dimension = 2; - val->textureVal->textureDesc.isCube = true; - maybeParseOptions(parser, val.Ptr()); - return val; - } - else if (parser.AdvanceIf("AccelerationStructure")) - { - RefPtr<ShaderInputLayout::AccelerationStructureVal> val = - new ShaderInputLayout::AccelerationStructureVal(); - return val; - } - else - { - throw ShaderInputLayoutFormatException(String("Unknown shader input type '") + word + String("' at line") + String(parser.NextToken().Position.Line)); - } - parser.ReadToken(); - return nullptr; - } - - String parseName(Misc::TokenReader& parser) - { - typedef Misc::Token Token; - typedef Misc::TokenType TokenType; - - StringBuilder builder; + break; - Token nameToken = parser.ReadToken(); - if (nameToken.Type != TokenType::Identifier) + case TokenType::Identifier: { - throw ShaderInputLayoutFormatException(StringBuilder() << "Invalid input syntax at line " << parser.NextToken().Position.Line); - } - builder << nameToken.Content; + if (parser.AdvanceIf("new")) + { + RefPtr<ShaderInputLayout::ObjectVal> val = new ShaderInputLayout::ObjectVal; - for(;;) - { - Token token = parser.NextToken(0); + if (parser.NextToken().Type == TokenType::Identifier) + { + val->typeName = parseTypeName(parser); + } - if (token.Type == TokenType::LBracket) + val->contentVal = parseValExpr(parser); + return val; + } + else if (parser.AdvanceIf("out")) { - parser.ReadToken(); - int index = parser.ReadInt(); - SLANG_ASSERT(index >= 0); - parser.ReadMatchingToken(TokenType::RBracket); - - builder << "[" << index << "]"; + auto val = parseValExpr(parser); + val->isOutput = true; + return val; } - else if (token.Type == TokenType::Dot) + else if (parser.AdvanceIf("specialize")) { - parser.ReadToken(); - Token identifierToken = parser.ReadMatchingToken(TokenType::Identifier); + RefPtr<ShaderInputLayout::SpecializeVal> val = + new ShaderInputLayout::SpecializeVal(); - builder << "." << identifierToken.Content; + parser.Read(Misc::TokenType::LParent); + while (!parser.IsEnd() && parser.NextToken().Type != Misc::TokenType::RParent) + { + val->typeArgs.add(parseTypeName(parser)); + if (!parser.AdvanceIf(",")) + break; + } + parser.Read(Misc::TokenType::RParent); + val->contentVal = parseValExpr(parser); + return val; + } + else if (parser.AdvanceIf("dynamic")) + { + RefPtr<ShaderInputLayout::SpecializeVal> val = + new ShaderInputLayout::SpecializeVal(); + val->typeArgs.add("__Dynamic"); + val->contentVal = parseValExpr(parser); + return val; } else { - return builder; + // We assume that any other word is introducing one of the other + // cases for a parse-able value. + return parseVal(parser); } } + break; + + default: + throw ShaderInputLayoutFormatException( + String("Unexpected '") + parser.NextToken().Content + String("' at line") + + String(parser.NextToken().Position.Line)); } + } - void parseFieldBindings(Misc::TokenReader& parser, ShaderInputLayout::Field& ioField) + RefPtr<ShaderInputLayout::Val> parseVal(Misc::TokenReader& parser) + { + auto word = parser.NextToken().Content; + if (parser.AdvanceIf("begin_array")) { - // parse bindings - if (parser.LookAhead(":")) - { - parser.Read(":"); - while (!parser.IsEnd()) - { - if (parser.AdvanceIf("out")) - { - ioField.val->isOutput = true; - } - else if (parser.AdvanceIf("name")) - { - // Optionally consume '=' - if (parser.NextToken().Type == Misc::TokenType::OpAssign) - { - parser.ReadToken(); - } + RefPtr<ShaderInputLayout::ArrayVal> val = new ShaderInputLayout::ArrayVal; + pushParentVal(val); + return val; + } + else if (parser.AdvanceIf("begin_object")) + { + RefPtr<ShaderInputLayout::ObjectVal> val = new ShaderInputLayout::ObjectVal; + maybeParseOptions(parser, val.Ptr()); - ioField.name = parseName(parser); - } - else - { - fprintf(stderr, "Invalid TEST_INPUT syntax '%s'\n", parser.NextToken().Content.getBuffer()); - break; - } + RefPtr<ShaderInputLayout::AggVal> contentVal = new ShaderInputLayout::AggVal; + val->contentVal = contentVal; + pushParentVal(contentVal); - if (parser.LookAhead(",")) - parser.Read(","); - } - } + return val; } - - void pushParentVal(ShaderInputLayout::ParentVal* val) + else if (parser.AdvanceIf("uniform")) { - parentValStack.add(parentVal); - parentVal = val; + RefPtr<ShaderInputLayout::DataVal> val = new ShaderInputLayout::DataVal; + maybeParseOptions(parser, val.Ptr()); + return val; } - - void parseValEntry(Misc::TokenReader& parser) + else if (parser.AdvanceIf("cbuffer")) { - auto parentForNewVal = parentVal; + // A `cbuffer` is basically just an object where the content of + // the object is being provided by `uniform` data instead. - ShaderInputLayout::Field field; - field.val = parseVal(parser); - parseFieldBindings(parser, field); + RefPtr<ShaderInputLayout::ObjectVal> objVal = new ShaderInputLayout::ObjectVal; - parentForNewVal->addField(field); - } + RefPtr<ShaderInputLayout::DataVal> dataVal = new ShaderInputLayout::DataVal; + maybeParseOptions(parser, dataVal.Ptr()); + + objVal->contentVal = dataVal; - void parseSetEntry(Misc::TokenReader& parser) + return objVal; + } + else if (parser.AdvanceIf("ubuffer")) + { + RefPtr<ShaderInputLayout::BufferVal> val = new ShaderInputLayout::BufferVal; + val->bufferDesc.type = InputBufferType::StorageBuffer; + maybeParseOptions(parser, val.Ptr()); + return val; + } + else if (parser.AdvanceIf("Texture1D")) + { + RefPtr<ShaderInputLayout::TextureVal> val = new ShaderInputLayout::TextureVal; + val->textureDesc.dimension = 1; + maybeParseOptions(parser, val.Ptr()); + return val; + } + else if (parser.AdvanceIf("RWTextureBuffer")) + { + RefPtr<ShaderInputLayout::BufferVal> val = new ShaderInputLayout::BufferVal; + val->bufferDesc.type = InputBufferType::StorageBuffer; + maybeParseOptions(parser, val.Ptr()); + return val; + } + else if (parser.AdvanceIf("Texture2D")) + { + RefPtr<ShaderInputLayout::TextureVal> val = new ShaderInputLayout::TextureVal; + val->textureDesc.dimension = 2; + maybeParseOptions(parser, val.Ptr()); + return val; + } + else if (parser.AdvanceIf("Texture3D")) + { + RefPtr<ShaderInputLayout::TextureVal> val = new ShaderInputLayout::TextureVal; + val->textureDesc.dimension = 3; + maybeParseOptions(parser, val.Ptr()); + return val; + } + else if (parser.AdvanceIf("TextureCube")) + { + RefPtr<ShaderInputLayout::TextureVal> val = new ShaderInputLayout::TextureVal; + val->textureDesc.dimension = 2; + val->textureDesc.isCube = true; + maybeParseOptions(parser, val.Ptr()); + return val; + } + else if (parser.AdvanceIf("RWTexture1D")) + { + RefPtr<ShaderInputLayout::TextureVal> val = new ShaderInputLayout::TextureVal; + val->textureDesc.dimension = 1; + val->textureDesc.isRWTexture = true; + maybeParseOptions(parser, val.Ptr()); + return val; + } + else if (parser.AdvanceIf("RWTexture2D")) + { + RefPtr<ShaderInputLayout::TextureVal> val = new ShaderInputLayout::TextureVal; + val->textureDesc.dimension = 2; + val->textureDesc.isRWTexture = true; + maybeParseOptions(parser, val.Ptr()); + return val; + } + else if (parser.AdvanceIf("RWTexture3D")) + { + RefPtr<ShaderInputLayout::TextureVal> val = new ShaderInputLayout::TextureVal; + val->textureDesc.dimension = 3; + val->textureDesc.isRWTexture = true; + maybeParseOptions(parser, val.Ptr()); + return val; + } + else if (parser.AdvanceIf("RWTextureCube")) + { + RefPtr<ShaderInputLayout::TextureVal> val = new ShaderInputLayout::TextureVal; + val->textureDesc.dimension = 2; + val->textureDesc.isCube = true; + val->textureDesc.isRWTexture = true; + maybeParseOptions(parser, val.Ptr()); + return val; + } + else if (parser.AdvanceIf("Sampler")) + { + RefPtr<ShaderInputLayout::SamplerVal> val = new ShaderInputLayout::SamplerVal; + maybeParseOptions(parser, val.Ptr()); + return val; + } + else if (parser.AdvanceIf("TextureSampler1D")) + { + RefPtr<ShaderInputLayout::CombinedTextureSamplerVal> val = + new ShaderInputLayout::CombinedTextureSamplerVal; + val->textureVal = new ShaderInputLayout::TextureVal; + val->samplerVal = new ShaderInputLayout::SamplerVal; + val->textureVal->textureDesc.dimension = 1; + maybeParseOptions(parser, val.Ptr()); + return val; + } + else if (parser.AdvanceIf("TextureSampler2D")) + { + RefPtr<ShaderInputLayout::CombinedTextureSamplerVal> val = + new ShaderInputLayout::CombinedTextureSamplerVal; + val->textureVal = new ShaderInputLayout::TextureVal; + val->samplerVal = new ShaderInputLayout::SamplerVal; + val->textureVal->textureDesc.dimension = 2; + maybeParseOptions(parser, val.Ptr()); + return val; + } + else if (parser.AdvanceIf("TextureSampler3D")) { - auto parentForNewVal = parentVal; + RefPtr<ShaderInputLayout::CombinedTextureSamplerVal> val = + new ShaderInputLayout::CombinedTextureSamplerVal; + val->textureVal = new ShaderInputLayout::TextureVal; + val->samplerVal = new ShaderInputLayout::SamplerVal; + val->textureVal->textureDesc.dimension = 3; + maybeParseOptions(parser, val.Ptr()); + return val; + } + else if (parser.AdvanceIf("TextureSamplerCube")) + { + RefPtr<ShaderInputLayout::CombinedTextureSamplerVal> val = + new ShaderInputLayout::CombinedTextureSamplerVal; + val->textureVal = new ShaderInputLayout::TextureVal; + val->samplerVal = new ShaderInputLayout::SamplerVal; + val->textureVal->textureDesc.dimension = 2; + val->textureVal->textureDesc.isCube = true; + maybeParseOptions(parser, val.Ptr()); + return val; + } + else if (parser.AdvanceIf("AccelerationStructure")) + { + RefPtr<ShaderInputLayout::AccelerationStructureVal> val = + new ShaderInputLayout::AccelerationStructureVal(); + return val; + } + else + { + throw ShaderInputLayoutFormatException( + String("Unknown shader input type '") + word + String("' at line") + + String(parser.NextToken().Position.Line)); + } + parser.ReadToken(); + return nullptr; + } - ShaderInputLayout::Field field; - field.name = parseName(parser); - parser.Read(Misc::TokenType::OpAssign); - field.val = parseValExpr(parser); + String parseName(Misc::TokenReader& parser) + { + typedef Misc::Token Token; + typedef Misc::TokenType TokenType; - parentForNewVal->addField(field); - } + StringBuilder builder; - void parseTypeConformance(Misc::TokenReader& parser) + Token nameToken = parser.ReadToken(); + if (nameToken.Type != TokenType::Identifier) { - ShaderInputLayout::TypeConformanceVal conformance; - conformance.derivedTypeName = parseTypeName(parser); - parser.Read(":"); - conformance.baseTypeName = parseTypeName(parser); - if (parser.AdvanceIf("=")) - conformance.idOverride = parser.ReadInt(); - layout->typeConformances.add(conformance); + throw ShaderInputLayoutFormatException( + StringBuilder() << "Invalid input syntax at line " + << parser.NextToken().Position.Line); } + builder << nameToken.Content; - void parseLine(Misc::TokenReader& parser) + for (;;) { - if (parser.LookAhead("entryPointSpecializationArg") - || parser.LookAhead("type") - || parser.LookAhead("entryPointExistentialType")) + Token token = parser.NextToken(0); + + if (token.Type == TokenType::LBracket) { parser.ReadToken(); - StringBuilder typeExp; - while (!parser.IsEnd()) - typeExp << parser.ReadToken().Content; - layout->entryPointSpecializationArgs.add(typeExp); + int index = parser.ReadInt(); + SLANG_ASSERT(index >= 0); + parser.ReadMatchingToken(TokenType::RBracket); + + builder << "[" << index << "]"; } - else if (parser.LookAhead("globalSpecializationArg") - || parser.LookAhead("global_type") - || parser.LookAhead("globalExistentialType")) + else if (token.Type == TokenType::Dot) { parser.ReadToken(); - StringBuilder typeExp; - while (!parser.IsEnd()) - typeExp << parser.ReadToken().Content; - layout->globalSpecializationArgs.add(typeExp); - } - else if (parser.AdvanceIf("render_targets")) - { - layout->numRenderTargets = parser.ReadInt(); - } - else if( parser.AdvanceIf("end") ) - { - parentVal = parentValStack.getLast(); - parentValStack.removeLast(); - } - else if( parser.AdvanceIf("set") ) - { - parseSetEntry(parser); - } - else if (parser.AdvanceIf("type_conformance")) - { - parseTypeConformance(parser); + Token identifierToken = parser.ReadMatchingToken(TokenType::Identifier); + + builder << "." << identifierToken.Content; } else { - parseValEntry(parser); + return builder; } } + } - RefPtr<ShaderInputLayout::AggVal> parse(const char * source) + void parseFieldBindings(Misc::TokenReader& parser, ShaderInputLayout::Field& ioField) + { + // parse bindings + if (parser.LookAhead(":")) { - RefPtr<ShaderInputLayout::AggVal> rootVal = new ShaderInputLayout::AggVal; - parentVal = rootVal; - - auto lines = Misc::Split(source, '\n'); - for (auto & line : lines) + parser.Read(":"); + while (!parser.IsEnd()) { - if (line.startsWith("//TEST_INPUT:")) + if (parser.AdvanceIf("out")) { - auto lineContent = line.subString(13, line.getLength() - 13); - Misc::TokenReader parser(lineContent); - try - { - parseLine(parser); - } - catch (const Misc::TextFormatException&) + ioField.val->isOutput = true; + } + else if (parser.AdvanceIf("name")) + { + // Optionally consume '=' + if (parser.NextToken().Type == Misc::TokenType::OpAssign) { - StringBuilder msg; - msg << "Invalid input syntax at line " << parser.NextToken().Position.Line; - throw ShaderInputLayoutFormatException(msg); + parser.ReadToken(); } + + ioField.name = parseName(parser); } + else + { + fprintf( + stderr, + "Invalid TEST_INPUT syntax '%s'\n", + parser.NextToken().Content.getBuffer()); + break; + } + + if (parser.LookAhead(",")) + parser.Read(","); } + } + } - // TODO: check that stack has been maintained correctly... + void pushParentVal(ShaderInputLayout::ParentVal* val) + { + parentValStack.add(parentVal); + parentVal = val; + } - return rootVal; - } - }; + void parseValEntry(Misc::TokenReader& parser) + { + auto parentForNewVal = parentVal; + + ShaderInputLayout::Field field; + field.val = parseVal(parser); + parseFieldBindings(parser, field); + + parentForNewVal->addField(field); + } - void ShaderInputLayout::parse(RandomGenerator* rand, const char * source) + void parseSetEntry(Misc::TokenReader& parser) { - rootVal = nullptr; - globalSpecializationArgs.clear(); - entryPointSpecializationArgs.clear(); + auto parentForNewVal = parentVal; + + ShaderInputLayout::Field field; + field.name = parseName(parser); + parser.Read(Misc::TokenType::OpAssign); + field.val = parseValExpr(parser); - ShaderInputLayoutParser parser(this, rand); - rootVal = parser.parse(source); + parentForNewVal->addField(field); } - /* static */SlangResult ShaderInputLayout::writeBinding(slang::TypeLayoutReflection* typeLayout, const void* data, size_t sizeInBytes, WriterHelper writer) + void parseTypeConformance(Misc::TokenReader& parser) { - typedef slang::TypeReflection::ScalarType ScalarType; + ShaderInputLayout::TypeConformanceVal conformance; + conformance.derivedTypeName = parseTypeName(parser); + parser.Read(":"); + conformance.baseTypeName = parseTypeName(parser); + if (parser.AdvanceIf("=")) + conformance.idOverride = parser.ReadInt(); + layout->typeConformances.add(conformance); + } - slang::TypeReflection::ScalarType scalarType = slang::TypeReflection::ScalarType::None; + void parseLine(Misc::TokenReader& parser) + { + if (parser.LookAhead("entryPointSpecializationArg") || parser.LookAhead("type") || + parser.LookAhead("entryPointExistentialType")) + { + parser.ReadToken(); + StringBuilder typeExp; + while (!parser.IsEnd()) + typeExp << parser.ReadToken().Content; + layout->entryPointSpecializationArgs.add(typeExp); + } + else if ( + parser.LookAhead("globalSpecializationArg") || parser.LookAhead("global_type") || + parser.LookAhead("globalExistentialType")) + { + parser.ReadToken(); + StringBuilder typeExp; + while (!parser.IsEnd()) + typeExp << parser.ReadToken().Content; + layout->globalSpecializationArgs.add(typeExp); + } + else if (parser.AdvanceIf("render_targets")) + { + layout->numRenderTargets = parser.ReadInt(); + } + else if (parser.AdvanceIf("end")) + { + parentVal = parentValStack.getLast(); + parentValStack.removeLast(); + } + else if (parser.AdvanceIf("set")) + { + parseSetEntry(parser); + } + else if (parser.AdvanceIf("type_conformance")) + { + parseTypeConformance(parser); + } + else + { + parseValEntry(parser); + } + } - slang::TypeLayoutReflection* elementTypeLayout = nullptr; + RefPtr<ShaderInputLayout::AggVal> parse(const char* source) + { + RefPtr<ShaderInputLayout::AggVal> rootVal = new ShaderInputLayout::AggVal; + parentVal = rootVal; - if (typeLayout) + auto lines = Misc::Split(source, '\n'); + for (auto& line : lines) { - switch (typeLayout->getKind()) + if (line.startsWith("//TEST_INPUT:")) { - - //case slang::TypeReflection::Kind::Struct: - case slang::TypeReflection::Kind::Array: - case slang::TypeReflection::Kind::Matrix: - case slang::TypeReflection::Kind::Vector: + auto lineContent = line.subString(13, line.getLength() - 13); + Misc::TokenReader parser(lineContent); + try { - elementTypeLayout = typeLayout->getElementTypeLayout(); - break; + parseLine(parser); } - case slang::TypeReflection::Kind::Scalar: + catch (const Misc::TextFormatException&) { - elementTypeLayout = typeLayout; - break; - } - case slang::TypeReflection::Kind::Resource: - { - elementTypeLayout = typeLayout->getElementTypeLayout(); - break; - } - case slang::TypeReflection::Kind::TextureBuffer: - case slang::TypeReflection::Kind::ShaderStorageBuffer: - { - elementTypeLayout = typeLayout->getElementTypeLayout(); - break; + StringBuilder msg; + msg << "Invalid input syntax at line " << parser.NextToken().Position.Line; + throw ShaderInputLayoutFormatException(msg); } } } - if (elementTypeLayout) - { - scalarType = elementTypeLayout->getScalarType(); - } + // TODO: check that stack has been maintained correctly... - if (scalarType != ScalarType::None && scalarType != ScalarType::Void) - { - UnownedStringSlice text = TypeTextUtil::getScalarTypeName(scalarType); - // Write out the type - writer.put("type: "); - writer.put(text); - writer.put("\n"); - } + return rootVal; + } +}; + +void ShaderInputLayout::parse(RandomGenerator* rand, const char* source) +{ + rootVal = nullptr; + globalSpecializationArgs.clear(); + entryPointSpecializationArgs.clear(); + + ShaderInputLayoutParser parser(this, rand); + rootVal = parser.parse(source); +} + +/* static */ SlangResult ShaderInputLayout::writeBinding( + slang::TypeLayoutReflection* typeLayout, + const void* data, + size_t sizeInBytes, + WriterHelper writer) +{ + typedef slang::TypeReflection::ScalarType ScalarType; - switch (scalarType) + slang::TypeReflection::ScalarType scalarType = slang::TypeReflection::ScalarType::None; + + slang::TypeLayoutReflection* elementTypeLayout = nullptr; + + if (typeLayout) + { + switch (typeLayout->getKind()) { - // TODO(JS): - // Bool is here, because it's not clear across APIs how bool is laid out in memory - default: - case ScalarType::None: - case ScalarType::Void: - case ScalarType::Bool: + + // case slang::TypeReflection::Kind::Struct: + case slang::TypeReflection::Kind::Array: + case slang::TypeReflection::Kind::Matrix: + case slang::TypeReflection::Kind::Vector: { - auto ptr = (const uint32_t*)data; - const size_t size = sizeInBytes / sizeof(ptr[0]); - for (size_t i = 0; i < size; ++i) - { - uint32_t v = ptr[i]; - writer.print("%X\n", v); - } + elementTypeLayout = typeLayout->getElementTypeLayout(); break; } - case ScalarType::Float16: + case slang::TypeReflection::Kind::Scalar: { - auto ptr = (const uint16_t*)data; - const size_t size = sizeInBytes / sizeof(ptr[0]); - for (size_t i = 0; i < size; ++i) - { - const float v = HalfToFloat(ptr[i]); - writer.print("%f\n", v); - } + elementTypeLayout = typeLayout; break; } - case ScalarType::UInt32: + case slang::TypeReflection::Kind::Resource: { - auto ptr = (const uint32_t*)data; - const size_t size = sizeInBytes / sizeof(ptr[0]); - for (size_t i = 0; i < size; ++i) - { - uint32_t v = ptr[i]; - writer.print("%u\n", v); - } + elementTypeLayout = typeLayout->getElementTypeLayout(); break; } - case ScalarType::Int32: + case slang::TypeReflection::Kind::TextureBuffer: + case slang::TypeReflection::Kind::ShaderStorageBuffer: { - auto ptr = (const int32_t*)data; - const size_t size = sizeInBytes / sizeof(ptr[0]); - for (size_t i = 0; i < size; ++i) - { - int32_t v = ptr[i]; - writer.print("%i\n", v); - } + elementTypeLayout = typeLayout->getElementTypeLayout(); break; } - case ScalarType::Int64: + } + } + + if (elementTypeLayout) + { + scalarType = elementTypeLayout->getScalarType(); + } + + if (scalarType != ScalarType::None && scalarType != ScalarType::Void) + { + UnownedStringSlice text = TypeTextUtil::getScalarTypeName(scalarType); + // Write out the type + writer.put("type: "); + writer.put(text); + writer.put("\n"); + } + + switch (scalarType) + { + // TODO(JS): + // Bool is here, because it's not clear across APIs how bool is laid out in memory + default: + case ScalarType::None: + case ScalarType::Void: + case ScalarType::Bool: + { + auto ptr = (const uint32_t*)data; + const size_t size = sizeInBytes / sizeof(ptr[0]); + for (size_t i = 0; i < size; ++i) + { + uint32_t v = ptr[i]; + writer.print("%X\n", v); + } + break; + } + case ScalarType::Float16: + { + auto ptr = (const uint16_t*)data; + const size_t size = sizeInBytes / sizeof(ptr[0]); + for (size_t i = 0; i < size; ++i) { - auto ptr = (const int64_t*)data; - const size_t size = sizeInBytes / sizeof(ptr[0]); - for (size_t i = 0; i < size; ++i) - { - int64_t v = ptr[i]; - writer.print("%" PRId64 "\n", v); - } - break; + const float v = HalfToFloat(ptr[i]); + writer.print("%f\n", v); } - case ScalarType::UInt64: + break; + } + case ScalarType::UInt32: + { + auto ptr = (const uint32_t*)data; + const size_t size = sizeInBytes / sizeof(ptr[0]); + for (size_t i = 0; i < size; ++i) { - auto ptr = (const uint64_t*)data; - const size_t size = sizeInBytes / sizeof(ptr[0]); - for (size_t i = 0; i < size; ++i) - { - uint64_t v = ptr[i]; - writer.print("%" PRIu64 "\n", v); - } - break; + uint32_t v = ptr[i]; + writer.print("%u\n", v); } - case ScalarType::Float32: + break; + } + case ScalarType::Int32: + { + auto ptr = (const int32_t*)data; + const size_t size = sizeInBytes / sizeof(ptr[0]); + for (size_t i = 0; i < size; ++i) { - auto ptr = (const float*)data; - const size_t size = sizeInBytes / sizeof(ptr[0]); - for (size_t i = 0; i < size; ++i) - { - const float v = ptr[i]; - writer.print("%f\n", v); - } - break; + int32_t v = ptr[i]; + writer.print("%i\n", v); } - case ScalarType::Float64: + break; + } + case ScalarType::Int64: + { + auto ptr = (const int64_t*)data; + const size_t size = sizeInBytes / sizeof(ptr[0]); + for (size_t i = 0; i < size; ++i) { - auto ptr = (const double*)data; - const size_t size = sizeInBytes / sizeof(ptr[0]); - for (size_t i = 0; i < size; ++i) - { - const double v = ptr[i]; - writer.print("%f\n", v); - } - break; + int64_t v = ptr[i]; + writer.print("%" PRId64 "\n", v); } + break; + } + case ScalarType::UInt64: + { + auto ptr = (const uint64_t*)data; + const size_t size = sizeInBytes / sizeof(ptr[0]); + for (size_t i = 0; i < size; ++i) + { + uint64_t v = ptr[i]; + writer.print("%" PRIu64 "\n", v); + } + break; + } + case ScalarType::Float32: + { + auto ptr = (const float*)data; + const size_t size = sizeInBytes / sizeof(ptr[0]); + for (size_t i = 0; i < size; ++i) + { + const float v = ptr[i]; + writer.print("%f\n", v); + } + break; + } + case ScalarType::Float64: + { + auto ptr = (const double*)data; + const size_t size = sizeInBytes / sizeof(ptr[0]); + for (size_t i = 0; i < size; ++i) + { + const double v = ptr[i]; + writer.print("%f\n", v); + } + break; } - - return SLANG_OK; } - void loadDataIntoHalf(uint16_t& out, const uint8_t& in) - { - out = FloatToHalf((float(in) / 255.0f)); - } - void loadDataIntoFloat(float& out, const uint8_t& in) - { - out = (float(in)/255.0f); - } - template<typename T> - void loadDataIntoUint(T& out, const uint8_t& in) - { - out = T(in); - } - template<typename T> - void loadDataIntoInt(T& out, const uint8_t& in) - { - out = T(in); - } + return SLANG_OK; +} - // T for type to return, F for function pointer to operate on uint8->T - template<typename T, typename F> - void generateTextureDataWithTargetTStorage(TextureData& output, const InputTextureDesc& desc, const rhi::FormatInfo& formatInfo, F loadUint8ToT) - { - // the following function assumes input of 0 or 1 since our testing framework only tests with 0 or 1 - TextureData work; - generateTextureDataRGB8(work, desc); +void loadDataIntoHalf(uint16_t& out, const uint8_t& in) +{ + out = FloatToHalf((float(in) / 255.0f)); +} +void loadDataIntoFloat(float& out, const uint8_t& in) +{ + out = (float(in) / 255.0f); +} +template<typename T> +void loadDataIntoUint(T& out, const uint8_t& in) +{ + out = T(in); +} +template<typename T> +void loadDataIntoInt(T& out, const uint8_t& in) +{ + out = T(in); +} - output.init(desc.format); +// T for type to return, F for function pointer to operate on uint8->T +template<typename T, typename F> +void generateTextureDataWithTargetTStorage( + TextureData& output, + const InputTextureDesc& desc, + const rhi::FormatInfo& formatInfo, + F loadUint8ToT) +{ + // the following function assumes input of 0 or 1 since our testing framework only tests with 0 + // or 1 + TextureData work; + generateTextureDataRGB8(work, desc); - output.m_textureSize = work.m_textureSize; - output.m_mipLevels = work.m_mipLevels; - output.m_arraySize = work.m_arraySize; + output.init(desc.format); - List<TextureData::Slice>& dstSlices = output.m_slices; + output.m_textureSize = work.m_textureSize; + output.m_mipLevels = work.m_mipLevels; + output.m_arraySize = work.m_arraySize; - Index numSlices = work.m_slices.getCount(); - dstSlices.setCount(numSlices); + List<TextureData::Slice>& dstSlices = output.m_slices; - for (int i = 0; i < numSlices; ++i) - { - const TextureData::Slice& srcSlice = work.m_slices[i]; + Index numSlices = work.m_slices.getCount(); + dstSlices.setCount(numSlices); - const Index pixelCount = srcSlice.valuesCount; - const uint8_t* srcPixels = (const uint8_t*)srcSlice.values; + for (int i = 0; i < numSlices; ++i) + { + const TextureData::Slice& srcSlice = work.m_slices[i]; - T* dstPixels = (T*)output.setSliceCount(i, pixelCount); - switch (formatInfo.channelCount) - { - case 1: + const Index pixelCount = srcSlice.valuesCount; + const uint8_t* srcPixels = (const uint8_t*)srcSlice.values; + + T* dstPixels = (T*)output.setSliceCount(i, pixelCount); + switch (formatInfo.channelCount) + { + case 1: { for (Index j = 0; j < pixelCount; ++j, srcPixels += 4, dstPixels += 1) { @@ -1198,7 +1251,7 @@ namespace renderer_test } break; } - case 2: + case 2: { for (Index j = 0; j < pixelCount; ++j, srcPixels += 4, dstPixels += 2) { @@ -1208,7 +1261,7 @@ namespace renderer_test } break; } - case 3: + case 3: { for (Index j = 0; j < pixelCount; ++j, srcPixels += 4, dstPixels += 3) { @@ -1219,7 +1272,7 @@ namespace renderer_test } break; } - case 4: + case 4: { for (Index j = 0; j < pixelCount; ++j, srcPixels += 4, dstPixels += 4) { @@ -1231,245 +1284,286 @@ namespace renderer_test } break; } - } } } - void generateTextureData(TextureData& output, const InputTextureDesc& desc) - { - const FormatInfo& formatInfo = getFormatInfo(desc.format); +} +void generateTextureData(TextureData& output, const InputTextureDesc& desc) +{ + const FormatInfo& formatInfo = getFormatInfo(desc.format); - switch (desc.format) + switch (desc.format) + { + case Format::R8G8B8A8_UNORM: { - case Format::R8G8B8A8_UNORM: - { - generateTextureDataRGB8(output, desc); - break; - } - case Format::R16_FLOAT: - case Format::R16G16_FLOAT: - case Format::R16G16B16A16_FLOAT: - { - generateTextureDataWithTargetTStorage<uint16_t>(output, desc, formatInfo, loadDataIntoHalf); - break; - } - case Format::R64_UINT: - { - generateTextureDataWithTargetTStorage<uint64_t>(output, desc, formatInfo, loadDataIntoUint<uint64_t>); - break; - } - case Format::R32_FLOAT: - case Format::R32G32_FLOAT: - case Format::R32G32B32_FLOAT: - case Format::R32G32B32A32_FLOAT: - case Format::D32_FLOAT: - { - generateTextureDataWithTargetTStorage<float>(output, desc, formatInfo, loadDataIntoFloat); - break; - } - case Format::R32_UINT: - case Format::R32G32_UINT: - case Format::R32G32B32_UINT: - case Format::R32G32B32A32_UINT: - { - generateTextureDataWithTargetTStorage<uint32_t>(output, desc, formatInfo, loadDataIntoUint<uint32_t>); - break; - } - case Format::R16_UINT: - case Format::R16G16_UINT: - case Format::R16G16B16A16_UINT: - { - generateTextureDataWithTargetTStorage<uint16_t>(output, desc, formatInfo, loadDataIntoUint<uint16_t>); - break; - } - case Format::R8_UINT: - case Format::R8G8_UINT: - case Format::R8G8B8A8_UINT: - { - generateTextureDataWithTargetTStorage<uint8_t>(output, desc, formatInfo, loadDataIntoUint<uint8_t>); - break; - } - case Format::R64_SINT: - { - generateTextureDataWithTargetTStorage<int64_t>(output, desc, formatInfo, loadDataIntoInt<int64_t>); - break; - } - case Format::R32_SINT: - case Format::R32G32_SINT: - case Format::R32G32B32_SINT: - case Format::R32G32B32A32_SINT: - { - generateTextureDataWithTargetTStorage<int32_t>(output, desc, formatInfo, loadDataIntoInt<int32_t>); - break; - } - case Format::R16_SINT: - case Format::R16G16_SINT: - case Format::R16G16B16A16_SINT: - { - generateTextureDataWithTargetTStorage<int16_t>(output, desc, formatInfo, loadDataIntoInt<int16_t>); - break; - } - case Format::R8_SINT: - case Format::R8G8_SINT: - case Format::R8G8B8A8_SINT: - { - generateTextureDataWithTargetTStorage<int8_t>(output, desc, formatInfo, loadDataIntoInt<int8_t>); - break; - } - default: - { - SLANG_ASSERT(!"Unhandled format"); - break; - } + generateTextureDataRGB8(output, desc); + break; } - } - - template <typename F> - void _iteratePixels(int dimension, int size, unsigned int * buffer, F f) - { - if (dimension == 1) - for (int i = 0; i < size; i++) - buffer[i] = f(i, 0, 0); - else if (dimension == 2) - for (int i = 0; i < size; i++) - for (int j = 0; j < size; j++) - buffer[i*size + j] = f(j, i, 0); - else if (dimension == 3) - for (int i = 0; i < size; i++) - for (int j = 0; j < size; j++) - for (int k = 0; k < size; k++) - buffer[i*size*size + j * size + k] = f(k, j, i); - }; - - void generateTextureDataRGB8(TextureData& output, const InputTextureDesc& inputDesc) - { - int arrLen = inputDesc.arrayLength; - if (arrLen == 0) - arrLen = 1; - - output.init(Format::R8G8B8A8_UNORM); - - enum class SimpleScalarType { - kUint, - kInt, - kFloat, - }; - SimpleScalarType type; - const rhi::FormatInfo& formatInfo = getFormatInfo(inputDesc.format); - switch (formatInfo.channelType) - { - case SLANG_SCALAR_TYPE_UINT64: - case SLANG_SCALAR_TYPE_UINT32: - case SLANG_SCALAR_TYPE_UINT16: - case SLANG_SCALAR_TYPE_UINT8: - type = SimpleScalarType::kUint; + case Format::R16_FLOAT: + case Format::R16G16_FLOAT: + case Format::R16G16B16A16_FLOAT: + { + generateTextureDataWithTargetTStorage<uint16_t>( + output, + desc, + formatInfo, + loadDataIntoHalf); break; - case SLANG_SCALAR_TYPE_INT64: - case SLANG_SCALAR_TYPE_INT32: - case SLANG_SCALAR_TYPE_INT16: - case SLANG_SCALAR_TYPE_INT8: - type = SimpleScalarType::kInt; + } + case Format::R64_UINT: + { + generateTextureDataWithTargetTStorage<uint64_t>( + output, + desc, + formatInfo, + loadDataIntoUint<uint64_t>); break; - case SLANG_SCALAR_TYPE_FLOAT64: - case SLANG_SCALAR_TYPE_FLOAT32: - case SLANG_SCALAR_TYPE_FLOAT16: - type = SimpleScalarType::kFloat; + } + case Format::R32_FLOAT: + case Format::R32G32_FLOAT: + case Format::R32G32B32_FLOAT: + case Format::R32G32B32A32_FLOAT: + case Format::D32_FLOAT: + { + generateTextureDataWithTargetTStorage<float>( + output, + desc, + formatInfo, + loadDataIntoFloat); break; - default: - type = SimpleScalarType::kUint; + } + case Format::R32_UINT: + case Format::R32G32_UINT: + case Format::R32G32B32_UINT: + case Format::R32G32B32A32_UINT: + { + generateTextureDataWithTargetTStorage<uint32_t>( + output, + desc, + formatInfo, + loadDataIntoUint<uint32_t>); + break; + } + case Format::R16_UINT: + case Format::R16G16_UINT: + case Format::R16G16B16A16_UINT: + { + generateTextureDataWithTargetTStorage<uint16_t>( + output, + desc, + formatInfo, + loadDataIntoUint<uint16_t>); + break; + } + case Format::R8_UINT: + case Format::R8G8_UINT: + case Format::R8G8B8A8_UINT: + { + generateTextureDataWithTargetTStorage<uint8_t>( + output, + desc, + formatInfo, + loadDataIntoUint<uint8_t>); + break; + } + case Format::R64_SINT: + { + generateTextureDataWithTargetTStorage<int64_t>( + output, + desc, + formatInfo, + loadDataIntoInt<int64_t>); break; } - //List<List<unsigned int>>& dataBuffer = output.dataBuffer; - int arraySize = arrLen; - if (inputDesc.isCube) - arraySize *= 6; - output.m_arraySize = arraySize; - output.m_textureSize = inputDesc.size; + case Format::R32_SINT: + case Format::R32G32_SINT: + case Format::R32G32B32_SINT: + case Format::R32G32B32A32_SINT: + { + generateTextureDataWithTargetTStorage<int32_t>( + output, + desc, + formatInfo, + loadDataIntoInt<int32_t>); + break; + } + case Format::R16_SINT: + case Format::R16G16_SINT: + case Format::R16G16B16A16_SINT: + { + generateTextureDataWithTargetTStorage<int16_t>( + output, + desc, + formatInfo, + loadDataIntoInt<int16_t>); + break; + } + case Format::R8_SINT: + case Format::R8G8_SINT: + case Format::R8G8B8A8_SINT: + { + generateTextureDataWithTargetTStorage<int8_t>( + output, + desc, + formatInfo, + loadDataIntoInt<int8_t>); + break; + } + default: + { + SLANG_ASSERT(!"Unhandled format"); + break; + } + } +} - const Index maxMipLevels = Math::Log2Floor(output.m_textureSize) + 1; - Index mipLevels = (inputDesc.mipMapCount <= 0) ? maxMipLevels : inputDesc.mipMapCount; - mipLevels = (mipLevels > maxMipLevels) ? maxMipLevels : mipLevels; +template<typename F> +void _iteratePixels(int dimension, int size, unsigned int* buffer, F f) +{ + if (dimension == 1) + for (int i = 0; i < size; i++) + buffer[i] = f(i, 0, 0); + else if (dimension == 2) + for (int i = 0; i < size; i++) + for (int j = 0; j < size; j++) + buffer[i * size + j] = f(j, i, 0); + else if (dimension == 3) + for (int i = 0; i < size; i++) + for (int j = 0; j < size; j++) + for (int k = 0; k < size; k++) + buffer[i * size * size + j * size + k] = f(k, j, i); +}; + +void generateTextureDataRGB8(TextureData& output, const InputTextureDesc& inputDesc) +{ + int arrLen = inputDesc.arrayLength; + if (arrLen == 0) + arrLen = 1; - output.m_mipLevels = int(mipLevels); - output.m_slices.setCount(output.m_mipLevels * output.m_arraySize); + output.init(Format::R8G8B8A8_UNORM); - int slice = 0; - for (int i = 0; i < arraySize; i++) + enum class SimpleScalarType + { + kUint, + kInt, + kFloat, + }; + SimpleScalarType type; + const rhi::FormatInfo& formatInfo = getFormatInfo(inputDesc.format); + switch (formatInfo.channelType) + { + case SLANG_SCALAR_TYPE_UINT64: + case SLANG_SCALAR_TYPE_UINT32: + case SLANG_SCALAR_TYPE_UINT16: + case SLANG_SCALAR_TYPE_UINT8: type = SimpleScalarType::kUint; break; + case SLANG_SCALAR_TYPE_INT64: + case SLANG_SCALAR_TYPE_INT32: + case SLANG_SCALAR_TYPE_INT16: + case SLANG_SCALAR_TYPE_INT8: type = SimpleScalarType::kInt; break; + case SLANG_SCALAR_TYPE_FLOAT64: + case SLANG_SCALAR_TYPE_FLOAT32: + case SLANG_SCALAR_TYPE_FLOAT16: type = SimpleScalarType::kFloat; break; + default: type = SimpleScalarType::kUint; break; + } + // List<List<unsigned int>>& dataBuffer = output.dataBuffer; + int arraySize = arrLen; + if (inputDesc.isCube) + arraySize *= 6; + output.m_arraySize = arraySize; + output.m_textureSize = inputDesc.size; + + const Index maxMipLevels = Math::Log2Floor(output.m_textureSize) + 1; + Index mipLevels = (inputDesc.mipMapCount <= 0) ? maxMipLevels : inputDesc.mipMapCount; + mipLevels = (mipLevels > maxMipLevels) ? maxMipLevels : mipLevels; + + output.m_mipLevels = int(mipLevels); + output.m_slices.setCount(output.m_mipLevels * output.m_arraySize); + + int slice = 0; + for (int i = 0; i < arraySize; i++) + { + for (int j = 0; j < output.m_mipLevels; j++) { - for (int j = 0; j < output.m_mipLevels; j++) - { - int size = output.m_textureSize >> j; - int bufferLen = size; - if (inputDesc.dimension == 2) - bufferLen *= size; - else if (inputDesc.dimension == 3) - bufferLen *= size*size; - - uint32_t* dst = (uint32_t*)output.setSliceCount(slice, bufferLen); - - if (type == SimpleScalarType::kFloat) - _iteratePixels(inputDesc.dimension, size, dst, [&](int x, int y, int z) -> unsigned int + int size = output.m_textureSize >> j; + int bufferLen = size; + if (inputDesc.dimension == 2) + bufferLen *= size; + else if (inputDesc.dimension == 3) + bufferLen *= size * size; + + uint32_t* dst = (uint32_t*)output.setSliceCount(slice, bufferLen); + + if (type == SimpleScalarType::kFloat) + _iteratePixels( + inputDesc.dimension, + size, + dst, + [&](int x, int y, int z) -> unsigned int + { + if (inputDesc.content == InputTextureContent::Zero) { - if (inputDesc.content == InputTextureContent::Zero) - { - return 0x0; - } - else if (inputDesc.content == InputTextureContent::One) - { + return 0x0; + } + else if (inputDesc.content == InputTextureContent::One) + { + return 0xFFFFFFFF; + } + else if (inputDesc.content == InputTextureContent::Gradient) + { + unsigned char r = (unsigned char)(x / (float)(size - 1) * 255.0f); + unsigned char g = (unsigned char)(y / (float)(size - 1) * 255.0f); + unsigned char b = (unsigned char)(z / (float)(size - 1) * 255.0f); + return 0xFF000000 + r + (g << 8) + (b << 16); + } + else if (inputDesc.content == InputTextureContent::ChessBoard) + { + unsigned int xSig = x < (size >> 1) ? 1 : 0; + unsigned int ySig = y < (size >> 1) ? 1 : 0; + unsigned int zSig = z < (size >> 1) ? 1 : 0; + auto sig = xSig ^ ySig ^ zSig; + if (sig) return 0xFFFFFFFF; - } - else if (inputDesc.content == InputTextureContent::Gradient) - { - unsigned char r = (unsigned char)(x / (float)(size - 1) * 255.0f); - unsigned char g = (unsigned char)(y / (float)(size - 1) * 255.0f); - unsigned char b = (unsigned char)(z / (float)(size - 1) * 255.0f); - return 0xFF000000 + r + (g << 8) + (b << 16); - } - else if (inputDesc.content == InputTextureContent::ChessBoard) - { - unsigned int xSig = x < (size >> 1) ? 1 : 0; - unsigned int ySig = y < (size >> 1) ? 1 : 0; - unsigned int zSig = z < (size >> 1) ? 1 : 0; - auto sig = xSig ^ ySig ^ zSig; - if (sig) - return 0xFFFFFFFF; - else - return 0xFF808080; - } + else + return 0xFF808080; + } + return 0x0; + }); + else if (type == SimpleScalarType::kUint || type == SimpleScalarType::kInt) + _iteratePixels( + inputDesc.dimension, + size, + dst, + [&](int x, int y, int z) -> unsigned int + { + if (inputDesc.content == InputTextureContent::Zero) + { return 0x0; - }); - else if (type == SimpleScalarType::kUint || type == SimpleScalarType::kInt) - _iteratePixels(inputDesc.dimension, size, dst, [&](int x, int y, int z) -> unsigned int + } + else if (inputDesc.content == InputTextureContent::One) { - if (inputDesc.content == InputTextureContent::Zero) - { - return 0x0; - } - else if (inputDesc.content == InputTextureContent::One) - { + return 0x01010101; + } + else if (inputDesc.content == InputTextureContent::Gradient) + { + unsigned char r = (unsigned char)(x / (float)(size - 1)); + unsigned char g = (unsigned char)(y / (float)(size - 1)); + unsigned char b = (unsigned char)(z / (float)(size - 1)); + return 0x01000000 + r + (g << 8) + (b << 16); + } + else if (inputDesc.content == InputTextureContent::ChessBoard) + { + unsigned int xSig = x < (size >> 1) ? 1 : 0; + unsigned int ySig = y < (size >> 1) ? 1 : 0; + unsigned int zSig = z < (size >> 1) ? 1 : 0; + auto sig = xSig ^ ySig ^ zSig; + if (sig) return 0x01010101; - } - else if (inputDesc.content == InputTextureContent::Gradient) - { - unsigned char r = (unsigned char)(x / (float)(size - 1)); - unsigned char g = (unsigned char)(y / (float)(size - 1)); - unsigned char b = (unsigned char)(z / (float)(size - 1)); - return 0x01000000 + r + (g << 8) + (b << 16); - } - else if (inputDesc.content == InputTextureContent::ChessBoard) - { - unsigned int xSig = x < (size >> 1) ? 1 : 0; - unsigned int ySig = y < (size >> 1) ? 1 : 0; - unsigned int zSig = z < (size >> 1) ? 1 : 0; - auto sig = xSig ^ ySig ^ zSig; - if (sig) - return 0x01010101; - else - return 0x0; - } - return 0x0; - }); - slice++; - } + else + return 0x0; + } + return 0x0; + }); + slice++; } } } +} // namespace renderer_test |
