summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2017-10-24 19:14:14 -0400
committerGitHub <noreply@github.com>2017-10-24 19:14:14 -0400
commit3043171dae37d18015d6cd26287d492c576f4f1a (patch)
tree1037732c1e90afd36b588851ce5755d64188bcdb
parentab64cf2ec05980d72cb2bad45e629d10ebbefdc1 (diff)
parent434d3428932ccaa0f6834d03c37adcab37d17a01 (diff)
Merge pull request #227 from csyonghe/master
Extending render-test to support various resource inputs
-rw-r--r--source/core/core.vcxproj2
-rw-r--r--source/core/text-io.h22
-rw-r--r--source/core/token-reader.cpp764
-rw-r--r--source/core/token-reader.h258
-rw-r--r--source/slang/bytecode.h2
-rw-r--r--source/slang/check.cpp3
-rw-r--r--source/slang/emit.cpp1
-rw-r--r--source/slang/ir.cpp6
-rw-r--r--source/slang/lower-to-ir.cpp1
-rw-r--r--source/slang/type-defs.h1
-rw-r--r--tests/compute/generics-simple.slang2
-rw-r--r--tests/compute/generics-simple.slang.expected.txt8
-rw-r--r--tests/compute/simple.slang2
-rw-r--r--tests/compute/simple.slang.actual.txt512
-rw-r--r--tests/compute/simple.slang.expected.txt8
-rw-r--r--tools/render-test/main.cpp49
-rw-r--r--tools/render-test/render-d3d11.cpp480
-rw-r--r--tools/render-test/render-gl.cpp15
-rw-r--r--tools/render-test/render-test.vcxproj13
-rw-r--r--tools/render-test/render-test.vcxproj.filters6
-rw-r--r--tools/render-test/render.h9
-rw-r--r--tools/render-test/shader-input-layout.cpp221
-rw-r--r--tools/render-test/shader-input-layout.h61
-rw-r--r--tools/slang-test/main.cpp20
24 files changed, 1842 insertions, 624 deletions
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 @@
<ClInclude Include="smart-pointer.h" />
<ClInclude Include="stream.h" />
<ClInclude Include="text-io.h" />
+ <ClInclude Include="token-reader.h" />
<ClInclude Include="type-traits.h" />
</ItemGroup>
<ItemGroup>
@@ -44,6 +45,7 @@
<ClCompile Include="slang-string.cpp" />
<ClCompile Include="stream.cpp" />
<ClCompile Include="text-io.cpp" />
+ <ClCompile Include="token-reader.cpp" />
</ItemGroup>
<ItemGroup>
<Natvis Include="core.natvis" />
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<String> Split(String text, char c)
- {
- List<String> 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..bf3294c8e
--- /dev/null
+++ b/source/core/token-reader.cpp
@@ -0,0 +1,764 @@
+#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<Token> & 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<Token> 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<Token> 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, (int)(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<Token> 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();
+ }
+
+ 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<Token> 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<String> Split(String text, char c)
+ {
+ List<String> 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 <assert.h>
namespace Slang
@@ -4887,7 +4888,7 @@ namespace Slang
if (auto decl = dynamic_cast<CallableDecl*>(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 1b5db065f..f76ab1db1 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/ir.cpp b/source/slang/ir.cpp
index 4c01e4fc1..14639de7e 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));
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/generics-simple.slang b/tests/compute/generics-simple.slang
index 0002e444b..5a4a2e765 100644
--- a/tests/compute/generics-simple.slang
+++ b/tests/compute/generics-simple.slang
@@ -1,5 +1,5 @@
//TEST(smoke,compute):COMPARE_COMPUTE:-xslang -use-ir
-
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out
// Confirm that generics syntax can be used in user
// code and generates valid output.
diff --git a/tests/compute/generics-simple.slang.expected.txt b/tests/compute/generics-simple.slang.expected.txt
index fdaa30664..98798bd61 100644
--- a/tests/compute/generics-simple.slang.expected.txt
+++ b/tests/compute/generics-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/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<float> outputBuffer;
diff --git a/tests/compute/simple.slang.actual.txt b/tests/compute/simple.slang.actual.txt
deleted file mode 100644
index e8a8ee20b..000000000
--- a/tests/compute/simple.slang.actual.txt
+++ /dev/null
@@ -1,512 +0,0 @@
-0
-1
-2
-3
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
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 6907ba40f..d3247e55f 100644
--- a/tools/render-test/main.cpp
+++ b/tools/render-test/main.cpp
@@ -5,7 +5,7 @@
#include "render-d3d11.h"
#include "render-gl.h"
#include "slang-support.h"
-
+#include "shader-input-layout.h"
#include <stdio.h>
#include <stdlib.h>
@@ -54,8 +54,9 @@ uintptr_t gConstantBufferSize, gComputeResultBufferSize;
Buffer* gConstantBuffer;
InputLayout* gInputLayout;
Buffer* gVertexBuffer;
-Buffer* gComputeResultBuffer;
-ShaderProgram* gShaderProgram;
+ShaderProgram* gShaderProgram;
+BindingState* gBindingState;
+ShaderInputLayout gShaderInputLayout;
// Entry point name to use for vertex/fragment shader
static char const* vertexEntryPointName = "vertexMain";
@@ -92,6 +93,8 @@ Error initializeShaders(
fclose(sourceFile);
sourceText[sourceSize] = 0;
+ gShaderInputLayout.Parse(sourceText);
+
ShaderCompileRequest::SourceInfo sourceInfo;
sourceInfo.path = sourcePath;
sourceInfo.text = sourceText;
@@ -121,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.
@@ -144,6 +137,7 @@ Error initializeInner(
err = initializeShaders(shaderCompiler);
if(err != Error::None) return err;
+ gBindingState = renderer->createBindingState(gShaderInputLayout);
// Do other initialization that doesn't depend on the source language.
@@ -157,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[] = {
@@ -222,7 +203,7 @@ void renderFrameInner(
renderer->setShaderProgram(gShaderProgram);
renderer->setConstantBuffer(0, gConstantBuffer);
-
+ renderer->setBindingState(gBindingState);
//
renderer->draw(3);
@@ -231,7 +212,7 @@ void renderFrameInner(
void runCompute(Renderer * renderer)
{
renderer->setShaderProgram(gShaderProgram);
- renderer->setStorageBuffer(0, gComputeResultBuffer);
+ renderer->setBindingState(gBindingState);
renderer->dispatchCompute(1, 1, 1);
}
@@ -403,7 +384,7 @@ int main(
{
if (message.message == WM_QUIT)
{
- return (int)message.wParam;
+ return (int)message.wParam;
}
TranslateMessage(&message);
@@ -428,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 6e9e04a78..8f73b4dd4 100644
--- a/tools/render-test/render-d3d11.cpp
+++ b/tools/render-test/render-d3d11.cpp
@@ -36,9 +36,26 @@
#endif
#endif
//
+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<D3DBinding> bindings;
+};
+
//
@@ -246,12 +263,12 @@ public:
ID3D11Device* dxDevice = NULL;
ID3D11DeviceContext* dxImmediateContext = NULL;
ID3D11Texture2D* dxBackBufferTexture = NULL;
- ID3D11RenderTargetView* dxBackBufferRTV = NULL;
-
+ List<ID3D11RenderTargetView*> dxRenderTargetViews;
+ List<ID3D11Texture2D *> dxRenderTargetTextures;
+ D3DBindingState * currentBindings = nullptr;
virtual void initialize(void* inWindowHandle) override
{
auto windowHandle = (HWND) inWindowHandle;
-
// Rather than statically link against D3D, we load it dynamically.
HMODULE d3d11 = LoadLibraryA("d3d11.dll");
@@ -321,10 +338,8 @@ public:
{
hr = D3D11CreateDeviceAndSwapChain_(
NULL, // adapter (use default)
-
D3D_DRIVER_TYPE_WARP,
-// D3D_DRIVER_TYPE_HARDWARE,
-
+// D3D_DRIVER_TYPE_HARDWARE,
NULL, // software
deviceFlags,
&featureLevels[ii],
@@ -352,21 +367,36 @@ public:
static const IID kIID_ID3D11Texture2D = {
0x6f15aaf2, 0xd208, 0x4e89, 0x9a, 0xb4, 0x48,
0x95, 0x35, 0xd3, 0x4f, 0x9c };
+
dxSwapChain->GetBuffer(
0,
kIID_ID3D11Texture2D,
(void**)&dxBackBufferTexture);
- dxDevice->CreateRenderTargetView(
- dxBackBufferTexture,
- NULL,
- &dxBackBufferRTV);
+ for (int i = 0; i < 8; i++)
+ {
+ ID3D11Texture2D* texture;
+ D3D11_TEXTURE2D_DESC textureDesc;
+ dxBackBufferTexture->GetDesc(&textureDesc);
+ dxDevice->CreateTexture2D(&textureDesc, nullptr, &texture);
+ ID3D11RenderTargetView * rtv;
+ D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+ rtvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+ rtvDesc.Texture2D.MipSlice = 0;
+ rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
+ dxDevice->CreateRenderTargetView(
+ texture,
+ &rtvDesc,
+ &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
@@ -389,13 +419,15 @@ 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
{
+ dxImmediateContext->CopyResource(dxBackBufferTexture, dxRenderTargetTextures[0]);
dxSwapChain->Present(0, 0);
}
@@ -404,7 +436,7 @@ public:
HRESULT hr = captureTextureToFile(
dxDevice,
dxImmediateContext,
- dxBackBufferTexture,
+ dxRenderTargetTextures[0],
outputPath);
if( FAILED(hr) )
{
@@ -558,24 +590,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;
}
@@ -585,19 +617,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
@@ -686,7 +726,7 @@ public:
virtual void draw(UInt vertexCount, UInt startVertex) override
{
auto dxContext = dxImmediateContext;
-
+ applyBindingState(false);
dxContext->Draw((UINT) vertexCount, (UINT) startVertex);
}
@@ -749,8 +789,388 @@ public:
virtual void dispatchCompute(int x, int y, int z) override
{
auto dxContext = dxImmediateContext;
+ applyBindingState(true);
dxContext->Dispatch(x, y, z);
}
+
+ void createInputBuffer(
+ InputBufferDesc & bufferDesc,
+ List<unsigned int> & bufferData,
+ ID3D11Buffer * &bufferOut,
+ ID3D11UnorderedAccessView * &viewOut,
+ ID3D11ShaderResourceView * &srvOut)
+ {
+ 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);
+ }
+
+ void createInputTexture(const InputTextureDesc & inputDesc, ID3D11ShaderResourceView * &viewOut)
+ {
+ int arrLen = inputDesc.arrayLength;
+ if (arrLen == 0)
+ arrLen = 1;
+ List<D3D11_SUBRESOURCE_DATA> subRes;
+ List<List<unsigned int>> 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_UNORM;
+ 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_UNORM;
+ 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_UNORM;
+ 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)
+ {
+ 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;
+ }
+
+ void 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 55647fb25..ff9d54eb6 100644
--- a/tools/render-test/render-gl.cpp
+++ b/tools/render-test/render-gl.cpp
@@ -613,6 +613,21 @@ public:
{
glDispatchCompute(x, y, z);
}
+
+ virtual BindingState * createBindingState(const ShaderInputLayout & layout)
+ {
+ return nullptr;
+ }
+
+ virtual void setBindingState(BindingState * state)
+ {
+
+ }
+
+ virtual void serializeOutput(BindingState* state, const char * fileName)
+ {
+
+ }
};
diff --git a/tools/render-test/render-test.vcxproj b/tools/render-test/render-test.vcxproj
index 94af429e8..0b0f6b05e 100644
--- a/tools/render-test/render-test.vcxproj
+++ b/tools/render-test/render-test.vcxproj
@@ -96,6 +96,8 @@
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>../../source/</AdditionalIncludeDirectories>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@@ -109,6 +111,8 @@
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>../../source/</AdditionalIncludeDirectories>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@@ -124,6 +128,8 @@
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>../../source/</AdditionalIncludeDirectories>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@@ -141,6 +147,8 @@
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>../../source/</AdditionalIncludeDirectories>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@@ -154,6 +162,7 @@
<ClCompile Include="options.cpp" />
<ClCompile Include="render-d3d11.cpp" />
<ClCompile Include="render-gl.cpp" />
+ <ClCompile Include="shader-input-layout.cpp" />
<ClCompile Include="slang-support.cpp" />
</ItemGroup>
<ItemGroup>
@@ -161,10 +170,14 @@
<ClInclude Include="render-d3d11.h" />
<ClInclude Include="render-gl.h" />
<ClInclude Include="render.h" />
+ <ClInclude Include="shader-input-layout.h" />
<ClInclude Include="slang-support.h" />
<ClInclude Include="window.h" />
</ItemGroup>
<ItemGroup>
+ <ProjectReference Include="..\..\source\core\core.vcxproj">
+ <Project>{f9be7957-8399-899e-0c49-e714fddd4b65}</Project>
+ </ProjectReference>
<ProjectReference Include="..\..\source\slang\slang.vcxproj">
<Project>{db00da62-0533-4afd-b59f-a67d5b3a0808}</Project>
</ProjectReference>
diff --git a/tools/render-test/render-test.vcxproj.filters b/tools/render-test/render-test.vcxproj.filters
index 6e0ff295a..985e24b8b 100644
--- a/tools/render-test/render-test.vcxproj.filters
+++ b/tools/render-test/render-test.vcxproj.filters
@@ -30,6 +30,9 @@
<ClCompile Include="slang-support.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="shader-input-layout.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="options.h">
@@ -50,5 +53,8 @@
<ClInclude Include="slang-support.h">
<Filter>Header Files</Filter>
</ClInclude>
+ <ClInclude Include="shader-input-layout.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
</ItemGroup>
</Project> \ No newline at end of file
diff --git a/tools/render-test/render.h b/tools/render-test/render.h
index 7f8f2fffa..706868e9a 100644
--- a/tools/render-test/render.h
+++ b/tools/render-test/render.h
@@ -3,13 +3,14 @@
#include "options.h"
#include "window.h"
+#include "shader-input-layout.h"
namespace renderer_test {
typedef struct Buffer Buffer;
typedef struct InputLayout InputLayout;
typedef struct ShaderProgram ShaderProgram;
-
+typedef struct BindingState BindingState;
struct ShaderCompileRequest
{
struct SourceInfo
@@ -89,11 +90,11 @@ 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;
-
+ virtual BindingState* createBindingState(const ShaderInputLayout & shaderInput) = 0;
virtual ShaderCompiler* getShaderCompiler() = 0;
virtual void* map(Buffer* buffer, MapFlavor flavor) = 0;
@@ -101,7 +102,7 @@ public:
virtual void setInputLayout(InputLayout* inputLayout) = 0;
virtual void setPrimitiveTopology(PrimitiveTopology topology) = 0;
-
+ virtual void setBindingState(BindingState * state) = 0;
virtual void setVertexBuffers(UInt startSlot, UInt slotCount, Buffer* const* buffers, UInt const* strides, UInt const* offsets) = 0;
inline void setVertexBuffer(UInt slot, Buffer* buffer, UInt stride, UInt offset = 0)
diff --git a/tools/render-test/shader-input-layout.cpp b/tools/render-test/shader-input-layout.cpp
new file mode 100644
index 000000000..b606a1a13
--- /dev/null
+++ b/tools/render-test/shader-input-layout.cpp
@@ -0,0 +1,221 @@
+#include "shader-input-layout.h"
+#include "core/token-reader.h"
+
+namespace renderer_test
+{
+ using namespace Slang;
+ void ShaderInputLayout::Parse(const char * source)
+ {
+ entries.Clear();
+ auto lines = Split(source, '\n');
+ for (auto & line : lines)
+ {
+ if (line.StartsWith("//TEST_INPUT:"))
+ {
+ auto lineContent = line.SubString(13, line.Length() - 13);
+ TokenReader parser(lineContent);
+ try
+ {
+ ShaderInputLayoutEntry entry;
+
+ if (parser.LookAhead("cbuffer"))
+ {
+ entry.type = ShaderInputType::Buffer;
+ entry.bufferDesc.type = InputBufferType::ConstantBuffer;
+ }
+ else if (parser.LookAhead("ubuffer"))
+ {
+ entry.type = ShaderInputType::Buffer;
+ entry.bufferDesc.type = InputBufferType::StorageBuffer;
+ }
+ else if (parser.LookAhead("Texture1D"))
+ {
+ entry.type = ShaderInputType::Texture;
+ entry.textureDesc.dimension = 1;
+ }
+ else if (parser.LookAhead("Texture2D"))
+ {
+ entry.type = ShaderInputType::Texture;
+ entry.textureDesc.dimension = 2;
+ }
+ else if (parser.LookAhead("Texture3D"))
+ {
+ entry.type = ShaderInputType::Texture;
+ entry.textureDesc.dimension = 3;
+ }
+ else if (parser.LookAhead("TextureCube"))
+ {
+ entry.type = ShaderInputType::Texture;
+ 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;
+ }
+ else if (parser.LookAhead("Sampler1D"))
+ {
+ entry.type = ShaderInputType::CombinedTextureSampler;
+ entry.textureDesc.dimension = 1;
+ }
+ else if (parser.LookAhead("Sampler2D"))
+ {
+ entry.type = ShaderInputType::CombinedTextureSampler;
+ entry.textureDesc.dimension = 2;
+ }
+ else if (parser.LookAhead("Sampler3D"))
+ {
+ entry.type = ShaderInputType::CombinedTextureSampler;
+ entry.textureDesc.dimension = 3;
+ }
+ else if (parser.LookAhead("SamplerCube"))
+ {
+ entry.type = ShaderInputType::CombinedTextureSampler;
+ 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("("))
+ {
+ parser.Read("(");
+ while (!parser.IsEnd() && !parser.LookAhead(")"))
+ {
+ auto word = parser.ReadWord();
+ if (word == "depth")
+ {
+ entry.textureDesc.isDepthTexture = true;
+ }
+ else if (word == "depthCompare")
+ {
+ entry.samplerDesc.isCompareSampler = true;
+ }
+ else if (word == "arrayLength")
+ {
+ parser.Read("=");
+ entry.textureDesc.arrayLength = parser.ReadInt();
+ }
+ else if (word == "stride")
+ {
+ parser.Read("=");
+ entry.bufferDesc.stride = parser.ReadInt();
+ }
+ else if (word == "size")
+ {
+ parser.Read("=");
+ entry.textureDesc.size = parser.ReadInt();
+ }
+ else if (word == "data")
+ {
+ parser.Read("=");
+ parser.Read("[");
+ while (!parser.IsEnd() && !parser.LookAhead("]"))
+ {
+ if (parser.NextToken().Type == TokenType::IntLiteral)
+ {
+ entry.bufferData.Add(parser.ReadUInt());
+ }
+ else
+ {
+ auto floatNum = parser.ReadFloat();
+ entry.bufferData.Add(*(unsigned int*)&floatNum);
+ }
+ }
+ 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(":");
+ while (!parser.IsEnd())
+ {
+ if (parser.LookAhead("dxbinding"))
+ {
+ 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)
+ {
+ throw TextFormatException("Invalid input syntax at line " + parser.NextToken().Position.Line);
+ }
+ }
+ }
+
+
+ }
+} \ No newline at end of file
diff --git a/tools/render-test/shader-input-layout.h b/tools/render-test/shader-input-layout.h
new file mode 100644
index 000000000..f2258b7b9
--- /dev/null
+++ b/tools/render-test/shader-input-layout.h
@@ -0,0 +1,61 @@
+#ifndef SLANG_TEST_SHADER_INPUT_LAYOUT_H
+#define SLANG_TEST_SHADER_INPUT_LAYOUT_H
+
+#include "core/basic.h"
+
+namespace renderer_test
+{
+ enum class ShaderInputType
+ {
+ 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
+ {
+ ConstantBuffer, StorageBuffer
+ };
+ struct InputBufferDesc
+ {
+ InputBufferType type = InputBufferType::ConstantBuffer;
+ int stride = 0; // stride == 0 indicates an unstructured buffer.
+ };
+ struct InputSamplerDesc
+ {
+ bool isCompareSampler = false;
+ };
+ class ShaderInputLayoutEntry
+ {
+ public:
+ ShaderInputType type;
+ Slang::List<unsigned int> bufferData;
+ InputTextureDesc textureDesc;
+ InputBufferDesc bufferDesc;
+ InputSamplerDesc samplerDesc;
+ bool isOutput = false;
+ int hlslBinding = -1;
+ int glslBinding = -1;
+ int glslLocation = -1;
+ };
+ class ShaderInputLayout
+ {
+ public:
+ Slang::List<ShaderInputLayoutEntry> entries;
+ int numRenderTargets = 1;
+ void Parse(const char * source);
+ };
+}
+
+#endif \ No newline at end of file
diff --git a/tools/slang-test/main.cpp b/tools/slang-test/main.cpp
index d85a3856b..cdea6b4dc 100644
--- a/tools/slang-test/main.cpp
+++ b/tools/slang-test/main.cpp
@@ -1,6 +1,7 @@
// main.cpp
#include "../../source/core/slang-io.h"
+#include "../../source/core/token-reader.h"
using namespace Slang;
@@ -20,7 +21,6 @@ using namespace Slang;
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
-
enum OutputMode
{
// Default mode is to write test results to the console
@@ -1164,12 +1164,20 @@ TestResult doComputeComparisonTestRunImpl(TestInput& input, const char * langOpt
auto referenceProgramOutput = Split(File::ReadAllText(referenceOutput), '\n');
if (actualProgramOutput.Count() < referenceProgramOutput.Count())
return kTestResult_Fail;
- for (int i = 0; i < referenceProgramOutput.Count(); i++)
+ 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)
- return kTestResult_Fail;
+ auto reference = referenceProgramOutput[i];
+ auto actual = actualProgramOutput[i];
+ if (actual != reference)
+ {
+ // try to parse reference as float, and compare again
+ auto val = StringToFloat(reference);
+ auto uval = String((unsigned int)FloatAsInt(val), 16).ToUpper();
+ if (actual != uval)
+ return kTestResult_Fail;
+ else
+ return kTestResult_Pass;
+ }
}
return kTestResult_Pass;
}