1#!/usr/bin/python
2# Copyright 2017 The ANGLE Project Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5#
6# gen_uniform_type_table.py:
7#  Code generation for OpenGL uniform type info tables.
8#  NOTE: don't run this script directly. Run scripts/run_code_generation.py.
9
10from datetime import date
11
12import sys
13
14all_uniform_types = [
15    "GL_NONE", "GL_BOOL", "GL_BOOL_VEC2", "GL_BOOL_VEC3", "GL_BOOL_VEC4", "GL_FLOAT",
16    "GL_FLOAT_MAT2", "GL_FLOAT_MAT2x3", "GL_FLOAT_MAT2x4", "GL_FLOAT_MAT3", "GL_FLOAT_MAT3x2",
17    "GL_FLOAT_MAT3x4", "GL_FLOAT_MAT4", "GL_FLOAT_MAT4x2", "GL_FLOAT_MAT4x3", "GL_FLOAT_VEC2",
18    "GL_FLOAT_VEC3", "GL_FLOAT_VEC4", "GL_IMAGE_2D", "GL_IMAGE_2D_ARRAY", "GL_IMAGE_3D",
19    "GL_IMAGE_CUBE", "GL_IMAGE_CUBE_MAP_ARRAY", "GL_IMAGE_BUFFER", "GL_INT", "GL_INT_IMAGE_2D",
20    "GL_INT_IMAGE_2D_ARRAY", "GL_INT_IMAGE_3D", "GL_INT_IMAGE_CUBE", "GL_INT_IMAGE_CUBE_MAP_ARRAY",
21    "GL_INT_IMAGE_BUFFER", "GL_INT_SAMPLER_2D", "GL_INT_SAMPLER_2D_ARRAY",
22    "GL_INT_SAMPLER_2D_MULTISAMPLE", "GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY", "GL_INT_SAMPLER_3D",
23    "GL_INT_SAMPLER_CUBE", "GL_INT_SAMPLER_CUBE_MAP_ARRAY", "GL_INT_SAMPLER_BUFFER", "GL_INT_VEC2",
24    "GL_INT_VEC3", "GL_INT_VEC4", "GL_SAMPLER_2D", "GL_SAMPLER_2D_ARRAY",
25    "GL_SAMPLER_2D_ARRAY_SHADOW", "GL_SAMPLER_2D_MULTISAMPLE", "GL_SAMPLER_2D_MULTISAMPLE_ARRAY",
26    "GL_SAMPLER_2D_RECT_ANGLE", "GL_SAMPLER_2D_SHADOW", "GL_SAMPLER_3D", "GL_SAMPLER_CUBE",
27    "GL_SAMPLER_CUBE_MAP_ARRAY", "GL_SAMPLER_BUFFER", "GL_SAMPLER_CUBE_SHADOW",
28    "GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW", "GL_SAMPLER_EXTERNAL_OES", "GL_UNSIGNED_INT",
29    "GL_UNSIGNED_INT_ATOMIC_COUNTER", "GL_UNSIGNED_INT_IMAGE_2D", "GL_UNSIGNED_INT_IMAGE_2D_ARRAY",
30    "GL_UNSIGNED_INT_IMAGE_3D", "GL_UNSIGNED_INT_IMAGE_CUBE",
31    "GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY", "GL_UNSIGNED_INT_IMAGE_BUFFER",
32    "GL_UNSIGNED_INT_SAMPLER_2D", "GL_UNSIGNED_INT_SAMPLER_2D_ARRAY",
33    "GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE", "GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY",
34    "GL_UNSIGNED_INT_SAMPLER_3D", "GL_UNSIGNED_INT_SAMPLER_CUBE",
35    "GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY", "GL_UNSIGNED_INT_SAMPLER_BUFFER",
36    "GL_UNSIGNED_INT_VEC2", "GL_UNSIGNED_INT_VEC3", "GL_UNSIGNED_INT_VEC4",
37    "GL_SAMPLER_VIDEO_IMAGE_WEBGL"
38]
39
40# Uniform texture types. Be wary of substrings finding the wrong types.
41# e.g. with 2D_MULTISAMPLE/2D_ARRAY and 2D.
42texture_types = {
43    "2D": "2D",
44    "2D_ARRAY": "2D_ARRAY",
45    "2D_ARRAY_SHADOW": "2D_ARRAY",
46    "2D_MULTISAMPLE": "2D_MULTISAMPLE",
47    "2D_MULTISAMPLE_ARRAY": "2D_MULTISAMPLE_ARRAY",
48    "2D_RECT_ANGLE": "2D",
49    "2D_SHADOW": "2D",
50    "3D": "3D",
51    "CUBE": "CUBE_MAP",
52    "CUBE_SHADOW": "CUBE_MAP",
53    "EXTERNAL_OES": "EXTERNAL_OES",
54    "RECT": "RECTANGLE",
55    "CUBE_MAP_ARRAY": "CUBE_MAP_ARRAY",
56    "BUFFER": "BUFFER",
57    "VIDEO_IMAGE_WEBGL": "VIDEO_IMAGE_WEBGL",
58}
59
60template_cpp = """// GENERATED FILE - DO NOT EDIT.
61// Generated by {script_name}.
62//
63// Copyright {copyright_year} The ANGLE Project Authors. All rights reserved.
64// Use of this source code is governed by a BSD-style license that can be
65// found in the LICENSE file.
66//
67// Uniform type info table:
68//   Metadata about a particular uniform format, indexed by GL type.
69
70#include <array>
71#include "common/utilities.h"
72
73using namespace angle;
74
75namespace gl
76{{
77
78namespace
79{{
80constexpr std::array<UniformTypeInfo, {total_count}> kInfoTable =
81{{{{
82{uniform_type_info_data}
83}}}};
84
85size_t GetTypeInfoIndex(GLenum uniformType)
86{{
87    switch (uniformType)
88    {{
89{uniform_type_index_cases}
90        default:
91            UNREACHABLE();
92            return 0;
93    }}
94}}
95}}  // anonymous namespace
96
97const UniformTypeInfo &GetUniformTypeInfo(GLenum uniformType)
98{{
99    ASSERT(kInfoTable[GetTypeInfoIndex(uniformType)].type == uniformType);
100    return kInfoTable[GetTypeInfoIndex(uniformType)];
101}}
102
103}}  // namespace gl
104"""
105
106type_info_data_template = """{{{type}, {component_type}, {texture_type}, {transposed_type}, {bool_type}, {sampler_format}, {rows}, {columns}, {components}, {component_size}, {internal_size}, {external_size}, {is_sampler}, {is_matrix}, {is_image}, {glsl_asfloat} }}"""
107type_index_case_template = """case {enum_value}: return {index_value};"""
108
109
110def cpp_bool(value):
111    return "true" if value else "false"
112
113
114def get_component_type(uniform_type):
115    if uniform_type.find("GL_BOOL") == 0:
116        return "GL_BOOL"
117    elif uniform_type.find("GL_FLOAT") == 0:
118        return "GL_FLOAT"
119    elif uniform_type.find("GL_INT") == 0:
120        return "GL_INT"
121    elif uniform_type.find("GL_UNSIGNED_INT") == 0:
122        return "GL_UNSIGNED_INT"
123    elif uniform_type == "GL_NONE":
124        return "GL_NONE"
125    else:
126        return "GL_INT"
127
128
129def get_texture_type(uniform_type):
130    for sampler_type, tex_type in texture_types.items():
131        if uniform_type.endswith(sampler_type):
132            return "GL_TEXTURE_" + tex_type
133    return "GL_NONE"
134
135
136def get_transposed_type(uniform_type):
137    if "_MAT" in uniform_type:
138        if "x" in uniform_type:
139            return "GL_FLOAT_MAT" + uniform_type[-1] + "x" + uniform_type[uniform_type.find("_MAT")
140                                                                          + 4]
141        else:
142            return uniform_type
143    else:
144        return "GL_NONE"
145
146
147def get_bool_type(uniform_type):
148    if uniform_type == "GL_INT" or uniform_type == "GL_UNSIGNED_INT" or uniform_type == "GL_FLOAT":
149        return "GL_BOOL"
150    elif "_VEC" in uniform_type:
151        return "GL_BOOL_VEC" + uniform_type[-1]
152    else:
153        return "GL_NONE"
154
155
156def get_sampler_format(uniform_type):
157    if not "_SAMPLER_" in uniform_type:
158        return "SamplerFormat::InvalidEnum"
159    elif "_SHADOW" in uniform_type:
160        return "SamplerFormat::Shadow"
161    elif "GL_UNSIGNED_INT_SAMPLER_" in uniform_type:
162        return "SamplerFormat::Unsigned"
163    elif "GL_INT_SAMPLER_" in uniform_type:
164        return "SamplerFormat::Signed"
165    else:
166        return "SamplerFormat::Float"
167
168
169def get_rows(uniform_type):
170    if uniform_type == "GL_NONE":
171        return "0"
172    elif "_MAT" in uniform_type:
173        return uniform_type[-1]
174    else:
175        return "1"
176
177
178def get_columns(uniform_type):
179    if uniform_type == "GL_NONE":
180        return "0"
181    elif "_VEC" in uniform_type:
182        return uniform_type[-1]
183    elif "_MAT" in uniform_type:
184        return uniform_type[uniform_type.find("_MAT") + 4]
185    else:
186        return "1"
187
188
189def get_components(uniform_type):
190    return str(int(get_rows(uniform_type)) * int(get_columns(uniform_type)))
191
192
193def get_component_size(uniform_type):
194    component_type = get_component_type(uniform_type)
195    if component_type == "GL_BOOL":
196        return "sizeof(GLint)"
197    elif component_type == "GL_FLOAT":
198        return "sizeof(GLfloat)"
199    elif component_type == "GL_INT":
200        return "sizeof(GLint)"
201    elif component_type == "GL_UNSIGNED_INT":
202        return "sizeof(GLuint)"
203    elif component_type == "GL_NONE":
204        return "0"
205    else:
206        raise "Invalid component type: " + component_type
207
208
209def get_internal_size(uniform_type):
210    return get_component_size(uniform_type) + " * " + str(int(get_rows(uniform_type)) * 4)
211
212
213def get_external_size(uniform_type):
214    return get_component_size(uniform_type) + " * " + get_components(uniform_type)
215
216
217def get_is_sampler(uniform_type):
218    return cpp_bool("_SAMPLER_" in uniform_type)
219
220
221def get_is_matrix(uniform_type):
222    return cpp_bool("_MAT" in uniform_type)
223
224
225def get_is_image(uniform_type):
226    return cpp_bool("_VIDEO_" not in uniform_type and "_IMAGE_" in uniform_type)
227
228
229def get_glsl_asfloat(uniform_type):
230    component_type = get_component_type(uniform_type)
231    if component_type == "GL_BOOL":
232        return '""'
233    elif component_type == "GL_FLOAT":
234        return '""'
235    elif component_type == "GL_INT":
236        return '"intBitsToFloat"'
237    elif component_type == "GL_UNSIGNED_INT":
238        return '"uintBitsToFloat"'
239    elif component_type == "GL_NONE":
240        return '""'
241    else:
242        raise "Invalid component type: " + component_type
243
244
245def gen_type_info(uniform_type):
246    return type_info_data_template.format(
247        type=uniform_type,
248        component_type=get_component_type(uniform_type),
249        texture_type=get_texture_type(uniform_type),
250        transposed_type=get_transposed_type(uniform_type),
251        bool_type=get_bool_type(uniform_type),
252        sampler_format=get_sampler_format(uniform_type),
253        rows=get_rows(uniform_type),
254        columns=get_columns(uniform_type),
255        components=get_components(uniform_type),
256        component_size=get_component_size(uniform_type),
257        internal_size=get_internal_size(uniform_type),
258        external_size=get_external_size(uniform_type),
259        is_sampler=get_is_sampler(uniform_type),
260        is_matrix=get_is_matrix(uniform_type),
261        is_image=get_is_image(uniform_type),
262        glsl_asfloat=get_glsl_asfloat(uniform_type))
263
264
265def gen_type_index_case(index, uniform_type):
266    return "case " + uniform_type + ": return " + str(index) + ";"
267
268
269def main():
270
271    # auto_script parameters.
272    if len(sys.argv) > 1:
273        inputs = []
274        outputs = ['uniform_type_info_autogen.cpp']
275
276        if sys.argv[1] == 'inputs':
277            print ','.join(inputs)
278        elif sys.argv[1] == 'outputs':
279            print ','.join(outputs)
280        else:
281            print('Invalid script parameters')
282            return 1
283        return 0
284
285    uniform_type_info_data = ",\n".join(
286        [gen_type_info(uniform_type) for uniform_type in all_uniform_types])
287    uniform_type_index_cases = "\n".join([
288        gen_type_index_case(index, uniform_type)
289        for index, uniform_type in enumerate(all_uniform_types)
290    ])
291
292    with open('uniform_type_info_autogen.cpp', 'wt') as out_file:
293        output_cpp = template_cpp.format(
294            script_name=sys.argv[0],
295            copyright_year=date.today().year,
296            total_count=len(all_uniform_types),
297            uniform_type_info_data=uniform_type_info_data,
298            uniform_type_index_cases=uniform_type_index_cases)
299        out_file.write(output_cpp)
300        out_file.close()
301    return 0
302
303
304if __name__ == '__main__':
305    sys.exit(main())
306