From 0ee4d4b54732239b946bae7fde32bb21aa5a3ec3 Mon Sep 17 00:00:00 2001 From: "YONGH\\yongh" Date: Fri, 20 Oct 2017 18:24:30 -0400 Subject: in-progress work: allow render-test to generate and bind various resource inputs for running test shaders with arbitrary parameter definitions. This commit contains the parser of the resource input definition. --- source/core/core.vcxproj | 2 + source/core/text-io.h | 22 -- source/core/token-reader.cpp | 868 +++++++++++++++++++++++++++++++++++++++++ source/core/token-reader.h | 258 ++++++++++++ source/slang/bytecode.h | 2 +- source/slang/check.cpp | 3 +- source/slang/emit.cpp | 1 + source/slang/glsl.meta.slang.h | 2 +- source/slang/ir.cpp | 6 +- source/slang/lower-to-ir.cpp | 1 + 10 files changed, 1137 insertions(+), 28 deletions(-) create mode 100644 source/core/token-reader.cpp create mode 100644 source/core/token-reader.h (limited to 'source') diff --git a/source/core/core.vcxproj b/source/core/core.vcxproj index ba9fe3d98..350482686 100644 --- a/source/core/core.vcxproj +++ b/source/core/core.vcxproj @@ -36,6 +36,7 @@ + @@ -44,6 +45,7 @@ + diff --git a/source/core/text-io.h b/source/core/text-io.h index e4bdc6e2d..c914e340a 100644 --- a/source/core/text-io.h +++ b/source/core/text-io.h @@ -311,28 +311,6 @@ namespace Slang stream = 0; } }; - - inline List Split(String text, char c) - { - List result; - StringBuilder sb; - for (int i = 0; i < text.Length(); i++) - { - if (text[i] == c) - { - auto str = sb.ToString(); - if (str.Length() != 0) - result.Add(str); - sb.Clear(); - } - else - sb << text[i]; - } - auto lastStr = sb.ToString(); - if (lastStr.Length()) - result.Add(lastStr); - return result; - } } #endif diff --git a/source/core/token-reader.cpp b/source/core/token-reader.cpp new file mode 100644 index 000000000..5f7115112 --- /dev/null +++ b/source/core/token-reader.cpp @@ -0,0 +1,868 @@ +#include "token-reader.h" + +namespace Slang +{ + enum class TokenizeErrorType + { + InvalidCharacter, InvalidEscapeSequence + }; + + enum class State + { + Start, Identifier, Operator, Int, Hex, Fixed, Double, Char, String, MultiComment, SingleComment + }; + + enum class LexDerivative + { + None, Line, File + }; + + inline bool IsLetter(char ch) + { + return ((ch >= 'a' && ch <= 'z') || + (ch >= 'A' && ch <= 'Z') || ch == '_'); + } + + inline bool IsDigit(char ch) + { + return ch >= '0' && ch <= '9'; + } + + inline bool IsPunctuation(char ch) + { + return ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '%' || + ch == '!' || ch == '^' || ch == '&' || ch == '(' || ch == ')' || + ch == '=' || ch == '{' || ch == '}' || ch == '[' || ch == ']' || + ch == '|' || ch == ';' || ch == ',' || ch == '.' || ch == '<' || + ch == '>' || ch == '~' || ch == '@' || ch == ':' || ch == '?' || ch == '#'; + } + + inline bool IsWhiteSpace(char ch) + { + return (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r' || ch == '\v'); + } + + void ParseOperators(const String & str, List & tokens, TokenFlags& tokenFlags, int line, int col, int startPos, String fileName) + { + int pos = 0; + while (pos < (int)str.Length()) + { + wchar_t curChar = str[pos]; + wchar_t nextChar = (pos < (int)str.Length() - 1) ? str[pos + 1] : '\0'; + wchar_t nextNextChar = (pos < (int)str.Length() - 2) ? str[pos + 2] : '\0'; + auto InsertToken = [&](TokenType type, const String & ct) + { + tokens.Add(Token(type, ct, line, col + pos, pos + startPos, fileName, tokenFlags)); + tokenFlags = 0; + }; + switch (curChar) + { + case '+': + if (nextChar == '+') + { + InsertToken(TokenType::OpInc, "++"); + pos += 2; + } + else if (nextChar == '=') + { + InsertToken(TokenType::OpAddAssign, "+="); + pos += 2; + } + else + { + InsertToken(TokenType::OpAdd, "+"); + pos++; + } + break; + case '-': + if (nextChar == '-') + { + InsertToken(TokenType::OpDec, "--"); + pos += 2; + } + else if (nextChar == '=') + { + InsertToken(TokenType::OpSubAssign, "-="); + pos += 2; + } + else if (nextChar == '>') + { + InsertToken(TokenType::RightArrow, "->"); + pos += 2; + } + else + { + InsertToken(TokenType::OpSub, "-"); + pos++; + } + break; + case '*': + if (nextChar == '=') + { + InsertToken(TokenType::OpMulAssign, "*="); + pos += 2; + } + else + { + InsertToken(TokenType::OpMul, "*"); + pos++; + } + break; + case '/': + if (nextChar == '=') + { + InsertToken(TokenType::OpDivAssign, "/="); + pos += 2; + } + else + { + InsertToken(TokenType::OpDiv, "/"); + pos++; + } + break; + case '%': + if (nextChar == '=') + { + InsertToken(TokenType::OpModAssign, "%="); + pos += 2; + } + else + { + InsertToken(TokenType::OpMod, "%"); + pos++; + } + break; + case '|': + if (nextChar == '|') + { + InsertToken(TokenType::OpOr, "||"); + pos += 2; + } + else if (nextChar == '=') + { + InsertToken(TokenType::OpOrAssign, "|="); + pos += 2; + } + else + { + InsertToken(TokenType::OpBitOr, "|"); + pos++; + } + break; + case '&': + if (nextChar == '&') + { + InsertToken(TokenType::OpAnd, "&&"); + pos += 2; + } + else if (nextChar == '=') + { + InsertToken(TokenType::OpAndAssign, "&="); + pos += 2; + } + else + { + InsertToken(TokenType::OpBitAnd, "&"); + pos++; + } + break; + case '^': + if (nextChar == '=') + { + InsertToken(TokenType::OpXorAssign, "^="); + pos += 2; + } + else + { + InsertToken(TokenType::OpBitXor, "^"); + pos++; + } + break; + case '>': + if (nextChar == '>') + { + if (nextNextChar == '=') + { + InsertToken(TokenType::OpShrAssign, ">>="); + pos += 3; + } + else + { + InsertToken(TokenType::OpRsh, ">>"); + pos += 2; + } + } + else if (nextChar == '=') + { + InsertToken(TokenType::OpGeq, ">="); + pos += 2; + } + else + { + InsertToken(TokenType::OpGreater, ">"); + pos++; + } + break; + case '<': + if (nextChar == '<') + { + if (nextNextChar == '=') + { + InsertToken(TokenType::OpShlAssign, "<<="); + pos += 3; + } + else + { + InsertToken(TokenType::OpLsh, "<<"); + pos += 2; + } + } + else if (nextChar == '=') + { + InsertToken(TokenType::OpLeq, "<="); + pos += 2; + } + else + { + InsertToken(TokenType::OpLess, "<"); + pos++; + } + break; + case '=': + if (nextChar == '=') + { + InsertToken(TokenType::OpEql, "=="); + pos += 2; + } + else + { + InsertToken(TokenType::OpAssign, "="); + pos++; + } + break; + case '!': + if (nextChar == '=') + { + InsertToken(TokenType::OpNeq, "!="); + pos += 2; + } + else + { + InsertToken(TokenType::OpNot, "!"); + pos++; + } + break; + case '?': + InsertToken(TokenType::QuestionMark, "?"); + pos++; + break; + case '@': + InsertToken(TokenType::At, "@"); + pos++; + break; + case '#': + if (nextChar == '#') + { + InsertToken(TokenType::PoundPound, "##"); + pos += 2; + } + else + { + InsertToken(TokenType::Pound, "#"); + pos++; + } + pos++; + break; + case ':': + InsertToken(TokenType::Colon, ":"); + pos++; + break; + case '~': + InsertToken(TokenType::OpBitNot, "~"); + pos++; + break; + case ';': + InsertToken(TokenType::Semicolon, ";"); + pos++; + break; + case ',': + InsertToken(TokenType::Comma, ","); + pos++; + break; + case '.': + InsertToken(TokenType::Dot, "."); + pos++; + break; + case '{': + InsertToken(TokenType::LBrace, "{"); + pos++; + break; + case '}': + InsertToken(TokenType::RBrace, "}"); + pos++; + break; + case '[': + InsertToken(TokenType::LBracket, "["); + pos++; + break; + case ']': + InsertToken(TokenType::RBracket, "]"); + pos++; + break; + case '(': + InsertToken(TokenType::LParent, "("); + pos++; + break; + case ')': + InsertToken(TokenType::RParent, ")"); + pos++; + break; + } + } + } + + List TokenizeText(const String & fileName, const String & text) + { + int lastPos = 0, pos = 0; + int line = 1, col = 0; + String file = fileName; + State state = State::Start; + StringBuilder tokenBuilder; + int tokenLine, tokenCol; + List tokenList; + LexDerivative derivative = LexDerivative::None; + TokenFlags tokenFlags = TokenFlag::AtStartOfLine; + auto InsertToken = [&](TokenType type) + { + derivative = LexDerivative::None; + tokenList.Add(Token(type, tokenBuilder.ToString(), tokenLine, tokenCol, pos, file, tokenFlags)); + tokenFlags = 0; + tokenBuilder.Clear(); + }; + auto ProcessTransferChar = [&](char nextChar) + { + switch (nextChar) + { + case '\\': + case '\"': + case '\'': + tokenBuilder.Append(nextChar); + break; + case 't': + tokenBuilder.Append('\t'); + break; + case 's': + tokenBuilder.Append(' '); + break; + case 'n': + tokenBuilder.Append('\n'); + break; + case 'r': + tokenBuilder.Append('\r'); + break; + case 'b': + tokenBuilder.Append('\b'); + break; + } + }; + while (pos <= (int)text.Length()) + { + char curChar = (pos < (int)text.Length() ? text[pos] : ' '); + char nextChar = (pos < (int)text.Length() - 1) ? text[pos + 1] : '\0'; + if (lastPos != pos) + { + if (curChar == '\n') + { + line++; + col = 0; + } + else + col++; + lastPos = pos; + } + + switch (state) + { + case State::Start: + if (IsLetter(curChar)) + { + state = State::Identifier; + tokenLine = line; + tokenCol = col; + } + else if (IsDigit(curChar)) + { + state = State::Int; + tokenLine = line; + tokenCol = col; + } + else if (curChar == '\'') + { + state = State::Char; + pos++; + tokenLine = line; + tokenCol = col; + } + else if (curChar == '"') + { + state = State::String; + pos++; + tokenLine = line; + tokenCol = col; + } + else if (curChar == '\r' || curChar == '\n') + { + tokenFlags |= TokenFlag::AtStartOfLine | TokenFlag::AfterWhitespace; + pos++; + } + else if (curChar == ' ' || curChar == '\t' || curChar == -62 || curChar == -96) // -62/-96:non-break space + { + tokenFlags |= TokenFlag::AfterWhitespace; + pos++; + } + else if (curChar == '/' && nextChar == '/') + { + state = State::SingleComment; + pos += 2; + } + else if (curChar == '/' && nextChar == '*') + { + pos += 2; + state = State::MultiComment; + } + else if (curChar == '.' && IsDigit(nextChar)) + { + tokenBuilder.Append("0."); + state = State::Fixed; + pos++; + } + else if (IsPunctuation(curChar)) + { + state = State::Operator; + tokenLine = line; + tokenCol = col; + } + else + { + pos++; + } + break; + case State::Identifier: + if (IsLetter(curChar) || IsDigit(curChar)) + { + tokenBuilder.Append(curChar); + pos++; + } + else + { + auto tokenStr = tokenBuilder.ToString(); +#if 0 + if (tokenStr == "#line_reset#") + { + line = 0; + col = 0; + tokenBuilder.Clear(); + } + else if (tokenStr == "#line") + { + derivative = LexDerivative::Line; + tokenBuilder.Clear(); + } + else if (tokenStr == "#file") + { + derivative = LexDerivative::File; + tokenBuilder.Clear(); + line = 0; + col = 0; + } + else +#endif + InsertToken(TokenType::Identifier); + state = State::Start; + } + break; + case State::Operator: + if (IsPunctuation(curChar) && !((curChar == '/' && nextChar == '/') || (curChar == '/' && nextChar == '*'))) + { + tokenBuilder.Append(curChar); + pos++; + } + else + { + //do token analyze + ParseOperators(tokenBuilder.ToString(), tokenList, tokenFlags, tokenLine, tokenCol, pos - tokenBuilder.Length(), file); + tokenBuilder.Clear(); + state = State::Start; + } + break; + case State::Int: + if (IsDigit(curChar)) + { + tokenBuilder.Append(curChar); + pos++; + } + else if (curChar == '.') + { + state = State::Fixed; + tokenBuilder.Append(curChar); + pos++; + } + else if (curChar == 'e' || curChar == 'E') + { + state = State::Double; + tokenBuilder.Append(curChar); + if (nextChar == '-' || nextChar == '+') + { + tokenBuilder.Append(nextChar); + pos++; + } + pos++; + } + else if (curChar == 'x') + { + state = State::Hex; + tokenBuilder.Append(curChar); + pos++; + } + else if (curChar == 'u') + { + pos++; + tokenBuilder.Append(curChar); + InsertToken(TokenType::IntLiteral); + state = State::Start; + } + else + { + if (derivative == LexDerivative::Line) + { + derivative = LexDerivative::None; + line = StringToInt(tokenBuilder.ToString()) - 1; + col = 0; + tokenBuilder.Clear(); + } + else + { + InsertToken(TokenType::IntLiteral); + } + state = State::Start; + } + break; + case State::Hex: + if (IsDigit(curChar) || (curChar >= 'a' && curChar <= 'f') || (curChar >= 'A' && curChar <= 'F')) + { + tokenBuilder.Append(curChar); + pos++; + } + else + { + InsertToken(TokenType::IntLiteral); + state = State::Start; + } + break; + case State::Fixed: + if (IsDigit(curChar)) + { + tokenBuilder.Append(curChar); + pos++; + } + else if (curChar == 'e' || curChar == 'E') + { + state = State::Double; + tokenBuilder.Append(curChar); + if (nextChar == '-' || nextChar == '+') + { + tokenBuilder.Append(nextChar); + pos++; + } + pos++; + } + else + { + if (curChar == 'f') + pos++; + InsertToken(TokenType::DoubleLiteral); + state = State::Start; + } + break; + case State::Double: + if (IsDigit(curChar)) + { + tokenBuilder.Append(curChar); + pos++; + } + else + { + if (curChar == 'f') + pos++; + InsertToken(TokenType::DoubleLiteral); + state = State::Start; + } + break; + case State::String: + if (curChar != '"') + { + if (curChar == '\\') + { + ProcessTransferChar(nextChar); + pos++; + } + else + tokenBuilder.Append(curChar); + } + else + { + if (derivative == LexDerivative::File) + { + derivative = LexDerivative::None; + file = tokenBuilder.ToString(); + tokenBuilder.Clear(); + } + else + { + InsertToken(TokenType::StringLiteral); + } + state = State::Start; + } + pos++; + break; + case State::Char: + if (curChar != '\'') + { + if (curChar == '\\') + { + ProcessTransferChar(nextChar); + pos++; + } + else + tokenBuilder.Append(curChar); + } + else + { + InsertToken(TokenType::CharLiteral); + state = State::Start; + } + pos++; + break; + case State::SingleComment: + if (curChar == '\n') + { + state = State::Start; + tokenFlags |= TokenFlag::AtStartOfLine | TokenFlag::AfterWhitespace; + } + pos++; + break; + case State::MultiComment: + if (curChar == '*' && nextChar == '/') + { + state = State::Start; + tokenFlags |= TokenFlag::AfterWhitespace; + pos += 2; + } + else + pos++; + break; + } + } + return tokenList; + } + List TokenizeText(const String & text) + { + return TokenizeText("", text); + } + + String EscapeStringLiteral(String str) + { + StringBuilder sb; + sb << "\""; + for (int i = 0; i < (int)str.Length(); i++) + { + switch (str[i]) + { + case ' ': + sb << "\\s"; + break; + case '\n': + sb << "\\n"; + break; + case '\r': + sb << "\\r"; + break; + case '\t': + sb << "\\t"; + break; + case '\v': + sb << "\\v"; + break; + case '\'': + sb << "\\\'"; + break; + case '\"': + sb << "\\\""; + break; + case '\\': + sb << "\\\\"; + break; + default: + sb << str[i]; + break; + } + } + sb << "\""; + return sb.ProduceString(); + } + + String UnescapeStringLiteral(String str) + { + StringBuilder sb; + for (int i = 0; i < (int)str.Length(); i++) + { + if (str[i] == '\\' && i < (int)str.Length() - 1) + { + switch (str[i + 1]) + { + case 's': + sb << " "; + break; + case 't': + sb << '\t'; + break; + case 'n': + sb << '\n'; + break; + case 'r': + sb << '\r'; + break; + case 'v': + sb << '\v'; + break; + case '\'': + sb << '\''; + break; + case '\"': + sb << "\""; + break; + case '\\': + sb << "\\"; + break; + default: + i = i - 1; + sb << str[i]; + } + i++; + } + else + sb << str[i]; + } + return sb.ProduceString(); + } + + + String TokenTypeToString(TokenType type) + { + switch (type) + { + case TokenType::EndOfFile: + return "end of file"; + case TokenType::Unknown: + return "UnknownToken"; + case TokenType::Identifier: + return "identifier"; + case TokenType::IntLiteral: + return "integer literal"; + case TokenType::DoubleLiteral: + return "floating-point literal"; + case TokenType::StringLiteral: + return "string literal"; + case TokenType::CharLiteral: + return "character literal"; + case TokenType::QuestionMark: + return "'?'"; + case TokenType::Colon: + return "':'"; + case TokenType::Semicolon: + return "';'"; + case TokenType::Comma: + return "','"; + case TokenType::LBrace: + return "'{'"; + case TokenType::RBrace: + return "'}'"; + case TokenType::LBracket: + return "'['"; + case TokenType::RBracket: + return "']'"; + case TokenType::LParent: + return "'('"; + case TokenType::RParent: + return "')'"; + case TokenType::At: + return "'@'"; + case TokenType::OpAssign: + return "'='"; + case TokenType::OpAdd: + return "'+'"; + case TokenType::OpSub: + return "'-'"; + case TokenType::OpMul: + return "'*'"; + case TokenType::OpDiv: + return "'/'"; + case TokenType::OpMod: + return "'%'"; + case TokenType::OpNot: + return "'!'"; + case TokenType::OpLsh: + return "'<<'"; + case TokenType::OpRsh: + return "'>>'"; + case TokenType::OpAddAssign: + return "'+='"; + case TokenType::OpSubAssign: + return "'-='"; + case TokenType::OpMulAssign: + return "'*='"; + case TokenType::OpDivAssign: + return "'/='"; + case TokenType::OpModAssign: + return "'%='"; + case TokenType::OpEql: + return "'=='"; + case TokenType::OpNeq: + return "'!='"; + case TokenType::OpGreater: + return "'>'"; + case TokenType::OpLess: + return "'<'"; + case TokenType::OpGeq: + return "'>='"; + case TokenType::OpLeq: + return "'<='"; + case TokenType::OpAnd: + return "'&&'"; + case TokenType::OpOr: + return "'||'"; + case TokenType::OpBitXor: + return "'^'"; + case TokenType::OpBitAnd: + return "'&'"; + case TokenType::OpBitOr: + return "'|'"; + case TokenType::OpInc: + return "'++'"; + case TokenType::OpDec: + return "'--'"; + case TokenType::Pound: + return "'#'"; + case TokenType::PoundPound: + return "'##'"; + default: + return ""; + } + } + + TokenReader::TokenReader(String text) + { + this->tokens = TokenizeText("", text); + tokenPtr = 0; + } +} diff --git a/source/core/token-reader.h b/source/core/token-reader.h new file mode 100644 index 000000000..aaebad756 --- /dev/null +++ b/source/core/token-reader.h @@ -0,0 +1,258 @@ +#ifndef CORE_TOKEN_READER_H +#define CORE_TOKEN_READER_H + +#include "basic.h" + +namespace Slang +{ + enum class TokenType + { + EndOfFile = -1, + // illegal + Unknown, + // identifier + Identifier, + // constant + IntLiteral, DoubleLiteral, StringLiteral, CharLiteral, + // operators + Semicolon, Comma, Dot, LBrace, RBrace, LBracket, RBracket, LParent, RParent, + OpAssign, OpAdd, OpSub, OpMul, OpDiv, OpMod, OpNot, OpBitNot, OpLsh, OpRsh, + OpEql, OpNeq, OpGreater, OpLess, OpGeq, OpLeq, + OpAnd, OpOr, OpBitXor, OpBitAnd, OpBitOr, + OpInc, OpDec, OpAddAssign, OpSubAssign, OpMulAssign, OpDivAssign, OpModAssign, + OpShlAssign, OpShrAssign, OpOrAssign, OpAndAssign, OpXorAssign, + + QuestionMark, Colon, RightArrow, At, Pound, PoundPound, + }; + + class CodePosition + { + public: + int Line = -1, Col = -1, Pos = -1; + String FileName; + String ToString() + { + StringBuilder sb(100); + sb << FileName; + if (Line != -1) + sb << "(" << Line << ")"; + return sb.ProduceString(); + } + CodePosition() = default; + CodePosition(int line, int col, int pos, String fileName) + { + Line = line; + Col = col; + Pos = pos; + this->FileName = fileName; + } + bool operator < (const CodePosition & pos) const + { + return FileName < pos.FileName || (FileName == pos.FileName && Line < pos.Line) || + (FileName == pos.FileName && Line == pos.Line && Col < pos.Col); + } + bool operator == (const CodePosition & pos) const + { + return FileName == pos.FileName && Line == pos.Line && Col == pos.Col; + } + }; + + enum TokenFlag : unsigned int + { + AtStartOfLine = 1 << 0, + AfterWhitespace = 1 << 1, + }; + typedef unsigned int TokenFlags; + + class Token + { + public: + TokenType Type = TokenType::Unknown; + String Content; + CodePosition Position; + TokenFlags flags; + Token() = default; + Token(TokenType type, const String & content, int line, int col, int pos, String fileName, TokenFlags flags = 0) + : flags(flags) + { + Type = type; + Content = content; + Position = CodePosition(line, col, pos, fileName); + } + }; + + class TextFormatException : public Exception + { + public: + TextFormatException(String message) + : Exception(message) + {} + }; + + class TokenReader + { + private: + bool legal; + List tokens; + int tokenPtr; + public: + TokenReader(String text); + int ReadInt() + { + auto token = ReadToken(); + bool neg = false; + if (token.Content == '-') + { + neg = true; + token = ReadToken(); + } + if (token.Type == TokenType::IntLiteral) + { + if (neg) + return -StringToInt(token.Content); + else + return StringToInt(token.Content); + } + throw TextFormatException("Text parsing error: int expected."); + } + unsigned int ReadUInt() + { + auto token = ReadToken(); + if (token.Type == TokenType::IntLiteral) + { + return StringToUInt(token.Content); + } + throw TextFormatException("Text parsing error: int expected."); + } + double ReadDouble() + { + auto token = ReadToken(); + bool neg = false; + if (token.Content == '-') + { + neg = true; + token = ReadToken(); + } + if (token.Type == TokenType::DoubleLiteral || token.Type == TokenType::IntLiteral) + { + if (neg) + return -StringToDouble(token.Content); + else + return StringToDouble(token.Content); + } + throw TextFormatException("Text parsing error: floating point value expected."); + } + float ReadFloat() + { + return (float)ReadDouble(); + } + String ReadWord() + { + auto token = ReadToken(); + if (token.Type == TokenType::Identifier) + { + return token.Content; + } + throw TextFormatException("Text parsing error: identifier expected."); + } + String Read(const char * expectedStr) + { + auto token = ReadToken(); + if (token.Content == expectedStr) + { + return token.Content; + } + throw TextFormatException("Text parsing error: \'" + String(expectedStr) + "\' expected."); + } + String Read(String expectedStr) + { + auto token = ReadToken(); + if (token.Content == expectedStr) + { + return token.Content; + } + throw TextFormatException("Text parsing error: \'" + expectedStr + "\' expected."); + } + + String ReadStringLiteral() + { + auto token = ReadToken(); + if (token.Type == TokenType::StringLiteral) + { + return token.Content; + } + throw TextFormatException("Text parsing error: string literal expected."); + } + void Back(int count) + { + tokenPtr -= count; + } + Token ReadToken() + { + if (tokenPtr < (int)tokens.Count()) + { + auto &rs = tokens[tokenPtr]; + tokenPtr++; + return rs; + } + throw TextFormatException("Unexpected ending."); + } + Token NextToken(int offset = 0) + { + if (tokenPtr + offset < (int)tokens.Count()) + return tokens[tokenPtr + offset]; + else + { + Token rs; + rs.Type = TokenType::Unknown; + return rs; + } + } + bool LookAhead(String token) + { + if (tokenPtr < (int)tokens.Count()) + { + auto next = NextToken(); + return next.Content == token; + } + else + { + return false; + } + } + bool IsEnd() + { + return tokenPtr == (int)tokens.Count(); + } + public: + bool IsLegalText() + { + return legal; + } + }; + + inline List Split(String text, char c) + { + List result; + StringBuilder sb; + for (int i = 0; i < (int)text.Length(); i++) + { + if (text[i] == c) + { + auto str = sb.ToString(); + if (str.Length() != 0) + result.Add(str); + sb.Clear(); + } + else + sb << text[i]; + } + auto lastStr = sb.ToString(); + if (lastStr.Length()) + result.Add(lastStr); + return result; + } +} + + +#endif \ No newline at end of file diff --git a/source/slang/bytecode.h b/source/slang/bytecode.h index f38007ba9..75b9f15cd 100644 --- a/source/slang/bytecode.h +++ b/source/slang/bytecode.h @@ -243,7 +243,7 @@ struct BCHeader // entry points for each target. }; -struct CompileRequest; +class CompileRequest; void generateBytecodeForCompileRequest( CompileRequest* compileReq); diff --git a/source/slang/check.cpp b/source/slang/check.cpp index f12e7e55d..5ebb22999 100644 --- a/source/slang/check.cpp +++ b/source/slang/check.cpp @@ -4,6 +4,7 @@ #include "compiler.h" #include "visitor.h" +#include "../core/secure-crt.h" #include namespace Slang @@ -4887,7 +4888,7 @@ namespace Slang if (auto decl = dynamic_cast(candidate.item.declRef.decl)) { char buffer[1024]; - sprintf(buffer, "[this:%p, primary:%p, next:%p]", + sprintf_s(buffer, sizeof(buffer), "[this:%p, primary:%p, next:%p]", decl, decl->primaryDecl, decl->nextDecl); diff --git a/source/slang/emit.cpp b/source/slang/emit.cpp index 971f0345b..da9489a75 100644 --- a/source/slang/emit.cpp +++ b/source/slang/emit.cpp @@ -4517,6 +4517,7 @@ emitDeclImpl(decl, nullptr); switch(inst->op) { + case 0: // nothing yet default: emit(getIRName(inst)); break; diff --git a/source/slang/glsl.meta.slang.h b/source/slang/glsl.meta.slang.h index e43a51ea9..a4aade3c2 100644 --- a/source/slang/glsl.meta.slang.h +++ b/source/slang/glsl.meta.slang.h @@ -173,7 +173,7 @@ sb << "syntax patch : GLSLPatchModifier;\n"; // [GLSL 4.5] Interpolation Qualifiers sb << "syntax smooth : SimpleModifier;\n"; sb << "syntax flat : SimpleModifier;\n"; -sb << "syntax noperspectie : SimpleModifier;\n"; +sb << "syntax noperspective : SimpleModifier;\n"; // [GLSL 4.3.2] Constant Qualifier diff --git a/source/slang/ir.cpp b/source/slang/ir.cpp index 5ace50397..4bf9de5d3 100644 --- a/source/slang/ir.cpp +++ b/source/slang/ir.cpp @@ -1614,9 +1614,9 @@ namespace Slang // There are several ops we want to special-case here, // so that they will be more pleasant to look at. // +#if 0 switch (op) { -#if 0 case kIROp_Module: dumpIndent(context); dump(context, "module\n"); @@ -1688,11 +1688,11 @@ namespace Slang dumpChildrenRaw(context, block); } return; -#endif default: break; } +#endif #if 0 // We also want to special-case based on the *type* @@ -2918,7 +2918,7 @@ namespace Slang // TODO: are there any instruction types that need to be handled // specially here? That would be anything that has more state // than is visible in its operand list... - + case 0: // nothing yet default: { // The common case is that we just need to construct a cloned diff --git a/source/slang/lower-to-ir.cpp b/source/slang/lower-to-ir.cpp index a3d67b670..327902e4a 100644 --- a/source/slang/lower-to-ir.cpp +++ b/source/slang/lower-to-ir.cpp @@ -338,6 +338,7 @@ LoweredValInfo emitCallToVal( auto builder = context->irBuilder; switch (funcVal.flavor) { + case LoweredValInfo::Flavor::None: default: return LoweredValInfo::simple( builder->emitCallInst(type, getSimpleVal(context, funcVal), argCount, args)); -- cgit v1.2.3 From cc6184ebc4d0611be892eaff119de99f8b9e1ca6 Mon Sep 17 00:00:00 2001 From: Yong He Date: Mon, 23 Oct 2017 10:35:44 -0400 Subject: Work in-progress: simple compute test passed. (d3d renderer) --- source/slang/type-defs.h | 1 - tests/compute/simple.slang | 2 +- tests/compute/simple.slang.expected.txt | 8 +- tools/render-test/main.cpp | 35 +-- tools/render-test/render-d3d11.cpp | 462 ++++++++++++++++++++++++++++-- tools/render-test/render-gl.cpp | 5 + tools/render-test/render.h | 2 +- tools/render-test/shader-input-layout.cpp | 115 +++++--- tools/render-test/shader-input-layout.h | 11 +- tools/slang-test/main.cpp | 6 +- 10 files changed, 541 insertions(+), 106 deletions(-) (limited to 'source') diff --git a/source/slang/type-defs.h b/source/slang/type-defs.h index e928efb65..7ec801a14 100644 --- a/source/slang/type-defs.h +++ b/source/slang/type-defs.h @@ -318,7 +318,6 @@ SYNTAX_CLASS(GroupSharedType, Type) RAW( virtual ~GroupSharedType() { - int f = 0; } virtual Slang::String ToString() override; diff --git a/tests/compute/simple.slang b/tests/compute/simple.slang index 3f43c8cc7..8f53a79b2 100644 --- a/tests/compute/simple.slang +++ b/tests/compute/simple.slang @@ -1,5 +1,5 @@ //TEST(smoke,compute):COMPARE_COMPUTE: - +//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out // This is a basic test for Slang compute shader. RWStructuredBuffer outputBuffer; diff --git a/tests/compute/simple.slang.expected.txt b/tests/compute/simple.slang.expected.txt index fdaa30664..98798bd61 100644 --- a/tests/compute/simple.slang.expected.txt +++ b/tests/compute/simple.slang.expected.txt @@ -1,4 +1,4 @@ -0.0 -1.0 -2.0 -3.0 \ No newline at end of file +0 +3F800000 +40000000 +40400000 \ No newline at end of file diff --git a/tools/render-test/main.cpp b/tools/render-test/main.cpp index 02b1963ff..c19238f5d 100644 --- a/tools/render-test/main.cpp +++ b/tools/render-test/main.cpp @@ -54,7 +54,6 @@ uintptr_t gConstantBufferSize, gComputeResultBufferSize; Buffer* gConstantBuffer; InputLayout* gInputLayout; Buffer* gVertexBuffer; -Buffer* gComputeResultBuffer; ShaderProgram* gShaderProgram; BindingState* gBindingState; ShaderInputLayout gShaderInputLayout; @@ -125,16 +124,6 @@ Error initializeShaders( return Error::None; } - -void outputComputeResult(Renderer* renderer, const char * fileName) -{ - float* data = (float*)renderer->map(gComputeResultBuffer, MapFlavor::HostRead); - FILE* f = fopen(fileName, "wt"); - for (auto i = 0u; i < gComputeResultBufferSize / sizeof(UInt); i++) - fprintf(f, "%.9g\n", data[i]); - fclose(f); -} - // // At initialization time, we are going to load and compile our Slang shader // code, and then create the D3D11 API objects we need for rendering. @@ -162,20 +151,7 @@ Error initializeInner( gConstantBuffer = renderer->createBuffer(constantBufferDesc); if(!gConstantBuffer) return Error::Unexpected; - - gComputeResultBufferSize = 512 * sizeof(float); - BufferDesc computeResultBufferDesc; - computeResultBufferDesc.size = gComputeResultBufferSize; - computeResultBufferDesc.flavor = BufferFlavor::Storage; - gComputeResultBuffer = renderer->createBuffer(computeResultBufferDesc); - if (!gComputeResultBufferSize) - return Error::Unexpected; - // initialize buffer to 0 - char * ptr = (char*)renderer->map(gComputeResultBuffer, MapFlavor::HostWrite); - for (auto i = 0u; i < gComputeResultBufferSize; i++) - ptr[i] = 0; - renderer->unmap(gComputeResultBuffer); - + // Input Assembler (IA) InputElementDesc inputElements[] = { @@ -236,7 +212,6 @@ void renderFrameInner( void runCompute(Renderer * renderer) { renderer->setShaderProgram(gShaderProgram); - renderer->setStorageBuffer(0, gComputeResultBuffer); renderer->setBindingState(gBindingState); renderer->dispatchCompute(1, 1, 1); } @@ -434,10 +409,10 @@ int main( // If we are in a mode where output is requested, we need to snapshot the back buffer here if (gOptions.outputPath) { - if (gOptions.shaderType == ShaderProgramType::Compute) - outputComputeResult(renderer, gOptions.outputPath); - else - renderer->captureScreenShot(gOptions.outputPath); + if (gOptions.shaderType == ShaderProgramType::Compute) + renderer->serializeOutput(gBindingState, gOptions.outputPath); + else + renderer->captureScreenShot(gOptions.outputPath); return 0; } diff --git a/tools/render-test/render-d3d11.cpp b/tools/render-test/render-d3d11.cpp index 98b18e447..2b8f12104 100644 --- a/tools/render-test/render-d3d11.cpp +++ b/tools/render-test/render-d3d11.cpp @@ -40,6 +40,22 @@ using namespace Slang; namespace renderer_test { +struct D3DBinding +{ + ShaderInputType type; + ID3D11ShaderResourceView * srv = nullptr; + ID3D11UnorderedAccessView * uav = nullptr; + ID3D11Buffer * buffer = nullptr; + ID3D11SamplerState * samplerState = nullptr; + int binding = 0; + bool isOutput = false; + int bufferLength = 0; +}; +struct D3DBindingState +{ + List bindings; +}; + // @@ -248,7 +264,9 @@ public: ID3D11DeviceContext* dxImmediateContext = NULL; ID3D11Texture2D* dxBackBufferTexture = NULL; ID3D11RenderTargetView* dxBackBufferRTV = NULL; - + List dxRenderTargetViews; + List dxRenderTargetTextures; + D3DBindingState * currentBindings = nullptr; virtual void initialize(void* inWindowHandle) override { auto windowHandle = (HWND) inWindowHandle; @@ -362,12 +380,32 @@ public: dxBackBufferTexture, NULL, &dxBackBufferRTV); - + dxRenderTargetViews.Add(dxBackBufferRTV); + for (int i = 0; i < 7; i++) + { + ID3D11Texture2D* texture; + D3D11_TEXTURE2D_DESC textureDesc; + dxBackBufferTexture->GetDesc(&textureDesc); + textureDesc.ArraySize = 1; + textureDesc.BindFlags = D3D11_BIND_RENDER_TARGET; + textureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; + textureDesc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT; + textureDesc.Usage = D3D11_USAGE_DEFAULT; + textureDesc.MiscFlags = 0; + dxDevice->CreateTexture2D(&textureDesc, nullptr, &texture); + ID3D11RenderTargetView * rtv; + dxDevice->CreateRenderTargetView( + texture, + NULL, + &rtv); + dxRenderTargetViews.Add(rtv); + dxRenderTargetTextures.Add(texture); + } // We immediately bind the back-buffer render target view, and we aren't // going to switch. We don't bother with a depth buffer. dxImmediateContext->OMSetRenderTargets( - 1, - &dxBackBufferRTV, + dxRenderTargetViews.Count(), + dxRenderTargetViews.Buffer(), NULL); // Similarly, we are going to set up a viewport once, and then never @@ -390,9 +428,10 @@ public: virtual void clearFrame() override { - dxImmediateContext->ClearRenderTargetView( - dxBackBufferRTV, - clearColor); + for (auto i = 0u; i < dxRenderTargetViews.Count(); i++) + dxImmediateContext->ClearRenderTargetView( + dxRenderTargetViews[i], + clearColor); } virtual void presentFrame() override @@ -559,24 +598,24 @@ public: return (InputLayout*) dxInputLayout; } - virtual void* map(Buffer* buffer, MapFlavor flavor) override + void* map(ID3D11Buffer * buffer, MapFlavor flavor) { auto dxContext = dxImmediateContext; - auto dxBuffer = ((D3DBuffer*)buffer)->buffer; + auto dxBuffer = buffer; D3D11_MAP dxMapFlavor; - switch( flavor ) + switch (flavor) { case MapFlavor::WriteDiscard: dxMapFlavor = D3D11_MAP_WRITE_DISCARD; break; - case MapFlavor::HostWrite: - dxMapFlavor = D3D11_MAP_WRITE; - break; - case MapFlavor::HostRead: - dxMapFlavor = D3D11_MAP_READ; - break; + case MapFlavor::HostWrite: + dxMapFlavor = D3D11_MAP_WRITE; + break; + case MapFlavor::HostRead: + dxMapFlavor = D3D11_MAP_READ; + break; default: return nullptr; } @@ -586,19 +625,27 @@ public: // per-frame (we always use an identity projection). D3D11_MAPPED_SUBRESOURCE dxMapped; HRESULT hr = dxContext->Map(dxBuffer, 0, dxMapFlavor, 0, &dxMapped); - if(FAILED(hr)) + if (FAILED(hr)) return nullptr; return dxMapped.pData; } - virtual void unmap(Buffer* buffer) override + virtual void* map(Buffer* buffer, MapFlavor flavor) override + { + return map(((D3DBuffer*)buffer)->buffer, flavor); + } + + void unmap(ID3D11Buffer * buffer) { auto dxContext = dxImmediateContext; + dxContext->Unmap(buffer, 0); + } + virtual void unmap(Buffer* buffer) override + { auto dxBuffer = ((D3DBuffer*)buffer)->buffer; - - dxContext->Unmap(dxBuffer, 0); + unmap(dxBuffer); } virtual void setInputLayout(InputLayout* inputLayout) override @@ -687,7 +734,7 @@ public: virtual void draw(UInt vertexCount, UInt startVertex) override { auto dxContext = dxImmediateContext; - + applyBindingState(false); dxContext->Draw((UINT) vertexCount, (UINT) startVertex); } @@ -750,27 +797,386 @@ public: virtual void dispatchCompute(int x, int y, int z) override { auto dxContext = dxImmediateContext; + applyBindingState(true); dxContext->Dispatch(x, y, z); } - struct D3DBinding + void createInputBuffer( + InputBufferDesc & bufferDesc, + List & bufferData, + ID3D11Buffer * &bufferOut, + ID3D11UnorderedAccessView * &viewOut, + ID3D11ShaderResourceView * &srvOut) { - ID3D11ShaderResourceView * resourceView; + auto dxContext = dxImmediateContext; + D3D11_BUFFER_DESC desc = {0}; + desc.ByteWidth = bufferData.Count() * sizeof(unsigned int); + if (bufferDesc.type == InputBufferType::ConstantBuffer) + { + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER | D3D11_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + } + else + { + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; + if (bufferDesc.stride != 0) + { + desc.StructureByteStride = bufferDesc.stride; + desc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED; + } + else + { + desc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS; + } + } + D3D11_SUBRESOURCE_DATA data = {0}; + data.pSysMem = bufferData.Buffer(); + dxDevice->CreateBuffer(&desc, &data, &bufferOut); + int elemSize = bufferDesc.stride <= 0 ? 1 : bufferDesc.stride; + if (bufferDesc.type == InputBufferType::StorageBuffer) + { + D3D11_UNORDERED_ACCESS_VIEW_DESC viewDesc; + memset(&viewDesc, 0, sizeof(viewDesc)); + viewDesc.Buffer.FirstElement = 0; + viewDesc.Buffer.NumElements = (UINT)(bufferData.Count() * sizeof(unsigned int) / elemSize); + viewDesc.Buffer.Flags = 0; + viewDesc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER; + viewDesc.Format = DXGI_FORMAT_UNKNOWN; + dxDevice->CreateUnorderedAccessView(bufferOut, &viewDesc, &viewOut); + } + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + memset(&srvDesc, 0, sizeof(srvDesc)); + srvDesc.Buffer.FirstElement = 0; + srvDesc.Buffer.ElementWidth = elemSize; + srvDesc.Buffer.NumElements = (UINT)(bufferData.Count() * sizeof(unsigned int) / elemSize); + srvDesc.Buffer.ElementOffset = 0; + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER; + srvDesc.Format = DXGI_FORMAT_UNKNOWN; + dxDevice->CreateShaderResourceView(bufferOut, &srvDesc, &srvOut); + } - }; - struct D3DBindingState + void createInputTexture(const InputTextureDesc & inputDesc, ID3D11ShaderResourceView * &viewOut) { - List bindings; - }; + int arrLen = inputDesc.arrayLength; + if (arrLen == 0) + arrLen = 1; + List subRes; + List> dataBuffer; + int arraySize = arrLen; + if (inputDesc.isCube) + arraySize *= 6; + int textureSize = inputDesc.size; + int textureMipLevels = Math::Log2Floor(textureSize) + 1; + subRes.SetSize(textureMipLevels * arraySize); + dataBuffer.SetSize(subRes.Count()); + + auto iteratePixels = [&](int dimension, int size, unsigned int * buffer, auto 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); + }; + + int slice = 0; + for (int i = 0; i < arraySize; i++) + { + for (int j = 0; j < textureMipLevels; j++) + { + int size = textureSize >> j; + int bufferLen = size; + if (inputDesc.dimension == 2) + bufferLen *= size; + else if (inputDesc.dimension == 3) + bufferLen *= size*size; + dataBuffer[slice].SetSize(bufferLen); + subRes[slice].pSysMem = dataBuffer[slice].Buffer(); + subRes[slice].SysMemPitch = sizeof(unsigned int) * size; + subRes[slice].SysMemSlicePitch = sizeof(unsigned int) * size * size; + + iteratePixels(inputDesc.dimension, size, dataBuffer[slice].Buffer(), [&](int x, int y, int z) -> unsigned int + { + if (inputDesc.content == InputTextureContent::Zero) + { + 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 + return 0xFF808080; + } + return 0x0; + }); + slice++; + } + } + if (inputDesc.dimension == 1) + { + D3D11_TEXTURE1D_DESC desc = { 0 }; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET | D3D11_BIND_UNORDERED_ACCESS; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; + desc.Format = DXGI_FORMAT_R8G8B8A8_SNORM; + desc.MiscFlags = D3D11_RESOURCE_MISC_GENERATE_MIPS; + desc.MipLevels = textureMipLevels; + desc.ArraySize = arraySize; + desc.Width = textureSize; + desc.Usage = D3D11_USAGE_DEFAULT; + + ID3D11Texture1D * texture; + dxDevice->CreateTexture1D(&desc, subRes.Buffer(), &texture); + D3D11_SHADER_RESOURCE_VIEW_DESC viewDesc; + + viewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1D; + if (inputDesc.arrayLength != 0) + viewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1DARRAY; + viewDesc.Texture1D.MipLevels = textureMipLevels; + viewDesc.Texture1D.MostDetailedMip = 0; + viewDesc.Texture1DArray.ArraySize = arraySize; + viewDesc.Texture1DArray.FirstArraySlice = 0; + viewDesc.Texture1DArray.MipLevels = textureMipLevels; + viewDesc.Texture1DArray.MostDetailedMip = 0; + dxDevice->CreateShaderResourceView(texture, &viewDesc, &viewOut); + } + else if (inputDesc.dimension == 2) + { + D3D11_SHADER_RESOURCE_VIEW_DESC viewDesc; + D3D11_TEXTURE2D_DESC desc = { 0 }; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET | D3D11_BIND_UNORDERED_ACCESS; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; + desc.Format = DXGI_FORMAT_R8G8B8A8_SNORM; + desc.MiscFlags = D3D11_RESOURCE_MISC_GENERATE_MIPS; + desc.MipLevels = textureMipLevels; + desc.ArraySize = arraySize; + if (inputDesc.isCube) + { + desc.MiscFlags |= D3D11_RESOURCE_MISC_TEXTURECUBE; + viewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE; + viewDesc.TextureCube.MipLevels = textureMipLevels; + viewDesc.TextureCube.MostDetailedMip = 0; + viewDesc.TextureCubeArray.MipLevels = textureMipLevels; + viewDesc.TextureCubeArray.MostDetailedMip = 0; + viewDesc.TextureCubeArray.First2DArrayFace = 0; + viewDesc.TextureCubeArray.NumCubes = inputDesc.arrayLength; + } + else + { + viewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + viewDesc.Texture2D.MipLevels = textureMipLevels; + viewDesc.Texture2D.MostDetailedMip = 0; + viewDesc.Texture2DArray.ArraySize = arraySize; + viewDesc.Texture2DArray.FirstArraySlice = 0; + viewDesc.Texture2DArray.MipLevels = textureMipLevels; + viewDesc.Texture2DArray.MostDetailedMip = 0; + } + if (inputDesc.arrayLength != 0) + viewDesc.ViewDimension = (D3D11_SRV_DIMENSION)(int)(viewDesc.ViewDimension + 1); + desc.Width = textureSize; + desc.Height = textureSize; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + ID3D11Texture2D * texture; + dxDevice->CreateTexture2D(&desc, subRes.Buffer(), &texture); + dxDevice->CreateShaderResourceView(texture, &viewDesc, &viewOut); + } + else if (inputDesc.dimension == 3) + { + D3D11_SHADER_RESOURCE_VIEW_DESC viewDesc; + D3D11_TEXTURE3D_DESC desc = { 0 }; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET | D3D11_BIND_UNORDERED_ACCESS; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; + desc.Format = DXGI_FORMAT_R8G8B8A8_SNORM; + desc.MiscFlags = D3D11_RESOURCE_MISC_GENERATE_MIPS; + desc.MipLevels = textureMipLevels; + viewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D; + desc.Width = textureSize; + desc.Height = textureSize; + desc.Depth = textureSize; + desc.Usage = D3D11_USAGE_DEFAULT; + ID3D11Texture3D * texture; + dxDevice->CreateTexture3D(&desc, subRes.Buffer(), &texture); + if (inputDesc.arrayLength != 0) + viewDesc.ViewDimension = (D3D11_SRV_DIMENSION)(int)(viewDesc.ViewDimension + 1); + viewDesc.Texture3D.MipLevels = textureMipLevels; + viewDesc.Texture3D.MostDetailedMip = 0; + dxDevice->CreateShaderResourceView(texture, &viewDesc, &viewOut); + } + } + void createInputSampler(const InputSamplerDesc & inputDesc, ID3D11SamplerState * & stateOut) + { + D3D11_SAMPLER_DESC desc; + memset(&desc, 0, sizeof(desc)); + desc.AddressU = desc.AddressV = desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; + if (inputDesc.isCompareSampler) + { + desc.ComparisonFunc = D3D11_COMPARISON_LESS_EQUAL; + desc.Filter = D3D11_FILTER_MIN_LINEAR_MAG_MIP_POINT; + } + else + desc.Filter = D3D11_FILTER_ANISOTROPIC; + desc.MaxAnisotropy = 16; + desc.MinLOD = 0.0f; + desc.MaxLOD = 100.0f; + dxDevice->CreateSamplerState(&desc, &stateOut); + } virtual BindingState * createBindingState(const ShaderInputLayout & layout) { - return nullptr; + D3DBindingState * rs = new D3DBindingState(); + for (auto & entry : layout.entries) + { + D3DBinding rsEntry; + rsEntry.type = entry.type; + rsEntry.binding = entry.hlslBinding; + rsEntry.isOutput = entry.isOutput; + switch (entry.type) + { + case ShaderInputType::Buffer: + { + createInputBuffer(entry.bufferDesc, entry.bufferData, rsEntry.buffer, rsEntry.uav, rsEntry.srv); + rsEntry.bufferLength = entry.bufferData.Count() * sizeof(unsigned int); + } + break; + case ShaderInputType::Texture: + { + createInputTexture(entry.textureDesc, rsEntry.srv); + } + break; + case ShaderInputType::Sampler: + { + createInputSampler(entry.samplerDesc, rsEntry.samplerState); + } + break; + case ShaderInputType::CombinedTextureSampler: + { + throw "not implemented"; + } + break; + } + rs->bindings.Add(rsEntry); + } + return (BindingState*)rs; + } + + bool applyBindingState(bool isCompute) + { + auto dxContext = dxImmediateContext; + for (auto & binding : currentBindings->bindings) + { + if (binding.type == ShaderInputType::Buffer) + { + if (binding.uav) + { + if (isCompute) + dxContext->CSSetUnorderedAccessViews(binding.binding, 1, &binding.uav, nullptr); + else + dxContext->OMSetRenderTargetsAndUnorderedAccessViews(D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL, + nullptr, nullptr, binding.binding, 1, &binding.uav, nullptr); + } + else + { + if (isCompute) + dxContext->CSSetShaderResources(binding.binding, 1, &binding.srv); + else + { + dxContext->PSSetShaderResources(binding.binding, 1, &binding.srv); + dxContext->VSSetShaderResources(binding.binding, 1, &binding.srv); + } + } + } + else if (binding.type == ShaderInputType::Texture) + { + if (binding.uav) + { + if (isCompute) + dxContext->CSSetUnorderedAccessViews(binding.binding, 1, &binding.uav, nullptr); + else + dxContext->OMSetRenderTargetsAndUnorderedAccessViews(D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL, + nullptr, nullptr, binding.binding, 1, &binding.uav, nullptr); + } + else + { + if (isCompute) + dxContext->CSSetShaderResources(binding.binding, 1, &binding.srv); + else + { + dxContext->PSSetShaderResources(binding.binding, 1, &binding.srv); + dxContext->VSSetShaderResources(binding.binding, 1, &binding.srv); + } + } + } + else if (binding.type == ShaderInputType::Sampler) + { + if (isCompute) + dxContext->CSSetSamplers(binding.binding, 1, &binding.samplerState); + else + { + dxContext->PSSetSamplers(binding.binding, 1, &binding.samplerState); + dxContext->VSSetSamplers(binding.binding, 1, &binding.samplerState); + } + } + else + throw "not implemented"; + } } virtual void setBindingState(BindingState * state) { + auto dxBindingState = (D3DBindingState*) state; + currentBindings = dxBindingState; + } + virtual void serializeOutput(BindingState* state, const char * fileName) + { + auto dxContext = dxImmediateContext; + auto dxBindingState = (D3DBindingState*)state; + FILE * f = fopen(fileName, "wt"); + for (auto & binding : dxBindingState->bindings) + { + if (binding.isOutput) + { + if (binding.buffer) + { + auto ptr = (unsigned int *)map(binding.buffer, MapFlavor::HostRead); + for (auto i = 0u; i < binding.bufferLength / sizeof(unsigned int); i++) + fprintf(f, "%X\n", ptr[i]); + unmap(binding.buffer); + } + else + { + throw "not implemented"; + } + } + } + fclose(f); } }; diff --git a/tools/render-test/render-gl.cpp b/tools/render-test/render-gl.cpp index 79dd09ad9..ff9d54eb6 100644 --- a/tools/render-test/render-gl.cpp +++ b/tools/render-test/render-gl.cpp @@ -623,6 +623,11 @@ public: { } + + virtual void serializeOutput(BindingState* state, const char * fileName) + { + + } }; diff --git a/tools/render-test/render.h b/tools/render-test/render.h index 426b0738a..706868e9a 100644 --- a/tools/render-test/render.h +++ b/tools/render-test/render.h @@ -90,7 +90,7 @@ public: virtual void presentFrame() = 0; virtual void captureScreenShot(char const* outputPath) = 0; - + virtual void serializeOutput(BindingState * state, char const* outputPath) = 0; virtual Buffer* createBuffer(BufferDesc const& desc) = 0; virtual InputLayout* createInputLayout(InputElementDesc const* inputElements, UInt inputElementCount) = 0; diff --git a/tools/render-test/shader-input-layout.cpp b/tools/render-test/shader-input-layout.cpp index c97028441..b606a1a13 100644 --- a/tools/render-test/shader-input-layout.cpp +++ b/tools/render-test/shader-input-layout.cpp @@ -49,6 +49,31 @@ namespace renderer_test entry.textureDesc.dimension = 2; entry.textureDesc.isCube = true; } + else if (parser.LookAhead("RWTexture1D")) + { + entry.type = ShaderInputType::Texture; + entry.textureDesc.dimension = 1; + entry.textureDesc.isRWTexture = true; + } + else if (parser.LookAhead("RWTexture2D")) + { + entry.type = ShaderInputType::Texture; + entry.textureDesc.dimension = 2; + entry.textureDesc.isRWTexture = true; + } + else if (parser.LookAhead("RWTexture3D")) + { + entry.type = ShaderInputType::Texture; + entry.textureDesc.dimension = 3; + entry.textureDesc.isRWTexture = true; + } + else if (parser.LookAhead("RWTextureCube")) + { + entry.type = ShaderInputType::Texture; + entry.textureDesc.dimension = 2; + entry.textureDesc.isCube = true; + entry.textureDesc.isRWTexture = true; + } else if (parser.LookAhead("Sampler")) { entry.type = ShaderInputType::Sampler; @@ -74,6 +99,11 @@ namespace renderer_test entry.textureDesc.dimension = 2; entry.textureDesc.isCube = true; } + else if (parser.LookAhead("render_targets")) + { + numRenderTargets = parser.ReadInt(); + continue; + } parser.ReadToken(); // parse options if (parser.LookAhead("(")) @@ -100,6 +130,11 @@ namespace renderer_test parser.Read("="); entry.bufferDesc.stride = parser.ReadInt(); } + else if (word == "size") + { + parser.Read("="); + entry.textureDesc.size = parser.ReadInt(); + } else if (word == "data") { parser.Read("="); @@ -118,55 +153,61 @@ namespace renderer_test } parser.Read("]"); } + else if (word == "content") + { + parser.Read("="); + auto contentWord = parser.ReadWord(); + if (contentWord == "zero") + entry.textureDesc.content = InputTextureContent::Zero; + else if (contentWord == "one") + entry.textureDesc.content = InputTextureContent::One; + else if (contentWord == "chessboard") + entry.textureDesc.content = InputTextureContent::ChessBoard; + else + entry.textureDesc.content = InputTextureContent::Gradient; + } if (parser.LookAhead(",")) parser.Read(","); else break; } - parser.Read(")"); - // parse bindings - if (parser.LookAhead(":")) + } + parser.Read(")"); + // parse bindings + if (parser.LookAhead(":")) + { + parser.Read(":"); + while (!parser.IsEnd()) { - parser.Read(":"); - while (!parser.IsEnd()) + if (parser.LookAhead("dxbinding")) { - if (parser.LookAhead("register")) - { - parser.ReadToken(); - parser.Read("("); - auto reg = parser.ReadWord(); - entry.hlslRegister = parser.ReadInt(); - parser.Read(")"); - } - else if (parser.LookAhead("layout")) - { - parser.ReadToken(); - parser.Read("("); - while (!parser.IsEnd() && !parser.LookAhead(")")) - { - auto word = parser.ReadWord(); - if (word == "binding") - { - parser.Read("="); - entry.glslBinding = parser.ReadInt(); - } - else if (word == "location") - { - parser.Read("="); - entry.glslLocation = parser.ReadInt(); - } - if (parser.LookAhead(",")) - parser.Read(","); - else - break; - } - parser.Read(")"); - } + parser.ReadToken(); + parser.Read("("); + entry.hlslBinding = parser.ReadInt(); + parser.Read(")"); + } + else if (parser.LookAhead("glbinding")) + { + parser.ReadToken(); + parser.Read("("); + entry.glslBinding = entry.glslLocation = parser.ReadInt(); if (parser.LookAhead(",")) + { parser.Read(","); + entry.glslLocation = parser.ReadInt(); + } + parser.Read(")"); + } + else if (parser.LookAhead("out")) + { + parser.ReadToken(); + entry.isOutput = true; } + if (parser.LookAhead(",")) + parser.Read(","); } } + entries.Add(entry); } catch (TextFormatException) { diff --git a/tools/render-test/shader-input-layout.h b/tools/render-test/shader-input-layout.h index 788a72224..f2258b7b9 100644 --- a/tools/render-test/shader-input-layout.h +++ b/tools/render-test/shader-input-layout.h @@ -9,12 +9,19 @@ namespace renderer_test { Buffer, Texture, Sampler, CombinedTextureSampler }; + enum class InputTextureContent + { + Zero, One, ChessBoard, Gradient + }; struct InputTextureDesc { int dimension = 2; int arrayLength = 0; bool isCube = false; bool isDepthTexture = false; + bool isRWTexture = false; + int size = 4; + InputTextureContent content = InputTextureContent::One; }; enum class InputBufferType { @@ -37,7 +44,8 @@ namespace renderer_test InputTextureDesc textureDesc; InputBufferDesc bufferDesc; InputSamplerDesc samplerDesc; - int hlslRegister = -1; + bool isOutput = false; + int hlslBinding = -1; int glslBinding = -1; int glslLocation = -1; }; @@ -45,6 +53,7 @@ namespace renderer_test { public: Slang::List entries; + int numRenderTargets = 1; void Parse(const char * source); }; } diff --git a/tools/slang-test/main.cpp b/tools/slang-test/main.cpp index 181c34b00..272c1b618 100644 --- a/tools/slang-test/main.cpp +++ b/tools/slang-test/main.cpp @@ -1147,9 +1147,9 @@ TestResult doComputeComparisonTestRunImpl(TestInput& input, const char * langOpt return kTestResult_Fail; for (int i = 0; i < (int)referenceProgramOutput.Count(); i++) { - auto reference = StringToFloat(referenceProgramOutput[i]); - auto actual = StringToFloat(actualProgramOutput[i]); - if (abs(actual - reference) > 1e-7f) + auto reference = referenceProgramOutput[i]; + auto actual = actualProgramOutput[i]; + if (actual != reference) return kTestResult_Fail; } return kTestResult_Pass; -- cgit v1.2.3 From c68224e3e9158e54bdd7c0abe294e0bbf3f6e1a5 Mon Sep 17 00:00:00 2001 From: Yong He Date: Mon, 23 Oct 2017 11:25:44 -0400 Subject: try fix linux build --- source/core/token-reader.cpp | 106 +------------------------------------------ 1 file changed, 1 insertion(+), 105 deletions(-) (limited to 'source') diff --git a/source/core/token-reader.cpp b/source/core/token-reader.cpp index 5f7115112..bf3294c8e 100644 --- a/source/core/token-reader.cpp +++ b/source/core/token-reader.cpp @@ -490,7 +490,7 @@ namespace Slang else { //do token analyze - ParseOperators(tokenBuilder.ToString(), tokenList, tokenFlags, tokenLine, tokenCol, pos - tokenBuilder.Length(), file); + ParseOperators(tokenBuilder.ToString(), tokenList, tokenFlags, tokenLine, tokenCol, (int)(pos - tokenBuilder.Length()), file); tokenBuilder.Clear(); state = State::Start; } @@ -756,110 +756,6 @@ namespace Slang return sb.ProduceString(); } - - String TokenTypeToString(TokenType type) - { - switch (type) - { - case TokenType::EndOfFile: - return "end of file"; - case TokenType::Unknown: - return "UnknownToken"; - case TokenType::Identifier: - return "identifier"; - case TokenType::IntLiteral: - return "integer literal"; - case TokenType::DoubleLiteral: - return "floating-point literal"; - case TokenType::StringLiteral: - return "string literal"; - case TokenType::CharLiteral: - return "character literal"; - case TokenType::QuestionMark: - return "'?'"; - case TokenType::Colon: - return "':'"; - case TokenType::Semicolon: - return "';'"; - case TokenType::Comma: - return "','"; - case TokenType::LBrace: - return "'{'"; - case TokenType::RBrace: - return "'}'"; - case TokenType::LBracket: - return "'['"; - case TokenType::RBracket: - return "']'"; - case TokenType::LParent: - return "'('"; - case TokenType::RParent: - return "')'"; - case TokenType::At: - return "'@'"; - case TokenType::OpAssign: - return "'='"; - case TokenType::OpAdd: - return "'+'"; - case TokenType::OpSub: - return "'-'"; - case TokenType::OpMul: - return "'*'"; - case TokenType::OpDiv: - return "'/'"; - case TokenType::OpMod: - return "'%'"; - case TokenType::OpNot: - return "'!'"; - case TokenType::OpLsh: - return "'<<'"; - case TokenType::OpRsh: - return "'>>'"; - case TokenType::OpAddAssign: - return "'+='"; - case TokenType::OpSubAssign: - return "'-='"; - case TokenType::OpMulAssign: - return "'*='"; - case TokenType::OpDivAssign: - return "'/='"; - case TokenType::OpModAssign: - return "'%='"; - case TokenType::OpEql: - return "'=='"; - case TokenType::OpNeq: - return "'!='"; - case TokenType::OpGreater: - return "'>'"; - case TokenType::OpLess: - return "'<'"; - case TokenType::OpGeq: - return "'>='"; - case TokenType::OpLeq: - return "'<='"; - case TokenType::OpAnd: - return "'&&'"; - case TokenType::OpOr: - return "'||'"; - case TokenType::OpBitXor: - return "'^'"; - case TokenType::OpBitAnd: - return "'&'"; - case TokenType::OpBitOr: - return "'|'"; - case TokenType::OpInc: - return "'++'"; - case TokenType::OpDec: - return "'--'"; - case TokenType::Pound: - return "'#'"; - case TokenType::PoundPound: - return "'##'"; - default: - return ""; - } - } - TokenReader::TokenReader(String text) { this->tokens = TokenizeText("", text); -- cgit v1.2.3