| # -*- coding: utf-8 -*- |
| |
| #------------------------------------------------------------------------- |
| # drawElements Quality Program utilities |
| # -------------------------------------- |
| # |
| # Copyright 2015 The Android Open Source Project |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| # |
| #------------------------------------------------------------------------- |
| |
| import sys |
| import itertools |
| from collections import namedtuple |
| from genutil import * |
| |
| # Templates |
| |
| declarationTemplate = """ |
| case ${{NAME}} |
| ${{COMPILE_FAIL}} |
| values {} |
| |
| vertex "" |
| #version 300 es |
| precision mediump float; |
| in highp vec4 dEQP_Position; |
| |
| ${{VARIABLE_VTX}} |
| |
| void main() |
| { |
| x0 = 1.0; |
| x1 = 2.0; |
| gl_Position = dEQP_Position; |
| } |
| "" |
| |
| fragment "" |
| #version 300 es |
| precision mediump float; |
| layout(location = 0) out mediump vec4 dEQP_FragColor; |
| |
| ${{VARIABLE_FRG}} |
| |
| void main() |
| { |
| float result = (x0 + x1 + x2) / 3.0; |
| dEQP_FragColor = vec4(result, result, result, 1.0); |
| } |
| "" |
| end |
| """[1:-1] |
| |
| parameterTemplate = """ |
| case ${{NAME}} |
| ${{COMPILE_FAIL}} |
| version 300 es |
| values {} |
| |
| both "" |
| #version 300 es |
| precision mediump float; |
| ${DECLARATIONS} |
| |
| float foo0 (${{PARAMETER0}}) |
| { |
| return x + 1.0; |
| } |
| |
| void foo1 (${{PARAMETER1}}) |
| { |
| x = 1.0; |
| } |
| |
| float foo2 (${{PARAMETER2}}) |
| { |
| return x + 1.0; |
| } |
| |
| void main() |
| { |
| ${SETUP} |
| float result; |
| foo1(result); |
| float x0 = foo0(1.0); |
| foo2(result); |
| ${OUTPUT} |
| } |
| "" |
| end |
| """[1:-1] |
| |
| # Classes |
| |
| class DeclarationCase(ShaderCase): |
| def __init__(self, compileFail, invariantInput, paramList): |
| self.compileFail = 'expect compile_fail' if compileFail else 'expect pass' |
| self.name = '' |
| var0 = '' |
| var1 = '' |
| var2 = '' |
| |
| for p in paramList: |
| self.name += p.name |
| if paramList.index(p) != len(paramList)-1: |
| self.name += '_' |
| |
| var0 += p.vars[0] + ' ' |
| var1 += p.vars[1] + ' ' |
| var2 += p.vars[2] + ' ' |
| |
| if invariantInput: |
| self.name += "_invariant_input" |
| |
| var0 += 'float x0;\n' |
| var1 += 'float x1;\n' |
| var2 += 'float x2;' |
| |
| variables = (var0 + var1 + var2).strip() |
| variables = variables.replace(" ", " ") |
| self.variableVtx = variables.replace("anon_centroid", "out") |
| self.variableFrg = variables.replace("anon_centroid", "in") |
| self.variableVtx = self.variableVtx.replace("centroid", "centroid out") |
| self.variableFrg = self.variableFrg.replace("centroid", "centroid in") |
| |
| self.variableFrg = self.variableFrg.replace("invariant", "") # input variable cannot be invariant... |
| if invariantInput: |
| self.variableFrg = "invariant " + self.variableFrg # ...unless we are doing a negative test |
| |
| def __str__(self): |
| params = { |
| "NAME" : self.name, |
| "COMPILE_FAIL" : self.compileFail, |
| "VARIABLE_VTX" : self.variableVtx, |
| "VARIABLE_FRG" : self.variableFrg |
| } |
| return fillTemplate(declarationTemplate, params) |
| |
| class ParameterCase(ShaderCase): |
| def __init__(self, compileFail, paramList): |
| self.compileFail = "expect compile_fail" if compileFail else "expect pass" |
| self.name = '' |
| self.param0 = '' |
| self.param1 = '' |
| self.param2 = '' |
| |
| for p in paramList: |
| self.name += p.name |
| if paramList.index(p) != len(paramList)-1: |
| self.name += '_' |
| |
| self.param0 += p.vars[0] + ' ' |
| self.param1 += p.vars[1] + ' ' |
| self.param2 += p.vars[2] + ' ' |
| |
| self.param0 += 'float x' |
| self.param1 += 'float x' |
| self.param2 += 'float x' |
| self.param0 = self.param0.replace(" ", " ") |
| self.param1 = self.param1.replace(" ", " ") |
| self.param2 = self.param2.replace(" ", " ") |
| |
| def __str__(self): |
| params = { |
| "NAME" : self.name, |
| "COMPILE_FAIL" : self.compileFail, |
| "PARAMETER0" : self.param0, |
| "PARAMETER1" : self.param1, |
| "PARAMETER2" : self.param2, |
| } |
| return fillTemplate(parameterTemplate, params) |
| |
| # Declarations |
| |
| CaseFormat = namedtuple('CaseFormat', 'name vars') |
| |
| DECL_INVARIANT = CaseFormat("invariant", [ "invariant", "", "" ]) |
| DECL_INTERPOLATION = CaseFormat("interp", [ "smooth", "flat", "" ]) |
| DECL_STORAGE = CaseFormat("storage", [ "centroid", "anon_centroid", "uniform" ]) |
| DECL_PRECISION = CaseFormat("precision", [ "lowp", "mediump", "highp" ]) |
| |
| PARAM_STORAGE = CaseFormat("storage", [ "const", "", ""]) |
| PARAM_PARAMETER = CaseFormat("parameter", [ "in", "out", "inout" ]) |
| PARAM_PRECISION = CaseFormat("precision", [ "lowp", "mediump", "highp" ]) |
| |
| # Order of qualification tests |
| |
| validDeclarationCases = [] |
| invalidDeclarationCases = [] |
| validParameterCases = [] |
| invalidParameterCases = [] |
| |
| declFormats = [ |
| [DECL_INVARIANT, DECL_INTERPOLATION, DECL_STORAGE, DECL_PRECISION], |
| [DECL_INTERPOLATION, DECL_STORAGE, DECL_PRECISION], |
| [DECL_INVARIANT, DECL_INTERPOLATION, DECL_STORAGE], |
| [DECL_INVARIANT, DECL_STORAGE, DECL_PRECISION], |
| [DECL_STORAGE, DECL_PRECISION], |
| [DECL_INTERPOLATION, DECL_STORAGE], |
| [DECL_INVARIANT, DECL_STORAGE] |
| ] |
| |
| paramFormats = [ |
| [PARAM_STORAGE, PARAM_PARAMETER, PARAM_PRECISION], |
| [PARAM_STORAGE, PARAM_PARAMETER], |
| [PARAM_STORAGE, PARAM_PRECISION], |
| [PARAM_PARAMETER, PARAM_PRECISION] |
| ] |
| print(len(paramFormats)) |
| |
| for f in declFormats: |
| for p in itertools.permutations(f): |
| if list(p) == f: |
| validDeclarationCases.append(DeclarationCase(False, False, p)) # Correct order |
| else: |
| invalidDeclarationCases.append(DeclarationCase(True, False, p)) # Incorrect order |
| |
| for f in declFormats: |
| invalidDeclarationCases.append(DeclarationCase(True, True, f)) # Correct order but invariant is not allowed as and input parameter |
| |
| for f in paramFormats: |
| for p in itertools.permutations(f): |
| if list(p) == f: |
| validParameterCases.append(ParameterCase(False, p)) # Correct order |
| else: |
| invalidParameterCases.append(ParameterCase(True, p)) # Incorrect order |
| |
| qualificationOrderCases = [ |
| CaseGroup("variables", "Order of qualification in variable declarations.", children = [ |
| CaseGroup("valid", "Valid orderings.", validDeclarationCases), |
| CaseGroup("invalid", "Invalid orderings.", invalidDeclarationCases) |
| ]), |
| CaseGroup("parameters", "Order of qualification in function parameters.", children = [ |
| CaseGroup("valid", "Valid orderings.", validParameterCases), |
| CaseGroup("invalid", "Invalid orderings.", invalidParameterCases) |
| ]) |
| ] |
| |
| # Main program |
| |
| if __name__ == "__main__": |
| print("Generating shader case files.") |
| writeAllCases("qualification_order.test", qualificationOrderCases) |