from genutil import * allCases = [] VERTEX = "VERTEX" FRAGMENT = "FRAGMENT" CASE_FRAGMENT_SHADER_TEMPLATE = """ case ${{NAME}} version 300 es expect ${{EXPECT}} vertex "" #version 300 es precision highp float; in vec4 a_pos; void main() { gl_Position = a_pos; } "" fragment "" ${{SOURCE}} "" end"""[1:] CASE_VERTEX_SHADER_TEMPLATE = """ case ${{NAME}} version 300 es expect ${{EXPECT}} vertex "" ${{SOURCE}} "" fragment "" #version 300 es precision highp float; layout(location=0) out vec4 o_color; void main() { o_color = vec4(1.0); } "" end"""[1:] class UniformBlockCase(ShaderCase): def __init__(self, name, shaderType, source, valid): self.name = name self.shaderType = shaderType self.source = source self.valid = valid def __str__(self): if self.shaderType == FRAGMENT: sourceParams = { "OUTPUT": "o_color", "OUTPUT_DECLARATION": "layout(location=0) out vec4 o_color;" } source = fillTemplate(self.source, sourceParams) testCaseParams = { "NAME": self.name, "SOURCE": source, "EXPECT": ("build_successful" if self.valid else "compile_fail") } return fillTemplate(CASE_FRAGMENT_SHADER_TEMPLATE, testCaseParams) elif self.shaderType == VERTEX: sourceParams = { "OUTPUT": "gl_Position", "OUTPUT_DECLARATION": "" } source = fillTemplate(self.source, sourceParams) testCaseParams = { "NAME": self.name, "SOURCE": source, "EXPECT": ("build_successful" if self.valid else "compile_fail") } return fillTemplate(CASE_VERTEX_SHADER_TEMPLATE, testCaseParams) assert False def createCases(name, source, valid): return [UniformBlockCase(name + "_vertex", VERTEX, source, valid), UniformBlockCase(name + "_fragment", FRAGMENT, source, valid)] repeatShaderTemplate = """ #version 300 es precision highp float; ${{OUTPUT_DECLARATION}} uniform UniformBlock { uniform vec4 uniformMember; } uniformBlock; void main() { ${{OUTPUT}} = uniformBlock.uniformMember; }"""[1:] layoutQualifierShaderTemplate = """ #version 300 es precision highp float; ${{OUTPUT_DECLARATION}} layout(%s) uniform UniformBlock { vec4 uniformMember; } uniformBlock; void main() { ${{OUTPUT}} = uniformBlock.uniformMember; }"""[1:] layoutGlobalQualifierShaderTemplate = """ #version 300 es precision highp float; layout(%s) uniform; ${{OUTPUT_DECLARATION}} uniform UniformBlock { vec4 uniformMember; } uniformBlock; void main() { ${{OUTPUT}} = uniformBlock.uniformMember; }"""[1:] layoutMemberQualifierShaderTemplate = """ #version 300 es precision highp float; ${{OUTPUT_DECLARATION}} uniform UniformBlock { layout(%s) mat4 uniformMember; } uniformBlock; void main() { ${{OUTPUT}} = uniformBlock.uniformMember[0]; }"""[1:] layoutMemberVec4QualifierShaderTemplate = """ #version 300 es precision highp float; ${{OUTPUT_DECLARATION}} uniform UniformBlock { layout(%s) vec4 uniformMember; } uniformBlock; void main() { ${{OUTPUT}} = uniformBlock.uniformMember; }"""[1:] noInstanceNameShaderTemplate = """ #version 300 es precision highp float; ${{OUTPUT_DECLARATION}} uniform UniformBlock { vec4 uniformMember; }; void main() { ${{OUTPUT}} = uniformMember; }"""[1:] sameVariableAndInstanceNameShaderTemplate = """ #version 300 es precision highp float; ${{OUTPUT_DECLARATION}} uniform UniformBlock { vec4 uniformMember; } uniformBlock; void main() { vec4 uniformBlock = vec4(0.0); ${{OUTPUT}} = uniformBlock; }"""[1:] sameVariableAndBlockNameShaderTemplate = """ #version 300 es precision highp float; ${{OUTPUT_DECLARATION}} uniform UniformBlock { vec4 uniformMember; } uniformBlock; void main() { vec4 UniformBlock = vec4(0.0); ${{OUTPUT}} = UniformBlock + uniformBlock.uniformMember; }"""[1:] repeatedBlockShaderTemplate = """ #version 300 es precision highp float; ${{OUTPUT_DECLARATION}} uniform UniformBlock { vec4 uniformMember; } uniformBlockA; uniform UniformBlock { vec4 uniformMember; } uniformBlockB; void main() { ${{OUTPUT}} = uniformBlockA.uniformMember + uniformBlockB.uniformMember; }"""[1:] repeatedBlockNoInstanceNameShaderTemplate = """ #version 300 es precision highp float; ${{OUTPUT_DECLARATION}} uniform UniformBlock { vec4 uniformMember; } uniformBlock; uniform UniformBlock { vec4 uniformMember; }; void main() { ${{OUTPUT}} = uniformBlock.uniformMember + uniformMember; }"""[1:] structMemberShaderTemplate = """ #version 300 es precision highp float; ${{OUTPUT_DECLARATION}} struct Struct { vec4 uniformMember; }; uniform UniformBlock { Struct st; } uniformBlock; void main() { ${{OUTPUT}} = uniformBlock.st.uniformMember; }"""[1:] layoutStructMemberQualifierShaderTemplate = """ #version 300 es precision highp float; ${{OUTPUT_DECLARATION}} struct Struct { vec4 uniformMember; }; uniform UniformBlock { layout(%s) Struct st; } uniformBlock; void main() { ${{OUTPUT}} = uniformBlock.st.uniformMember; }"""[1:] longIdentifierBlockNameShaderTemplate = (""" #version 300 es precision highp float; ${{OUTPUT_DECLARATION}} // Total of 1024 characters uniform """ + ("a" * 1024) + """ { vec4 uniformMember; } uniformBlock; void main() { ${{OUTPUT}} = uniformBlock.uniformMember; }""")[1:] longIdentifierInstanceNameShaderTemplate = (""" #version 300 es precision highp float; ${{OUTPUT_DECLARATION}} uniform UniformBlock { vec4 uniformMember; } """ + ("a" * 1024) + """; // Total of 1024 characters void main() { ${{OUTPUT}} = """ + ("a" * 1024) + """.uniformMember; }""")[1:] underscoreIdentifierInstanceNameShaderTemplate = (""" #version 300 es precision highp float; ${{OUTPUT_DECLARATION}} uniform UniformBlock { vec4 uniformMember; } _; void main() { ${{OUTPUT}} = _.uniformMember; }""")[1:] underscoreIdentifierBlockNameShaderTemplate = (""" #version 300 es precision highp float; ${{OUTPUT_DECLARATION}} uniform _ { vec4 uniformMember; } uniformBlock; void main() { ${{OUTPUT}} = uniformBlock.uniformMember; }""")[1:] validCases = (createCases("repeat_interface_qualifier", repeatShaderTemplate, True) + sum([createCases("layout_%s" % qualifier, layoutQualifierShaderTemplate % qualifier, True) for qualifier in ["shared", "packed", "std140", "row_major", "column_major"]], []) + createCases("layout_all", layoutQualifierShaderTemplate % "shared, packed, std140, row_major, column_major", True) + createCases("layout_all_8_times", layoutQualifierShaderTemplate % str.join(", ", ["shared", "packed", "std140", "row_major", "column_major"] * 8), True) + sum([createCases("global_layout_%s" % qualifier, layoutGlobalQualifierShaderTemplate % qualifier, True) for qualifier in ["shared", "packed", "std140", "row_major", "column_major"]], []) + createCases("global_layout_all", layoutGlobalQualifierShaderTemplate % "shared, packed, std140, row_major, column_major", True) + createCases("global_layout_all_8_times", layoutGlobalQualifierShaderTemplate % str.join(", ", ["shared", "packed", "std140", "row_major", "column_major"] * 8), True) + sum([createCases("member_layout_%s" % qualifier, layoutMemberQualifierShaderTemplate % qualifier, True) for qualifier in ["row_major", "column_major"]], []) + sum([createCases("member_layout_%s_vec4" % qualifier, layoutMemberVec4QualifierShaderTemplate % qualifier, True) for qualifier in ["row_major", "column_major"]], []) + createCases("member_layout_all", layoutMemberQualifierShaderTemplate % "row_major, column_major", True) + createCases("member_layout_all_8_times", layoutMemberQualifierShaderTemplate % str.join(", ", ["row_major", "column_major"] * 8), True) + createCases("no_instance_name", noInstanceNameShaderTemplate, True) + createCases("same_variable_and_block_name", sameVariableAndBlockNameShaderTemplate, True) + createCases("same_variable_and_instance_name", sameVariableAndInstanceNameShaderTemplate, True) + createCases("struct_member", structMemberShaderTemplate, True) + sum([createCases("struct_member_layout_%s" % qualifier, layoutStructMemberQualifierShaderTemplate % qualifier, True) for qualifier in ["row_major", "column_major"]], []) + createCases("struct_member_layout_all", layoutStructMemberQualifierShaderTemplate % "row_major, column_major", True) + createCases("struct_member_layout_all_8_times", layoutStructMemberQualifierShaderTemplate % str.join(", ", ["row_major", "column_major"] * 8), True) + createCases("long_block_name", longIdentifierBlockNameShaderTemplate, True) + createCases("long_instance_name", longIdentifierInstanceNameShaderTemplate, True) + createCases("underscore_block_name", underscoreIdentifierBlockNameShaderTemplate, True) + createCases("underscore_instance_name", underscoreIdentifierInstanceNameShaderTemplate, True)) invalidMemberInterfaceQualifierShaderTemplate = """ #version 300 es precision highp float; ${{OUTPUT_DECLARATION}} uniform UniformBlock { %s vec4 uniformMember; } uniformBlock; void main() { ${{OUTPUT}} = uniformBlock.uniformMember; }"""[1:] conflictingInstanceNamesShaderTemplate = """ #version 300 es precision highp float; ${{OUTPUT_DECLARATION}} uniform UniformBlockA { vec4 uniformMember; } uniformBlock; uniform UniformBlockB { vec4 uniformMember; } uniformBlock; void main() { ${{OUTPUT}} = uniformBlock.uniformMember; }"""[1:] conflictingFunctionAndInstanceNameShaderTemplate = """ #version 300 es precision highp float; ${{OUTPUT_DECLARATION}} uniform UniformBlock { vec4 uniformMember; } uniformBlock; float uniformBlock (float x) { return x; } void main() { ${{OUTPUT}} = uniformBlock.uniformMember; }"""[1:] conflictingFunctionAndBlockNameShaderTemplate = """ #version 300 es precision highp float; ${{OUTPUT_DECLARATION}} uniform UniformBlock { vec4 uniformMember; } uniformBlock; float UniformBlock (float x) { return x; } void main() { ${{OUTPUT}} = uniformBlock.uniformMember; }"""[1:] conflictingVariableAndInstanceNameShaderTemplate = """ #version 300 es precision highp float; ${{OUTPUT_DECLARATION}} uniform UniformBlock { vec4 uniformMember; } uniformBlock; %s vec4 uniformBlock; void main() { ${{OUTPUT}} = uniformBlock.uniformMember; }"""[1:] conflictingVariableAndBlockNameShaderTemplate = """ #version 300 es precision highp float; ${{OUTPUT_DECLARATION}} uniform UniformBlock { vec4 uniformMember; } uniformBlock; %s vec4 UniformBlock; void main() { ${{OUTPUT}} = uniformBlock.uniformMember; }"""[1:] matchingInstanceAndBlockNameShaderTemplate = """ #version 300 es precision highp float; ${{OUTPUT_DECLARATION}} uniform UniformBlock { vec4 uniformMember; } UniformBlock; void main() { ${{OUTPUT}} = UniformBlock.uniformMember; }"""[1:] referenceUsingBlockNameShaderTemplate = """ #version 300 es precision highp float; ${{OUTPUT_DECLARATION}} uniform UniformBlock { vec4 uniformMember; } uniformBlock; void main() { ${{OUTPUT}} = UniformBlock.uniformMember; }"""[1:] emptyBlockShaderTemplate = """ #version 300 es precision highp float; ${{OUTPUT_DECLARATION}} uniform UniformBlock { } uniformBlock; void main() { ${{OUTPUT}} = vec4(0.0); }"""[1:] emptyLayoutShaderTemplate = """ #version 300 es precision highp float; ${{OUTPUT_DECLARATION}} layout() uniform UniformBlock { vec4 uniformMember; } uniformBlock; void main() { ${{OUTPUT}} = uniformBlock.uniformMember; }"""[1:] emptyGlobalLayoutShaderTemplate = """ #version 300 es precision highp float; layout() uniform; ${{OUTPUT_DECLARATION}} uniform UniformBlock { vec4 uniformMember; } uniformBlock; void main() { ${{OUTPUT}} = uniformBlock.uniformMember; }"""[1:] emptyMemberLayoutShaderTemplate = """ #version 300 es precision highp float; ${{OUTPUT_DECLARATION}} uniform UniformBlock { layout() vec4 uniformMember; } uniformBlock; void main() { ${{OUTPUT}} = uniformBlock.uniformMember; }"""[1:] invalidMemberLayoutShaderTemplate = """ #version 300 es precision highp float; ${{OUTPUT_DECLARATION}} uniform UniformBlock { layout(%s) vec4 uniformMember; } uniformBlock; void main() { ${{OUTPUT}} = uniformBlock.uniformMember; }"""[1:] structureDefinitionShaderTemplate = """ #version 300 es precision highp float; ${{OUTPUT_DECLARATION}} uniform UniformBlock { struct A { vec4 uniformMember; } a; } uniformBlock; void main() { ${{OUTPUT}} = uniformBlock.a.uniformMember; }"""[1:] samplerShaderTemplate = """ #version 300 es precision highp float; ${{OUTPUT_DECLARATION}} uniform UniformBlock { sampler2D sampler; vec4 uniformMember; } uniformBlock; void main() { ${{OUTPUT}} = uniformBlock.uniformMember; }"""[1:] missingBlockNameShaderTemplate = """ #version 300 es precision highp float; ${{OUTPUT_DECLARATION}} uniform { vec4 uniformMember; } uniformBlock; void main() { ${{OUTPUT}} = uniformBlock.uniformMember; }"""[1:] invalidNumberBlockNameShaderTemplate = """ #version 300 es precision highp float; ${{OUTPUT_DECLARATION}} uniform 0UniformBlock { vec4 uniformMember; } uniformBlock; void main() { ${{OUTPUT}} = uniformBlock.uniformMember; }"""[1:] invalidHashBlockNameShaderTemplate = """ #version 300 es precision highp float; ${{OUTPUT_DECLARATION}} uniform #UniformBlock { vec4 uniformMember; } uniformBlock; void main() { ${{OUTPUT}} = uniformBlock.uniformMember; }"""[1:] invalidDollarBlockNameShaderTemplate = """ #version 300 es precision highp float; ${{OUTPUT_DECLARATION}} uniform $UniformBlock { vec4 uniformMember; } uniformBlock; void main() { ${{OUTPUT}} = uniformBlock.uniformMember; }"""[1:] invalidIdentifierBlockNameShaderTemplate = """ #version 300 es precision highp float; ${{OUTPUT_DECLARATION}} uniform gl_UniformBlock { vec4 uniformMember; } uniformBlock; void main() { ${{OUTPUT}} = uniformBlock.uniformMember; }"""[1:] tooLongIdentifierBlockNameShaderTemplate = (""" #version 300 es precision highp float; ${{OUTPUT_DECLARATION}} // Total of 1025 characters uniform """ + ("a" * 1025) + """ { vec4 uniformMember; } uniformBlock; void main() { ${{OUTPUT}} = uniformBlock.uniformMember; }""")[1:] invalidNumberInstanceNameShaderTemplate = """ #version 300 es precision highp float; ${{OUTPUT_DECLARATION}} uniform UniformInstance { vec4 uniformMember; } 0uniformBlock; void main() { ${{OUTPUT}} = 0uniformBlock.uniformMember; }"""[1:] invalidHashInstanceNameShaderTemplate = """ #version 300 es precision highp float; ${{OUTPUT_DECLARATION}} uniform UniformInstance { vec4 uniformMember; } #uniformBlock; void main() { ${{OUTPUT}} = #uniformBlock.uniformMember; }"""[1:] invalidDollarInstanceNameShaderTemplate = """ #version 300 es precision highp float; ${{OUTPUT_DECLARATION}} uniform UniformInstance { vec4 uniformMember; } $uniformBlock; void main() { ${{OUTPUT}} = $uniformBlock.uniformMember; }"""[1:] invalidIdentifierInstanceNameShaderTemplate = """ #version 300 es precision highp float; ${{OUTPUT_DECLARATION}} uniform UniformBlock { vec4 uniformMember; } gl_uniformBlock; void main() { ${{OUTPUT}} = gl_uniformBlock.uniformMember; }"""[1:] tooLongIdentifierInstanceNameShaderTemplate = (""" #version 300 es precision highp float; ${{OUTPUT_DECLARATION}} uniform UniformBlock { vec4 uniformMember; } """ + ("a" * 1025) + """; // Total of 1025 characters void main() { ${{OUTPUT}} = """ + ("a" * 1025) + """.uniformMember; }""")[1:] invalidCases = ( sum([createCases("member_%s_interface_qualifier" % qualifier, invalidMemberInterfaceQualifierShaderTemplate % qualifier, False) for qualifier in ["in", "out", "buffer", "attribute", "varying"]], []) + createCases("conflicting_instance_names", conflictingInstanceNamesShaderTemplate, False) + createCases("conflicting_function_and_instance_name", conflictingFunctionAndInstanceNameShaderTemplate, False) + createCases("conflicting_function_and_block_name", conflictingFunctionAndBlockNameShaderTemplate, False) + sum([createCases("conflicting_%s_and_instance_name" % qualifier, conflictingVariableAndInstanceNameShaderTemplate % qualifier, False) for qualifier in ["uniform", "in", "out"]], []) + sum([createCases("conflicting_%s_and_block_name" % qualifier, conflictingVariableAndBlockNameShaderTemplate % qualifier, False) for qualifier in ["uniform", "in", "out"]], []) + createCases("matching_instance_and_block_name", matchingInstanceAndBlockNameShaderTemplate, False) + createCases("reference_using_block_name", referenceUsingBlockNameShaderTemplate, False) + createCases("empty_block", emptyBlockShaderTemplate, False) + createCases("empty_layout", emptyLayoutShaderTemplate, False) + createCases("empty_member_layout", emptyMemberLayoutShaderTemplate, False) + createCases("empty_global_layout", emptyGlobalLayoutShaderTemplate, False) + createCases("structure_definition", structureDefinitionShaderTemplate, False) + sum([createCases("member_layout_%s" % qualifier, invalidMemberLayoutShaderTemplate % qualifier, False) for qualifier in ["shared", "packed", "std140"]], []) + createCases("missing_block_name", missingBlockNameShaderTemplate, False) + createCases("invalid_number_block_name", invalidNumberBlockNameShaderTemplate, False) + createCases("invalid_hash_block_name", invalidHashBlockNameShaderTemplate, False) + createCases("invalid_dollar_block_name", invalidDollarBlockNameShaderTemplate, False) + createCases("invalid_identifier_block_name", invalidIdentifierBlockNameShaderTemplate, False) + createCases("too_long_block_name", tooLongIdentifierBlockNameShaderTemplate, False) + createCases("invalid_number_instance_name", invalidNumberInstanceNameShaderTemplate, False) + createCases("invalid_hash_instance_name", invalidDollarInstanceNameShaderTemplate, False) + createCases("invalid_dollar_instance_name", invalidDollarInstanceNameShaderTemplate, False) + createCases("invalid_identifier_instance_name", invalidIdentifierInstanceNameShaderTemplate, False) + createCases("repeated_block", repeatedBlockShaderTemplate, False) + createCases("repeated_block_no_instance_name", repeatedBlockNoInstanceNameShaderTemplate, False) ) allCases.append(CaseGroup("valid", "Valid uniform interface block syntax tests.", validCases)) allCases.append(CaseGroup("invalid", "Invalid uniform interface block syntax tests.", invalidCases)) if __name__ == "__main__": print "Generating shader case files." writeAllCases("uniform_block.test", allCases)