--- /dev/null
+{ "access-new-vector-inside-if-condition.amber", "access-new-vector-inside-if-condition","A shader that accesses a new vector within an if condition" },
+{ "always-false-if-in-do-while.amber", "always-false-if-in-do-while", "A fragment shader with an always false if." },
+{ "always-false-if-with-discard-return.amber", "always-false-if-with-discard-return", "A fragment shader with discard keyword and a return" },
+{ "barrier-in-loop-with-break.amber", "barrier-in-loop-with-break", "A compute shader with a barrier in a loop with a break" },
+{ "call-if-while-switch.amber", "call-if-while-switch", "A fragment shader with a call, if, while, switch" },
+{ "color-write-in-loop.amber", "color-write-in-loop", "A fragment shader that writes to color in a loop" },
+{ "complex-nested-loops-and-call.amber", "complex-nested-loops-and-call", "A fragment shader with complex nested loops, breaks, etc." },
+{ "conditional-return-in-infinite-while.amber", "conditional-return-in-infinite-while", "A shader with conditional return inside an infinite loop" },
+{ "continue-and-merge.amber", "continue-and-merge", "A fragment shader with two nested loops" },
+{ "control-flow-in-function.amber", "control-flow-in-function", "A fragment shader with a lot of control flow" },
+{ "control-flow-switch.amber", "control-flow-switch", "A fragment shader with somewhat complex control flow and a switch" },
+{ "dead-barriers-in-loops.amber", "dead-barriers-in-loops", "A compute shader with dead barriers" },
+{ "dead-struct-init.amber", "dead-struct-init", "A fragment shader that uses struct initializers" },
+{ "disc-and-add-in-func-in-loop.amber", "disc-and-add-in-func-in-loop", "A fragment shader with discard and add in function in loop" },
+{ "discard-continue-return.amber", "discard-continue-return", "A fragment shader with a discard, continue, and return" },
+{ "discard-in-array-manipulating-loop.amber", "discard-in-array-manipulating-loop", "An array-manipulating fragment shader with a discard" },
+{ "do-while-loop-in-conditionals.amber", "do-while-loop-in-conditionals", "A fragment shader with do-while loop in conditional nest" },
+{ "do-while-with-always-true-if.amber", "do-while-with-always-true-if", "A fragment shader with a do while that always returns" },
+{ "early-return-and-barrier.amber", "early-return-and-barrier", "A compute shader with an early return and a barrier" },
+{ "for-condition-always-false.amber", "for-condition-always-false", "A fragment shader that uses a for loop with condition always false" },
+{ "for-loop-with-return.amber", "for-loop-with-return", "A fragment shader with a for loop that loops only once" },
+{ "for-with-ifs-and-return.amber", "for-with-ifs-and-return", "A fragment shader with two ifs and return/continue inside a for loop" },
+{ "fragcoord-control-flow.amber", "fragcoord-control-flow", "A fragment shader that uses FragCoord and somewhat complex control flow" },
+{ "fragcoord-control-flow-2.amber", "fragcoord-control-flow-2", "A fragment shader that uses FragCoord and somewhat complex control flow" },
+{ "if-and-switch.amber", "if-and-switch", "A fragment shader with a switch and some data flow" },
+{ "loop-call-discard.amber", "loop-call-discard", "A fragment shader with nested loops and a function call" },
+{ "loop-dead-if-loop.amber", "loop-dead-if-loop", "A fragment shader with a loop, dead if, and a loop" },
+{ "loop-nested-ifs.amber", "loop-nested-ifs", "A fragment shader with a for loop containing nested ifs" },
+{ "loops-breaks-returns.amber", "loops-breaks-returns", "A compute shader with loops, breaks, returns" },
+{ "loops-ifs-continues-call.amber", "loops-ifs-continues-call", "A fragment shader with nested control flow and a call" },
+{ "mat-array-deep-control-flow.amber", "mat-array-deep-control-flow", "A fragment shader that uses an array of matrices and has deep control flow" },
+{ "mat-array-distance.amber", "mat-array-distance", "A fragment shader that uses an array of matrices and distance" },
+{ "matrices-and-return-in-loop.amber", "matrices-and-return-in-loop", "A fragment shader with matrices and a return in a loop" },
+{ "max-mix-conditional-discard.amber", "max-mix-conditional-discard", "A fragment shader with an expression used in two discard guards" },
+{ "mix-floor-add.amber", "mix-floor-add", "A fragment shader with mix, uintBitsToFloat, and floor" },
+{ "nested-for-loops-with-return.amber", "nested-for-loops-with-return", "A fragment shader with two nested for loops with return" },
+{ "nested-ifs-and-return-in-for-loop.amber", "nested-ifs-and-return-in-for-loop", "A fragment shader with return in nest of ifs, inside loop" },
+{ "nested-loops-switch.amber", "nested-loops-switch", "A fragment shader with nested loops and a switch" },
+{ "pow-vec4.amber", "pow-vec4", "A fragment shader that uses pow" },
+{ "return-before-writing-wrong-color.amber", "return-before-writing-wrong-color", "A fragment shader with return before writing wrong color" },
+{ "return-float-from-while-loop.amber", "return-float-from-while-loop", "A fragment shader with unreachable while loop" },
+{ "return-in-loop-in-function.amber", "return-in-loop-in-function", "A fragment shader with early return from loop in function" },
+{ "returned-boolean-in-vector.amber", "returned-boolean-in-vector", "A fragment shader with returned boolean in vector" },
+{ "similar-nested-ifs.amber", "similar-nested-ifs", "A fragment shader with similar nested ifs and loops" },
+{ "struct-used-as-temporary.amber", "struct-used-as-temporary", "A fragment shader that uses a temporary struct variable" },
+{ "switch-if-discard.amber", "switch-if-discard", "A fragment shader with a switch, if, and discard" },
+{ "switch-with-empty-if-false.amber", "switch-with-empty-if-false", "A fragment shader with always false if in switch statement" },
+{ "swizzle-struct-init-min.amber", "swizzle-struct-init-min", "A fragment shader that uses vector swizzles, struct initializers, and min" },
+{ "two-for-loops-with-barrier-function.amber", "two-for-loops-with-barrier-function", "A compute shader with two barrier functions" },
+{ "two-loops-matrix.amber", "two-loops-matrix", "A fragment shader with two loops and some matrices" },
+{ "two-loops-set-struct.amber", "two-loops-set-struct", "A fragment shader with two loops that write to a struct" },
+{ "two-loops-with-break.amber", "two-loops-with-break", "A fragment shader with two loops with breaks" },
+{ "two-nested-do-whiles.amber", "two-nested-do-whiles", "A fragment shader with nested do while" },
+{ "two-nested-for-loops-with-returns.amber", "two-nested-for-loops-with-returns", "A compute shader with two nested for loops" },
+{ "two-nested-infinite-loops-discard.amber", "two-nested-infinite-loops-discard", "A fragment shader with an always false if function" },
+{ "undefined-integer-in-function.amber", "undefined-integer-in-function", "A fragment shader with nested do while and undefined int" },
+{ "uninitialized-var-decrement-and-add.amber", "uninitialized-var-decrement-and-add", "A fragment shader that uses an uninitialized variable" },
+{ "undefined-assign-in-infinite-loop.amber", "undefined-assign-in-infinite-loop", "A fragment shader with uninitialized read in infinite loop" },
+{ "unreachable-barrier-in-loops.amber", "unreachable-barrier-in-loops", "A compute shader with an unreachable barrier in a loop nest" },
+{ "unreachable-continue-statement.amber", "unreachable-continue-statement", "A fragment shader with unreachable continue statement" },
+{ "unreachable-discard-statement-in-if.amber", "unreachable-discard-statement-in-if", "A fragment shader with discard keyword and a return" },
+{ "unreachable-discard-statement.amber", "unreachable-discard-statement", "A fragment shader with unreachable discard statement" },
+{ "unreachable-loops.amber", "unreachable-loops", "Fragment shader that writes red despite unreachable loops" },
+{ "unreachable-loops-in-switch.amber", "unreachable-loops-in-switch", "A fragment shader with unreachable loops in a switch" },
+{ "unreachable-return-in-loop.amber", "unreachable-return-in-loop", "A fragment shader with an unreachable return in a loop" },
+{ "while-function-always-false.amber", "while-function-always-false", "A fragment shader with an always false while function" },
+{ "while-inside-switch.amber", "while-inside-switch", "A fragment shader that uses a while loop inside a switch" },
+{ "write-before-break.amber", "write-before-break", "Fragment shader that writes red before loop break" },
+{ "write-red-in-loop-nest.amber", "write-red-in-loop-nest", "A fragment shader that writes red in a nest of loops" },
+{ "wrong-color-in-always-false-if.amber", "wrong-color-in-always-false-if", "A fragment shader with wrong color write in false if" },
{
tcu::TestContext& testCtx = group->getTestContext();
- static const struct
- {
- const std::string filename;
- const char* name;
- const char* description;
- }
- tests[] =
- {
- { "access-new-vector-inside-if-condition.amber", "access-new-vector-inside-if-condition","A shader that accesses a new vector within an if condition" },
- { "always-false-if-in-do-while.amber", "always-false-if-in-do-while", "A fragment shader with an always false if." },
- { "always-false-if-with-discard-return.amber", "always-false-if-with-discard-return", "A fragment shader with discard keyword and a return" },
- { "barrier-in-loop-with-break.amber", "barrier-in-loop-with-break", "A compute shader with a barrier in a loop with a break" },
- { "call-if-while-switch.amber", "call-if-while-switch", "A fragment shader with a call, if, while, switch" },
- { "color-write-in-loop.amber", "color-write-in-loop", "A fragment shader that writes to color in a loop" },
- { "complex-nested-loops-and-call.amber", "complex-nested-loops-and-call", "A fragment shader with complex nested loops, breaks, etc." },
- { "conditional-return-in-infinite-while.amber", "conditional-return-in-infinite-while", "A shader with conditional return inside an infinite loop" },
- { "continue-and-merge.amber", "continue-and-merge", "A fragment shader with two nested loops" },
- { "control-flow-in-function.amber", "control-flow-in-function", "A fragment shader with a lot of control flow" },
- { "control-flow-switch.amber", "control-flow-switch", "A fragment shader with somewhat complex control flow and a switch" },
- { "dead-barriers-in-loops.amber", "dead-barriers-in-loops", "A compute shader with dead barriers" },
- { "dead-struct-init.amber", "dead-struct-init", "A fragment shader that uses struct initializers" },
- { "disc-and-add-in-func-in-loop.amber", "disc-and-add-in-func-in-loop", "A fragment shader with discard and add in function in loop" },
- { "discard-continue-return.amber", "discard-continue-return", "A fragment shader with a discard, continue, and return" },
- { "discard-in-array-manipulating-loop.amber", "discard-in-array-manipulating-loop", "An array-manipulating fragment shader with a discard" },
- { "do-while-loop-in-conditionals.amber", "do-while-loop-in-conditionals", "A fragment shader with do-while loop in conditional nest" },
- { "do-while-with-always-true-if.amber", "do-while-with-always-true-if", "A fragment shader with a do while that always returns" },
- { "early-return-and-barrier.amber", "early-return-and-barrier", "A compute shader with an early return and a barrier" },
- { "for-condition-always-false.amber", "for-condition-always-false", "A fragment shader that uses a for loop with condition always false" },
- { "for-loop-with-return.amber", "for-loop-with-return", "A fragment shader with a for loop that loops only once" },
- { "for-with-ifs-and-return.amber", "for-with-ifs-and-return", "A fragment shader with two ifs and return/continue inside a for loop" },
- { "fragcoord-control-flow.amber", "fragcoord-control-flow", "A fragment shader that uses FragCoord and somewhat complex control flow" },
- { "fragcoord-control-flow-2.amber", "fragcoord-control-flow-2", "A fragment shader that uses FragCoord and somewhat complex control flow" },
- { "if-and-switch.amber", "if-and-switch", "A fragment shader with a switch and some data flow" },
- { "loop-call-discard.amber", "loop-call-discard", "A fragment shader with nested loops and a function call" },
- { "loop-dead-if-loop.amber", "loop-dead-if-loop", "A fragment shader with a loop, dead if, and a loop" },
- { "loop-nested-ifs.amber", "loop-nested-ifs", "A fragment shader with a for loop containing nested ifs" },
- { "loops-breaks-returns.amber", "loops-breaks-returns", "A compute shader with loops, breaks, returns" },
- { "loops-ifs-continues-call.amber", "loops-ifs-continues-call", "A fragment shader with nested control flow and a call" },
- { "mat-array-deep-control-flow.amber", "mat-array-deep-control-flow", "A fragment shader that uses an array of matrices and has deep control flow" },
- { "mat-array-distance.amber", "mat-array-distance", "A fragment shader that uses an array of matrices and distance" },
- { "matrices-and-return-in-loop.amber", "matrices-and-return-in-loop", "A fragment shader with matrices and a return in a loop" },
- { "max-mix-conditional-discard.amber", "max-mix-conditional-discard", "A fragment shader with an expression used in two discard guards" },
- { "mix-floor-add.amber", "mix-floor-add", "A fragment shader with mix, uintBitsToFloat, and floor" },
- { "nested-for-loops-with-return.amber", "nested-for-loops-with-return", "A fragment shader with two nested for loops with return" },
- { "nested-ifs-and-return-in-for-loop.amber", "nested-ifs-and-return-in-for-loop", "A fragment shader with return in nest of ifs, inside loop" },
- { "nested-loops-switch.amber", "nested-loops-switch", "A fragment shader with nested loops and a switch" },
- { "pow-vec4.amber", "pow-vec4", "A fragment shader that uses pow" },
- { "return-before-writing-wrong-color.amber", "return-before-writing-wrong-color", "A fragment shader with return before writing wrong color" },
- { "return-float-from-while-loop.amber", "return-float-from-while-loop", "A fragment shader with unreachable while loop" },
- { "return-in-loop-in-function.amber", "return-in-loop-in-function", "A fragment shader with early return from loop in function" },
- { "returned-boolean-in-vector.amber", "returned-boolean-in-vector", "A fragment shader with returned boolean in vector" },
- { "similar-nested-ifs.amber", "similar-nested-ifs", "A fragment shader with similar nested ifs and loops" },
- { "struct-used-as-temporary.amber", "struct-used-as-temporary", "A fragment shader that uses a temporary struct variable" },
- { "switch-if-discard.amber", "switch-if-discard", "A fragment shader with a switch, if, and discard" },
- { "switch-with-empty-if-false.amber", "switch-with-empty-if-false", "A fragment shader with always false if in switch statement" },
- { "swizzle-struct-init-min.amber", "swizzle-struct-init-min", "A fragment shader that uses vector swizzles, struct initializers, and min" },
- { "two-for-loops-with-barrier-function.amber", "two-for-loops-with-barrier-function", "A compute shader with two barrier functions" },
- { "two-loops-matrix.amber", "two-loops-matrix", "A fragment shader with two loops and some matrices" },
- { "two-loops-set-struct.amber", "two-loops-set-struct", "A fragment shader with two loops that write to a struct" },
- { "two-loops-with-break.amber", "two-loops-with-break", "A fragment shader with two loops with breaks" },
- { "two-nested-do-whiles.amber", "two-nested-do-whiles", "A fragment shader with nested do while" },
- { "two-nested-for-loops-with-returns.amber", "two-nested-for-loops-with-returns", "A compute shader with two nested for loops" },
- { "two-nested-infinite-loops-discard.amber", "two-nested-infinite-loops-discard", "A fragment shader with an always false if function" },
- { "undefined-integer-in-function.amber", "undefined-integer-in-function", "A fragment shader with nested do while and undefined int" },
- { "uninitialized-var-decrement-and-add.amber", "uninitialized-var-decrement-and-add", "A fragment shader that uses an uninitialized variable" },
- { "undefined-assign-in-infinite-loop.amber", "undefined-assign-in-infinite-loop", "A fragment shader with uninitialized read in infinite loop" },
- { "unreachable-barrier-in-loops.amber", "unreachable-barrier-in-loops", "A compute shader with an unreachable barrier in a loop nest" },
- { "unreachable-continue-statement.amber", "unreachable-continue-statement", "A fragment shader with unreachable continue statement" },
- { "unreachable-discard-statement-in-if.amber", "unreachable-discard-statement-in-if", "A fragment shader with discard keyword and a return" },
- { "unreachable-discard-statement.amber", "unreachable-discard-statement", "A fragment shader with unreachable discard statement" },
- { "unreachable-loops.amber", "unreachable-loops", "Fragment shader that writes red despite unreachable loops" },
- { "unreachable-loops-in-switch.amber", "unreachable-loops-in-switch", "A fragment shader with unreachable loops in a switch" },
- { "unreachable-return-in-loop.amber", "unreachable-return-in-loop", "A fragment shader with an unreachable return in a loop" },
- { "while-function-always-false.amber", "while-function-always-false", "A fragment shader with an always false while function" },
- { "while-inside-switch.amber", "while-inside-switch", "A fragment shader that uses a while loop inside a switch" },
- { "write-before-break.amber", "write-before-break", "Fragment shader that writes red before loop break" },
- { "write-red-in-loop-nest.amber", "write-red-in-loop-nest", "A fragment shader that writes red in a nest of loops" },
- { "wrong-color-in-always-false-if.amber", "wrong-color-in-always-false-if", "A fragment shader with wrong color write in false if" },
- };
-
- for (size_t i = 0; i < sizeof tests / sizeof tests[0]; i++)
- group->addChild(createAmberTestCase(testCtx, tests[i].name, tests[i].description, "graphicsfuzz", tests[i].filename));
+ createAmberTestsFromIndexFile(testCtx, group, "index.txt", "graphicsfuzz");
}
} // anonymous
const std::string& filename,
const std::vector<std::string> requirements = std::vector<std::string>());
+void createAmberTestsFromIndexFile (tcu::TestContext& testCtx,
+ tcu::TestCaseGroup* group,
+ const std::string filename,
+ const char* category);
+
} // cts_amber
} // vkt
namespace cts_amber
{
+class AmberIndexFileParser
+{
+ char* m_buf;
+ size_t m_idx;
+ size_t m_len;
+ static const int m_fieldLen = 256;
+ char m_scratch[m_fieldLen];
+ char m_filenameField[m_fieldLen];
+ char m_testnameField[m_fieldLen];
+ char m_descField[m_fieldLen];
+
+ bool isWhitespace (char c)
+ {
+ if (c == ' ' ||
+ c == '\t' ||
+ c == '\r' ||
+ c == '\n')
+ {
+ return true;
+ }
+ return false;
+ }
+
+ void skipWhitespace (void)
+ {
+ while (m_idx < m_len && isWhitespace(m_buf[m_idx]))
+ m_idx++;
+ }
+
+ void accept (char c)
+ {
+ if (m_buf[m_idx] == c)
+ m_idx++;
+ }
+
+ void expect (char c)
+ {
+ if (m_buf[m_idx] != c || m_idx >= m_len)
+ TCU_THROW(ResourceError, "Error parsing amber index file");
+
+ m_idx++;
+ }
+
+ void captureString (char* field)
+ {
+ int i = 0;
+
+ while (m_idx < m_len && i < m_fieldLen && m_buf[m_idx] != '"')
+ {
+ field[i] = m_buf[m_idx];
+ i++;
+ m_idx++;
+ }
+
+ field[i] = 0;
+ m_idx++;
+ }
+
+ char* loadFile (const char* filename, size_t& len)
+ {
+ FILE* f = fopen(filename, "rb");
+
+ if (f == 0)
+ {
+ std::string error("Unable to open index file ");
+ error.append(filename);
+ TCU_THROW(ResourceError, error.c_str());
+ }
+
+ fseek(f, 0, SEEK_END);
+ len = ftell(f);
+ fseek(f, 0, SEEK_SET);
+ char* buf = new char[len + 1];
+
+ if (fread(buf, 1, len, f) != len)
+ {
+ delete[] buf;
+ fclose(f);
+ std::string error("File i/o error reading index file ");
+ error.append(filename);
+ TCU_THROW(ResourceError, error.c_str());
+ }
+
+ buf[len] = 0;
+ fclose(f);
+ return buf;
+ }
+
+public:
+ AmberIndexFileParser (const char* filename, const char* category)
+ {
+ std::string indexFilename("vulkan/amber/");
+ indexFilename.append(category);
+ indexFilename.append("/");
+ indexFilename.append(filename);
+
+ m_buf = loadFile(indexFilename.c_str(), m_len);
+ m_idx = 0;
+ }
+
+ ~AmberIndexFileParser (void)
+ {
+ delete[] m_buf;
+ }
+
+ AmberTestCase* parse (const char* category, tcu::TestContext& testCtx)
+ {
+ // Format:
+ // {"filename","test name","description"[,requirement[,requirement[,requirement..]]]}[,]
+ // Things inside [] are optional. Whitespace is allowed everywhere.
+ //
+ // For example, test without requirements might be:
+ // {"testname.amber","test name","test description"},
+
+ if (m_idx < m_len)
+ {
+ skipWhitespace();
+ expect('{');
+ skipWhitespace();
+ expect('"');
+ captureString(m_filenameField);
+ skipWhitespace();
+ expect(',');
+ skipWhitespace();
+ expect('"');
+ captureString(m_testnameField);
+ skipWhitespace();
+ expect(',');
+ skipWhitespace();
+ expect('"');
+ captureString(m_descField);
+ skipWhitespace();
+
+ std::string testFilename("vulkan/amber/");
+ testFilename.append(category);
+ testFilename.append("/");
+ testFilename.append(m_filenameField);
+ AmberTestCase *testCase = new AmberTestCase(testCtx, m_testnameField, m_descField, testFilename);
+
+ while (m_idx < m_len && m_buf[m_idx] == ',')
+ {
+ accept(',');
+ skipWhitespace();
+ expect('"');
+ captureString(m_scratch);
+ skipWhitespace();
+ testCase->addRequirement(m_scratch);
+ }
+
+ expect('}');
+ skipWhitespace();
+ accept(',');
+ skipWhitespace();
+ return testCase;
+ }
+ return 0;
+ }
+};
+
+void createAmberTestsFromIndexFile (tcu::TestContext& testCtx, tcu::TestCaseGroup* group, const std::string filename, const char* category)
+{
+ AmberTestCase* testCase = 0;
+ AmberIndexFileParser parser(filename.c_str(), category);
+
+ do
+ {
+ testCase = parser.parse(category, testCtx);
+ if (testCase)
+ {
+ group->addChild(testCase);
+ }
+ } while (testCase);
+}
+
AmberTestCase* createAmberTestCase (tcu::TestContext& testCtx,
const char* name,
const char* description,