mirror of
https://github.com/bkaradzic/bgfx.git
synced 2026-02-17 20:52:36 +01:00
Updated glsl-optimizer.
This commit is contained in:
4
3rdparty/glsl-optimizer/.gitignore
vendored
4
3rdparty/glsl-optimizer/.gitignore
vendored
@@ -1,3 +1,4 @@
|
||||
node_modules
|
||||
*.a
|
||||
*.dll
|
||||
*.exe
|
||||
@@ -73,4 +74,5 @@ glsl_compiler
|
||||
.settings/
|
||||
.pydevproject
|
||||
|
||||
build
|
||||
build
|
||||
metalTemp.metal
|
||||
|
||||
5
3rdparty/glsl-optimizer/CMakeLists.txt
vendored
5
3rdparty/glsl-optimizer/CMakeLists.txt
vendored
@@ -36,6 +36,11 @@ target_link_libraries(glsl_compiler glsl_optimizer)
|
||||
file(GLOB glsl_test_sources tests/*.cpp)
|
||||
add_executable(glsl_test ${glsl_test_sources})
|
||||
target_link_libraries(glsl_test glsl_optimizer)
|
||||
if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
|
||||
# OSX-specific build requirements
|
||||
find_library(OpenGL_LIBRARY OpenGL )
|
||||
target_link_libraries(glsl_test ${OpenGL_LIBRARY})
|
||||
endif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
|
||||
|
||||
file(GLOB glslopt_sources contrib/glslopt/*.cpp)
|
||||
add_executable(glslopt ${glslopt_sources})
|
||||
|
||||
54
3rdparty/glsl-optimizer/Changelog.md
vendored
54
3rdparty/glsl-optimizer/Changelog.md
vendored
@@ -1,6 +1,60 @@
|
||||
GLSL optimizer Change Log
|
||||
=========================
|
||||
|
||||
2014 10
|
||||
-------
|
||||
|
||||
Goodies:
|
||||
|
||||
* Support for translating GLSL shaders into Apple Metal shading language.
|
||||
Exactly same process; GLSL in (preferably ES3 variant), optimization passes, Metal out.
|
||||
All uniforms currently will be put into one constant buffer.
|
||||
Pass kGlslTargetMetal target to get Metal.
|
||||
* Shader reflection API. See glslopt_shader_get_* functions. Binding indices
|
||||
are only automatically assigned on Metal now; on GL/ES targets the reflection API is only
|
||||
useful to get list of inputs/uniforms, their names and types.
|
||||
* Improved dead code elimation: some cases of swizzled/masked assignments where same variable was on both sides
|
||||
were not eliminated if that variable was totally unused later.
|
||||
* Merged with upstream Mesa, comes with new optimizations (min/max pruning, tree rebalancing, vector_insert lowering).
|
||||
|
||||
Fixes:
|
||||
|
||||
* sampler3D declarations were missing precision qualifier on GLES3.0.
|
||||
|
||||
|
||||
2014 09
|
||||
-------
|
||||
|
||||
Goodies:
|
||||
|
||||
* Supports GL_EXT_draw_buffers in ES2.0, for MRT.
|
||||
|
||||
|
||||
2014 08
|
||||
-------
|
||||
|
||||
Goodies:
|
||||
|
||||
* Supports GL_EXT_shader_framebuffer_fetch now, in both ES2.0 & 3.0.
|
||||
|
||||
Fixes:
|
||||
|
||||
* Fixed printing of infinities & NaNs.
|
||||
* Fixed vectorization pass in some cases going wrong on texture lookups.
|
||||
|
||||
|
||||
2014 06
|
||||
-------
|
||||
|
||||
Goodies:
|
||||
|
||||
* Optimization: split vectors with only some used components into scalars.
|
||||
|
||||
Fixes:
|
||||
|
||||
* Fixed more issues with for-loop printing.
|
||||
* Fixed printing of unsigned integer swizzled & constants.
|
||||
|
||||
2014 03
|
||||
-------
|
||||
|
||||
|
||||
17
3rdparty/glsl-optimizer/README.md
vendored
17
3rdparty/glsl-optimizer/README.md
vendored
@@ -2,16 +2,19 @@ GLSL optimizer
|
||||
==============
|
||||
|
||||
A C++ library that takes GLSL shaders, does some GPU-independent optimizations on them
|
||||
and outputs GLSL back. Optimizations are function inlining, dead code removal, copy propagation,
|
||||
and outputs GLSL or Metal source back. Optimizations are function inlining, dead code removal, copy propagation,
|
||||
constant folding, constant propagation, arithmetic optimizations and so on.
|
||||
|
||||
Apparently quite a few mobile platforms are pretty bad at optimizing GLSL shaders; and
|
||||
Apparently quite a few mobile platforms are pretty bad at optimizing shaders; and
|
||||
unfortunately they *also* lack offline shader compilers. So using a GLSL optimizer offline
|
||||
before can make the shader run much faster on a platform like that. See performance numbers
|
||||
in [this blog post](http://aras-p.info/blog/2010/09/29/glsl-optimizer/).
|
||||
|
||||
Even for drivers that have decent shader optimization, GLSL optimizer could be useful to just strip away
|
||||
dead code, make shaders smaller and do uniform/input reflection offline.
|
||||
|
||||
Almost all actual code is [Mesa 3D's GLSL](http://cgit.freedesktop.org/mesa/mesa/log/)
|
||||
compiler; all this library does is spits out optimized GLSL back, and adds GLES type precision
|
||||
compiler; all this library does is spits out optimized GLSL or Metal back, and adds GLES type precision
|
||||
handling to the optimizer.
|
||||
|
||||
This GLSL optimizer is made for [Unity's](http://unity3d.com/) purposes and is built-in
|
||||
@@ -19,7 +22,7 @@ starting with Unity 3.0.
|
||||
|
||||
GLSL Optimizer is licensed according to the terms of the MIT license.
|
||||
|
||||
See badly maintained [change log](Changelog.md).
|
||||
See [change log here](Changelog.md).
|
||||
|
||||
|
||||
Usage
|
||||
@@ -38,7 +41,7 @@ This will build the optimizer library and some executable binaries.
|
||||
|
||||
Interface for the library is `src/glsl/glsl_optimizer.h`. General usage is:
|
||||
|
||||
ctx = glslopt_initialize();
|
||||
ctx = glslopt_initialize(targetVersion);
|
||||
for (lots of shaders) {
|
||||
shader = glslopt_optimize (ctx, shaderType, shaderSource, options);
|
||||
if (glslopt_get_status (shader)) {
|
||||
@@ -59,7 +62,7 @@ and run `glsl_optimizer_tests` project; in Xcode use `projects/xcode5/glsl_optim
|
||||
project. The test executable requires path to the `tests` folder as an argument.
|
||||
|
||||
Each test comes as three text files; input, expected IR dump and expected optimized
|
||||
GLSL dump.
|
||||
GLSL dump. GLES3 tests are also converted into Metal.
|
||||
|
||||
If you're making changes to the project and want pull requests accepted easier, I'd
|
||||
appreciate if there would be no test suite regressions. If you are implementing a
|
||||
@@ -70,7 +73,7 @@ Notes
|
||||
-----
|
||||
|
||||
* GLSL versions 1.10 and 1.20 are supported. 1.10 is the default, use #version 120 to specify
|
||||
1.20.
|
||||
1.20. Higher GLSL versions might work, but aren't tested now.
|
||||
* GLSL ES versions 1.00 and 3.00 are supported.
|
||||
|
||||
|
||||
|
||||
9
3rdparty/glsl-optimizer/binding.gyp
vendored
9
3rdparty/glsl-optimizer/binding.gyp
vendored
@@ -4,16 +4,19 @@
|
||||
],
|
||||
'targets': [
|
||||
{
|
||||
"include_dirs" : [
|
||||
"<!(node -e \"require('nan')\")"
|
||||
],
|
||||
'target_name': 'glslOptimizer',
|
||||
'dependencies': [
|
||||
'src/glsl_optimizer_lib.gyp:*',
|
||||
],
|
||||
'sources': [
|
||||
'src/node/binding.cpp',
|
||||
'src/node/compiler.cpp',
|
||||
'src/node/compiler.h',
|
||||
'src/node/shader.cpp',
|
||||
'src/node/shader.h',
|
||||
'src/node/shader.cpp',
|
||||
'src/node/compiler.h',
|
||||
'src/node/compiler.cpp'
|
||||
],
|
||||
'conditions': [
|
||||
['OS=="win"', {
|
||||
|
||||
23
3rdparty/glsl-optimizer/contrib/glslopt/Main.cpp
vendored
23
3rdparty/glsl-optimizer/contrib/glslopt/Main.cpp
vendored
@@ -1,3 +1,4 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
@@ -9,15 +10,18 @@ static int printhelp(const char* msg)
|
||||
{
|
||||
if (msg) printf("%s\n\n\n", msg);
|
||||
printf("Usage: glslopt <-f|-v> <input shader> [<output shader>]\n");
|
||||
printf("\t-f : fragment shader\n");
|
||||
printf("\t-f : fragment shader (default)\n");
|
||||
printf("\t-v : vertex shader\n");
|
||||
printf("\t-1 : target OpenGL (default)\n");
|
||||
printf("\t-2 : target OpenGL ES 2.0\n");
|
||||
printf("\t-3 : target OpenGL ES 3.0\n");
|
||||
printf("\n\tIf no output specified, output is to [input].out.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
static bool init()
|
||||
static bool init(glslopt_target target)
|
||||
{
|
||||
gContext = glslopt_initialize(kGlslTargetOpenGL);
|
||||
gContext = glslopt_initialize(target);
|
||||
if( !gContext )
|
||||
return false;
|
||||
return true;
|
||||
@@ -51,7 +55,7 @@ static char* loadFile(const char* filename)
|
||||
|
||||
static bool saveFile(const char* filename, const char* data)
|
||||
{
|
||||
int size = (int)strlen(data)+1;
|
||||
int size = (int)strlen(data);
|
||||
|
||||
FILE* file = fopen(filename, "wt");
|
||||
if( !file )
|
||||
@@ -101,6 +105,7 @@ int main(int argc, char* argv[])
|
||||
return printhelp(NULL);
|
||||
|
||||
bool vertexShader = false, freename = false;
|
||||
glslopt_target languageTarget = kGlslTargetOpenGL;
|
||||
const char* source = 0;
|
||||
char* dest = 0;
|
||||
|
||||
@@ -110,8 +115,14 @@ int main(int argc, char* argv[])
|
||||
{
|
||||
if( 0 == strcmp("-v", argv[i]) )
|
||||
vertexShader = true;
|
||||
if( 0 == strcmp("-f", argv[i]) )
|
||||
else if( 0 == strcmp("-f", argv[i]) )
|
||||
vertexShader = false;
|
||||
else if( 0 == strcmp("-1", argv[i]) )
|
||||
languageTarget = kGlslTargetOpenGL;
|
||||
else if( 0 == strcmp("-2", argv[i]) )
|
||||
languageTarget = kGlslTargetOpenGLES20;
|
||||
else if( 0 == strcmp("-3", argv[i]) )
|
||||
languageTarget = kGlslTargetOpenGLES30;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -125,7 +136,7 @@ int main(int argc, char* argv[])
|
||||
if( !source )
|
||||
return printhelp("Must give a source");
|
||||
|
||||
if( !init() )
|
||||
if( !init(languageTarget) )
|
||||
{
|
||||
printf("Failed to initialize glslopt!\n");
|
||||
return 1;
|
||||
|
||||
25
3rdparty/glsl-optimizer/package.json
vendored
25
3rdparty/glsl-optimizer/package.json
vendored
@@ -8,14 +8,31 @@
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/donny-dont/glsl-optimizer.git"
|
||||
"url": "https://github.com/aras-p/glsl-optimizer.git"
|
||||
},
|
||||
"keywords": [
|
||||
"glsl",
|
||||
"webgl"
|
||||
"webgl",
|
||||
"shader",
|
||||
"optimize",
|
||||
"optimizer",
|
||||
"opengl",
|
||||
"essl",
|
||||
"es",
|
||||
"opengles"
|
||||
],
|
||||
"author": "Don Olmstead",
|
||||
"readmeFilename": "README.md",
|
||||
"author": "Aras Pranckevičius",
|
||||
"license": "MIT",
|
||||
"gypfile": true,
|
||||
"readmeFilename": "README.md"
|
||||
"bugs": {
|
||||
"url": "https://github.com/aras-p/glsl-optimizer/issues"
|
||||
},
|
||||
"homepage": "https://github.com/aras-p/glsl-optimizer",
|
||||
"directories": {
|
||||
"test": "tests"
|
||||
},
|
||||
"dependencies": {
|
||||
"nan": "~1.2.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>../../src/mesa;../../include/c99;../../include;../../src/glsl;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>../../src/mesa;../../src;../../include/c99;../../include;../../src/glsl;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;NOMINMAX;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;__STDC_VERSION__=199901L;__STDC__;strdup=_strdup;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<ExceptionHandling>
|
||||
@@ -97,7 +97,7 @@
|
||||
</Midl>
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>../../src/mesa;../../include/c99;../../include;../../src/glsl;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>../../src/mesa;../../src;../../include/c99;../../include;../../src/glsl;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;NOMINMAX;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;__STDC_VERSION__=199901L;__STDC__;strdup=_strdup;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<ExceptionHandling>
|
||||
@@ -120,7 +120,7 @@
|
||||
<ClCompile>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>../../src/mesa;../../include/c99;../../include;../../src/glsl;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>../../src/mesa;../../src;../../include/c99;../../include;../../src/glsl;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;NOMINMAX;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;__STDC_VERSION__=199901L;__STDC__;strdup=_strdup;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ExceptionHandling>
|
||||
</ExceptionHandling>
|
||||
@@ -145,7 +145,7 @@
|
||||
<ClCompile>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>../../src/mesa;../../include/c99;../../include;../../src/glsl;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>../../src/mesa;../../src;../../include/c99;../../include;../../src/glsl;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;NOMINMAX;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;__STDC_VERSION__=199901L;__STDC__;strdup=_strdup;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ExceptionHandling>
|
||||
</ExceptionHandling>
|
||||
@@ -179,6 +179,7 @@
|
||||
<ClInclude Include="..\..\src\glsl\ir_hierarchical_visitor.h" />
|
||||
<ClInclude Include="..\..\src\glsl\ir_optimization.h" />
|
||||
<ClInclude Include="..\..\src\glsl\ir_print_glsl_visitor.h" />
|
||||
<ClInclude Include="..\..\src\glsl\ir_print_metal_visitor.h" />
|
||||
<ClInclude Include="..\..\src\glsl\ir_print_visitor.h" />
|
||||
<ClInclude Include="..\..\src\glsl\ir_rvalue_visitor.h" />
|
||||
<ClInclude Include="..\..\src\glsl\ir_stats.h" />
|
||||
@@ -192,13 +193,11 @@
|
||||
<ClInclude Include="..\..\src\glsl\list.h" />
|
||||
<ClInclude Include="..\..\src\glsl\loop_analysis.h" />
|
||||
<ClInclude Include="..\..\src\glsl\program.h" />
|
||||
<ClInclude Include="..\..\src\glsl\ralloc.h" />
|
||||
<ClInclude Include="..\..\src\glsl\s_expression.h" />
|
||||
<ClInclude Include="..\..\src\glsl\standalone_scaffolding.h" />
|
||||
<ClInclude Include="..\..\src\glsl\strtod.h" />
|
||||
<ClInclude Include="..\..\src\glsl\glcpp\glcpp-parse.h" />
|
||||
<ClInclude Include="..\..\src\glsl\glcpp\glcpp.h" />
|
||||
<ClInclude Include="..\..\src\mesa\main\hash_table.h" />
|
||||
<ClInclude Include="..\..\src\mesa\program\hash_table.h" />
|
||||
<ClInclude Include="..\..\src\mesa\program\prog_instruction.h" />
|
||||
<ClInclude Include="..\..\src\mesa\program\prog_parameter.h" />
|
||||
@@ -215,6 +214,8 @@
|
||||
<ClInclude Include="..\..\src\mesa\main\macros.h" />
|
||||
<ClInclude Include="..\..\src\mesa\main\mtypes.h" />
|
||||
<ClInclude Include="..\..\src\mesa\main\simple_list.h" />
|
||||
<ClInclude Include="..\..\src\util\hash_table.h" />
|
||||
<ClInclude Include="..\..\src\util\ralloc.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\src\glsl\ast_array_index.cpp" />
|
||||
@@ -246,6 +247,7 @@
|
||||
<ClCompile Include="..\..\src\glsl\ir_hv_accept.cpp" />
|
||||
<ClCompile Include="..\..\src\glsl\ir_import_prototypes.cpp" />
|
||||
<ClCompile Include="..\..\src\glsl\ir_print_glsl_visitor.cpp" />
|
||||
<ClCompile Include="..\..\src\glsl\ir_print_metal_visitor.cpp" />
|
||||
<ClCompile Include="..\..\src\glsl\ir_print_visitor.cpp" />
|
||||
<ClCompile Include="..\..\src\glsl\ir_rvalue_visitor.cpp" />
|
||||
<ClCompile Include="..\..\src\glsl\ir_stats.cpp" />
|
||||
@@ -273,6 +275,7 @@
|
||||
<ClCompile Include="..\..\src\glsl\lower_mat_op_to_vec.cpp" />
|
||||
<ClCompile Include="..\..\src\glsl\lower_named_interface_blocks.cpp" />
|
||||
<ClCompile Include="..\..\src\glsl\lower_noise.cpp" />
|
||||
<ClCompile Include="..\..\src\glsl\lower_offset_array.cpp" />
|
||||
<ClCompile Include="..\..\src\glsl\lower_output_reads.cpp" />
|
||||
<ClCompile Include="..\..\src\glsl\lower_packed_varyings.cpp" />
|
||||
<ClCompile Include="..\..\src\glsl\lower_packing_builtins.cpp" />
|
||||
@@ -282,6 +285,7 @@
|
||||
<ClCompile Include="..\..\src\glsl\lower_vec_index_to_cond_assign.cpp" />
|
||||
<ClCompile Include="..\..\src\glsl\lower_vec_index_to_swizzle.cpp" />
|
||||
<ClCompile Include="..\..\src\glsl\lower_vector.cpp" />
|
||||
<ClCompile Include="..\..\src\glsl\lower_vertex_id.cpp" />
|
||||
<ClCompile Include="..\..\src\glsl\main.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
@@ -296,6 +300,7 @@
|
||||
<ClCompile Include="..\..\src\glsl\opt_copy_propagation.cpp" />
|
||||
<ClCompile Include="..\..\src\glsl\opt_copy_propagation_elements.cpp" />
|
||||
<ClCompile Include="..\..\src\glsl\opt_cse.cpp" />
|
||||
<ClCompile Include="..\..\src\glsl\opt_dead_builtin_variables.cpp" />
|
||||
<ClCompile Include="..\..\src\glsl\opt_dead_builtin_varyings.cpp" />
|
||||
<ClCompile Include="..\..\src\glsl\opt_dead_code.cpp" />
|
||||
<ClCompile Include="..\..\src\glsl\opt_dead_code_local.cpp" />
|
||||
@@ -304,13 +309,15 @@
|
||||
<ClCompile Include="..\..\src\glsl\opt_flip_matrices.cpp" />
|
||||
<ClCompile Include="..\..\src\glsl\opt_function_inlining.cpp" />
|
||||
<ClCompile Include="..\..\src\glsl\opt_if_simplification.cpp" />
|
||||
<ClCompile Include="..\..\src\glsl\opt_minmax.cpp" />
|
||||
<ClCompile Include="..\..\src\glsl\opt_noop_swizzle.cpp" />
|
||||
<ClCompile Include="..\..\src\glsl\opt_rebalance_tree.cpp" />
|
||||
<ClCompile Include="..\..\src\glsl\opt_redundant_jumps.cpp" />
|
||||
<ClCompile Include="..\..\src\glsl\opt_structure_splitting.cpp" />
|
||||
<ClCompile Include="..\..\src\glsl\opt_swizzle_swizzle.cpp" />
|
||||
<ClCompile Include="..\..\src\glsl\opt_tree_grafting.cpp" />
|
||||
<ClCompile Include="..\..\src\glsl\opt_vectorize.cpp" />
|
||||
<ClCompile Include="..\..\src\glsl\ralloc.c" />
|
||||
<ClCompile Include="..\..\src\glsl\opt_vector_splitting.cpp" />
|
||||
<ClCompile Include="..\..\src\glsl\s_expression.cpp" />
|
||||
<ClCompile Include="..\..\src\glsl\standalone_scaffolding.cpp" />
|
||||
<ClCompile Include="..\..\src\glsl\strtod.c" />
|
||||
@@ -323,10 +330,11 @@
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\glsl\glcpp\pp.c" />
|
||||
<ClCompile Include="..\..\src\mesa\main\hash_table.c" />
|
||||
<ClCompile Include="..\..\src\mesa\main\imports.c" />
|
||||
<ClCompile Include="..\..\src\mesa\program\prog_hash_table.c" />
|
||||
<ClCompile Include="..\..\src\mesa\program\symbol_table.c" />
|
||||
<ClCompile Include="..\..\src\util\hash_table.c" />
|
||||
<ClCompile Include="..\..\src\util\ralloc.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<CustomBuildStep Include="..\..\src\glsl\glsl_lexer.lpp">
|
||||
|
||||
@@ -60,6 +60,9 @@
|
||||
<ClInclude Include="..\..\src\glsl\ir_print_glsl_visitor.h">
|
||||
<Filter>src\glsl</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\glsl\ir_print_metal_visitor.h">
|
||||
<Filter>src\glsl</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\glsl\ir_print_visitor.h">
|
||||
<Filter>src\glsl</Filter>
|
||||
</ClInclude>
|
||||
@@ -87,9 +90,6 @@
|
||||
<ClInclude Include="..\..\src\glsl\program.h">
|
||||
<Filter>src\glsl</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\glsl\ralloc.h">
|
||||
<Filter>src\glsl</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\glsl\s_expression.h">
|
||||
<Filter>src\glsl</Filter>
|
||||
</ClInclude>
|
||||
@@ -153,9 +153,6 @@
|
||||
<ClInclude Include="..\..\src\glsl\ir_uniform.h">
|
||||
<Filter>src\glsl</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\mesa\main\hash_table.h">
|
||||
<Filter>src\mesa\main</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\mesa\program\hash_table.h">
|
||||
<Filter>src\mesa\program</Filter>
|
||||
</ClInclude>
|
||||
@@ -174,6 +171,12 @@
|
||||
<ClInclude Include="..\..\src\glsl\ir_stats.h">
|
||||
<Filter>src\glsl</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\util\hash_table.h">
|
||||
<Filter>src\util</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\util\ralloc.h">
|
||||
<Filter>src\util</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\src\glsl\ast_expr.cpp">
|
||||
@@ -254,6 +257,9 @@
|
||||
<ClCompile Include="..\..\src\glsl\ir_print_glsl_visitor.cpp">
|
||||
<Filter>src\glsl</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\glsl\ir_print_metal_visitor.cpp">
|
||||
<Filter>src\glsl</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\glsl\ir_print_visitor.cpp">
|
||||
<Filter>src\glsl</Filter>
|
||||
</ClCompile>
|
||||
@@ -389,9 +395,6 @@
|
||||
<ClCompile Include="..\..\src\glsl\opt_vectorize.cpp">
|
||||
<Filter>src\glsl</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\glsl\ralloc.c">
|
||||
<Filter>src\glsl</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\glsl\s_expression.cpp">
|
||||
<Filter>src\glsl</Filter>
|
||||
</ClCompile>
|
||||
@@ -416,9 +419,6 @@
|
||||
<ClCompile Include="..\..\src\mesa\program\symbol_table.c">
|
||||
<Filter>src\mesa\program</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\mesa\main\hash_table.c">
|
||||
<Filter>src\mesa\main</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\mesa\main\imports.c">
|
||||
<Filter>src\mesa\main</Filter>
|
||||
</ClCompile>
|
||||
@@ -455,6 +455,9 @@
|
||||
<ClCompile Include="..\..\src\glsl\lower_named_interface_blocks.cpp">
|
||||
<Filter>src\glsl</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\glsl\lower_offset_array.cpp">
|
||||
<Filter>src\glsl</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\glsl\lower_output_reads.cpp">
|
||||
<Filter>src\glsl</Filter>
|
||||
</ClCompile>
|
||||
@@ -464,9 +467,21 @@
|
||||
<ClCompile Include="..\..\src\glsl\lower_vector_insert.cpp">
|
||||
<Filter>src\glsl</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\glsl\lower_vertex_id.cpp">
|
||||
<Filter>src\glsl</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\glsl\builtin_types.cpp">
|
||||
<Filter>src\glsl</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\glsl\opt_dead_builtin_variables.cpp">
|
||||
<Filter>src\glsl</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\glsl\opt_minmax.cpp">
|
||||
<Filter>src\glsl</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\glsl\opt_rebalance_tree.cpp">
|
||||
<Filter>src\glsl</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\glsl\opt_dead_builtin_varyings.cpp">
|
||||
<Filter>src\glsl</Filter>
|
||||
</ClCompile>
|
||||
@@ -476,6 +491,15 @@
|
||||
<ClCompile Include="..\..\src\glsl\ir_stats.cpp">
|
||||
<Filter>src\glsl</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\glsl\opt_vector_splitting.cpp">
|
||||
<Filter>src\glsl</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\util\hash_table.c">
|
||||
<Filter>src\util</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\util\ralloc.c">
|
||||
<Filter>src\util</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\..\README.md" />
|
||||
|
||||
@@ -26,6 +26,16 @@
|
||||
2B3854711293BE5000F3E692 /* opt_structure_splitting.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B38545A1293BE5000F3E692 /* opt_structure_splitting.cpp */; };
|
||||
2B3854721293BE5000F3E692 /* opt_swizzle_swizzle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B38545B1293BE5000F3E692 /* opt_swizzle_swizzle.cpp */; };
|
||||
2B3854731293BE5000F3E692 /* opt_tree_grafting.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B38545C1293BE5000F3E692 /* opt_tree_grafting.cpp */; };
|
||||
2B39E41519E959F9001C6A17 /* hash_table.c in Sources */ = {isa = PBXBuildFile; fileRef = 2B39E41019E959F9001C6A17 /* hash_table.c */; };
|
||||
2B39E41619E959F9001C6A17 /* hash_table.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B39E41119E959F9001C6A17 /* hash_table.h */; };
|
||||
2B39E41719E959F9001C6A17 /* macros.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B39E41219E959F9001C6A17 /* macros.h */; };
|
||||
2B39E41819E959F9001C6A17 /* ralloc.c in Sources */ = {isa = PBXBuildFile; fileRef = 2B39E41319E959F9001C6A17 /* ralloc.c */; };
|
||||
2B39E41919E959F9001C6A17 /* ralloc.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B39E41419E959F9001C6A17 /* ralloc.h */; };
|
||||
2B39E41F19E95FA7001C6A17 /* lower_offset_array.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B39E41A19E95FA7001C6A17 /* lower_offset_array.cpp */; };
|
||||
2B39E42019E95FA7001C6A17 /* lower_vertex_id.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B39E41B19E95FA7001C6A17 /* lower_vertex_id.cpp */; };
|
||||
2B39E42119E95FA7001C6A17 /* opt_dead_builtin_variables.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B39E41C19E95FA7001C6A17 /* opt_dead_builtin_variables.cpp */; };
|
||||
2B39E42219E95FA7001C6A17 /* opt_minmax.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B39E41D19E95FA7001C6A17 /* opt_minmax.cpp */; };
|
||||
2B39E42319E95FA7001C6A17 /* opt_rebalance_tree.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B39E41E19E95FA7001C6A17 /* opt_rebalance_tree.cpp */; };
|
||||
2B3A6B9015FA043D000DCBE1 /* link_uniforms.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B3A6B8E15FA043D000DCBE1 /* link_uniforms.cpp */; };
|
||||
2B3A6B9715FA0468000DCBE1 /* link_uniform_initializers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B3A6B9515FA0468000DCBE1 /* link_uniform_initializers.cpp */; };
|
||||
2B3A6BA815FA0494000DCBE1 /* lower_clip_distance.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B3A6B9C15FA0494000DCBE1 /* lower_clip_distance.cpp */; };
|
||||
@@ -60,8 +70,6 @@
|
||||
2B8979E2182CB62900718F8A /* link_atomics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B8979E1182CB62900718F8A /* link_atomics.cpp */; };
|
||||
2B92A05E15F9FF4700CFED4A /* builtin_variables.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B92A05C15F9FF4700CFED4A /* builtin_variables.cpp */; };
|
||||
2B9F0A3D189664F3002FF617 /* opt_vectorize.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B9F0A3C189664F3002FF617 /* opt_vectorize.cpp */; };
|
||||
2BA07FAB1352E7BB00A1C074 /* ralloc.c in Sources */ = {isa = PBXBuildFile; fileRef = 2BA07FA91352E7BB00A1C074 /* ralloc.c */; };
|
||||
2BA07FAC1352E7BB00A1C074 /* ralloc.h in Headers */ = {isa = PBXBuildFile; fileRef = 2BA07FAA1352E7BB00A1C074 /* ralloc.h */; };
|
||||
2BA55A9C1207FEA6002DC82D /* ast_expr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2BA55A511207FEA6002DC82D /* ast_expr.cpp */; };
|
||||
2BA55A9D1207FEA6002DC82D /* ast_function.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2BA55A521207FEA6002DC82D /* ast_function.cpp */; };
|
||||
2BA55A9E1207FEA6002DC82D /* ast_to_hir.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2BA55A531207FEA6002DC82D /* ast_to_hir.cpp */; };
|
||||
@@ -118,6 +126,7 @@
|
||||
2BA7E14617D0AEB200D5C475 /* lower_vector_insert.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2BA7E13C17D0AEB200D5C475 /* lower_vector_insert.cpp */; };
|
||||
2BA7E14817D0AEB200D5C475 /* opt_dead_builtin_varyings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2BA7E13D17D0AEB200D5C475 /* opt_dead_builtin_varyings.cpp */; };
|
||||
2BA7E14A17D0AEB200D5C475 /* opt_flip_matrices.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2BA7E13E17D0AEB200D5C475 /* opt_flip_matrices.cpp */; };
|
||||
2BA84CA619580C9D0021BE1D /* opt_vector_splitting.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2BA84CA519580C9D0021BE1D /* opt_vector_splitting.cpp */; };
|
||||
2BB2F5B012B8F1580052C6B0 /* lower_discard.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2BB2F5AA12B8F1580052C6B0 /* lower_discard.cpp */; };
|
||||
2BB2F5B112B8F1580052C6B0 /* lower_instructions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2BB2F5AB12B8F1580052C6B0 /* lower_instructions.cpp */; };
|
||||
2BB2F5B212B8F1580052C6B0 /* lower_vector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2BB2F5AC12B8F1580052C6B0 /* lower_vector.cpp */; };
|
||||
@@ -150,9 +159,9 @@
|
||||
2BBD9DBC1719698C00515007 /* lower_packed_varyings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2BBD9DB61719698900515007 /* lower_packed_varyings.cpp */; };
|
||||
2BBD9DBE1719698C00515007 /* lower_packing_builtins.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2BBD9DB71719698A00515007 /* lower_packing_builtins.cpp */; };
|
||||
2BBD9DC01719698C00515007 /* opt_flatten_nested_if_blocks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2BBD9DB81719698B00515007 /* opt_flatten_nested_if_blocks.cpp */; };
|
||||
2BBD9DC4171969F700515007 /* hash_table.c in Sources */ = {isa = PBXBuildFile; fileRef = 2BBD9DC2171969F700515007 /* hash_table.c */; };
|
||||
2BBD9DC6171969F700515007 /* hash_table.h in Headers */ = {isa = PBXBuildFile; fileRef = 2BBD9DC3171969F700515007 /* hash_table.h */; };
|
||||
2BBD9DC817196A3B00515007 /* imports.c in Sources */ = {isa = PBXBuildFile; fileRef = 2BBD9DC717196A3B00515007 /* imports.c */; };
|
||||
2BCF3A8D19ADE1E50057C395 /* ir_print_metal_visitor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2BCF3A8B19ADE1E50057C395 /* ir_print_metal_visitor.cpp */; };
|
||||
2BCF3A8E19ADE1E50057C395 /* ir_print_metal_visitor.h in Headers */ = {isa = PBXBuildFile; fileRef = 2BCF3A8C19ADE1E50057C395 /* ir_print_metal_visitor.h */; };
|
||||
2BDCB95D184E182B0075CE6F /* ir_stats.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2BDCB95B184E182B0075CE6F /* ir_stats.cpp */; };
|
||||
2BDCB95E184E182B0075CE6F /* ir_stats.h in Headers */ = {isa = PBXBuildFile; fileRef = 2BDCB95C184E182B0075CE6F /* ir_stats.h */; };
|
||||
2BEC22EA1356E98300B5E301 /* opt_copy_propagation_elements.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2BEC22CB1356E94E00B5E301 /* opt_copy_propagation_elements.cpp */; };
|
||||
@@ -178,6 +187,16 @@
|
||||
2B38545A1293BE5000F3E692 /* opt_structure_splitting.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = opt_structure_splitting.cpp; path = ../../src/glsl/opt_structure_splitting.cpp; sourceTree = SOURCE_ROOT; };
|
||||
2B38545B1293BE5000F3E692 /* opt_swizzle_swizzle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = opt_swizzle_swizzle.cpp; path = ../../src/glsl/opt_swizzle_swizzle.cpp; sourceTree = SOURCE_ROOT; };
|
||||
2B38545C1293BE5000F3E692 /* opt_tree_grafting.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = opt_tree_grafting.cpp; path = ../../src/glsl/opt_tree_grafting.cpp; sourceTree = SOURCE_ROOT; };
|
||||
2B39E41019E959F9001C6A17 /* hash_table.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = hash_table.c; path = ../../src/util/hash_table.c; sourceTree = "<group>"; };
|
||||
2B39E41119E959F9001C6A17 /* hash_table.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = hash_table.h; path = ../../src/util/hash_table.h; sourceTree = "<group>"; };
|
||||
2B39E41219E959F9001C6A17 /* macros.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = macros.h; path = ../../src/util/macros.h; sourceTree = "<group>"; };
|
||||
2B39E41319E959F9001C6A17 /* ralloc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = ralloc.c; path = ../../src/util/ralloc.c; sourceTree = "<group>"; };
|
||||
2B39E41419E959F9001C6A17 /* ralloc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ralloc.h; path = ../../src/util/ralloc.h; sourceTree = "<group>"; };
|
||||
2B39E41A19E95FA7001C6A17 /* lower_offset_array.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = lower_offset_array.cpp; path = ../../src/glsl/lower_offset_array.cpp; sourceTree = "<group>"; };
|
||||
2B39E41B19E95FA7001C6A17 /* lower_vertex_id.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = lower_vertex_id.cpp; path = ../../src/glsl/lower_vertex_id.cpp; sourceTree = "<group>"; };
|
||||
2B39E41C19E95FA7001C6A17 /* opt_dead_builtin_variables.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = opt_dead_builtin_variables.cpp; path = ../../src/glsl/opt_dead_builtin_variables.cpp; sourceTree = "<group>"; };
|
||||
2B39E41D19E95FA7001C6A17 /* opt_minmax.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = opt_minmax.cpp; path = ../../src/glsl/opt_minmax.cpp; sourceTree = "<group>"; };
|
||||
2B39E41E19E95FA7001C6A17 /* opt_rebalance_tree.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = opt_rebalance_tree.cpp; path = ../../src/glsl/opt_rebalance_tree.cpp; sourceTree = "<group>"; };
|
||||
2B3A6B8E15FA043D000DCBE1 /* link_uniforms.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = link_uniforms.cpp; path = ../../src/glsl/link_uniforms.cpp; sourceTree = SOURCE_ROOT; };
|
||||
2B3A6B9515FA0468000DCBE1 /* link_uniform_initializers.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = link_uniform_initializers.cpp; path = ../../src/glsl/link_uniform_initializers.cpp; sourceTree = SOURCE_ROOT; };
|
||||
2B3A6B9C15FA0494000DCBE1 /* lower_clip_distance.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = lower_clip_distance.cpp; path = ../../src/glsl/lower_clip_distance.cpp; sourceTree = SOURCE_ROOT; };
|
||||
@@ -214,8 +233,6 @@
|
||||
2B8979E1182CB62900718F8A /* link_atomics.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = link_atomics.cpp; path = ../../src/glsl/link_atomics.cpp; sourceTree = "<group>"; };
|
||||
2B92A05C15F9FF4700CFED4A /* builtin_variables.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = builtin_variables.cpp; path = ../../src/glsl/builtin_variables.cpp; sourceTree = SOURCE_ROOT; };
|
||||
2B9F0A3C189664F3002FF617 /* opt_vectorize.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = opt_vectorize.cpp; path = ../../src/glsl/opt_vectorize.cpp; sourceTree = "<group>"; };
|
||||
2BA07FA91352E7BB00A1C074 /* ralloc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = ralloc.c; path = ../../src/glsl/ralloc.c; sourceTree = SOURCE_ROOT; };
|
||||
2BA07FAA1352E7BB00A1C074 /* ralloc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ralloc.h; path = ../../src/glsl/ralloc.h; sourceTree = SOURCE_ROOT; };
|
||||
2BA0808A1352EBFB00A1C074 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = main.cpp; path = ../../src/glsl/main.cpp; sourceTree = SOURCE_ROOT; };
|
||||
2BA55A511207FEA6002DC82D /* ast_expr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ast_expr.cpp; path = ../../src/glsl/ast_expr.cpp; sourceTree = SOURCE_ROOT; };
|
||||
2BA55A521207FEA6002DC82D /* ast_function.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ast_function.cpp; path = ../../src/glsl/ast_function.cpp; sourceTree = SOURCE_ROOT; };
|
||||
@@ -275,6 +292,7 @@
|
||||
2BA7E13C17D0AEB200D5C475 /* lower_vector_insert.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = lower_vector_insert.cpp; path = ../../src/glsl/lower_vector_insert.cpp; sourceTree = "<group>"; };
|
||||
2BA7E13D17D0AEB200D5C475 /* opt_dead_builtin_varyings.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = opt_dead_builtin_varyings.cpp; path = ../../src/glsl/opt_dead_builtin_varyings.cpp; sourceTree = "<group>"; };
|
||||
2BA7E13E17D0AEB200D5C475 /* opt_flip_matrices.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = opt_flip_matrices.cpp; path = ../../src/glsl/opt_flip_matrices.cpp; sourceTree = "<group>"; };
|
||||
2BA84CA519580C9D0021BE1D /* opt_vector_splitting.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = opt_vector_splitting.cpp; path = ../../src/glsl/opt_vector_splitting.cpp; sourceTree = "<group>"; };
|
||||
2BB2F5AA12B8F1580052C6B0 /* lower_discard.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = lower_discard.cpp; path = ../../src/glsl/lower_discard.cpp; sourceTree = SOURCE_ROOT; };
|
||||
2BB2F5AB12B8F1580052C6B0 /* lower_instructions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = lower_instructions.cpp; path = ../../src/glsl/lower_instructions.cpp; sourceTree = SOURCE_ROOT; };
|
||||
2BB2F5AC12B8F1580052C6B0 /* lower_vector.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = lower_vector.cpp; path = ../../src/glsl/lower_vector.cpp; sourceTree = SOURCE_ROOT; };
|
||||
@@ -308,9 +326,9 @@
|
||||
2BBD9DB61719698900515007 /* lower_packed_varyings.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = lower_packed_varyings.cpp; path = ../../src/glsl/lower_packed_varyings.cpp; sourceTree = "<group>"; };
|
||||
2BBD9DB71719698A00515007 /* lower_packing_builtins.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = lower_packing_builtins.cpp; path = ../../src/glsl/lower_packing_builtins.cpp; sourceTree = "<group>"; };
|
||||
2BBD9DB81719698B00515007 /* opt_flatten_nested_if_blocks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = opt_flatten_nested_if_blocks.cpp; path = ../../src/glsl/opt_flatten_nested_if_blocks.cpp; sourceTree = "<group>"; };
|
||||
2BBD9DC2171969F700515007 /* hash_table.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = hash_table.c; path = ../../src/mesa/main/hash_table.c; sourceTree = "<group>"; };
|
||||
2BBD9DC3171969F700515007 /* hash_table.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = hash_table.h; path = ../../src/mesa/main/hash_table.h; sourceTree = "<group>"; };
|
||||
2BBD9DC717196A3B00515007 /* imports.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = imports.c; path = ../../src/mesa/main/imports.c; sourceTree = "<group>"; };
|
||||
2BCF3A8B19ADE1E50057C395 /* ir_print_metal_visitor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ir_print_metal_visitor.cpp; path = ../../src/glsl/ir_print_metal_visitor.cpp; sourceTree = "<group>"; };
|
||||
2BCF3A8C19ADE1E50057C395 /* ir_print_metal_visitor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ir_print_metal_visitor.h; path = ../../src/glsl/ir_print_metal_visitor.h; sourceTree = "<group>"; };
|
||||
2BDCB95B184E182B0075CE6F /* ir_stats.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ir_stats.cpp; path = ../../src/glsl/ir_stats.cpp; sourceTree = "<group>"; };
|
||||
2BDCB95C184E182B0075CE6F /* ir_stats.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ir_stats.h; path = ../../src/glsl/ir_stats.h; sourceTree = "<group>"; };
|
||||
2BEC22CB1356E94E00B5E301 /* opt_copy_propagation_elements.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = opt_copy_propagation_elements.cpp; path = ../../src/glsl/opt_copy_propagation_elements.cpp; sourceTree = SOURCE_ROOT; };
|
||||
@@ -341,6 +359,7 @@
|
||||
08FB7795FE84155DC02AAC07 /* Source */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
2B39E40F19E959E0001C6A17 /* util */,
|
||||
2BB7259A135094A60057D8B5 /* mesa */,
|
||||
2B47D9FC1209C85400937F2C /* program */,
|
||||
2BA55A501207FE41002DC82D /* glsl */,
|
||||
@@ -356,6 +375,18 @@
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
2B39E40F19E959E0001C6A17 /* util */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
2B39E41019E959F9001C6A17 /* hash_table.c */,
|
||||
2B39E41119E959F9001C6A17 /* hash_table.h */,
|
||||
2B39E41219E959F9001C6A17 /* macros.h */,
|
||||
2B39E41319E959F9001C6A17 /* ralloc.c */,
|
||||
2B39E41419E959F9001C6A17 /* ralloc.h */,
|
||||
);
|
||||
name = util;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
2B47D9FC1209C85400937F2C /* program */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -434,6 +465,8 @@
|
||||
2BA55A801207FEA6002DC82D /* ir_optimization.h */,
|
||||
2BA55A811207FEA6002DC82D /* ir_print_glsl_visitor.cpp */,
|
||||
2BA55A821207FEA6002DC82D /* ir_print_glsl_visitor.h */,
|
||||
2BCF3A8B19ADE1E50057C395 /* ir_print_metal_visitor.cpp */,
|
||||
2BCF3A8C19ADE1E50057C395 /* ir_print_metal_visitor.h */,
|
||||
2BA55A831207FEA6002DC82D /* ir_print_visitor.cpp */,
|
||||
2BA55A841207FEA6002DC82D /* ir_print_visitor.h */,
|
||||
2B62490D12191339003F6EEE /* ir_rvalue_visitor.cpp */,
|
||||
@@ -473,6 +506,7 @@
|
||||
2B38544A1293BE5000F3E692 /* lower_mat_op_to_vec.cpp */,
|
||||
2BA7E13B17D0AEB200D5C475 /* lower_named_interface_blocks.cpp */,
|
||||
2BBA49251254706A00D42573 /* lower_noise.cpp */,
|
||||
2B39E41A19E95FA7001C6A17 /* lower_offset_array.cpp */,
|
||||
2B3A6B9E15FA0494000DCBE1 /* lower_output_reads.cpp */,
|
||||
2BBD9DB61719698900515007 /* lower_packed_varyings.cpp */,
|
||||
2BBD9DB71719698A00515007 /* lower_packing_builtins.cpp */,
|
||||
@@ -482,6 +516,7 @@
|
||||
2B38544E1293BE5000F3E692 /* lower_vec_index_to_swizzle.cpp */,
|
||||
2BB2F5AC12B8F1580052C6B0 /* lower_vector.cpp */,
|
||||
2BA7E13C17D0AEB200D5C475 /* lower_vector_insert.cpp */,
|
||||
2B39E41B19E95FA7001C6A17 /* lower_vertex_id.cpp */,
|
||||
2BA0808A1352EBFB00A1C074 /* main.cpp */,
|
||||
2B38544F1293BE5000F3E692 /* opt_algebraic.cpp */,
|
||||
2B3A6BA115FA0494000DCBE1 /* opt_array_splitting.cpp */,
|
||||
@@ -491,6 +526,7 @@
|
||||
2B3854531293BE5000F3E692 /* opt_copy_propagation.cpp */,
|
||||
2BEC22CB1356E94E00B5E301 /* opt_copy_propagation_elements.cpp */,
|
||||
2B8979DF182C195C00718F8A /* opt_cse.cpp */,
|
||||
2B39E41C19E95FA7001C6A17 /* opt_dead_builtin_variables.cpp */,
|
||||
2BA7E13D17D0AEB200D5C475 /* opt_dead_builtin_varyings.cpp */,
|
||||
2B3854551293BE5000F3E692 /* opt_dead_code.cpp */,
|
||||
2B3854541293BE5000F3E692 /* opt_dead_code_local.cpp */,
|
||||
@@ -499,15 +535,16 @@
|
||||
2BA7E13E17D0AEB200D5C475 /* opt_flip_matrices.cpp */,
|
||||
2B3854571293BE5000F3E692 /* opt_function_inlining.cpp */,
|
||||
2B3854581293BE5000F3E692 /* opt_if_simplification.cpp */,
|
||||
2B39E41D19E95FA7001C6A17 /* opt_minmax.cpp */,
|
||||
2B3854591293BE5000F3E692 /* opt_noop_swizzle.cpp */,
|
||||
2B39E41E19E95FA7001C6A17 /* opt_rebalance_tree.cpp */,
|
||||
2BBA49271254706A00D42573 /* opt_redundant_jumps.cpp */,
|
||||
2B38545A1293BE5000F3E692 /* opt_structure_splitting.cpp */,
|
||||
2B38545B1293BE5000F3E692 /* opt_swizzle_swizzle.cpp */,
|
||||
2B38545C1293BE5000F3E692 /* opt_tree_grafting.cpp */,
|
||||
2B9F0A3C189664F3002FF617 /* opt_vectorize.cpp */,
|
||||
2BA84CA519580C9D0021BE1D /* opt_vector_splitting.cpp */,
|
||||
2BA55A991207FEA6002DC82D /* program.h */,
|
||||
2BA07FA91352E7BB00A1C074 /* ralloc.c */,
|
||||
2BA07FAA1352E7BB00A1C074 /* ralloc.h */,
|
||||
2BA55A9A1207FEA6002DC82D /* s_expression.cpp */,
|
||||
2BA55A9B1207FEA6002DC82D /* s_expression.h */,
|
||||
2B655A7613E0324F00B5278F /* standalone_scaffolding.cpp */,
|
||||
@@ -522,8 +559,6 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
2BBD9DC717196A3B00515007 /* imports.c */,
|
||||
2BBD9DC2171969F700515007 /* hash_table.c */,
|
||||
2BBD9DC3171969F700515007 /* hash_table.h */,
|
||||
2BB7259B135094BE0057D8B5 /* compiler.h */,
|
||||
2BB7259C135094BE0057D8B5 /* config.h */,
|
||||
2BB7259D135094BE0057D8B5 /* context.h */,
|
||||
@@ -549,6 +584,7 @@
|
||||
2BA55AA01207FEA6002DC82D /* ast.h in Headers */,
|
||||
2BA55AA71207FEA6002DC82D /* glsl_optimizer.h in Headers */,
|
||||
2BA55AA91207FEA6002DC82D /* glsl_parser_extras.h in Headers */,
|
||||
2B39E41619E959F9001C6A17 /* hash_table.h in Headers */,
|
||||
2BA55AAB1207FEA6002DC82D /* glsl_parser.h in Headers */,
|
||||
2BA55AAD1207FEA6002DC82D /* glsl_symbol_table.h in Headers */,
|
||||
2BA55AAF1207FEA6002DC82D /* glsl_types.h in Headers */,
|
||||
@@ -558,8 +594,10 @@
|
||||
2BA55AC31207FEA6002DC82D /* ir_hierarchical_visitor.h in Headers */,
|
||||
2BA55ACB1207FEA6002DC82D /* ir_optimization.h in Headers */,
|
||||
2BA55ACD1207FEA6002DC82D /* ir_print_glsl_visitor.h in Headers */,
|
||||
2B39E41919E959F9001C6A17 /* ralloc.h in Headers */,
|
||||
2BA55ACF1207FEA6002DC82D /* ir_print_visitor.h in Headers */,
|
||||
2BA55AD61207FEA6002DC82D /* ir_unused_structs.h in Headers */,
|
||||
2BCF3A8E19ADE1E50057C395 /* ir_print_metal_visitor.h in Headers */,
|
||||
2BA55AD91207FEA6002DC82D /* ir_variable_refcount.h in Headers */,
|
||||
2BA55ADD1207FEA6002DC82D /* ir_visitor.h in Headers */,
|
||||
2BA55ADF1207FEA6002DC82D /* ir.h in Headers */,
|
||||
@@ -567,6 +605,7 @@
|
||||
2BA55AE31207FEA6002DC82D /* list.h in Headers */,
|
||||
2BA55AE41207FEA6002DC82D /* program.h in Headers */,
|
||||
2BA55AE61207FEA6002DC82D /* s_expression.h in Headers */,
|
||||
2B39E41719E959F9001C6A17 /* macros.h in Headers */,
|
||||
2B47DA021209C87B00937F2C /* hash_table.h in Headers */,
|
||||
2B47DA041209C87B00937F2C /* symbol_table.h in Headers */,
|
||||
2B62491212191339003F6EEE /* ir_rvalue_visitor.h in Headers */,
|
||||
@@ -586,7 +625,6 @@
|
||||
2BA7E13F17D0AEB200D5C475 /* builtin_type_macros.h in Headers */,
|
||||
2BDCB95E184E182B0075CE6F /* ir_stats.h in Headers */,
|
||||
2BB725B5135094BE0057D8B5 /* simple_list.h in Headers */,
|
||||
2BA07FAC1352E7BB00A1C074 /* ralloc.h in Headers */,
|
||||
2B655A7A13E0324F00B5278F /* standalone_scaffolding.h in Headers */,
|
||||
2B3A6BDB15FA08E1000DCBE1 /* ir_builder.h in Headers */,
|
||||
2B6AC7B9161EC99C0094FD86 /* prog_instruction.h in Headers */,
|
||||
@@ -596,7 +634,6 @@
|
||||
2B6AC8AD161ED9080094FD86 /* glminimal.h in Headers */,
|
||||
2BBD9DB11719694100515007 /* link_uniform_block_active_visitor.h in Headers */,
|
||||
2BBD9DBB1719698C00515007 /* link_varyings.h in Headers */,
|
||||
2BBD9DC6171969F700515007 /* hash_table.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -660,10 +697,12 @@
|
||||
2BA55AA41207FEA6002DC82D /* glsl_lexer.cpp in Sources */,
|
||||
2BDCB95D184E182B0075CE6F /* ir_stats.cpp in Sources */,
|
||||
2BA55AA61207FEA6002DC82D /* glsl_optimizer.cpp in Sources */,
|
||||
2B39E41F19E95FA7001C6A17 /* lower_offset_array.cpp in Sources */,
|
||||
2BA55AA81207FEA6002DC82D /* glsl_parser_extras.cpp in Sources */,
|
||||
2BA55AAA1207FEA6002DC82D /* glsl_parser.cpp in Sources */,
|
||||
2BA55AAE1207FEA6002DC82D /* glsl_types.cpp in Sources */,
|
||||
2BA55AB01207FEA6002DC82D /* hir_field_selection.cpp in Sources */,
|
||||
2BCF3A8D19ADE1E50057C395 /* ir_print_metal_visitor.cpp in Sources */,
|
||||
2BA55AB21207FEA6002DC82D /* ir_basic_block.cpp in Sources */,
|
||||
2BA55AB41207FEA6002DC82D /* ir_clone.cpp in Sources */,
|
||||
2BA55AB51207FEA6002DC82D /* ir_constant_expression.cpp in Sources */,
|
||||
@@ -691,6 +730,7 @@
|
||||
2B78C91D1858B052007F5D2A /* ir_equals.cpp in Sources */,
|
||||
2B6A99F61223B1670059FBED /* glcpp-parse.c in Sources */,
|
||||
2B6A99FB1223B1670059FBED /* pp.c in Sources */,
|
||||
2BA84CA619580C9D0021BE1D /* opt_vector_splitting.cpp in Sources */,
|
||||
2BBA49281254706A00D42573 /* glsl_symbol_table.cpp in Sources */,
|
||||
2BBA492A1254706A00D42573 /* loop_analysis.cpp in Sources */,
|
||||
2BBA492C1254706A00D42573 /* loop_controls.cpp in Sources */,
|
||||
@@ -701,6 +741,7 @@
|
||||
2BBA49301254706A00D42573 /* opt_redundant_jumps.cpp in Sources */,
|
||||
2B38545F1293BE5000F3E692 /* lower_if_to_cond_assign.cpp in Sources */,
|
||||
2B3854601293BE5000F3E692 /* lower_jumps.cpp in Sources */,
|
||||
2B39E42319E95FA7001C6A17 /* opt_rebalance_tree.cpp in Sources */,
|
||||
2B3854611293BE5000F3E692 /* lower_mat_op_to_vec.cpp in Sources */,
|
||||
2B3854641293BE5000F3E692 /* lower_vec_index_to_cond_assign.cpp in Sources */,
|
||||
2B3854651293BE5000F3E692 /* lower_vec_index_to_swizzle.cpp in Sources */,
|
||||
@@ -709,6 +750,7 @@
|
||||
2B3854681293BE5000F3E692 /* opt_constant_propagation.cpp in Sources */,
|
||||
2B3854691293BE5000F3E692 /* opt_constant_variable.cpp in Sources */,
|
||||
2B38546A1293BE5000F3E692 /* opt_copy_propagation.cpp in Sources */,
|
||||
2B39E42019E95FA7001C6A17 /* lower_vertex_id.cpp in Sources */,
|
||||
2B38546B1293BE5000F3E692 /* opt_dead_code_local.cpp in Sources */,
|
||||
2B8979E2182CB62900718F8A /* link_atomics.cpp in Sources */,
|
||||
2B38546C1293BE5000F3E692 /* opt_dead_code.cpp in Sources */,
|
||||
@@ -723,12 +765,13 @@
|
||||
2BB2F5B012B8F1580052C6B0 /* lower_discard.cpp in Sources */,
|
||||
2BB2F5B112B8F1580052C6B0 /* lower_instructions.cpp in Sources */,
|
||||
2BB2F5B212B8F1580052C6B0 /* lower_vector.cpp in Sources */,
|
||||
2B39E42219E95FA7001C6A17 /* opt_minmax.cpp in Sources */,
|
||||
2BB2F5B412B8F1580052C6B0 /* strtod.c in Sources */,
|
||||
2BA07FAB1352E7BB00A1C074 /* ralloc.c in Sources */,
|
||||
2BA7E14017D0AEB200D5C475 /* builtin_types.cpp in Sources */,
|
||||
2BEC22EA1356E98300B5E301 /* opt_copy_propagation_elements.cpp in Sources */,
|
||||
2B8979E0182C195C00718F8A /* opt_cse.cpp in Sources */,
|
||||
2B655A7313E0322E00B5278F /* ir_function_detect_recursion.cpp in Sources */,
|
||||
2B39E42119E95FA7001C6A17 /* opt_dead_builtin_variables.cpp in Sources */,
|
||||
2B655A7913E0324F00B5278F /* standalone_scaffolding.cpp in Sources */,
|
||||
2BA7E14A17D0AEB200D5C475 /* opt_flip_matrices.cpp in Sources */,
|
||||
2BA7E14217D0AEB200D5C475 /* link_interface_blocks.cpp in Sources */,
|
||||
@@ -736,11 +779,13 @@
|
||||
2B3A6B9015FA043D000DCBE1 /* link_uniforms.cpp in Sources */,
|
||||
2B3A6B9715FA0468000DCBE1 /* link_uniform_initializers.cpp in Sources */,
|
||||
2B3A6BA815FA0494000DCBE1 /* lower_clip_distance.cpp in Sources */,
|
||||
2B39E41819E959F9001C6A17 /* ralloc.c in Sources */,
|
||||
2B3A6BA915FA0494000DCBE1 /* lower_discard_flow.cpp in Sources */,
|
||||
2B3A6BAA15FA0494000DCBE1 /* lower_output_reads.cpp in Sources */,
|
||||
2B3A6BAC15FA0494000DCBE1 /* lower_ubo_reference.cpp in Sources */,
|
||||
2B3A6BAD15FA0494000DCBE1 /* opt_array_splitting.cpp in Sources */,
|
||||
2B3A6BDA15FA08E1000DCBE1 /* ir_builder.cpp in Sources */,
|
||||
2B39E41519E959F9001C6A17 /* hash_table.c in Sources */,
|
||||
2BBD9DAD1719694100515007 /* ast_array_index.cpp in Sources */,
|
||||
2BBD9DAF1719694100515007 /* link_uniform_block_active_visitor.cpp in Sources */,
|
||||
2BBD9DB21719694100515007 /* link_uniform_blocks.cpp in Sources */,
|
||||
@@ -748,7 +793,6 @@
|
||||
2BBD9DBC1719698C00515007 /* lower_packed_varyings.cpp in Sources */,
|
||||
2BBD9DBE1719698C00515007 /* lower_packing_builtins.cpp in Sources */,
|
||||
2BBD9DC01719698C00515007 /* opt_flatten_nested_if_blocks.cpp in Sources */,
|
||||
2BBD9DC4171969F700515007 /* hash_table.c in Sources */,
|
||||
2BBD9DC817196A3B00515007 /* imports.c in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
@@ -793,6 +837,7 @@
|
||||
HEADER_SEARCH_PATHS = (
|
||||
../../include,
|
||||
../../src/mesa,
|
||||
../../src,
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.6;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
@@ -808,6 +853,7 @@
|
||||
HEADER_SEARCH_PATHS = (
|
||||
../../include,
|
||||
../../src/mesa,
|
||||
../../src,
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.6;
|
||||
};
|
||||
|
||||
1
3rdparty/glsl-optimizer/removeDeletedByUs.sh
vendored
1
3rdparty/glsl-optimizer/removeDeletedByUs.sh
vendored
@@ -4,6 +4,7 @@ git rm -rf docs
|
||||
git rm -rf m4
|
||||
git rm -rf src/egl
|
||||
git rm -rf src/glsl/glcpp/tests
|
||||
git rm -rf src/loader
|
||||
git rm -rf src/mapi
|
||||
git rm -rf src/mesa/drivers
|
||||
git rm -rf src/mesa/main/tests
|
||||
|
||||
4
3rdparty/glsl-optimizer/src/glsl/.gitignore
vendored
4
3rdparty/glsl-optimizer/src/glsl/.gitignore
vendored
@@ -2,3 +2,7 @@ glsl_compiler
|
||||
glsl_parser.output
|
||||
builtincompiler
|
||||
glsl_test
|
||||
subtest-cr/
|
||||
subtest-lf/
|
||||
subtest-cr-lf/
|
||||
subtest-lf-cr/
|
||||
|
||||
24
3rdparty/glsl-optimizer/src/glsl/Makefile
vendored
24
3rdparty/glsl-optimizer/src/glsl/Makefile
vendored
@@ -2,17 +2,18 @@
|
||||
|
||||
CPPFLAGS += -I../talloc \
|
||||
-I../mesa \
|
||||
-I../mapi
|
||||
-I../mapi \
|
||||
-I../../include
|
||||
|
||||
CXXFLAGS += -s -Wall -Os -fdata-sections -ffunction-sections
|
||||
CFLAGS += -s -Wall -Os -fdata-sections -ffunction-sections
|
||||
|
||||
# This list gleaned from the VC project file. Update when needed
|
||||
SRC = ast_expr.cpp \
|
||||
SRC = ast_expr.cpp \
|
||||
ast_function.cpp \
|
||||
ast_to_hir.cpp \
|
||||
ast_type.cpp \
|
||||
builtin_function.cpp \
|
||||
builtin_functions.cpp \
|
||||
glsl_lexer.cpp \
|
||||
glsl_optimizer.cpp \
|
||||
glsl_parser.cpp \
|
||||
@@ -22,6 +23,7 @@ SRC = ast_expr.cpp \
|
||||
hir_field_selection.cpp \
|
||||
ir.cpp \
|
||||
ir_basic_block.cpp \
|
||||
ir_builder.cpp \
|
||||
ir_clone.cpp \
|
||||
ir_constant_expression.cpp \
|
||||
ir_equals.cpp \
|
||||
@@ -33,12 +35,12 @@ SRC = ast_expr.cpp \
|
||||
ir_hv_accept.cpp \
|
||||
ir_import_prototypes.cpp \
|
||||
ir_print_glsl_visitor.cpp \
|
||||
ir_print_metal_visitor.cpp \
|
||||
ir_print_visitor.cpp \
|
||||
ir_reader.cpp \
|
||||
ir_rvalue_visitor.cpp \
|
||||
ir_stats.cpp \
|
||||
ir_unused_structs.cpp \
|
||||
ir_validate.cpp \
|
||||
ir_variable.cpp \
|
||||
ir_variable_refcount.cpp \
|
||||
link_functions.cpp \
|
||||
linker.cpp \
|
||||
@@ -55,17 +57,20 @@ SRC = ast_expr.cpp \
|
||||
lower_vec_index_to_cond_assign.cpp \
|
||||
lower_vec_index_to_swizzle.cpp \
|
||||
lower_vector.cpp \
|
||||
main.cpp \
|
||||
opt_algebraic.cpp \
|
||||
opt_array_splitting.cpp \
|
||||
opt_constant_folding.cpp \
|
||||
opt_constant_propagation.cpp \
|
||||
opt_constant_variable.cpp \
|
||||
opt_copy_propagation.cpp \
|
||||
opt_copy_propagation_elements.cpp \
|
||||
opt_cse.cpp \
|
||||
opt_dead_builtin_varyings.cpp \
|
||||
opt_dead_code.cpp \
|
||||
opt_dead_code_local.cpp \
|
||||
opt_dead_functions.cpp \
|
||||
opt_discard_simplification.cpp \
|
||||
opt_flatten_nested_if_blocks.cpp \
|
||||
opt_flip_matrices.cpp \
|
||||
opt_function_inlining.cpp \
|
||||
opt_if_simplification.cpp \
|
||||
opt_noop_swizzle.cpp \
|
||||
@@ -80,9 +85,10 @@ SRC = ast_expr.cpp \
|
||||
strtod.c \
|
||||
glcpp/glcpp-lex.c \
|
||||
glcpp/glcpp-parse.c \
|
||||
glcpp/glcpp.c \
|
||||
glcpp/pp.c \
|
||||
../mesa/program/hash_table.c \
|
||||
../mesa/main/hash_table.c \
|
||||
../mesa/main/imports.c \
|
||||
../mesa/program/prog_hash_table.c \
|
||||
../mesa/program/symbol_table.c
|
||||
|
||||
|
||||
|
||||
7
3rdparty/glsl-optimizer/src/glsl/SConscript
vendored
7
3rdparty/glsl-optimizer/src/glsl/SConscript
vendored
@@ -8,12 +8,15 @@ env = env.Clone()
|
||||
|
||||
env.Prepend(CPPPATH = [
|
||||
'#include',
|
||||
'#src',
|
||||
'#src/mapi',
|
||||
'#src/mesa',
|
||||
'#src/glsl',
|
||||
'#src/glsl/glcpp',
|
||||
])
|
||||
|
||||
env.Prepend(LIBS = [mesautil])
|
||||
|
||||
# Make glcpp-parse.h and glsl_parser.h reachable from the include path.
|
||||
env.Append(CPPPATH = [Dir('.').abspath, Dir('glcpp').abspath])
|
||||
|
||||
@@ -55,7 +58,6 @@ if env['msvc']:
|
||||
|
||||
# Copy these files to avoid generation object files into src/mesa/program
|
||||
env.Prepend(CPPPATH = ['#src/mesa/main'])
|
||||
env.Command('hash_table.c', '#src/mesa/main/hash_table.c', Copy('$TARGET', '$SOURCE'))
|
||||
env.Command('imports.c', '#src/mesa/main/imports.c', Copy('$TARGET', '$SOURCE'))
|
||||
# Copy these files to avoid generation object files into src/mesa/program
|
||||
env.Prepend(CPPPATH = ['#src/mesa/program'])
|
||||
@@ -65,7 +67,6 @@ env.Command('symbol_table.c', '#src/mesa/program/symbol_table.c', Copy('$TARGET'
|
||||
compiler_objs = env.StaticObject(source_lists['GLSL_COMPILER_CXX_FILES'])
|
||||
|
||||
mesa_objs = env.StaticObject([
|
||||
'hash_table.c',
|
||||
'imports.c',
|
||||
'prog_hash_table.c',
|
||||
'symbol_table.c',
|
||||
@@ -106,6 +107,6 @@ env.Alias('glsl_compiler', glsl_compiler)
|
||||
|
||||
glcpp = env.Program(
|
||||
target = 'glcpp/glcpp',
|
||||
source = ['glcpp/glcpp.c'] + mesa_objs,
|
||||
source = ['glcpp/glcpp.c', 'tests/common.c'] + mesa_objs,
|
||||
)
|
||||
env.Alias('glcpp', glcpp)
|
||||
|
||||
87
3rdparty/glsl-optimizer/src/glsl/ast.h
vendored
87
3rdparty/glsl-optimizer/src/glsl/ast.h
vendored
@@ -75,10 +75,10 @@ public:
|
||||
struct YYLTYPE locp;
|
||||
|
||||
locp.source = this->location.source;
|
||||
locp.first_line = this->location.line;
|
||||
locp.first_column = this->location.column;
|
||||
locp.last_line = locp.first_line;
|
||||
locp.last_column = locp.first_column;
|
||||
locp.first_line = this->location.first_line;
|
||||
locp.first_column = this->location.first_column;
|
||||
locp.last_line = this->location.last_line;
|
||||
locp.last_column = this->location.last_column;
|
||||
|
||||
return locp;
|
||||
}
|
||||
@@ -91,17 +91,35 @@ public:
|
||||
void set_location(const struct YYLTYPE &locp)
|
||||
{
|
||||
this->location.source = locp.source;
|
||||
this->location.line = locp.first_line;
|
||||
this->location.column = locp.first_column;
|
||||
this->location.first_line = locp.first_line;
|
||||
this->location.first_column = locp.first_column;
|
||||
this->location.last_line = locp.last_line;
|
||||
this->location.last_column = locp.last_column;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the source location range of an AST node using two location nodes
|
||||
*
|
||||
* \sa ast_node::set_location
|
||||
*/
|
||||
void set_location_range(const struct YYLTYPE &begin, const struct YYLTYPE &end)
|
||||
{
|
||||
this->location.source = begin.source;
|
||||
this->location.first_line = begin.first_line;
|
||||
this->location.last_line = end.last_line;
|
||||
this->location.first_column = begin.first_column;
|
||||
this->location.last_column = end.last_column;
|
||||
}
|
||||
|
||||
/**
|
||||
* Source location of the AST node.
|
||||
*/
|
||||
struct {
|
||||
unsigned source; /**< GLSL source number. */
|
||||
unsigned line; /**< Line number within the source string. */
|
||||
unsigned column; /**< Column in the line. */
|
||||
unsigned source; /**< GLSL source number. */
|
||||
unsigned first_line; /**< First line number within the source string. */
|
||||
unsigned first_column; /**< First column in the first line. */
|
||||
unsigned last_line; /**< Last line number within the source string. */
|
||||
unsigned last_column; /**< Last column in the last line. */
|
||||
} location;
|
||||
|
||||
exec_node link;
|
||||
@@ -199,6 +217,13 @@ public:
|
||||
virtual ir_rvalue *hir(exec_list *instructions,
|
||||
struct _mesa_glsl_parse_state *state);
|
||||
|
||||
virtual void hir_no_rvalue(exec_list *instructions,
|
||||
struct _mesa_glsl_parse_state *state);
|
||||
|
||||
ir_rvalue *do_hir(exec_list *instructions,
|
||||
struct _mesa_glsl_parse_state *state,
|
||||
bool needs_rvalue);
|
||||
|
||||
virtual void print(void) const;
|
||||
|
||||
enum ast_operators oper;
|
||||
@@ -269,6 +294,9 @@ public:
|
||||
virtual ir_rvalue *hir(exec_list *instructions,
|
||||
struct _mesa_glsl_parse_state *state);
|
||||
|
||||
virtual void hir_no_rvalue(exec_list *instructions,
|
||||
struct _mesa_glsl_parse_state *state);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Is this function call actually a constructor?
|
||||
@@ -280,14 +308,14 @@ class ast_array_specifier : public ast_node {
|
||||
public:
|
||||
/** Unsized array specifier ([]) */
|
||||
explicit ast_array_specifier(const struct YYLTYPE &locp)
|
||||
: dimension_count(1), is_unsized_array(true)
|
||||
: is_unsized_array(true)
|
||||
{
|
||||
set_location(locp);
|
||||
}
|
||||
|
||||
/** Sized array specifier ([dim]) */
|
||||
ast_array_specifier(const struct YYLTYPE &locp, ast_expression *dim)
|
||||
: dimension_count(1), is_unsized_array(false)
|
||||
: is_unsized_array(false)
|
||||
{
|
||||
set_location(locp);
|
||||
array_dimensions.push_tail(&dim->link);
|
||||
@@ -296,14 +324,10 @@ public:
|
||||
void add_dimension(ast_expression *dim)
|
||||
{
|
||||
array_dimensions.push_tail(&dim->link);
|
||||
dimension_count++;
|
||||
}
|
||||
|
||||
virtual void print(void) const;
|
||||
|
||||
/* Count including sized and unsized dimensions */
|
||||
unsigned dimension_count;
|
||||
|
||||
/* If true, this means that the array has an unsized outermost dimension. */
|
||||
bool is_unsized_array;
|
||||
|
||||
@@ -345,6 +369,9 @@ public:
|
||||
|
||||
virtual ir_rvalue *hir(exec_list *instructions,
|
||||
struct _mesa_glsl_parse_state *state);
|
||||
|
||||
virtual void hir_no_rvalue(exec_list *instructions,
|
||||
struct _mesa_glsl_parse_state *state);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -397,6 +424,7 @@ struct ast_type_qualifier {
|
||||
union {
|
||||
struct {
|
||||
unsigned invariant:1;
|
||||
unsigned precise:1;
|
||||
unsigned constant:1;
|
||||
unsigned attribute:1;
|
||||
unsigned varying:1;
|
||||
@@ -477,6 +505,13 @@ struct ast_type_qualifier {
|
||||
unsigned read_only:1; /**< "readonly" qualifier. */
|
||||
unsigned write_only:1; /**< "writeonly" qualifier. */
|
||||
/** \} */
|
||||
|
||||
/** \name Layout qualifiers for GL_ARB_gpu_shader5 */
|
||||
/** \{ */
|
||||
unsigned invocations:1;
|
||||
unsigned stream:1; /**< Has stream value assigned */
|
||||
unsigned explicit_stream:1; /**< stream value assigned explicitly by shader code */
|
||||
/** \} */
|
||||
}
|
||||
/** \brief Set of flags, accessed by name. */
|
||||
q;
|
||||
@@ -488,6 +523,9 @@ struct ast_type_qualifier {
|
||||
/** Precision of the type (highp/medium/lowp). */
|
||||
unsigned precision:2;
|
||||
|
||||
/** Geometry shader invocations for GL_ARB_gpu_shader5. */
|
||||
int invocations;
|
||||
|
||||
/**
|
||||
* Location specified via GL_ARB_explicit_attrib_location layout
|
||||
*
|
||||
@@ -506,6 +544,9 @@ struct ast_type_qualifier {
|
||||
/** Maximum output vertices in GLSL 1.50 geometry shaders. */
|
||||
int max_vertices;
|
||||
|
||||
/** Stream in GLSL 1.50 geometry shaders. */
|
||||
unsigned stream;
|
||||
|
||||
/** Input or output primitive type in GLSL 1.50 geometry shaders */
|
||||
GLenum prim_type;
|
||||
|
||||
@@ -587,6 +628,12 @@ struct ast_type_qualifier {
|
||||
bool merge_qualifier(YYLTYPE *loc,
|
||||
_mesa_glsl_parse_state *state,
|
||||
ast_type_qualifier q);
|
||||
|
||||
bool merge_in_qualifier(YYLTYPE *loc,
|
||||
_mesa_glsl_parse_state *state,
|
||||
ast_type_qualifier q,
|
||||
ast_node* &node);
|
||||
|
||||
};
|
||||
|
||||
class ast_declarator_list;
|
||||
@@ -705,13 +752,11 @@ public:
|
||||
exec_list declarations;
|
||||
|
||||
/**
|
||||
* Special flag for vertex shader "invariant" declarations.
|
||||
*
|
||||
* Vertex shaders can contain "invariant" variable redeclarations that do
|
||||
* not include a type. For example, "invariant gl_Position;". This flag
|
||||
* is used to note these cases when no type is specified.
|
||||
* Flags for redeclarations. In these cases, no type is specified, to
|
||||
* `type` is allowed to be NULL. In all other cases, this would be an error.
|
||||
*/
|
||||
int invariant;
|
||||
int invariant; /** < `invariant` redeclaration */
|
||||
int precise; /** < `precise` redeclaration */
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -88,8 +88,14 @@ update_max_array_access(ir_rvalue *ir, unsigned idx, YYLTYPE *loc,
|
||||
unsigned field_index =
|
||||
deref_record->record->type->field_index(deref_record->field);
|
||||
assert(field_index < interface_type->length);
|
||||
if (idx > deref_var->var->max_ifc_array_access[field_index]) {
|
||||
deref_var->var->max_ifc_array_access[field_index] = idx;
|
||||
|
||||
unsigned *const max_ifc_array_access =
|
||||
deref_var->var->get_max_ifc_array_access();
|
||||
|
||||
assert(max_ifc_array_access != NULL);
|
||||
|
||||
if (idx > max_ifc_array_access[field_index]) {
|
||||
max_ifc_array_access[field_index] = idx;
|
||||
|
||||
/* Check whether this access will, as a side effect, implicitly
|
||||
* cause the size of a built-in array to be too large.
|
||||
@@ -181,7 +187,8 @@ _mesa_ast_array_index_to_hir(void *mem_ctx,
|
||||
if (array->type->is_unsized_array()) {
|
||||
_mesa_glsl_error(&loc, state, "unsized array index must be constant");
|
||||
} else if (array->type->fields.array->is_interface()
|
||||
&& array->variable_referenced()->data.mode == ir_var_uniform) {
|
||||
&& array->variable_referenced()->data.mode == ir_var_uniform
|
||||
&& !state->is_version(400, 0) && !state->ARB_gpu_shader5_enable) {
|
||||
/* Page 46 in section 4.3.7 of the OpenGL ES 3.00 spec says:
|
||||
*
|
||||
* "All indexes used to index a uniform block array must be
|
||||
@@ -212,6 +219,13 @@ _mesa_ast_array_index_to_hir(void *mem_ctx,
|
||||
* as using a loop counter as the index to an array of samplers. If the
|
||||
* loop in unrolled, the code should compile correctly. Instead, emit a
|
||||
* warning.
|
||||
*
|
||||
* In GLSL 4.00 / ARB_gpu_shader5, this requirement is relaxed again to allow
|
||||
* indexing with dynamically uniform expressions. Note that these are not
|
||||
* required to be uniforms or expressions based on them, but merely that the
|
||||
* values must not diverge between shader invocations run together. If the
|
||||
* values *do* diverge, then the behavior of the operation requiring a
|
||||
* dynamically uniform expression is undefined.
|
||||
*/
|
||||
if (array->type->element_type()->is_sampler()) {
|
||||
if (!state->is_version(130, 100)) {
|
||||
@@ -226,7 +240,7 @@ _mesa_ast_array_index_to_hir(void *mem_ctx,
|
||||
"expressions will be forbidden in GLSL 1.30 "
|
||||
"and later");
|
||||
}
|
||||
} else {
|
||||
} else if (!state->is_version(400, 0) && !state->ARB_gpu_shader5_enable) {
|
||||
_mesa_glsl_error(&loc, state,
|
||||
"sampler arrays indexed with non-constant "
|
||||
"expressions is forbidden in GLSL 1.30 and "
|
||||
|
||||
133
3rdparty/glsl-optimizer/src/glsl/ast_function.cpp
vendored
133
3rdparty/glsl-optimizer/src/glsl/ast_function.cpp
vendored
@@ -41,8 +41,7 @@ process_parameters(exec_list *instructions, exec_list *actual_parameters,
|
||||
{
|
||||
unsigned count = 0;
|
||||
|
||||
foreach_list (n, parameters) {
|
||||
ast_node *const ast = exec_node_data(ast_node, n, link);
|
||||
foreach_list_typed(ast_node, ast, link, parameters) {
|
||||
ir_rvalue *result = ast->hir(instructions, state);
|
||||
|
||||
ir_constant *const constant = result->constant_expression_value();
|
||||
@@ -82,9 +81,7 @@ prototype_string(const glsl_type *return_type, const char *name,
|
||||
ralloc_asprintf_append(&str, "%s(", name);
|
||||
|
||||
const char *comma = "";
|
||||
foreach_list(node, parameters) {
|
||||
const ir_variable *const param = (ir_variable *) node;
|
||||
|
||||
foreach_in_list(const ir_variable, param, parameters) {
|
||||
ralloc_asprintf_append(&str, "%s%s", comma, param->type->name);
|
||||
comma = ", ";
|
||||
}
|
||||
@@ -158,35 +155,35 @@ verify_image_parameter(YYLTYPE *loc, _mesa_glsl_parse_state *state,
|
||||
* qualifiers. [...] It is legal to have additional qualifiers
|
||||
* on a formal parameter, but not to have fewer."
|
||||
*/
|
||||
if (actual->data.image.coherent && !formal->data.image.coherent) {
|
||||
if (actual->data.image_coherent && !formal->data.image_coherent) {
|
||||
_mesa_glsl_error(loc, state,
|
||||
"function call parameter `%s' drops "
|
||||
"`coherent' qualifier", formal->name);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (actual->data.image._volatile && !formal->data.image._volatile) {
|
||||
if (actual->data.image_volatile && !formal->data.image_volatile) {
|
||||
_mesa_glsl_error(loc, state,
|
||||
"function call parameter `%s' drops "
|
||||
"`volatile' qualifier", formal->name);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (actual->data.image.restrict_flag && !formal->data.image.restrict_flag) {
|
||||
if (actual->data.image_restrict && !formal->data.image_restrict) {
|
||||
_mesa_glsl_error(loc, state,
|
||||
"function call parameter `%s' drops "
|
||||
"`restrict' qualifier", formal->name);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (actual->data.image.read_only && !formal->data.image.read_only) {
|
||||
if (actual->data.image_read_only && !formal->data.image_read_only) {
|
||||
_mesa_glsl_error(loc, state,
|
||||
"function call parameter `%s' drops "
|
||||
"`readonly' qualifier", formal->name);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (actual->data.image.write_only && !formal->data.image.write_only) {
|
||||
if (actual->data.image_write_only && !formal->data.image_write_only) {
|
||||
_mesa_glsl_error(loc, state,
|
||||
"function call parameter `%s' drops "
|
||||
"`writeonly' qualifier", formal->name);
|
||||
@@ -211,12 +208,11 @@ verify_parameter_modes(_mesa_glsl_parse_state *state,
|
||||
exec_node *actual_ir_node = actual_ir_parameters.head;
|
||||
exec_node *actual_ast_node = actual_ast_parameters.head;
|
||||
|
||||
foreach_list(formal_node, &sig->parameters) {
|
||||
foreach_in_list(const ir_variable, formal, &sig->parameters) {
|
||||
/* The lists must be the same length. */
|
||||
assert(!actual_ir_node->is_tail_sentinel());
|
||||
assert(!actual_ast_node->is_tail_sentinel());
|
||||
|
||||
const ir_variable *const formal = (ir_variable *) formal_node;
|
||||
const ir_rvalue *const actual = (ir_rvalue *) actual_ir_node;
|
||||
const ast_expression *const actual_ast =
|
||||
exec_node_data(ast_expression, actual_ast_node, link);
|
||||
@@ -235,6 +231,24 @@ verify_parameter_modes(_mesa_glsl_parse_state *state,
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Verify that shader_in parameters are shader inputs */
|
||||
if (formal->data.must_be_shader_input) {
|
||||
ir_variable *var = actual->variable_referenced();
|
||||
if (var && var->data.mode != ir_var_shader_in) {
|
||||
_mesa_glsl_error(&loc, state,
|
||||
"parameter `%s` must be a shader input",
|
||||
formal->name);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (actual->ir_type == ir_type_swizzle) {
|
||||
_mesa_glsl_error(&loc, state,
|
||||
"parameter `%s` must not be swizzled",
|
||||
formal->name);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Verify that 'out' and 'inout' actual parameters are lvalues. */
|
||||
if (formal->data.mode == ir_var_function_out
|
||||
|| formal->data.mode == ir_var_function_inout) {
|
||||
@@ -448,14 +462,17 @@ generate_call(exec_list *instructions, ir_function_signature *sig,
|
||||
ir_dereference_variable *deref = NULL;
|
||||
if (!sig->return_type->is_void()) {
|
||||
/* Create a new temporary to hold the return value. */
|
||||
char *const name = ir_variable::temporaries_allocate_names
|
||||
? ralloc_asprintf(ctx, "%s_retval", sig->function_name())
|
||||
: NULL;
|
||||
|
||||
ir_variable *var;
|
||||
|
||||
var = new(ctx) ir_variable(sig->return_type,
|
||||
ralloc_asprintf(ctx, "%s_retval",
|
||||
sig->function_name()),
|
||||
ir_var_temporary, precision_for_call(sig,actual_parameters));
|
||||
var = new(ctx) ir_variable(sig->return_type, name, ir_var_temporary, precision_for_call(sig,actual_parameters));
|
||||
instructions->push_tail(var);
|
||||
|
||||
ralloc_free(name);
|
||||
|
||||
deref = new(ctx) ir_dereference_variable(var);
|
||||
}
|
||||
ir_call *call = new(ctx) ir_call(sig, deref, actual_parameters);
|
||||
@@ -490,20 +507,21 @@ match_function_by_name(const char *name,
|
||||
goto done; /* no match */
|
||||
|
||||
if (f != NULL) {
|
||||
/* In desktop GL, the presence of a user-defined signature hides any
|
||||
* built-in signatures, so we must ignore them. In contrast, in ES2
|
||||
* user-defined signatures add new overloads, so we must consider them.
|
||||
*/
|
||||
bool allow_builtins = state->es_shader || !f->has_user_signature();
|
||||
|
||||
/* Look for a match in the local shader. If exact, we're done. */
|
||||
bool is_exact = false;
|
||||
sig = local_sig = f->matching_signature(state, actual_parameters,
|
||||
&is_exact);
|
||||
allow_builtins, &is_exact);
|
||||
if (is_exact)
|
||||
goto done;
|
||||
|
||||
if (!state->es_shader && f->has_user_signature()) {
|
||||
/* In desktop GL, the presence of a user-defined signature hides any
|
||||
* built-in signatures, so we must ignore them. In contrast, in ES2
|
||||
* user-defined signatures add new overloads, so we must proceed.
|
||||
*/
|
||||
if (!allow_builtins)
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
/* Local shader has no exact candidates; check the built-ins. */
|
||||
@@ -532,9 +550,7 @@ print_function_prototypes(_mesa_glsl_parse_state *state, YYLTYPE *loc,
|
||||
if (f == NULL)
|
||||
return;
|
||||
|
||||
foreach_list (node, &f->signatures) {
|
||||
ir_function_signature *sig = (ir_function_signature *) node;
|
||||
|
||||
foreach_in_list(ir_function_signature, sig, &f->signatures) {
|
||||
if (sig->is_builtin() && !sig->is_builtin_available(state))
|
||||
continue;
|
||||
|
||||
@@ -744,8 +760,7 @@ process_vec_mat_constructor(exec_list *instructions,
|
||||
bool all_parameters_are_constant = true;
|
||||
|
||||
/* Type cast each parameter and, if possible, fold constants. */
|
||||
foreach_list_safe(n, &actual_parameters) {
|
||||
ir_rvalue *ir = (ir_rvalue *) n;
|
||||
foreach_in_list_safe(ir_rvalue, ir, &actual_parameters) {
|
||||
ir_rvalue *result = ir;
|
||||
|
||||
/* Apply implicit conversions (not the scalar constructor rules!). See
|
||||
@@ -755,7 +770,7 @@ process_vec_mat_constructor(exec_list *instructions,
|
||||
glsl_type::get_instance(GLSL_TYPE_FLOAT,
|
||||
ir->type->vector_elements,
|
||||
ir->type->matrix_columns);
|
||||
if (result->type->can_implicitly_convert_to(desired_type)) {
|
||||
if (result->type->can_implicitly_convert_to(desired_type, state)) {
|
||||
/* Even though convert_component() implements the constructor
|
||||
* conversion rules (not the implicit conversion rules), its safe
|
||||
* to use it here because we already checked that the implicit
|
||||
@@ -803,12 +818,22 @@ process_vec_mat_constructor(exec_list *instructions,
|
||||
instructions->push_tail(var);
|
||||
|
||||
int i = 0;
|
||||
foreach_list(node, &actual_parameters) {
|
||||
ir_rvalue *rhs = (ir_rvalue *) node;
|
||||
ir_rvalue *lhs = new(ctx) ir_dereference_array(var,
|
||||
new(ctx) ir_constant(i));
|
||||
|
||||
ir_instruction *assignment = new(ctx) ir_assignment(lhs, rhs, NULL);
|
||||
foreach_in_list(ir_rvalue, rhs, &actual_parameters) {
|
||||
ir_instruction *assignment = NULL;
|
||||
|
||||
if (var->type->is_matrix()) {
|
||||
ir_rvalue *lhs = new(ctx) ir_dereference_array(var,
|
||||
new(ctx) ir_constant(i));
|
||||
assignment = new(ctx) ir_assignment(lhs, rhs, NULL);
|
||||
} else {
|
||||
/* use writemask rather than index for vector */
|
||||
assert(var->type->is_vector());
|
||||
assert(i < 4);
|
||||
ir_dereference *lhs = new(ctx) ir_dereference_variable(var);
|
||||
assignment = new(ctx) ir_assignment(lhs, rhs, NULL, (unsigned)(1 << i));
|
||||
}
|
||||
|
||||
instructions->push_tail(assignment);
|
||||
|
||||
i++;
|
||||
@@ -873,8 +898,7 @@ process_array_constructor(exec_list *instructions,
|
||||
bool all_parameters_are_constant = true;
|
||||
|
||||
/* Type cast each parameter and, if possible, fold constants. */
|
||||
foreach_list_safe(n, &actual_parameters) {
|
||||
ir_rvalue *ir = (ir_rvalue *) n;
|
||||
foreach_in_list_safe(ir_rvalue, ir, &actual_parameters) {
|
||||
ir_rvalue *result = ir;
|
||||
|
||||
/* Apply implicit conversions (not the scalar constructor rules!). See
|
||||
@@ -884,7 +908,7 @@ process_array_constructor(exec_list *instructions,
|
||||
glsl_type::get_instance(GLSL_TYPE_FLOAT,
|
||||
ir->type->vector_elements,
|
||||
ir->type->matrix_columns);
|
||||
if (result->type->can_implicitly_convert_to(desired_type)) {
|
||||
if (result->type->can_implicitly_convert_to(desired_type, state)) {
|
||||
/* Even though convert_component() implements the constructor
|
||||
* conversion rules (not the implicit conversion rules), its safe
|
||||
* to use it here because we already checked that the implicit
|
||||
@@ -924,8 +948,7 @@ process_array_constructor(exec_list *instructions,
|
||||
instructions->push_tail(var);
|
||||
|
||||
int i = 0;
|
||||
foreach_list(node, &actual_parameters) {
|
||||
ir_rvalue *rhs = (ir_rvalue *) node;
|
||||
foreach_in_list(ir_rvalue, rhs, &actual_parameters) {
|
||||
ir_rvalue *lhs = new(ctx) ir_dereference_array(var,
|
||||
new(ctx) ir_constant(i));
|
||||
|
||||
@@ -946,8 +969,8 @@ static ir_constant *
|
||||
constant_record_constructor(const glsl_type *constructor_type,
|
||||
exec_list *parameters, void *mem_ctx)
|
||||
{
|
||||
foreach_list(node, parameters) {
|
||||
ir_constant *constant = ((ir_instruction *) node)->as_constant();
|
||||
foreach_in_list(ir_instruction, node, parameters) {
|
||||
ir_constant *constant = node->as_constant();
|
||||
if (constant == NULL)
|
||||
return NULL;
|
||||
node->replace_with(constant);
|
||||
@@ -1022,8 +1045,7 @@ emit_inline_vector_constructor(const glsl_type *type, unsigned ast_precision,
|
||||
|
||||
memset(&data, 0, sizeof(data));
|
||||
|
||||
foreach_list(node, parameters) {
|
||||
ir_rvalue *param = (ir_rvalue *) node;
|
||||
foreach_in_list(ir_rvalue, param, parameters) {
|
||||
var->data.precision = higher_precision ((glsl_precision)var->data.precision, param->get_precision());
|
||||
unsigned rhs_components = param->type->components();
|
||||
|
||||
@@ -1081,8 +1103,7 @@ emit_inline_vector_constructor(const glsl_type *type, unsigned ast_precision,
|
||||
}
|
||||
|
||||
base_component = 0;
|
||||
foreach_list(node, parameters) {
|
||||
ir_rvalue *param = (ir_rvalue *) node;
|
||||
foreach_in_list(ir_rvalue, param, parameters) {
|
||||
unsigned rhs_components = param->type->components();
|
||||
|
||||
/* Do not try to assign more components to the vector than it has!
|
||||
@@ -1368,8 +1389,7 @@ emit_inline_matrix_constructor(const glsl_type *type, int ast_precision,
|
||||
unsigned col_idx = 0;
|
||||
unsigned row_idx = 0;
|
||||
|
||||
foreach_list (node, parameters) {
|
||||
ir_rvalue *const rhs = (ir_rvalue *) node;
|
||||
foreach_in_list(ir_rvalue, rhs, parameters) {
|
||||
const unsigned components_remaining_this_column = rows - row_idx;
|
||||
unsigned rhs_components = rhs->type->components();
|
||||
unsigned rhs_base = 0;
|
||||
@@ -1613,10 +1633,10 @@ ast_function_expression::hir(exec_list *instructions,
|
||||
unsigned matrix_parameters = 0;
|
||||
unsigned nonmatrix_parameters = 0;
|
||||
exec_list actual_parameters;
|
||||
glsl_precision params_precision = glsl_precision_undefined;
|
||||
|
||||
foreach_list (n, &this->expressions) {
|
||||
ast_node *ast = exec_node_data(ast_node, n, link);
|
||||
ir_rvalue *result = ast->hir(instructions, state)->as_rvalue();
|
||||
foreach_list_typed(ast_node, ast, link, &this->expressions) {
|
||||
ir_rvalue *result = ast->hir(instructions, state);
|
||||
|
||||
/* From page 50 (page 56 of the PDF) of the GLSL 1.50 spec:
|
||||
*
|
||||
@@ -1646,6 +1666,7 @@ ast_function_expression::hir(exec_list *instructions,
|
||||
nonmatrix_parameters++;
|
||||
|
||||
actual_parameters.push_tail(result);
|
||||
params_precision = higher_precision(params_precision, result->get_precision());
|
||||
components_used += result->type->components();
|
||||
}
|
||||
|
||||
@@ -1695,9 +1716,7 @@ ast_function_expression::hir(exec_list *instructions,
|
||||
* need to break them up into a series of column vectors.
|
||||
*/
|
||||
if (constructor_type->base_type != GLSL_TYPE_FLOAT) {
|
||||
foreach_list_safe(n, &actual_parameters) {
|
||||
ir_rvalue *matrix = (ir_rvalue *) n;
|
||||
|
||||
foreach_in_list_safe(ir_rvalue, matrix, &actual_parameters) {
|
||||
if (!matrix->type->is_matrix())
|
||||
continue;
|
||||
|
||||
@@ -1721,9 +1740,7 @@ ast_function_expression::hir(exec_list *instructions,
|
||||
bool all_parameters_are_constant = true;
|
||||
|
||||
/* Type cast each parameter and, if possible, fold constants.*/
|
||||
foreach_list_safe(n, &actual_parameters) {
|
||||
ir_rvalue *ir = (ir_rvalue *) n;
|
||||
|
||||
foreach_in_list_safe(ir_rvalue, ir, &actual_parameters) {
|
||||
const glsl_type *desired_type =
|
||||
glsl_type::get_instance(constructor_type->base_type,
|
||||
ir->type->vector_elements,
|
||||
@@ -1755,13 +1772,13 @@ ast_function_expression::hir(exec_list *instructions,
|
||||
return dereference_component((ir_rvalue *) actual_parameters.head,
|
||||
0);
|
||||
} else if (constructor_type->is_vector()) {
|
||||
return emit_inline_vector_constructor(constructor_type, ast_precision_none, // TODO: type->precision,
|
||||
return emit_inline_vector_constructor(constructor_type, params_precision,
|
||||
instructions,
|
||||
&actual_parameters,
|
||||
ctx);
|
||||
} else {
|
||||
assert(constructor_type->is_matrix());
|
||||
return emit_inline_matrix_constructor(constructor_type, ast_precision_none, // TODO: type->precision,
|
||||
return emit_inline_matrix_constructor(constructor_type, params_precision,
|
||||
instructions,
|
||||
&actual_parameters,
|
||||
ctx);
|
||||
|
||||
2501
3rdparty/glsl-optimizer/src/glsl/ast_to_hir.cpp
vendored
2501
3rdparty/glsl-optimizer/src/glsl/ast_to_hir.cpp
vendored
File diff suppressed because it is too large
Load Diff
169
3rdparty/glsl-optimizer/src/glsl/ast_type.cpp
vendored
169
3rdparty/glsl-optimizer/src/glsl/ast_type.cpp
vendored
@@ -122,14 +122,28 @@ ast_type_qualifier::merge_qualifier(YYLTYPE *loc,
|
||||
ubo_binding_mask.flags.q.explicit_binding = 1;
|
||||
ubo_binding_mask.flags.q.explicit_offset = 1;
|
||||
|
||||
ast_type_qualifier stream_layout_mask;
|
||||
stream_layout_mask.flags.i = 0;
|
||||
stream_layout_mask.flags.q.stream = 1;
|
||||
|
||||
/* Uniform block layout qualifiers get to overwrite each
|
||||
* other (rightmost having priority), while all other
|
||||
* qualifiers currently don't allow duplicates.
|
||||
*/
|
||||
ast_type_qualifier allowed_duplicates_mask;
|
||||
allowed_duplicates_mask.flags.i =
|
||||
ubo_mat_mask.flags.i |
|
||||
ubo_layout_mask.flags.i |
|
||||
ubo_binding_mask.flags.i;
|
||||
|
||||
if ((this->flags.i & q.flags.i & ~(ubo_mat_mask.flags.i |
|
||||
ubo_layout_mask.flags.i |
|
||||
ubo_binding_mask.flags.i)) != 0) {
|
||||
/* Geometry shaders can have several layout qualifiers
|
||||
* assigning different stream values.
|
||||
*/
|
||||
if (state->stage == MESA_SHADER_GEOMETRY)
|
||||
allowed_duplicates_mask.flags.i |=
|
||||
stream_layout_mask.flags.i;
|
||||
|
||||
if ((this->flags.i & q.flags.i & ~allowed_duplicates_mask.flags.i) != 0) {
|
||||
_mesa_glsl_error(loc, state,
|
||||
"duplicate layout qualifiers used");
|
||||
return false;
|
||||
@@ -154,6 +168,49 @@ ast_type_qualifier::merge_qualifier(YYLTYPE *loc,
|
||||
this->max_vertices = q.max_vertices;
|
||||
}
|
||||
|
||||
if (q.flags.q.invocations) {
|
||||
if (this->flags.q.invocations && this->invocations != q.invocations) {
|
||||
_mesa_glsl_error(loc, state,
|
||||
"geometry shader set conflicting invocations "
|
||||
"(%d and %d)", this->invocations, q.invocations);
|
||||
return false;
|
||||
}
|
||||
this->invocations = q.invocations;
|
||||
}
|
||||
|
||||
if (state->stage == MESA_SHADER_GEOMETRY &&
|
||||
state->has_explicit_attrib_stream()) {
|
||||
if (q.flags.q.stream && q.stream >= state->ctx->Const.MaxVertexStreams) {
|
||||
_mesa_glsl_error(loc, state,
|
||||
"`stream' value is larger than MAX_VERTEX_STREAMS - 1 "
|
||||
"(%d > %d)",
|
||||
q.stream, state->ctx->Const.MaxVertexStreams - 1);
|
||||
}
|
||||
if (this->flags.q.explicit_stream &&
|
||||
this->stream >= state->ctx->Const.MaxVertexStreams) {
|
||||
_mesa_glsl_error(loc, state,
|
||||
"`stream' value is larger than MAX_VERTEX_STREAMS - 1 "
|
||||
"(%d > %d)",
|
||||
this->stream, state->ctx->Const.MaxVertexStreams - 1);
|
||||
}
|
||||
|
||||
if (!this->flags.q.explicit_stream) {
|
||||
if (q.flags.q.stream) {
|
||||
this->flags.q.stream = 1;
|
||||
this->stream = q.stream;
|
||||
} else if (!this->flags.q.stream && this->flags.q.out) {
|
||||
/* Assign default global stream value */
|
||||
this->flags.q.stream = 1;
|
||||
this->stream = state->out_qualifier->stream;
|
||||
}
|
||||
} else {
|
||||
if (q.flags.q.explicit_stream) {
|
||||
_mesa_glsl_error(loc, state,
|
||||
"duplicate layout `stream' qualifier");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((q.flags.i & ubo_mat_mask.flags.i) != 0)
|
||||
this->flags.i &= ~ubo_mat_mask.flags.i;
|
||||
if ((q.flags.i & ubo_layout_mask.flags.i) != 0)
|
||||
@@ -198,3 +255,109 @@ ast_type_qualifier::merge_qualifier(YYLTYPE *loc,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ast_type_qualifier::merge_in_qualifier(YYLTYPE *loc,
|
||||
_mesa_glsl_parse_state *state,
|
||||
ast_type_qualifier q,
|
||||
ast_node* &node)
|
||||
{
|
||||
void *mem_ctx = state;
|
||||
bool create_gs_ast = false;
|
||||
bool create_cs_ast = false;
|
||||
ast_type_qualifier valid_in_mask;
|
||||
valid_in_mask.flags.i = 0;
|
||||
|
||||
switch (state->stage) {
|
||||
case MESA_SHADER_GEOMETRY:
|
||||
if (q.flags.q.prim_type) {
|
||||
/* Make sure this is a valid input primitive type. */
|
||||
switch (q.prim_type) {
|
||||
case GL_POINTS:
|
||||
case GL_LINES:
|
||||
case GL_LINES_ADJACENCY:
|
||||
case GL_TRIANGLES:
|
||||
case GL_TRIANGLES_ADJACENCY:
|
||||
break;
|
||||
default:
|
||||
_mesa_glsl_error(loc, state,
|
||||
"invalid geometry shader input primitive type");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
create_gs_ast |=
|
||||
q.flags.q.prim_type &&
|
||||
!state->in_qualifier->flags.q.prim_type;
|
||||
|
||||
valid_in_mask.flags.q.prim_type = 1;
|
||||
valid_in_mask.flags.q.invocations = 1;
|
||||
break;
|
||||
case MESA_SHADER_FRAGMENT:
|
||||
if (q.flags.q.early_fragment_tests) {
|
||||
state->early_fragment_tests = true;
|
||||
} else {
|
||||
_mesa_glsl_error(loc, state, "invalid input layout qualifier");
|
||||
}
|
||||
break;
|
||||
case MESA_SHADER_COMPUTE:
|
||||
create_cs_ast |=
|
||||
q.flags.q.local_size != 0 &&
|
||||
state->in_qualifier->flags.q.local_size == 0;
|
||||
|
||||
valid_in_mask.flags.q.local_size = 7;
|
||||
break;
|
||||
default:
|
||||
_mesa_glsl_error(loc, state,
|
||||
"input layout qualifiers only valid in "
|
||||
"geometry, fragment and compute shaders");
|
||||
break;
|
||||
}
|
||||
|
||||
/* Generate an error when invalid input layout qualifiers are used. */
|
||||
if ((q.flags.i & ~valid_in_mask.flags.i) != 0) {
|
||||
_mesa_glsl_error(loc, state,
|
||||
"invalid input layout qualifiers used");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Input layout qualifiers can be specified multiple
|
||||
* times in separate declarations, as long as they match.
|
||||
*/
|
||||
if (this->flags.q.prim_type) {
|
||||
if (q.flags.q.prim_type &&
|
||||
this->prim_type != q.prim_type) {
|
||||
_mesa_glsl_error(loc, state,
|
||||
"conflicting input primitive types specified");
|
||||
}
|
||||
} else if (q.flags.q.prim_type) {
|
||||
state->in_qualifier->flags.q.prim_type = 1;
|
||||
state->in_qualifier->prim_type = q.prim_type;
|
||||
}
|
||||
|
||||
if (this->flags.q.invocations &&
|
||||
q.flags.q.invocations &&
|
||||
this->invocations != q.invocations) {
|
||||
_mesa_glsl_error(loc, state,
|
||||
"conflicting invocations counts specified");
|
||||
return false;
|
||||
} else if (q.flags.q.invocations) {
|
||||
this->flags.q.invocations = 1;
|
||||
this->invocations = q.invocations;
|
||||
}
|
||||
|
||||
if (create_gs_ast) {
|
||||
node = new(mem_ctx) ast_gs_input_layout(*loc, q.prim_type);
|
||||
} else if (create_cs_ast) {
|
||||
/* Infer a local_size of 1 for every unspecified dimension */
|
||||
unsigned local_size[3];
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (q.flags.q.local_size & (1 << i))
|
||||
local_size[i] = q.local_size[i];
|
||||
else
|
||||
local_size[i] = 1;
|
||||
}
|
||||
node = new(mem_ctx) ast_cs_input_layout(*loc, local_size);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -62,6 +62,10 @@
|
||||
#include "program/prog_instruction.h"
|
||||
#include <limits>
|
||||
|
||||
#define M_PIf ((float) M_PI)
|
||||
#define M_PI_2f ((float) M_PI_2)
|
||||
#define M_PI_4f ((float) M_PI_4)
|
||||
|
||||
using namespace ir_builder;
|
||||
|
||||
/**
|
||||
@@ -69,7 +73,7 @@ using namespace ir_builder;
|
||||
* @{
|
||||
*/
|
||||
static bool
|
||||
always_available(const _mesa_glsl_parse_state *state)
|
||||
always_available(const _mesa_glsl_parse_state *)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -219,13 +223,6 @@ shader_integer_mix(const _mesa_glsl_parse_state *state)
|
||||
return v130(state) && state->EXT_shader_integer_mix_enable;
|
||||
}
|
||||
|
||||
static bool
|
||||
shader_packing(const _mesa_glsl_parse_state *state)
|
||||
{
|
||||
return state->ARB_shading_language_packing_enable ||
|
||||
state->is_version(400, 0);
|
||||
}
|
||||
|
||||
static bool
|
||||
shader_packing_or_es3(const _mesa_glsl_parse_state *state)
|
||||
{
|
||||
@@ -233,12 +230,35 @@ shader_packing_or_es3(const _mesa_glsl_parse_state *state)
|
||||
state->is_version(400, 300);
|
||||
}
|
||||
|
||||
static bool
|
||||
shader_packing_or_es3_or_gpu_shader5(const _mesa_glsl_parse_state *state)
|
||||
{
|
||||
return state->ARB_shading_language_packing_enable ||
|
||||
state->ARB_gpu_shader5_enable ||
|
||||
state->is_version(400, 300);
|
||||
}
|
||||
|
||||
static bool
|
||||
gpu_shader5(const _mesa_glsl_parse_state *state)
|
||||
{
|
||||
return state->is_version(400, 0) || state->ARB_gpu_shader5_enable;
|
||||
}
|
||||
|
||||
static bool
|
||||
shader_packing_or_gpu_shader5(const _mesa_glsl_parse_state *state)
|
||||
{
|
||||
return state->ARB_shading_language_packing_enable ||
|
||||
gpu_shader5(state);
|
||||
}
|
||||
|
||||
static bool
|
||||
fs_gpu_shader5(const _mesa_glsl_parse_state *state)
|
||||
{
|
||||
return state->stage == MESA_SHADER_FRAGMENT &&
|
||||
(state->is_version(400, 0) || state->ARB_gpu_shader5_enable);
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
texture_array_lod(const _mesa_glsl_parse_state *state)
|
||||
{
|
||||
@@ -323,6 +343,14 @@ fs_oes_derivatives(const _mesa_glsl_parse_state *state)
|
||||
state->OES_standard_derivatives_enable);
|
||||
}
|
||||
|
||||
static bool
|
||||
fs_derivative_control(const _mesa_glsl_parse_state *state)
|
||||
{
|
||||
return state->stage == MESA_SHADER_FRAGMENT &&
|
||||
(state->is_version(450, 0) ||
|
||||
state->ARB_derivative_control_enable);
|
||||
}
|
||||
|
||||
static bool
|
||||
tex1d_lod(const _mesa_glsl_parse_state *state)
|
||||
{
|
||||
@@ -373,6 +401,12 @@ shader_image_load_store(const _mesa_glsl_parse_state *state)
|
||||
state->ARB_shader_image_load_store_enable);
|
||||
}
|
||||
|
||||
static bool
|
||||
gs_streams(const _mesa_glsl_parse_state *state)
|
||||
{
|
||||
return gpu_shader5(state) && gs_only(state);
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
/******************************************************************************/
|
||||
@@ -434,6 +468,7 @@ private:
|
||||
ir_swizzle *matrix_elt(ir_variable *var, int col, int row);
|
||||
|
||||
ir_expression *asin_expr(ir_variable *x);
|
||||
void do_atan(ir_factory &body, const glsl_type *type, ir_variable *res, operand y_over_x);
|
||||
|
||||
/**
|
||||
* Call function \param f with parameters specified as the linked
|
||||
@@ -608,12 +643,22 @@ private:
|
||||
|
||||
B0(EmitVertex)
|
||||
B0(EndPrimitive)
|
||||
ir_function_signature *_EmitStreamVertex(builtin_available_predicate avail,
|
||||
const glsl_type *stream_type);
|
||||
ir_function_signature *_EndStreamPrimitive(builtin_available_predicate avail,
|
||||
const glsl_type *stream_type);
|
||||
|
||||
B2(textureQueryLod);
|
||||
B1(textureQueryLevels);
|
||||
B1(dFdx);
|
||||
B1(dFdy);
|
||||
B1(fwidth);
|
||||
B1(dFdxCoarse);
|
||||
B1(dFdyCoarse);
|
||||
B1(fwidthCoarse);
|
||||
B1(dFdxFine);
|
||||
B1(dFdyFine);
|
||||
B1(fwidthFine);
|
||||
B1(noise1);
|
||||
B1(noise2);
|
||||
B1(noise3);
|
||||
@@ -631,6 +676,9 @@ private:
|
||||
B1(uaddCarry)
|
||||
B1(usubBorrow)
|
||||
B1(mulExtended)
|
||||
B1(interpolateAtCentroid)
|
||||
B1(interpolateAtOffset)
|
||||
B1(interpolateAtSample)
|
||||
|
||||
ir_function_signature *_atomic_intrinsic(builtin_available_predicate avail);
|
||||
ir_function_signature *_atomic_op(const char *intrinsic,
|
||||
@@ -699,7 +747,8 @@ builtin_builder::find(_mesa_glsl_parse_state *state,
|
||||
if (f == NULL)
|
||||
return NULL;
|
||||
|
||||
ir_function_signature *sig = f->matching_signature(state, actual_parameters);
|
||||
ir_function_signature *sig =
|
||||
f->matching_signature(state, actual_parameters, true);
|
||||
if (sig == NULL)
|
||||
return NULL;
|
||||
|
||||
@@ -1017,16 +1066,16 @@ builtin_builder::create_builtins()
|
||||
_uintBitsToFloat(glsl_type::uvec4_type),
|
||||
NULL);
|
||||
|
||||
add_function("packUnorm2x16", _packUnorm2x16(shader_packing_or_es3), NULL);
|
||||
add_function("packSnorm2x16", _packSnorm2x16(shader_packing_or_es3), NULL);
|
||||
add_function("packUnorm4x8", _packUnorm4x8(shader_packing), NULL);
|
||||
add_function("packSnorm4x8", _packSnorm4x8(shader_packing), NULL);
|
||||
add_function("unpackUnorm2x16", _unpackUnorm2x16(shader_packing_or_es3), NULL);
|
||||
add_function("unpackSnorm2x16", _unpackSnorm2x16(shader_packing_or_es3), NULL);
|
||||
add_function("unpackUnorm4x8", _unpackUnorm4x8(shader_packing), NULL);
|
||||
add_function("unpackSnorm4x8", _unpackSnorm4x8(shader_packing), NULL);
|
||||
add_function("packHalf2x16", _packHalf2x16(shader_packing_or_es3), NULL);
|
||||
add_function("unpackHalf2x16", _unpackHalf2x16(shader_packing_or_es3), NULL);
|
||||
add_function("packUnorm2x16", _packUnorm2x16(shader_packing_or_es3_or_gpu_shader5), NULL);
|
||||
add_function("packSnorm2x16", _packSnorm2x16(shader_packing_or_es3), NULL);
|
||||
add_function("packUnorm4x8", _packUnorm4x8(shader_packing_or_gpu_shader5), NULL);
|
||||
add_function("packSnorm4x8", _packSnorm4x8(shader_packing_or_gpu_shader5), NULL);
|
||||
add_function("unpackUnorm2x16", _unpackUnorm2x16(shader_packing_or_es3_or_gpu_shader5), NULL);
|
||||
add_function("unpackSnorm2x16", _unpackSnorm2x16(shader_packing_or_es3), NULL);
|
||||
add_function("unpackUnorm4x8", _unpackUnorm4x8(shader_packing_or_gpu_shader5), NULL);
|
||||
add_function("unpackSnorm4x8", _unpackSnorm4x8(shader_packing_or_gpu_shader5), NULL);
|
||||
add_function("packHalf2x16", _packHalf2x16(shader_packing_or_es3), NULL);
|
||||
add_function("unpackHalf2x16", _unpackHalf2x16(shader_packing_or_es3), NULL);
|
||||
|
||||
F(length)
|
||||
F(distance)
|
||||
@@ -1722,6 +1771,14 @@ builtin_builder::create_builtins()
|
||||
|
||||
add_function("EmitVertex", _EmitVertex(), NULL);
|
||||
add_function("EndPrimitive", _EndPrimitive(), NULL);
|
||||
add_function("EmitStreamVertex",
|
||||
_EmitStreamVertex(gs_streams, glsl_type::uint_type),
|
||||
_EmitStreamVertex(gs_streams, glsl_type::int_type),
|
||||
NULL);
|
||||
add_function("EndStreamPrimitive",
|
||||
_EndStreamPrimitive(gs_streams, glsl_type::uint_type),
|
||||
_EndStreamPrimitive(gs_streams, glsl_type::int_type),
|
||||
NULL);
|
||||
|
||||
add_function("textureQueryLOD",
|
||||
_textureQueryLod(glsl_type::sampler1D_type, glsl_type::float_type),
|
||||
@@ -1852,8 +1909,8 @@ builtin_builder::create_builtins()
|
||||
NULL);
|
||||
|
||||
add_function("texture2DProjLod",
|
||||
_texture(ir_txl, v110_lod, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec3_type, TEX_PROJECT),
|
||||
_texture(ir_txl, v110_lod, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec4_type, TEX_PROJECT),
|
||||
_texture(ir_txl, lod_exists_in_stage, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec3_type, TEX_PROJECT),
|
||||
_texture(ir_txl, lod_exists_in_stage, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec4_type, TEX_PROJECT),
|
||||
NULL);
|
||||
|
||||
add_function("texture3D",
|
||||
@@ -1880,7 +1937,7 @@ builtin_builder::create_builtins()
|
||||
NULL);
|
||||
|
||||
add_function("textureCubeLod",
|
||||
_texture(ir_txl, v110_lod, glsl_type::vec4_type, glsl_type::samplerCube_type, glsl_type::vec3_type),
|
||||
_texture(ir_txl, lod_exists_in_stage, glsl_type::vec4_type, glsl_type::samplerCube_type, glsl_type::vec3_type),
|
||||
NULL);
|
||||
|
||||
add_function("texture2DRect",
|
||||
@@ -2160,6 +2217,12 @@ builtin_builder::create_builtins()
|
||||
F(dFdx)
|
||||
F(dFdy)
|
||||
F(fwidth)
|
||||
F(dFdxCoarse)
|
||||
F(dFdyCoarse)
|
||||
F(fwidthCoarse)
|
||||
F(dFdxFine)
|
||||
F(dFdyFine)
|
||||
F(fwidthFine)
|
||||
F(noise1)
|
||||
F(noise2)
|
||||
F(noise3)
|
||||
@@ -2210,6 +2273,24 @@ builtin_builder::create_builtins()
|
||||
_mulExtended(glsl_type::uvec3_type),
|
||||
_mulExtended(glsl_type::uvec4_type),
|
||||
NULL);
|
||||
add_function("interpolateAtCentroid",
|
||||
_interpolateAtCentroid(glsl_type::float_type),
|
||||
_interpolateAtCentroid(glsl_type::vec2_type),
|
||||
_interpolateAtCentroid(glsl_type::vec3_type),
|
||||
_interpolateAtCentroid(glsl_type::vec4_type),
|
||||
NULL);
|
||||
add_function("interpolateAtOffset",
|
||||
_interpolateAtOffset(glsl_type::float_type),
|
||||
_interpolateAtOffset(glsl_type::vec2_type),
|
||||
_interpolateAtOffset(glsl_type::vec3_type),
|
||||
_interpolateAtOffset(glsl_type::vec4_type),
|
||||
NULL);
|
||||
add_function("interpolateAtSample",
|
||||
_interpolateAtSample(glsl_type::float_type),
|
||||
_interpolateAtSample(glsl_type::vec2_type),
|
||||
_interpolateAtSample(glsl_type::vec3_type),
|
||||
_interpolateAtSample(glsl_type::vec4_type),
|
||||
NULL);
|
||||
|
||||
add_function("atomicCounter",
|
||||
_atomic_op("__intrinsic_atomic_read",
|
||||
@@ -2584,11 +2665,11 @@ ir_expression *
|
||||
builtin_builder::asin_expr(ir_variable *x)
|
||||
{
|
||||
return mul(sign(x),
|
||||
sub(imm(1.5707964f),
|
||||
sub(imm(M_PI_2f),
|
||||
mul(sqrt(sub(imm(1.0f), abs(x))),
|
||||
add(imm(1.5707964f),
|
||||
add(imm(M_PI_2f),
|
||||
mul(abs(x),
|
||||
add(imm(-0.21460183f),
|
||||
add(imm(M_PI_4f - 1.0f),
|
||||
mul(abs(x),
|
||||
add(imm(0.086566724f),
|
||||
mul(abs(x), imm(-0.03102955f))))))))));
|
||||
@@ -2599,8 +2680,7 @@ builtin_builder::call(ir_function *f, ir_variable *ret, exec_list params)
|
||||
{
|
||||
exec_list actual_params;
|
||||
|
||||
foreach_list(node, ¶ms) {
|
||||
ir_variable *var = (ir_variable *) node;
|
||||
foreach_in_list(ir_variable, var, ¶ms) {
|
||||
actual_params.push_tail(var_ref(var));
|
||||
}
|
||||
|
||||
@@ -2632,7 +2712,7 @@ builtin_builder::_acos(const glsl_type *type)
|
||||
ir_variable *x = in_var(type, "x");
|
||||
MAKE_SIG(type, always_available, 1, x);
|
||||
|
||||
body.emit(ret(sub(imm(1.5707964f), asin_expr(x))));
|
||||
body.emit(ret(sub(imm(M_PI_2f), asin_expr(x))));
|
||||
|
||||
return sig;
|
||||
}
|
||||
@@ -2659,23 +2739,19 @@ builtin_builder::_atan2(const glsl_type *type)
|
||||
ir_factory outer_then(&outer_if->then_instructions, mem_ctx);
|
||||
|
||||
/* Then...call atan(y/x) */
|
||||
ir_variable *y_over_x = outer_then.make_temp(glsl_type::float_type, "y_over_x");
|
||||
outer_then.emit(assign(y_over_x, div(y, x)));
|
||||
outer_then.emit(assign(r, mul(y_over_x, rsq(add(mul(y_over_x, y_over_x),
|
||||
imm(1.0f))))));
|
||||
outer_then.emit(assign(r, asin_expr(r)));
|
||||
do_atan(body, glsl_type::float_type, r, div(y, x));
|
||||
|
||||
/* ...and fix it up: */
|
||||
ir_if *inner_if = new(mem_ctx) ir_if(less(x, imm(0.0f)));
|
||||
inner_if->then_instructions.push_tail(
|
||||
if_tree(gequal(y, imm(0.0f)),
|
||||
assign(r, add(r, imm(3.141593f))),
|
||||
assign(r, sub(r, imm(3.141593f)))));
|
||||
assign(r, add(r, imm(M_PIf))),
|
||||
assign(r, sub(r, imm(M_PIf)))));
|
||||
outer_then.emit(inner_if);
|
||||
|
||||
/* Else... */
|
||||
outer_if->else_instructions.push_tail(
|
||||
assign(r, mul(sign(y), imm(1.5707965f))));
|
||||
assign(r, mul(sign(y), imm(M_PI_2f))));
|
||||
|
||||
body.emit(outer_if);
|
||||
|
||||
@@ -2686,17 +2762,65 @@ builtin_builder::_atan2(const glsl_type *type)
|
||||
return sig;
|
||||
}
|
||||
|
||||
void
|
||||
builtin_builder::do_atan(ir_factory &body, const glsl_type *type, ir_variable *res, operand y_over_x)
|
||||
{
|
||||
/*
|
||||
* range-reduction, first step:
|
||||
*
|
||||
* / y_over_x if |y_over_x| <= 1.0;
|
||||
* x = <
|
||||
* \ 1.0 / y_over_x otherwise
|
||||
*/
|
||||
ir_variable *x = body.make_temp(type, "atan_x");
|
||||
body.emit(assign(x, div(min2(abs(y_over_x),
|
||||
imm(1.0f)),
|
||||
max2(abs(y_over_x),
|
||||
imm(1.0f)))));
|
||||
|
||||
/*
|
||||
* approximate atan by evaluating polynomial:
|
||||
*
|
||||
* x * 0.9999793128310355 - x^3 * 0.3326756418091246 +
|
||||
* x^5 * 0.1938924977115610 - x^7 * 0.1173503194786851 +
|
||||
* x^9 * 0.0536813784310406 - x^11 * 0.0121323213173444
|
||||
*/
|
||||
ir_variable *tmp = body.make_temp(type, "atan_tmp");
|
||||
body.emit(assign(tmp, mul(x, x)));
|
||||
body.emit(assign(tmp, mul(add(mul(sub(mul(add(mul(sub(mul(add(mul(imm(-0.0121323213173444f),
|
||||
tmp),
|
||||
imm(0.0536813784310406f)),
|
||||
tmp),
|
||||
imm(0.1173503194786851f)),
|
||||
tmp),
|
||||
imm(0.1938924977115610f)),
|
||||
tmp),
|
||||
imm(0.3326756418091246f)),
|
||||
tmp),
|
||||
imm(0.9999793128310355f)),
|
||||
x)));
|
||||
|
||||
/* range-reduction fixup */
|
||||
body.emit(assign(tmp, add(tmp,
|
||||
mul(b2f(greater(abs(y_over_x),
|
||||
imm(1.0f, type->components()))),
|
||||
add(mul(tmp,
|
||||
imm(-2.0f)),
|
||||
imm(M_PI_2f))))));
|
||||
|
||||
/* sign fixup */
|
||||
body.emit(assign(res, mul(tmp, sign(y_over_x))));
|
||||
}
|
||||
|
||||
ir_function_signature *
|
||||
builtin_builder::_atan(const glsl_type *type)
|
||||
{
|
||||
ir_variable *y_over_x = in_var(type, "y_over_x");
|
||||
MAKE_SIG(type, always_available, 1, y_over_x);
|
||||
|
||||
ir_variable *t = body.make_temp(type, "t");
|
||||
body.emit(assign(t, mul(y_over_x, rsq(add(mul(y_over_x, y_over_x),
|
||||
imm(1.0f))))));
|
||||
|
||||
body.emit(ret(asin_expr(t)));
|
||||
ir_variable *tmp = body.make_temp(type, "tmp");
|
||||
do_atan(body, type, tmp, y_over_x);
|
||||
body.emit(ret(tmp));
|
||||
|
||||
return sig;
|
||||
}
|
||||
@@ -3095,7 +3219,7 @@ builtin_builder::_length(const glsl_type *type)
|
||||
ir_variable *x = in_var(type, "x");
|
||||
MAKE_SIG(glsl_type::float_type, always_available, 1, x);
|
||||
|
||||
body.emit(ret(sqrt(dotlike(x, x))));
|
||||
body.emit(ret(sqrt(dot(x, x))));
|
||||
|
||||
return sig;
|
||||
}
|
||||
@@ -3185,7 +3309,7 @@ builtin_builder::_faceforward(const glsl_type *type)
|
||||
ir_variable *Nref = in_var(type, "Nref");
|
||||
MAKE_SIG(type, always_available, 3, N, I, Nref);
|
||||
|
||||
body.emit(if_tree(less(dotlike(Nref, I), imm(0.0f)),
|
||||
body.emit(if_tree(less(dot(Nref, I), imm(0.0f)),
|
||||
ret(N), ret(neg(N))));
|
||||
|
||||
return sig;
|
||||
@@ -3199,7 +3323,7 @@ builtin_builder::_reflect(const glsl_type *type)
|
||||
MAKE_SIG(type, always_available, 2, I, N);
|
||||
|
||||
/* I - 2 * dot(N, I) * N */
|
||||
body.emit(ret(sub(I, mul(imm(2.0f), mul(dotlike(N, I), N)))));
|
||||
body.emit(ret(sub(I, mul(imm(2.0f), mul(dot(N, I), N)))));
|
||||
|
||||
return sig;
|
||||
}
|
||||
@@ -3213,7 +3337,7 @@ builtin_builder::_refract(const glsl_type *type)
|
||||
MAKE_SIG(type, always_available, 3, I, N, eta);
|
||||
|
||||
ir_variable *n_dot_i = body.make_temp(glsl_type::float_type, "n_dot_i");
|
||||
body.emit(assign(n_dot_i, dotlike(N, I)));
|
||||
body.emit(assign(n_dot_i, dot(N, I)));
|
||||
|
||||
/* From the GLSL 1.10 specification:
|
||||
* k = 1.0 - eta * eta * (1.0 - dot(N, I) * dot(N, I))
|
||||
@@ -3917,7 +4041,28 @@ builtin_builder::_EmitVertex()
|
||||
{
|
||||
MAKE_SIG(glsl_type::void_type, gs_only, 0);
|
||||
|
||||
body.emit(new(mem_ctx) ir_emit_vertex());
|
||||
ir_rvalue *stream = new(mem_ctx) ir_constant(0, 1);
|
||||
body.emit(new(mem_ctx) ir_emit_vertex(stream));
|
||||
|
||||
return sig;
|
||||
}
|
||||
|
||||
ir_function_signature *
|
||||
builtin_builder::_EmitStreamVertex(builtin_available_predicate avail,
|
||||
const glsl_type *stream_type)
|
||||
{
|
||||
/* Section 8.12 (Geometry Shader Functions) of the GLSL 4.0 spec says:
|
||||
*
|
||||
* "Emit the current values of output variables to the current output
|
||||
* primitive on stream stream. The argument to stream must be a constant
|
||||
* integral expression."
|
||||
*/
|
||||
ir_variable *stream =
|
||||
new(mem_ctx) ir_variable(stream_type, "stream", ir_var_const_in, glsl_precision_undefined);
|
||||
|
||||
MAKE_SIG(glsl_type::void_type, avail, 1, stream);
|
||||
|
||||
body.emit(new(mem_ctx) ir_emit_vertex(var_ref(stream)));
|
||||
|
||||
return sig;
|
||||
}
|
||||
@@ -3927,7 +4072,28 @@ builtin_builder::_EndPrimitive()
|
||||
{
|
||||
MAKE_SIG(glsl_type::void_type, gs_only, 0);
|
||||
|
||||
body.emit(new(mem_ctx) ir_end_primitive());
|
||||
ir_rvalue *stream = new(mem_ctx) ir_constant(0, 1);
|
||||
body.emit(new(mem_ctx) ir_end_primitive(stream));
|
||||
|
||||
return sig;
|
||||
}
|
||||
|
||||
ir_function_signature *
|
||||
builtin_builder::_EndStreamPrimitive(builtin_available_predicate avail,
|
||||
const glsl_type *stream_type)
|
||||
{
|
||||
/* Section 8.12 (Geometry Shader Functions) of the GLSL 4.0 spec says:
|
||||
*
|
||||
* "Completes the current output primitive on stream stream and starts
|
||||
* a new one. The argument to stream must be a constant integral
|
||||
* expression."
|
||||
*/
|
||||
ir_variable *stream =
|
||||
new(mem_ctx) ir_variable(stream_type, "stream", ir_var_const_in, glsl_precision_undefined);
|
||||
|
||||
MAKE_SIG(glsl_type::void_type, avail, 1, stream);
|
||||
|
||||
body.emit(new(mem_ctx) ir_end_primitive(var_ref(stream)));
|
||||
|
||||
return sig;
|
||||
}
|
||||
@@ -3966,7 +4132,11 @@ builtin_builder::_textureQueryLevels(const glsl_type *sampler_type)
|
||||
}
|
||||
|
||||
UNOP(dFdx, ir_unop_dFdx, fs_oes_derivatives)
|
||||
UNOP(dFdxCoarse, ir_unop_dFdx_coarse, fs_derivative_control)
|
||||
UNOP(dFdxFine, ir_unop_dFdx_fine, fs_derivative_control)
|
||||
UNOP(dFdy, ir_unop_dFdy, fs_oes_derivatives)
|
||||
UNOP(dFdyCoarse, ir_unop_dFdy_coarse, fs_derivative_control)
|
||||
UNOP(dFdyFine, ir_unop_dFdy_fine, fs_derivative_control)
|
||||
|
||||
ir_function_signature *
|
||||
builtin_builder::_fwidth(const glsl_type *type)
|
||||
@@ -3979,6 +4149,30 @@ builtin_builder::_fwidth(const glsl_type *type)
|
||||
return sig;
|
||||
}
|
||||
|
||||
ir_function_signature *
|
||||
builtin_builder::_fwidthCoarse(const glsl_type *type)
|
||||
{
|
||||
ir_variable *p = in_var(type, "p");
|
||||
MAKE_SIG(type, fs_derivative_control, 1, p);
|
||||
|
||||
body.emit(ret(add(abs(expr(ir_unop_dFdx_coarse, p)),
|
||||
abs(expr(ir_unop_dFdy_coarse, p)))));
|
||||
|
||||
return sig;
|
||||
}
|
||||
|
||||
ir_function_signature *
|
||||
builtin_builder::_fwidthFine(const glsl_type *type)
|
||||
{
|
||||
ir_variable *p = in_var(type, "p");
|
||||
MAKE_SIG(type, fs_derivative_control, 1, p);
|
||||
|
||||
body.emit(ret(add(abs(expr(ir_unop_dFdx_fine, p)),
|
||||
abs(expr(ir_unop_dFdy_fine, p)))));
|
||||
|
||||
return sig;
|
||||
}
|
||||
|
||||
ir_function_signature *
|
||||
builtin_builder::_noise1(const glsl_type *type)
|
||||
{
|
||||
@@ -4245,6 +4439,44 @@ builtin_builder::_mulExtended(const glsl_type *type)
|
||||
return sig;
|
||||
}
|
||||
|
||||
ir_function_signature *
|
||||
builtin_builder::_interpolateAtCentroid(const glsl_type *type)
|
||||
{
|
||||
ir_variable *interpolant = in_var(type, "interpolant");
|
||||
interpolant->data.must_be_shader_input = 1;
|
||||
MAKE_SIG(type, fs_gpu_shader5, 1, interpolant);
|
||||
|
||||
body.emit(ret(interpolate_at_centroid(interpolant)));
|
||||
|
||||
return sig;
|
||||
}
|
||||
|
||||
ir_function_signature *
|
||||
builtin_builder::_interpolateAtOffset(const glsl_type *type)
|
||||
{
|
||||
ir_variable *interpolant = in_var(type, "interpolant");
|
||||
interpolant->data.must_be_shader_input = 1;
|
||||
ir_variable *offset = in_var(glsl_type::vec2_type, "offset");
|
||||
MAKE_SIG(type, fs_gpu_shader5, 2, interpolant, offset);
|
||||
|
||||
body.emit(ret(interpolate_at_offset(interpolant, offset)));
|
||||
|
||||
return sig;
|
||||
}
|
||||
|
||||
ir_function_signature *
|
||||
builtin_builder::_interpolateAtSample(const glsl_type *type)
|
||||
{
|
||||
ir_variable *interpolant = in_var(type, "interpolant");
|
||||
interpolant->data.must_be_shader_input = 1;
|
||||
ir_variable *sample_num = in_var(glsl_type::int_type, "sample_num");
|
||||
MAKE_SIG(type, fs_gpu_shader5, 2, interpolant, sample_num);
|
||||
|
||||
body.emit(ret(interpolate_at_sample(interpolant, sample_num)));
|
||||
|
||||
return sig;
|
||||
}
|
||||
|
||||
ir_function_signature *
|
||||
builtin_builder::_atomic_intrinsic(builtin_available_predicate avail)
|
||||
{
|
||||
@@ -4335,9 +4567,11 @@ builtin_builder::_image_prototype(const glsl_type *image_type,
|
||||
sig->parameters.push_tail(in_var(glsl_type::int_type, "sample"));
|
||||
|
||||
/* Data arguments. */
|
||||
for (unsigned i = 0; i < num_arguments; ++i)
|
||||
sig->parameters.push_tail(in_var(data_type,
|
||||
ralloc_asprintf(NULL, "arg%d", i)));
|
||||
for (unsigned i = 0; i < num_arguments; ++i) {
|
||||
char *arg_name = ralloc_asprintf(NULL, "arg%d", i);
|
||||
sig->parameters.push_tail(in_var(data_type, arg_name));
|
||||
ralloc_free(arg_name);
|
||||
}
|
||||
|
||||
/* Set the maximal set of qualifiers allowed for this image
|
||||
* built-in. Function calls with arguments having fewer
|
||||
@@ -4346,11 +4580,11 @@ builtin_builder::_image_prototype(const glsl_type *image_type,
|
||||
* accept everything that needs to be accepted, and reject cases
|
||||
* like loads from write-only or stores to read-only images.
|
||||
*/
|
||||
image->data.image.read_only = flags & IMAGE_FUNCTION_READ_ONLY;
|
||||
image->data.image.write_only = flags & IMAGE_FUNCTION_WRITE_ONLY;
|
||||
image->data.image.coherent = true;
|
||||
image->data.image._volatile = true;
|
||||
image->data.image.restrict_flag = true;
|
||||
image->data.image_read_only = (flags & IMAGE_FUNCTION_READ_ONLY) != 0;
|
||||
image->data.image_write_only = (flags & IMAGE_FUNCTION_WRITE_ONLY) != 0;
|
||||
image->data.image_coherent = true;
|
||||
image->data.image_volatile = true;
|
||||
image->data.image_restrict = true;
|
||||
|
||||
return sig;
|
||||
}
|
||||
@@ -4407,14 +4641,15 @@ builtin_builder::_memory_barrier(builtin_available_predicate avail)
|
||||
/******************************************************************************/
|
||||
|
||||
//@TODO: implement
|
||||
#define _glthread_DECLARE_STATIC_MUTEX(name)
|
||||
#define _glthread_LOCK_MUTEX(name)
|
||||
#define _glthread_UNLOCK_MUTEX(name)
|
||||
typedef int mtx_t;
|
||||
#define _MTX_INITIALIZER_NP 0
|
||||
#define mtx_lock(name)
|
||||
#define mtx_unlock(name)
|
||||
|
||||
|
||||
/* The singleton instance of builtin_builder. */
|
||||
static builtin_builder builtins;
|
||||
_glthread_DECLARE_STATIC_MUTEX(builtins_lock);
|
||||
static mtx_t builtins_lock = _MTX_INITIALIZER_NP;
|
||||
|
||||
/**
|
||||
* External API (exposing the built-in module to the rest of the compiler):
|
||||
@@ -4423,17 +4658,17 @@ _glthread_DECLARE_STATIC_MUTEX(builtins_lock);
|
||||
void
|
||||
_mesa_glsl_initialize_builtin_functions()
|
||||
{
|
||||
_glthread_LOCK_MUTEX(builtins_lock);
|
||||
mtx_lock(&builtins_lock);
|
||||
builtins.initialize();
|
||||
_glthread_UNLOCK_MUTEX(builtins_lock);
|
||||
mtx_unlock(&builtins_lock);
|
||||
}
|
||||
|
||||
void
|
||||
_mesa_glsl_release_builtin_functions()
|
||||
{
|
||||
_glthread_LOCK_MUTEX(builtins_lock);
|
||||
mtx_lock(&builtins_lock);
|
||||
builtins.release();
|
||||
_glthread_UNLOCK_MUTEX(builtins_lock);
|
||||
mtx_unlock(&builtins_lock);
|
||||
}
|
||||
|
||||
ir_function_signature *
|
||||
@@ -4441,9 +4676,9 @@ _mesa_glsl_find_builtin_function(_mesa_glsl_parse_state *state,
|
||||
const char *name, exec_list *actual_parameters)
|
||||
{
|
||||
ir_function_signature * s;
|
||||
_glthread_LOCK_MUTEX(builtins_lock);
|
||||
mtx_lock(&builtins_lock);
|
||||
s = builtins.find(state, name, actual_parameters);
|
||||
_glthread_UNLOCK_MUTEX(builtins_lock);
|
||||
mtx_unlock(&builtins_lock);
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
|
||||
#include "glsl_types.h"
|
||||
#include "glsl_parser_extras.h"
|
||||
#include "util/macros.h"
|
||||
|
||||
/**
|
||||
* Declarations of type flyweights (glsl_type::_foo_type) and
|
||||
@@ -48,69 +49,69 @@
|
||||
|
||||
#define STRUCT_TYPE(NAME) \
|
||||
const glsl_type glsl_type::_struct_##NAME##_type = \
|
||||
glsl_type(NAME##_fields, Elements(NAME##_fields), #NAME); \
|
||||
glsl_type(NAME##_fields, ARRAY_SIZE(NAME##_fields), #NAME); \
|
||||
const glsl_type *const glsl_type::struct_##NAME##_type = \
|
||||
&glsl_type::_struct_##NAME##_type;
|
||||
|
||||
static const struct glsl_struct_field gl_DepthRangeParameters_fields[] = {
|
||||
{ glsl_type::float_type, "near", false, glsl_precision_high, -1 },
|
||||
{ glsl_type::float_type, "far", false, glsl_precision_high, -1 },
|
||||
{ glsl_type::float_type, "diff", false, glsl_precision_high, -1 },
|
||||
{ glsl_type::float_type, "near", glsl_precision_high, -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
|
||||
{ glsl_type::float_type, "far", glsl_precision_high, -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
|
||||
{ glsl_type::float_type, "diff", glsl_precision_high, -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
|
||||
};
|
||||
|
||||
static const struct glsl_struct_field gl_PointParameters_fields[] = {
|
||||
{ glsl_type::float_type, "size", false, glsl_precision_undefined, -1 },
|
||||
{ glsl_type::float_type, "sizeMin", false, glsl_precision_undefined, -1 },
|
||||
{ glsl_type::float_type, "sizeMax", false, glsl_precision_undefined, -1 },
|
||||
{ glsl_type::float_type, "fadeThresholdSize", false, glsl_precision_undefined, -1 },
|
||||
{ glsl_type::float_type, "distanceConstantAttenuation", false, glsl_precision_undefined, -1 },
|
||||
{ glsl_type::float_type, "distanceLinearAttenuation", false, glsl_precision_undefined, -1 },
|
||||
{ glsl_type::float_type, "distanceQuadraticAttenuation", false, glsl_precision_undefined, -1 },
|
||||
{ glsl_type::float_type, "size", glsl_precision_undefined, -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
|
||||
{ glsl_type::float_type, "sizeMin", glsl_precision_undefined, -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
|
||||
{ glsl_type::float_type, "sizeMax", glsl_precision_undefined, -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
|
||||
{ glsl_type::float_type, "fadeThresholdSize", glsl_precision_undefined, -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
|
||||
{ glsl_type::float_type, "distanceConstantAttenuation", glsl_precision_undefined, -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
|
||||
{ glsl_type::float_type, "distanceLinearAttenuation", glsl_precision_undefined, -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
|
||||
{ glsl_type::float_type, "distanceQuadraticAttenuation", glsl_precision_undefined, -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
|
||||
};
|
||||
|
||||
static const struct glsl_struct_field gl_MaterialParameters_fields[] = {
|
||||
{ glsl_type::vec4_type, "emission", false, glsl_precision_undefined, -1 },
|
||||
{ glsl_type::vec4_type, "ambient", false, glsl_precision_undefined, -1 },
|
||||
{ glsl_type::vec4_type, "diffuse", false, glsl_precision_undefined, -1 },
|
||||
{ glsl_type::vec4_type, "specular", false, glsl_precision_undefined, -1 },
|
||||
{ glsl_type::float_type, "shininess", false, glsl_precision_undefined, -1 },
|
||||
{ glsl_type::vec4_type, "emission", glsl_precision_undefined, -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
|
||||
{ glsl_type::vec4_type, "ambient", glsl_precision_undefined, -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
|
||||
{ glsl_type::vec4_type, "diffuse", glsl_precision_undefined, -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
|
||||
{ glsl_type::vec4_type, "specular", glsl_precision_undefined, -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
|
||||
{ glsl_type::float_type, "shininess", glsl_precision_undefined, -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
|
||||
};
|
||||
|
||||
static const struct glsl_struct_field gl_LightSourceParameters_fields[] = {
|
||||
{ glsl_type::vec4_type, "ambient", false, glsl_precision_undefined, -1 },
|
||||
{ glsl_type::vec4_type, "diffuse", false, glsl_precision_undefined, -1 },
|
||||
{ glsl_type::vec4_type, "specular", false, glsl_precision_undefined, -1 },
|
||||
{ glsl_type::vec4_type, "position", false, glsl_precision_undefined, -1 },
|
||||
{ glsl_type::vec4_type, "halfVector", false, glsl_precision_undefined, -1 },
|
||||
{ glsl_type::vec3_type, "spotDirection", false, glsl_precision_undefined, -1 },
|
||||
{ glsl_type::float_type, "spotExponent", false, glsl_precision_undefined, -1 },
|
||||
{ glsl_type::float_type, "spotCutoff", false, glsl_precision_undefined, -1 },
|
||||
{ glsl_type::float_type, "spotCosCutoff", false, glsl_precision_undefined, -1 },
|
||||
{ glsl_type::float_type, "constantAttenuation", false, glsl_precision_undefined, -1 },
|
||||
{ glsl_type::float_type, "linearAttenuation", false, glsl_precision_undefined, -1 },
|
||||
{ glsl_type::float_type, "quadraticAttenuation", false, glsl_precision_undefined, -1 },
|
||||
{ glsl_type::vec4_type, "ambient", glsl_precision_undefined, -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
|
||||
{ glsl_type::vec4_type, "diffuse", glsl_precision_undefined, -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
|
||||
{ glsl_type::vec4_type, "specular", glsl_precision_undefined, -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
|
||||
{ glsl_type::vec4_type, "position", glsl_precision_undefined, -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
|
||||
{ glsl_type::vec4_type, "halfVector", glsl_precision_undefined, -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
|
||||
{ glsl_type::vec3_type, "spotDirection", glsl_precision_undefined, -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
|
||||
{ glsl_type::float_type, "spotExponent", glsl_precision_undefined, -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
|
||||
{ glsl_type::float_type, "spotCutoff", glsl_precision_undefined, -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
|
||||
{ glsl_type::float_type, "spotCosCutoff", glsl_precision_undefined, -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
|
||||
{ glsl_type::float_type, "constantAttenuation", glsl_precision_undefined, -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
|
||||
{ glsl_type::float_type, "linearAttenuation", glsl_precision_undefined, -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
|
||||
{ glsl_type::float_type, "quadraticAttenuation", glsl_precision_undefined, -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
|
||||
};
|
||||
|
||||
static const struct glsl_struct_field gl_LightModelParameters_fields[] = {
|
||||
{ glsl_type::vec4_type, "ambient", false, glsl_precision_undefined, -1 },
|
||||
{ glsl_type::vec4_type, "ambient", glsl_precision_undefined, -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
|
||||
};
|
||||
|
||||
static const struct glsl_struct_field gl_LightModelProducts_fields[] = {
|
||||
{ glsl_type::vec4_type, "sceneColor", false, glsl_precision_undefined, -1 },
|
||||
{ glsl_type::vec4_type, "sceneColor", glsl_precision_undefined, -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
|
||||
};
|
||||
|
||||
static const struct glsl_struct_field gl_LightProducts_fields[] = {
|
||||
{ glsl_type::vec4_type, "ambient", false, glsl_precision_undefined, -1 },
|
||||
{ glsl_type::vec4_type, "diffuse", false, glsl_precision_undefined, -1 },
|
||||
{ glsl_type::vec4_type, "specular", false, glsl_precision_undefined, -1 },
|
||||
{ glsl_type::vec4_type, "ambient", glsl_precision_undefined, -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
|
||||
{ glsl_type::vec4_type, "diffuse", glsl_precision_undefined, -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
|
||||
{ glsl_type::vec4_type, "specular", glsl_precision_undefined, -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
|
||||
};
|
||||
|
||||
static const struct glsl_struct_field gl_FogParameters_fields[] = {
|
||||
{ glsl_type::vec4_type, "color", false, glsl_precision_undefined, -1 },
|
||||
{ glsl_type::float_type, "density", false, glsl_precision_undefined, -1 },
|
||||
{ glsl_type::float_type, "start", false, glsl_precision_undefined, -1 },
|
||||
{ glsl_type::float_type, "end", false, glsl_precision_undefined, -1 },
|
||||
{ glsl_type::float_type, "scale", false, glsl_precision_undefined, -1 },
|
||||
{ glsl_type::vec4_type, "color", glsl_precision_undefined, -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
|
||||
{ glsl_type::float_type, "density", glsl_precision_undefined, -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
|
||||
{ glsl_type::float_type, "start", glsl_precision_undefined, -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
|
||||
{ glsl_type::float_type, "end", glsl_precision_undefined, -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
|
||||
{ glsl_type::float_type, "scale", glsl_precision_undefined, -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
|
||||
};
|
||||
|
||||
#include "builtin_type_macros.h"
|
||||
@@ -241,7 +242,7 @@ const static struct builtin_type_versions {
|
||||
T(atomic_uint, 420, 999)
|
||||
};
|
||||
|
||||
const glsl_type *const deprecated_types[] = {
|
||||
static const glsl_type *const deprecated_types[] = {
|
||||
glsl_type::struct_gl_PointParameters_type,
|
||||
glsl_type::struct_gl_MaterialParameters_type,
|
||||
glsl_type::struct_gl_LightSourceParameters_type,
|
||||
@@ -265,7 +266,7 @@ _mesa_glsl_initialize_types(struct _mesa_glsl_parse_state *state)
|
||||
{
|
||||
struct glsl_symbol_table *symbols = state->symbols;
|
||||
|
||||
for (unsigned i = 0; i < Elements(builtin_type_versions); i++) {
|
||||
for (unsigned i = 0; i < ARRAY_SIZE(builtin_type_versions); i++) {
|
||||
const struct builtin_type_versions *const t = &builtin_type_versions[i];
|
||||
if (state->is_version(t->min_gl, t->min_es)) {
|
||||
add_type(symbols, t->type);
|
||||
@@ -276,7 +277,7 @@ _mesa_glsl_initialize_types(struct _mesa_glsl_parse_state *state)
|
||||
* they're still present. We've removed them in 1.40+ (OpenGL 3.1+).
|
||||
*/
|
||||
if (!state->es_shader && state->language_version < 140) {
|
||||
for (unsigned i = 0; i < Elements(deprecated_types); i++) {
|
||||
for (unsigned i = 0; i < ARRAY_SIZE(deprecated_types); i++) {
|
||||
add_type(symbols, deprecated_types[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,27 +37,27 @@ struct gl_builtin_uniform_element {
|
||||
};
|
||||
struct gl_builtin_uniform_desc {
|
||||
const char *name;
|
||||
struct gl_builtin_uniform_element *elements;
|
||||
const struct gl_builtin_uniform_element *elements;
|
||||
unsigned int num_elements;
|
||||
};
|
||||
|
||||
|
||||
static struct gl_builtin_uniform_element gl_NumSamples_elements[] = {
|
||||
{NULL, {STATE_NUM_SAMPLES, 0, 0}, SWIZZLE_XXXX}
|
||||
static const struct gl_builtin_uniform_element gl_NumSamples_elements[] = {
|
||||
{NULL, {STATE_NUM_SAMPLES, 0, 0}, SWIZZLE_XXXX}
|
||||
};
|
||||
|
||||
|
||||
static struct gl_builtin_uniform_element gl_DepthRange_elements[] = {
|
||||
static const struct gl_builtin_uniform_element gl_DepthRange_elements[] = {
|
||||
{"near", {STATE_DEPTH_RANGE, 0, 0}, SWIZZLE_XXXX},
|
||||
{"far", {STATE_DEPTH_RANGE, 0, 0}, SWIZZLE_YYYY},
|
||||
{"diff", {STATE_DEPTH_RANGE, 0, 0}, SWIZZLE_ZZZZ},
|
||||
};
|
||||
|
||||
static struct gl_builtin_uniform_element gl_ClipPlane_elements[] = {
|
||||
static const struct gl_builtin_uniform_element gl_ClipPlane_elements[] = {
|
||||
{NULL, {STATE_CLIPPLANE, 0, 0}, SWIZZLE_XYZW}
|
||||
};
|
||||
|
||||
static struct gl_builtin_uniform_element gl_Point_elements[] = {
|
||||
static const struct gl_builtin_uniform_element gl_Point_elements[] = {
|
||||
{"size", {STATE_POINT_SIZE}, SWIZZLE_XXXX},
|
||||
{"sizeMin", {STATE_POINT_SIZE}, SWIZZLE_YYYY},
|
||||
{"sizeMax", {STATE_POINT_SIZE}, SWIZZLE_ZZZZ},
|
||||
@@ -67,7 +67,7 @@ static struct gl_builtin_uniform_element gl_Point_elements[] = {
|
||||
{"distanceQuadraticAttenuation", {STATE_POINT_ATTENUATION}, SWIZZLE_ZZZZ},
|
||||
};
|
||||
|
||||
static struct gl_builtin_uniform_element gl_FrontMaterial_elements[] = {
|
||||
static const struct gl_builtin_uniform_element gl_FrontMaterial_elements[] = {
|
||||
{"emission", {STATE_MATERIAL, 0, STATE_EMISSION}, SWIZZLE_XYZW},
|
||||
{"ambient", {STATE_MATERIAL, 0, STATE_AMBIENT}, SWIZZLE_XYZW},
|
||||
{"diffuse", {STATE_MATERIAL, 0, STATE_DIFFUSE}, SWIZZLE_XYZW},
|
||||
@@ -75,7 +75,7 @@ static struct gl_builtin_uniform_element gl_FrontMaterial_elements[] = {
|
||||
{"shininess", {STATE_MATERIAL, 0, STATE_SHININESS}, SWIZZLE_XXXX},
|
||||
};
|
||||
|
||||
static struct gl_builtin_uniform_element gl_BackMaterial_elements[] = {
|
||||
static const struct gl_builtin_uniform_element gl_BackMaterial_elements[] = {
|
||||
{"emission", {STATE_MATERIAL, 1, STATE_EMISSION}, SWIZZLE_XYZW},
|
||||
{"ambient", {STATE_MATERIAL, 1, STATE_AMBIENT}, SWIZZLE_XYZW},
|
||||
{"diffuse", {STATE_MATERIAL, 1, STATE_DIFFUSE}, SWIZZLE_XYZW},
|
||||
@@ -83,7 +83,7 @@ static struct gl_builtin_uniform_element gl_BackMaterial_elements[] = {
|
||||
{"shininess", {STATE_MATERIAL, 1, STATE_SHININESS}, SWIZZLE_XXXX},
|
||||
};
|
||||
|
||||
static struct gl_builtin_uniform_element gl_LightSource_elements[] = {
|
||||
static const struct gl_builtin_uniform_element gl_LightSource_elements[] = {
|
||||
{"ambient", {STATE_LIGHT, 0, STATE_AMBIENT}, SWIZZLE_XYZW},
|
||||
{"diffuse", {STATE_LIGHT, 0, STATE_DIFFUSE}, SWIZZLE_XYZW},
|
||||
{"specular", {STATE_LIGHT, 0, STATE_SPECULAR}, SWIZZLE_XYZW},
|
||||
@@ -102,67 +102,67 @@ static struct gl_builtin_uniform_element gl_LightSource_elements[] = {
|
||||
{"quadraticAttenuation", {STATE_LIGHT, 0, STATE_ATTENUATION}, SWIZZLE_ZZZZ},
|
||||
};
|
||||
|
||||
static struct gl_builtin_uniform_element gl_LightModel_elements[] = {
|
||||
static const struct gl_builtin_uniform_element gl_LightModel_elements[] = {
|
||||
{"ambient", {STATE_LIGHTMODEL_AMBIENT, 0}, SWIZZLE_XYZW},
|
||||
};
|
||||
|
||||
static struct gl_builtin_uniform_element gl_FrontLightModelProduct_elements[] = {
|
||||
static const struct gl_builtin_uniform_element gl_FrontLightModelProduct_elements[] = {
|
||||
{"sceneColor", {STATE_LIGHTMODEL_SCENECOLOR, 0}, SWIZZLE_XYZW},
|
||||
};
|
||||
|
||||
static struct gl_builtin_uniform_element gl_BackLightModelProduct_elements[] = {
|
||||
static const struct gl_builtin_uniform_element gl_BackLightModelProduct_elements[] = {
|
||||
{"sceneColor", {STATE_LIGHTMODEL_SCENECOLOR, 1}, SWIZZLE_XYZW},
|
||||
};
|
||||
|
||||
static struct gl_builtin_uniform_element gl_FrontLightProduct_elements[] = {
|
||||
static const struct gl_builtin_uniform_element gl_FrontLightProduct_elements[] = {
|
||||
{"ambient", {STATE_LIGHTPROD, 0, 0, STATE_AMBIENT}, SWIZZLE_XYZW},
|
||||
{"diffuse", {STATE_LIGHTPROD, 0, 0, STATE_DIFFUSE}, SWIZZLE_XYZW},
|
||||
{"specular", {STATE_LIGHTPROD, 0, 0, STATE_SPECULAR}, SWIZZLE_XYZW},
|
||||
};
|
||||
|
||||
static struct gl_builtin_uniform_element gl_BackLightProduct_elements[] = {
|
||||
static const struct gl_builtin_uniform_element gl_BackLightProduct_elements[] = {
|
||||
{"ambient", {STATE_LIGHTPROD, 0, 1, STATE_AMBIENT}, SWIZZLE_XYZW},
|
||||
{"diffuse", {STATE_LIGHTPROD, 0, 1, STATE_DIFFUSE}, SWIZZLE_XYZW},
|
||||
{"specular", {STATE_LIGHTPROD, 0, 1, STATE_SPECULAR}, SWIZZLE_XYZW},
|
||||
};
|
||||
|
||||
static struct gl_builtin_uniform_element gl_TextureEnvColor_elements[] = {
|
||||
static const struct gl_builtin_uniform_element gl_TextureEnvColor_elements[] = {
|
||||
{NULL, {STATE_TEXENV_COLOR, 0}, SWIZZLE_XYZW},
|
||||
};
|
||||
|
||||
static struct gl_builtin_uniform_element gl_EyePlaneS_elements[] = {
|
||||
static const struct gl_builtin_uniform_element gl_EyePlaneS_elements[] = {
|
||||
{NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_EYE_S}, SWIZZLE_XYZW},
|
||||
};
|
||||
|
||||
static struct gl_builtin_uniform_element gl_EyePlaneT_elements[] = {
|
||||
static const struct gl_builtin_uniform_element gl_EyePlaneT_elements[] = {
|
||||
{NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_EYE_T}, SWIZZLE_XYZW},
|
||||
};
|
||||
|
||||
static struct gl_builtin_uniform_element gl_EyePlaneR_elements[] = {
|
||||
static const struct gl_builtin_uniform_element gl_EyePlaneR_elements[] = {
|
||||
{NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_EYE_R}, SWIZZLE_XYZW},
|
||||
};
|
||||
|
||||
static struct gl_builtin_uniform_element gl_EyePlaneQ_elements[] = {
|
||||
static const struct gl_builtin_uniform_element gl_EyePlaneQ_elements[] = {
|
||||
{NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_EYE_Q}, SWIZZLE_XYZW},
|
||||
};
|
||||
|
||||
static struct gl_builtin_uniform_element gl_ObjectPlaneS_elements[] = {
|
||||
static const struct gl_builtin_uniform_element gl_ObjectPlaneS_elements[] = {
|
||||
{NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_S}, SWIZZLE_XYZW},
|
||||
};
|
||||
|
||||
static struct gl_builtin_uniform_element gl_ObjectPlaneT_elements[] = {
|
||||
static const struct gl_builtin_uniform_element gl_ObjectPlaneT_elements[] = {
|
||||
{NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_T}, SWIZZLE_XYZW},
|
||||
};
|
||||
|
||||
static struct gl_builtin_uniform_element gl_ObjectPlaneR_elements[] = {
|
||||
static const struct gl_builtin_uniform_element gl_ObjectPlaneR_elements[] = {
|
||||
{NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_R}, SWIZZLE_XYZW},
|
||||
};
|
||||
|
||||
static struct gl_builtin_uniform_element gl_ObjectPlaneQ_elements[] = {
|
||||
static const struct gl_builtin_uniform_element gl_ObjectPlaneQ_elements[] = {
|
||||
{NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_Q}, SWIZZLE_XYZW},
|
||||
};
|
||||
|
||||
static struct gl_builtin_uniform_element gl_Fog_elements[] = {
|
||||
static const struct gl_builtin_uniform_element gl_Fog_elements[] = {
|
||||
{"color", {STATE_FOG_COLOR}, SWIZZLE_XYZW},
|
||||
{"density", {STATE_FOG_PARAMS}, SWIZZLE_XXXX},
|
||||
{"start", {STATE_FOG_PARAMS}, SWIZZLE_YYYY},
|
||||
@@ -170,32 +170,24 @@ static struct gl_builtin_uniform_element gl_Fog_elements[] = {
|
||||
{"scale", {STATE_FOG_PARAMS}, SWIZZLE_WWWW},
|
||||
};
|
||||
|
||||
static struct gl_builtin_uniform_element gl_NormalScale_elements[] = {
|
||||
static const struct gl_builtin_uniform_element gl_NormalScale_elements[] = {
|
||||
{NULL, {STATE_NORMAL_SCALE}, SWIZZLE_XXXX},
|
||||
};
|
||||
|
||||
static struct gl_builtin_uniform_element gl_BumpRotMatrix0MESA_elements[] = {
|
||||
{NULL, {STATE_INTERNAL, STATE_ROT_MATRIX_0}, SWIZZLE_XYZW},
|
||||
};
|
||||
|
||||
static struct gl_builtin_uniform_element gl_BumpRotMatrix1MESA_elements[] = {
|
||||
{NULL, {STATE_INTERNAL, STATE_ROT_MATRIX_1}, SWIZZLE_XYZW},
|
||||
};
|
||||
|
||||
static struct gl_builtin_uniform_element gl_FogParamsOptimizedMESA_elements[] = {
|
||||
static const struct gl_builtin_uniform_element gl_FogParamsOptimizedMESA_elements[] = {
|
||||
{NULL, {STATE_INTERNAL, STATE_FOG_PARAMS_OPTIMIZED}, SWIZZLE_XYZW},
|
||||
};
|
||||
|
||||
static struct gl_builtin_uniform_element gl_CurrentAttribVertMESA_elements[] = {
|
||||
static const struct gl_builtin_uniform_element gl_CurrentAttribVertMESA_elements[] = {
|
||||
{NULL, {STATE_INTERNAL, STATE_CURRENT_ATTRIB, 0}, SWIZZLE_XYZW},
|
||||
};
|
||||
|
||||
static struct gl_builtin_uniform_element gl_CurrentAttribFragMESA_elements[] = {
|
||||
static const struct gl_builtin_uniform_element gl_CurrentAttribFragMESA_elements[] = {
|
||||
{NULL, {STATE_INTERNAL, STATE_CURRENT_ATTRIB_MAYBE_VP_CLAMPED, 0}, SWIZZLE_XYZW},
|
||||
};
|
||||
|
||||
#define MATRIX(name, statevar, modifier) \
|
||||
static struct gl_builtin_uniform_element name ## _elements[] = { \
|
||||
static const struct gl_builtin_uniform_element name ## _elements[] = { \
|
||||
{ NULL, { statevar, 0, 0, 0, modifier}, SWIZZLE_XYZW }, \
|
||||
{ NULL, { statevar, 0, 1, 1, modifier}, SWIZZLE_XYZW }, \
|
||||
{ NULL, { statevar, 0, 2, 2, modifier}, SWIZZLE_XYZW }, \
|
||||
@@ -238,7 +230,7 @@ MATRIX(gl_TextureMatrixTranspose,
|
||||
MATRIX(gl_TextureMatrixInverseTranspose,
|
||||
STATE_TEXTURE_MATRIX, STATE_MATRIX_INVERSE);
|
||||
|
||||
static struct gl_builtin_uniform_element gl_NormalMatrix_elements[] = {
|
||||
static const struct gl_builtin_uniform_element gl_NormalMatrix_elements[] = {
|
||||
{ NULL, { STATE_MODELVIEW_MATRIX, 0, 0, 0, STATE_MATRIX_INVERSE},
|
||||
MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_Z) },
|
||||
{ NULL, { STATE_MODELVIEW_MATRIX, 0, 1, 1, STATE_MATRIX_INVERSE},
|
||||
@@ -298,8 +290,6 @@ static const struct gl_builtin_uniform_desc _mesa_builtin_uniform_desc[] = {
|
||||
STATEVAR(gl_NormalMatrix),
|
||||
STATEVAR(gl_NormalScale),
|
||||
|
||||
STATEVAR(gl_BumpRotMatrix0MESA),
|
||||
STATEVAR(gl_BumpRotMatrix1MESA),
|
||||
STATEVAR(gl_FogParamsOptimizedMESA),
|
||||
STATEVAR(gl_CurrentAttribVertMESA),
|
||||
STATEVAR(gl_CurrentAttribFragMESA),
|
||||
@@ -341,7 +331,7 @@ per_vertex_accumulator::add_field(int slot, const glsl_type *type,
|
||||
assert(this->num_fields < ARRAY_SIZE(this->fields));
|
||||
this->fields[this->num_fields].type = type;
|
||||
this->fields[this->num_fields].name = name;
|
||||
this->fields[this->num_fields].row_major = false;
|
||||
this->fields[this->num_fields].matrix_layout = GLSL_MATRIX_LAYOUT_INHERITED;
|
||||
this->fields[this->num_fields].precision = prec;
|
||||
this->fields[this->num_fields].location = slot;
|
||||
this->fields[this->num_fields].interpolation = INTERP_QUALIFIER_NONE;
|
||||
@@ -402,7 +392,7 @@ private:
|
||||
|
||||
ir_variable *add_variable(const char *name, const glsl_type *type,
|
||||
enum ir_variable_mode mode, int slot, glsl_precision prec);
|
||||
ir_variable *add_uniform(const glsl_type *type, const char *name, glsl_precision prec);
|
||||
ir_variable *add_uniform(const glsl_type *type, const char *name, glsl_precision prec = glsl_precision_undefined);
|
||||
ir_variable *add_const(const char *name, int value);
|
||||
ir_variable *add_const_ivec3(const char *name, int x, int y, int z);
|
||||
void add_varying(int slot, const glsl_type *type, const char *name,
|
||||
@@ -421,6 +411,7 @@ private:
|
||||
|
||||
const glsl_type * const bool_t;
|
||||
const glsl_type * const int_t;
|
||||
const glsl_type * const uint_t;
|
||||
const glsl_type * const float_t;
|
||||
const glsl_type * const vec2_t;
|
||||
const glsl_type * const vec3_t;
|
||||
@@ -437,7 +428,7 @@ builtin_variable_generator::builtin_variable_generator(
|
||||
exec_list *instructions, struct _mesa_glsl_parse_state *state)
|
||||
: instructions(instructions), state(state), symtab(state->symbols),
|
||||
compatibility(!state->is_version(140, 100)),
|
||||
bool_t(glsl_type::bool_type), int_t(glsl_type::int_type),
|
||||
bool_t(glsl_type::bool_type), int_t(glsl_type::int_type), uint_t(glsl_type::uint_type),
|
||||
float_t(glsl_type::float_type), vec2_t(glsl_type::vec2_type),
|
||||
vec3_t(glsl_type::vec3_type), vec4_t(glsl_type::vec4_type),
|
||||
mat3_t(glsl_type::mat3_type), mat4_t(glsl_type::mat4_type)
|
||||
@@ -506,16 +497,14 @@ builtin_variable_generator::add_uniform(const glsl_type *type,
|
||||
&_mesa_builtin_uniform_desc[i];
|
||||
|
||||
const unsigned array_count = type->is_array() ? type->length : 1;
|
||||
uni->num_state_slots = array_count * statevar->num_elements;
|
||||
|
||||
ir_state_slot *slots =
|
||||
ralloc_array(uni, ir_state_slot, uni->num_state_slots);
|
||||
|
||||
uni->state_slots = slots;
|
||||
uni->allocate_state_slots(array_count * statevar->num_elements);
|
||||
|
||||
for (unsigned a = 0; a < array_count; a++) {
|
||||
for (unsigned j = 0; j < statevar->num_elements; j++) {
|
||||
struct gl_builtin_uniform_element *element = &statevar->elements[j];
|
||||
const struct gl_builtin_uniform_element *element =
|
||||
&statevar->elements[j];
|
||||
|
||||
memcpy(slots->tokens, element->tokens, sizeof(element->tokens));
|
||||
if (type->is_array()) {
|
||||
@@ -699,6 +688,12 @@ builtin_variable_generator::generate_constants()
|
||||
}
|
||||
|
||||
if (state->is_version(430, 0) || state->ARB_compute_shader_enable) {
|
||||
add_const("gl_MaxComputeAtomicCounterBuffers", MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS);
|
||||
add_const("gl_MaxComputeAtomicCounters", MAX_COMPUTE_ATOMIC_COUNTERS);
|
||||
add_const("gl_MaxComputeImageUniforms", MAX_COMPUTE_IMAGE_UNIFORMS);
|
||||
add_const("gl_MaxComputeTextureImageUnits", MAX_COMPUTE_TEXTURE_IMAGE_UNITS);
|
||||
add_const("gl_MaxComputeUniformComponents", MAX_COMPUTE_UNIFORM_COMPONENTS);
|
||||
|
||||
add_const_ivec3("gl_MaxComputeWorkGroupCount",
|
||||
state->Const.MaxComputeWorkGroupCount[0],
|
||||
state->Const.MaxComputeWorkGroupCount[1],
|
||||
@@ -763,24 +758,22 @@ builtin_variable_generator::generate_uniforms()
|
||||
add_uniform(array(vec4_t, VARYING_SLOT_MAX), "gl_CurrentAttribFragMESA", glsl_precision_undefined);
|
||||
|
||||
if (compatibility) {
|
||||
add_uniform(mat4_t, "gl_ModelViewMatrix", glsl_precision_undefined);
|
||||
add_uniform(mat4_t, "gl_ProjectionMatrix", glsl_precision_undefined);
|
||||
add_uniform(mat4_t, "gl_ModelViewProjectionMatrix", glsl_precision_undefined);
|
||||
add_uniform(mat3_t, "gl_NormalMatrix", glsl_precision_undefined);
|
||||
add_uniform(mat4_t, "gl_ModelViewMatrixInverse", glsl_precision_undefined);
|
||||
add_uniform(mat4_t, "gl_ProjectionMatrixInverse", glsl_precision_undefined);
|
||||
add_uniform(mat4_t, "gl_ModelViewProjectionMatrixInverse", glsl_precision_undefined);
|
||||
add_uniform(mat4_t, "gl_ModelViewMatrixTranspose", glsl_precision_undefined);
|
||||
add_uniform(mat4_t, "gl_ProjectionMatrixTranspose", glsl_precision_undefined);
|
||||
add_uniform(mat4_t, "gl_ModelViewProjectionMatrixTranspose", glsl_precision_undefined);
|
||||
add_uniform(mat4_t, "gl_ModelViewMatrixInverseTranspose", glsl_precision_undefined);
|
||||
add_uniform(mat4_t, "gl_ProjectionMatrixInverseTranspose", glsl_precision_undefined);
|
||||
add_uniform(mat4_t, "gl_ModelViewProjectionMatrixInverseTranspose", glsl_precision_undefined);
|
||||
add_uniform(float_t, "gl_NormalScale", glsl_precision_undefined);
|
||||
add_uniform(type("gl_LightModelParameters"), "gl_LightModel", glsl_precision_undefined);
|
||||
add_uniform(vec2_t, "gl_BumpRotMatrix0MESA", glsl_precision_undefined);
|
||||
add_uniform(vec2_t, "gl_BumpRotMatrix1MESA", glsl_precision_undefined);
|
||||
add_uniform(vec4_t, "gl_FogParamsOptimizedMESA", glsl_precision_undefined);
|
||||
add_uniform(mat4_t, "gl_ModelViewMatrix");
|
||||
add_uniform(mat4_t, "gl_ProjectionMatrix");
|
||||
add_uniform(mat4_t, "gl_ModelViewProjectionMatrix");
|
||||
add_uniform(mat3_t, "gl_NormalMatrix");
|
||||
add_uniform(mat4_t, "gl_ModelViewMatrixInverse");
|
||||
add_uniform(mat4_t, "gl_ProjectionMatrixInverse");
|
||||
add_uniform(mat4_t, "gl_ModelViewProjectionMatrixInverse");
|
||||
add_uniform(mat4_t, "gl_ModelViewMatrixTranspose");
|
||||
add_uniform(mat4_t, "gl_ProjectionMatrixTranspose");
|
||||
add_uniform(mat4_t, "gl_ModelViewProjectionMatrixTranspose");
|
||||
add_uniform(mat4_t, "gl_ModelViewMatrixInverseTranspose");
|
||||
add_uniform(mat4_t, "gl_ProjectionMatrixInverseTranspose");
|
||||
add_uniform(mat4_t, "gl_ModelViewProjectionMatrixInverseTranspose");
|
||||
add_uniform(float_t, "gl_NormalScale");
|
||||
add_uniform(type("gl_LightModelParameters"), "gl_LightModel");
|
||||
add_uniform(vec4_t, "gl_FogParamsOptimizedMESA");
|
||||
|
||||
const glsl_type *const mat4_array_type =
|
||||
array(mat4_t, state->Const.MaxTextureCoords);
|
||||
@@ -838,13 +831,15 @@ builtin_variable_generator::generate_vs_special_vars()
|
||||
{
|
||||
|
||||
if (state->is_version(130, 300))
|
||||
add_system_value(SYSTEM_VALUE_VERTEX_ID, int_t, "gl_VertexID", glsl_precision_high);
|
||||
add_system_value(SYSTEM_VALUE_VERTEX_ID, state->metal_target ? uint_t : int_t, "gl_VertexID", glsl_precision_high);
|
||||
if (state->ARB_draw_instanced_enable)
|
||||
add_system_value(SYSTEM_VALUE_INSTANCE_ID, int_t, "gl_InstanceIDARB", glsl_precision_high);
|
||||
if (state->ARB_draw_instanced_enable || state->is_version(140, 300))
|
||||
add_system_value(SYSTEM_VALUE_INSTANCE_ID, int_t, "gl_InstanceID", glsl_precision_high);
|
||||
add_system_value(SYSTEM_VALUE_INSTANCE_ID, state->metal_target ? uint_t : int_t, "gl_InstanceID", glsl_precision_high);
|
||||
if (state->AMD_vertex_shader_layer_enable)
|
||||
add_output(VARYING_SLOT_LAYER, int_t, "gl_Layer", glsl_precision_high);
|
||||
if (state->AMD_vertex_shader_viewport_index_enable)
|
||||
add_output(VARYING_SLOT_VIEWPORT, int_t, "gl_ViewportIndex", glsl_precision_high);
|
||||
if (compatibility) {
|
||||
add_input(VERT_ATTRIB_POS, vec4_t, "gl_Vertex", glsl_precision_high);
|
||||
add_input(VERT_ATTRIB_NORMAL, vec3_t, "gl_Normal", glsl_precision_medium);
|
||||
@@ -872,6 +867,8 @@ builtin_variable_generator::generate_gs_special_vars()
|
||||
add_output(VARYING_SLOT_LAYER, int_t, "gl_Layer", glsl_precision_high);
|
||||
if (state->ARB_viewport_array_enable)
|
||||
add_output(VARYING_SLOT_VIEWPORT, int_t, "gl_ViewportIndex", glsl_precision_high);
|
||||
if (state->ARB_gpu_shader5_enable)
|
||||
add_system_value(SYSTEM_VALUE_INVOCATION_ID, int_t, "gl_InvocationID", glsl_precision_high);
|
||||
|
||||
/* Although gl_PrimitiveID appears in tessellation control and tessellation
|
||||
* evaluation shaders, it has a different function there than it has in
|
||||
@@ -900,7 +897,7 @@ builtin_variable_generator::generate_fs_special_vars()
|
||||
add_input(VARYING_SLOT_POS, vec4_t, "gl_FragCoord", glsl_precision_high);
|
||||
add_input(VARYING_SLOT_FACE, bool_t, "gl_FrontFacing", glsl_precision_low);
|
||||
if (state->is_version(120, 100))
|
||||
add_input(VARYING_SLOT_PNTC, vec2_t, "gl_PointCoord", glsl_precision_medium);
|
||||
add_input(VARYING_SLOT_PNTC, vec2_t, "gl_PointCoord", state->metal_target ? glsl_precision_high : glsl_precision_medium);
|
||||
|
||||
if (state->is_version(150, 0)) {
|
||||
ir_variable *var =
|
||||
@@ -928,21 +925,28 @@ builtin_variable_generator::generate_fs_special_vars()
|
||||
ir_variable *const var =
|
||||
add_output(FRAG_RESULT_STENCIL, int_t, "gl_FragStencilRefARB", glsl_precision_high);
|
||||
if (state->ARB_shader_stencil_export_warn)
|
||||
var->warn_extension = "GL_ARB_shader_stencil_export";
|
||||
var->enable_extension_warning("GL_ARB_shader_stencil_export");
|
||||
}
|
||||
|
||||
if (state->AMD_shader_stencil_export_enable) {
|
||||
ir_variable *const var =
|
||||
add_output(FRAG_RESULT_STENCIL, int_t, "gl_FragStencilRefAMD", glsl_precision_high);
|
||||
if (state->AMD_shader_stencil_export_warn)
|
||||
var->warn_extension = "GL_AMD_shader_stencil_export";
|
||||
var->enable_extension_warning("GL_AMD_shader_stencil_export");
|
||||
}
|
||||
|
||||
if (state->EXT_frag_depth_enable) {
|
||||
ir_variable *const var =
|
||||
add_output(FRAG_RESULT_DEPTH, float_t, "gl_FragDepthEXT", glsl_precision_high);
|
||||
if (state->EXT_frag_depth_warn)
|
||||
var->warn_extension = "GL_EXT_frag_depth";
|
||||
var->enable_extension_warning("GL_EXT_frag_depth");
|
||||
}
|
||||
|
||||
if (state->EXT_shader_framebuffer_fetch_enable) {
|
||||
ir_variable *const var =
|
||||
add_input(VARYING_SLOT_VAR0, array(vec4_t, state->Const.MaxDrawBuffers), "gl_LastFragData", glsl_precision_medium);
|
||||
if (state->EXT_shader_framebuffer_fetch_warn)
|
||||
var->enable_extension_warning("GL_EXT_shader_framebuffer_fetch");
|
||||
}
|
||||
|
||||
if (state->ARB_sample_shading_enable) {
|
||||
@@ -961,6 +965,11 @@ builtin_variable_generator::generate_fs_special_vars()
|
||||
if (state->ARB_gpu_shader5_enable) {
|
||||
add_system_value(SYSTEM_VALUE_SAMPLE_MASK_IN, array(int_t, 1), "gl_SampleMaskIn", glsl_precision_high);
|
||||
}
|
||||
|
||||
if (state->ARB_fragment_layer_viewport_enable) {
|
||||
add_input(VARYING_SLOT_LAYER, int_t, "gl_Layer", glsl_precision_high);
|
||||
add_input(VARYING_SLOT_VIEWPORT, int_t, "gl_ViewportIndex", glsl_precision_high);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
980
3rdparty/glsl-optimizer/src/glsl/glcpp/glcpp-lex.c
vendored
980
3rdparty/glsl-optimizer/src/glsl/glcpp/glcpp-lex.c
vendored
File diff suppressed because it is too large
Load Diff
473
3rdparty/glsl-optimizer/src/glsl/glcpp/glcpp-lex.l
vendored
473
3rdparty/glsl-optimizer/src/glsl/glcpp/glcpp-lex.l
vendored
@@ -48,18 +48,112 @@ void glcpp_set_column (int column_no , yyscan_t yyscanner);
|
||||
if (parser->has_new_source_number) \
|
||||
yylloc->source = parser->new_source_number; \
|
||||
yylloc->first_column = yycolumn + 1; \
|
||||
yylloc->first_line = yylineno; \
|
||||
yylloc->first_line = yylloc->last_line = yylineno; \
|
||||
yycolumn += yyleng; \
|
||||
yylloc->last_column = yycolumn + 1; \
|
||||
parser->has_new_line_number = 0; \
|
||||
parser->has_new_source_number = 0; \
|
||||
} while(0);
|
||||
} while(0);
|
||||
|
||||
#define YY_USER_INIT \
|
||||
do { \
|
||||
yylineno = 1; \
|
||||
yycolumn = 1; \
|
||||
yycolumn = 0; \
|
||||
yylloc->source = 0; \
|
||||
} while(0)
|
||||
|
||||
/* It's ugly to have macros that have return statements inside of
|
||||
* them, but flex-based lexer generation is all built around the
|
||||
* return statement.
|
||||
*
|
||||
* To mitigate the ugliness, we defer as much of the logic as possible
|
||||
* to an actual function, not a macro (see
|
||||
* glcpplex_update_state_per_token) and we make the word RETURN
|
||||
* prominent in all of the macros which may return.
|
||||
*
|
||||
* The most-commonly-used macro is RETURN_TOKEN which will perform all
|
||||
* necessary state updates based on the provided token,, then
|
||||
* conditionally return the token. It will not return a token if the
|
||||
* parser is currently skipping tokens, (such as within #if
|
||||
* 0...#else).
|
||||
*
|
||||
* The RETURN_TOKEN_NEVER_SKIP macro is a lower-level variant that
|
||||
* makes the token returning unconditional. This is needed for things
|
||||
* like #if and the tokens of its condition, (since these must be
|
||||
* evaluated by the parser even when otherwise skipping).
|
||||
*
|
||||
* Finally, RETURN_STRING_TOKEN is a simple convenience wrapper on top
|
||||
* of RETURN_TOKEN that performs a string copy of yytext before the
|
||||
* return.
|
||||
*/
|
||||
#define RETURN_TOKEN_NEVER_SKIP(token) \
|
||||
do { \
|
||||
if (glcpp_lex_update_state_per_token (parser, token)) \
|
||||
return token; \
|
||||
} while (0)
|
||||
|
||||
#define RETURN_TOKEN(token) \
|
||||
do { \
|
||||
if (! parser->skipping) { \
|
||||
RETURN_TOKEN_NEVER_SKIP(token); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define RETURN_STRING_TOKEN(token) \
|
||||
do { \
|
||||
if (! parser->skipping) { \
|
||||
yylval->str = ralloc_strdup (yyextra, yytext); \
|
||||
RETURN_TOKEN_NEVER_SKIP (token); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
|
||||
/* Update all state necessary for each token being returned.
|
||||
*
|
||||
* Here we'll be tracking newlines and spaces so that the lexer can
|
||||
* alter its behavior as necessary, (for example, '#' has special
|
||||
* significance if it is the first non-whitespace, non-comment token
|
||||
* in a line, but does not otherwise).
|
||||
*
|
||||
* NOTE: If this function returns FALSE, then no token should be
|
||||
* returned at all. This is used to suprress duplicate SPACE tokens.
|
||||
*/
|
||||
static int
|
||||
glcpp_lex_update_state_per_token (glcpp_parser_t *parser, int token)
|
||||
{
|
||||
/* After the first non-space token in a line, we won't
|
||||
* allow any '#' to introduce a directive. */
|
||||
if (token == NEWLINE) {
|
||||
parser->first_non_space_token_this_line = 1;
|
||||
} else if (token != SPACE) {
|
||||
parser->first_non_space_token_this_line = 0;
|
||||
}
|
||||
|
||||
/* Track newlines just to know whether a newline needs
|
||||
* to be inserted if end-of-file comes early. */
|
||||
if (token == NEWLINE) {
|
||||
parser->last_token_was_newline = 1;
|
||||
} else {
|
||||
parser->last_token_was_newline = 0;
|
||||
}
|
||||
|
||||
/* Track spaces to avoid emitting multiple SPACE
|
||||
* tokens in a row. */
|
||||
if (token == SPACE) {
|
||||
if (! parser->last_token_was_space) {
|
||||
parser->last_token_was_space = 1;
|
||||
return 1;
|
||||
} else {
|
||||
parser->last_token_was_space = 1;
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
parser->last_token_was_space = 0;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
%}
|
||||
|
||||
%option bison-bridge bison-locations reentrant noyywrap
|
||||
@@ -67,15 +161,21 @@ void glcpp_set_column (int column_no , yyscan_t yyscanner);
|
||||
%option prefix="glcpp_"
|
||||
%option stack
|
||||
%option never-interactive
|
||||
%option warn nodefault
|
||||
|
||||
%x DONE COMMENT UNREACHABLE SKIP DEFINE NEWLINE_CATCHUP
|
||||
/* Note: When adding any start conditions to this list, you must also
|
||||
* update the "Internal compiler error" catch-all rule near the end of
|
||||
* this file. */
|
||||
|
||||
%x COMMENT DEFINE DONE HASH NEWLINE_CATCHUP UNREACHABLE
|
||||
|
||||
SPACE [[:space:]]
|
||||
NONSPACE [^[:space:]]
|
||||
NEWLINE [\n]
|
||||
HSPACE [ \t]
|
||||
HASH ^{HSPACE}*#{HSPACE}*
|
||||
HASH #
|
||||
NEWLINE (\r\n|\n\r|\r|\n)
|
||||
IDENTIFIER [_a-zA-Z][_a-zA-Z0-9]*
|
||||
PP_NUMBER [.]?[0-9]([._a-zA-Z0-9]|[eEpP][-+])*
|
||||
PUNCTUATION [][(){}.&*~!/%<>^|;,=+-]
|
||||
|
||||
/* The OTHER class is simply a catch-all for things that the CPP
|
||||
@@ -110,264 +210,363 @@ HEXADECIMAL_INTEGER 0[xX][0-9a-fA-F]+[uU]?
|
||||
parser->commented_newlines--;
|
||||
if (parser->commented_newlines == 0)
|
||||
BEGIN INITIAL;
|
||||
return NEWLINE;
|
||||
RETURN_TOKEN_NEVER_SKIP (NEWLINE);
|
||||
}
|
||||
|
||||
/* The handling of the SKIP vs INITIAL start states requires
|
||||
* some special handling. Typically, a lexer would change
|
||||
* start states with statements like "BEGIN SKIP" within the
|
||||
* lexer rules. We can't get away with that here, since we
|
||||
* need the parser to actually evaluate expressions for
|
||||
* directives like "#if".
|
||||
/* Set up the parser->skipping bit here before doing any lexing.
|
||||
*
|
||||
* So, here, in code that will be executed on every call to
|
||||
* the lexer,and before any rules, we examine the skip_stack
|
||||
* as set by the parser to know whether to change from INITIAL
|
||||
* to SKIP or from SKIP back to INITIAL.
|
||||
* This bit controls whether tokens are skipped, (as implemented by
|
||||
* RETURN_TOKEN), such as between "#if 0" and "#endif".
|
||||
*
|
||||
* Three cases cause us to switch out of the SKIP state and
|
||||
* back to the INITIAL state:
|
||||
* The parser maintains a skip_stack indicating whether we should be
|
||||
* skipping, (and nested levels of #if/#ifdef/#ifndef/#endif) will
|
||||
* push and pop items from the stack.
|
||||
*
|
||||
* 1. The top of the skip_stack is of type SKIP_NO_SKIP
|
||||
* This means we're still evaluating some #if
|
||||
* hierarchy, but we're on a branch of it where
|
||||
* content should not be skipped (such as "#if 1" or
|
||||
* "#else" or so).
|
||||
* Here are the rules for determining whether we are skipping:
|
||||
*
|
||||
* 2. The skip_stack is NULL meaning that we've reached
|
||||
* the last #endif.
|
||||
* 1. If the skip stack is NULL, we are outside of all #if blocks
|
||||
* and we are not skipping.
|
||||
*
|
||||
* 3. The lexing_if bit is set. This indicates that we
|
||||
* are lexing the expression following an "#if" of
|
||||
* "#elif". Even inside an "#if 0" we need to lex this
|
||||
* expression so the parser can correctly update the
|
||||
* skip_stack state.
|
||||
* 2. If the skip stack is non-NULL, the type of the top node in
|
||||
* the stack determines whether to skip. A type of
|
||||
* SKIP_NO_SKIP is used for blocks wheere we are emitting
|
||||
* tokens, (such as between #if 1 and #endif, or after the
|
||||
* #else of an #if 0, etc.).
|
||||
*
|
||||
* 3. The lexing_directive bit overrides the skip stack. This bit
|
||||
* is set when we are actively lexing the expression for a
|
||||
* pre-processor condition, (such as #if, #elif, or #else). In
|
||||
* this case, even if otherwise skipping, we need to emit the
|
||||
* tokens for this condition so that the parser can evaluate
|
||||
* the expression. (For, #else, there's no expression, but we
|
||||
* emit tokens so the parser can generate a nice error message
|
||||
* if there are any tokens here).
|
||||
*/
|
||||
if (YY_START == INITIAL || YY_START == SKIP) {
|
||||
if (parser->lexing_if ||
|
||||
parser->skip_stack == NULL ||
|
||||
parser->skip_stack->type == SKIP_NO_SKIP)
|
||||
{
|
||||
BEGIN INITIAL;
|
||||
} else {
|
||||
BEGIN SKIP;
|
||||
}
|
||||
if (parser->skip_stack &&
|
||||
parser->skip_stack->type != SKIP_NO_SKIP &&
|
||||
! parser->lexing_directive)
|
||||
{
|
||||
parser->skipping = 1;
|
||||
} else {
|
||||
parser->skipping = 0;
|
||||
}
|
||||
|
||||
/* Single-line comments */
|
||||
"//"[^\n]* {
|
||||
<INITIAL,DEFINE,HASH>"//"[^\r\n]* {
|
||||
}
|
||||
|
||||
/* Multi-line comments */
|
||||
"/*" { yy_push_state(COMMENT, yyscanner); }
|
||||
<COMMENT>[^*\n]*
|
||||
<COMMENT>[^*\n]*\n { yylineno++; yycolumn = 0; parser->commented_newlines++; }
|
||||
<COMMENT>"*"+[^*/\n]*
|
||||
<COMMENT>"*"+[^*/\n]*\n { yylineno++; yycolumn = 0; parser->commented_newlines++; }
|
||||
<INITIAL,DEFINE,HASH>"/*" { yy_push_state(COMMENT, yyscanner); }
|
||||
<COMMENT>[^*\r\n]*
|
||||
<COMMENT>[^*\r\n]*{NEWLINE} { yylineno++; yycolumn = 0; parser->commented_newlines++; }
|
||||
<COMMENT>"*"+[^*/\r\n]*
|
||||
<COMMENT>"*"+[^*/\r\n]*{NEWLINE} { yylineno++; yycolumn = 0; parser->commented_newlines++; }
|
||||
<COMMENT>"*"+"/" {
|
||||
yy_pop_state(yyscanner);
|
||||
if (yyextra->space_tokens)
|
||||
return SPACE;
|
||||
/* In the <HASH> start condition, we don't want any SPACE token. */
|
||||
if (yyextra->space_tokens && YY_START != HASH)
|
||||
RETURN_TOKEN (SPACE);
|
||||
}
|
||||
|
||||
{HASH}version{HSPACE}+ {
|
||||
yylval->str = ralloc_strdup (yyextra, yytext);
|
||||
{HASH} {
|
||||
|
||||
/* If the '#' is the first non-whitespace, non-comment token on this
|
||||
* line, then it introduces a directive, switch to the <HASH> start
|
||||
* condition.
|
||||
*
|
||||
* Otherwise, this is just punctuation, so return the HASH_TOKEN
|
||||
* token. */
|
||||
if (parser->first_non_space_token_this_line) {
|
||||
BEGIN HASH;
|
||||
}
|
||||
|
||||
RETURN_TOKEN_NEVER_SKIP (HASH_TOKEN);
|
||||
}
|
||||
|
||||
<HASH>version{HSPACE}+ {
|
||||
BEGIN INITIAL;
|
||||
yyextra->space_tokens = 0;
|
||||
return HASH_VERSION;
|
||||
RETURN_STRING_TOKEN (VERSION_TOKEN);
|
||||
}
|
||||
|
||||
/* Swallow empty #pragma directives, (to avoid confusing the
|
||||
* downstream compiler).
|
||||
*
|
||||
* Note: We use a simple regular expression for the lookahead
|
||||
* here. Specifically, we cannot use the complete {NEWLINE} expression
|
||||
* since it uses alternation and we've found that there's a flex bug
|
||||
* where using alternation in the lookahead portion of a pattern
|
||||
* triggers a buffer overrun. */
|
||||
<HASH>pragma{HSPACE}*/[\r\n] {
|
||||
BEGIN INITIAL;
|
||||
}
|
||||
|
||||
/* glcpp doesn't handle #extension, #version, or #pragma directives.
|
||||
* Simply pass them through to the main compiler's lexer/parser. */
|
||||
{HASH}(extension|pragma)[^\n]+ {
|
||||
if (parser->commented_newlines)
|
||||
BEGIN NEWLINE_CATCHUP;
|
||||
yylval->str = ralloc_strdup (yyextra, yytext);
|
||||
yylineno++;
|
||||
yycolumn = 0;
|
||||
return OTHER;
|
||||
<HASH>(extension|pragma)[^\r\n]* {
|
||||
BEGIN INITIAL;
|
||||
RETURN_STRING_TOKEN (PRAGMA);
|
||||
}
|
||||
|
||||
{HASH}line{HSPACE}+ {
|
||||
return HASH_LINE;
|
||||
<HASH>line{HSPACE}+ {
|
||||
BEGIN INITIAL;
|
||||
RETURN_TOKEN (LINE);
|
||||
}
|
||||
|
||||
<SKIP,INITIAL>{
|
||||
{HASH}ifdef {
|
||||
yyextra->lexing_if = 1;
|
||||
<HASH>{NEWLINE} {
|
||||
BEGIN INITIAL;
|
||||
RETURN_TOKEN_NEVER_SKIP (NEWLINE);
|
||||
}
|
||||
|
||||
/* For the pre-processor directives, we return these tokens
|
||||
* even when we are otherwise skipping. */
|
||||
<HASH>ifdef {
|
||||
BEGIN INITIAL;
|
||||
yyextra->lexing_directive = 1;
|
||||
yyextra->space_tokens = 0;
|
||||
return HASH_IFDEF;
|
||||
RETURN_TOKEN_NEVER_SKIP (IFDEF);
|
||||
}
|
||||
|
||||
{HASH}ifndef {
|
||||
yyextra->lexing_if = 1;
|
||||
<HASH>ifndef {
|
||||
BEGIN INITIAL;
|
||||
yyextra->lexing_directive = 1;
|
||||
yyextra->space_tokens = 0;
|
||||
return HASH_IFNDEF;
|
||||
RETURN_TOKEN_NEVER_SKIP (IFNDEF);
|
||||
}
|
||||
|
||||
{HASH}if/[^_a-zA-Z0-9] {
|
||||
yyextra->lexing_if = 1;
|
||||
<HASH>if/[^_a-zA-Z0-9] {
|
||||
BEGIN INITIAL;
|
||||
yyextra->lexing_directive = 1;
|
||||
yyextra->space_tokens = 0;
|
||||
return HASH_IF;
|
||||
RETURN_TOKEN_NEVER_SKIP (IF);
|
||||
}
|
||||
|
||||
{HASH}elif/[^_a-zA-Z0-9] {
|
||||
yyextra->lexing_if = 1;
|
||||
<HASH>elif/[^_a-zA-Z0-9] {
|
||||
BEGIN INITIAL;
|
||||
yyextra->lexing_directive = 1;
|
||||
yyextra->space_tokens = 0;
|
||||
return HASH_ELIF;
|
||||
RETURN_TOKEN_NEVER_SKIP (ELIF);
|
||||
}
|
||||
|
||||
{HASH}else {
|
||||
<HASH>else {
|
||||
BEGIN INITIAL;
|
||||
yyextra->space_tokens = 0;
|
||||
return HASH_ELSE;
|
||||
RETURN_TOKEN_NEVER_SKIP (ELSE);
|
||||
}
|
||||
|
||||
{HASH}endif {
|
||||
<HASH>endif {
|
||||
BEGIN INITIAL;
|
||||
yyextra->space_tokens = 0;
|
||||
return HASH_ENDIF;
|
||||
}
|
||||
RETURN_TOKEN_NEVER_SKIP (ENDIF);
|
||||
}
|
||||
|
||||
<SKIP>[^\n] {
|
||||
if (parser->commented_newlines)
|
||||
BEGIN NEWLINE_CATCHUP;
|
||||
<HASH>error[^\r\n]* {
|
||||
BEGIN INITIAL;
|
||||
RETURN_STRING_TOKEN (ERROR_TOKEN);
|
||||
}
|
||||
|
||||
{HASH}error.* {
|
||||
char *p;
|
||||
for (p = yytext; !isalpha(p[0]); p++); /* skip " # " */
|
||||
p += 5; /* skip "error" */
|
||||
glcpp_error(yylloc, yyextra, "#error%s", p);
|
||||
/* After we see a "#define" we enter the <DEFINE> start state
|
||||
* for the lexer. Within <DEFINE> we are looking for the first
|
||||
* identifier and specifically checking whether the identifier
|
||||
* is followed by a '(' or not, (to lex either a
|
||||
* FUNC_IDENTIFIER or an OBJ_IDENITIFIER token).
|
||||
*
|
||||
* While in the <DEFINE> state we also need to explicitly
|
||||
* handle a few other things that may appear before the
|
||||
* identifier:
|
||||
*
|
||||
* * Comments, (handled above with the main support for
|
||||
* comments).
|
||||
*
|
||||
* * Whitespace (simply ignored)
|
||||
*
|
||||
* * Anything else, (not an identifier, not a comment,
|
||||
* and not whitespace). This will generate an error.
|
||||
*/
|
||||
<HASH>define{HSPACE}* {
|
||||
if (! parser->skipping) {
|
||||
BEGIN DEFINE;
|
||||
yyextra->space_tokens = 0;
|
||||
RETURN_TOKEN (DEFINE_TOKEN);
|
||||
}
|
||||
}
|
||||
|
||||
{HASH}define{HSPACE}+ {
|
||||
<HASH>undef {
|
||||
BEGIN INITIAL;
|
||||
yyextra->space_tokens = 0;
|
||||
yy_push_state(DEFINE, yyscanner);
|
||||
return HASH_DEFINE;
|
||||
RETURN_TOKEN (UNDEF);
|
||||
}
|
||||
|
||||
<HASH>{HSPACE}+ {
|
||||
/* Nothing to do here. Importantly, don't leave the <HASH>
|
||||
* start condition, since it's legal to have space between the
|
||||
* '#' and the directive.. */
|
||||
}
|
||||
|
||||
/* This will catch any non-directive garbage after a HASH */
|
||||
<HASH>{NONSPACE} {
|
||||
BEGIN INITIAL;
|
||||
RETURN_TOKEN (GARBAGE);
|
||||
}
|
||||
|
||||
/* An identifier immediately followed by '(' */
|
||||
<DEFINE>{IDENTIFIER}/"(" {
|
||||
yy_pop_state(yyscanner);
|
||||
yylval->str = ralloc_strdup (yyextra, yytext);
|
||||
return FUNC_IDENTIFIER;
|
||||
BEGIN INITIAL;
|
||||
RETURN_STRING_TOKEN (FUNC_IDENTIFIER);
|
||||
}
|
||||
|
||||
/* An identifier not immediately followed by '(' */
|
||||
<DEFINE>{IDENTIFIER} {
|
||||
yy_pop_state(yyscanner);
|
||||
yylval->str = ralloc_strdup (yyextra, yytext);
|
||||
return OBJ_IDENTIFIER;
|
||||
BEGIN INITIAL;
|
||||
RETURN_STRING_TOKEN (OBJ_IDENTIFIER);
|
||||
}
|
||||
|
||||
{HASH}undef {
|
||||
yyextra->space_tokens = 0;
|
||||
return HASH_UNDEF;
|
||||
/* Whitespace */
|
||||
<DEFINE>{HSPACE}+ {
|
||||
/* Just ignore it. Nothing to do here. */
|
||||
}
|
||||
|
||||
{HASH} {
|
||||
yyextra->space_tokens = 0;
|
||||
return HASH;
|
||||
/* '/' not followed by '*', so not a comment. This is an error. */
|
||||
<DEFINE>[/][^*]{NONSPACE}* {
|
||||
BEGIN INITIAL;
|
||||
glcpp_error(yylloc, yyextra, "#define followed by a non-identifier: %s", yytext);
|
||||
RETURN_STRING_TOKEN (INTEGER_STRING);
|
||||
}
|
||||
|
||||
/* A character that can't start an identifier, comment, or
|
||||
* space. This is an error. */
|
||||
<DEFINE>[^_a-zA-Z/[:space:]]{NONSPACE}* {
|
||||
BEGIN INITIAL;
|
||||
glcpp_error(yylloc, yyextra, "#define followed by a non-identifier: %s", yytext);
|
||||
RETURN_STRING_TOKEN (INTEGER_STRING);
|
||||
}
|
||||
|
||||
{DECIMAL_INTEGER} {
|
||||
yylval->str = ralloc_strdup (yyextra, yytext);
|
||||
return INTEGER_STRING;
|
||||
RETURN_STRING_TOKEN (INTEGER_STRING);
|
||||
}
|
||||
|
||||
{OCTAL_INTEGER} {
|
||||
yylval->str = ralloc_strdup (yyextra, yytext);
|
||||
return INTEGER_STRING;
|
||||
RETURN_STRING_TOKEN (INTEGER_STRING);
|
||||
}
|
||||
|
||||
{HEXADECIMAL_INTEGER} {
|
||||
yylval->str = ralloc_strdup (yyextra, yytext);
|
||||
return INTEGER_STRING;
|
||||
RETURN_STRING_TOKEN (INTEGER_STRING);
|
||||
}
|
||||
|
||||
"<<" {
|
||||
return LEFT_SHIFT;
|
||||
RETURN_TOKEN (LEFT_SHIFT);
|
||||
}
|
||||
|
||||
">>" {
|
||||
return RIGHT_SHIFT;
|
||||
RETURN_TOKEN (RIGHT_SHIFT);
|
||||
}
|
||||
|
||||
"<=" {
|
||||
return LESS_OR_EQUAL;
|
||||
RETURN_TOKEN (LESS_OR_EQUAL);
|
||||
}
|
||||
|
||||
">=" {
|
||||
return GREATER_OR_EQUAL;
|
||||
RETURN_TOKEN (GREATER_OR_EQUAL);
|
||||
}
|
||||
|
||||
"==" {
|
||||
return EQUAL;
|
||||
RETURN_TOKEN (EQUAL);
|
||||
}
|
||||
|
||||
"!=" {
|
||||
return NOT_EQUAL;
|
||||
RETURN_TOKEN (NOT_EQUAL);
|
||||
}
|
||||
|
||||
"&&" {
|
||||
return AND;
|
||||
RETURN_TOKEN (AND);
|
||||
}
|
||||
|
||||
"||" {
|
||||
return OR;
|
||||
RETURN_TOKEN (OR);
|
||||
}
|
||||
|
||||
"++" {
|
||||
RETURN_TOKEN (PLUS_PLUS);
|
||||
}
|
||||
|
||||
"--" {
|
||||
RETURN_TOKEN (MINUS_MINUS);
|
||||
}
|
||||
|
||||
"##" {
|
||||
if (parser->is_gles)
|
||||
glcpp_error(yylloc, yyextra, "Token pasting (##) is illegal in GLES");
|
||||
return PASTE;
|
||||
if (! parser->skipping) {
|
||||
if (parser->is_gles)
|
||||
glcpp_error(yylloc, yyextra, "Token pasting (##) is illegal in GLES");
|
||||
RETURN_TOKEN (PASTE);
|
||||
}
|
||||
}
|
||||
|
||||
"defined" {
|
||||
return DEFINED;
|
||||
RETURN_TOKEN (DEFINED);
|
||||
}
|
||||
|
||||
{IDENTIFIER} {
|
||||
yylval->str = ralloc_strdup (yyextra, yytext);
|
||||
return IDENTIFIER;
|
||||
RETURN_STRING_TOKEN (IDENTIFIER);
|
||||
}
|
||||
|
||||
{PP_NUMBER} {
|
||||
RETURN_STRING_TOKEN (OTHER);
|
||||
}
|
||||
|
||||
{PUNCTUATION} {
|
||||
return yytext[0];
|
||||
RETURN_TOKEN (yytext[0]);
|
||||
}
|
||||
|
||||
{OTHER}+ {
|
||||
yylval->str = ralloc_strdup (yyextra, yytext);
|
||||
return OTHER;
|
||||
RETURN_STRING_TOKEN (OTHER);
|
||||
}
|
||||
|
||||
{HSPACE}+ {
|
||||
{HSPACE} {
|
||||
if (yyextra->space_tokens) {
|
||||
return SPACE;
|
||||
RETURN_TOKEN (SPACE);
|
||||
}
|
||||
}
|
||||
|
||||
<SKIP,INITIAL>\n {
|
||||
/* We preserve all newlines, even between #if 0..#endif, so no
|
||||
skipping.. */
|
||||
<*>{NEWLINE} {
|
||||
if (parser->commented_newlines) {
|
||||
BEGIN NEWLINE_CATCHUP;
|
||||
} else {
|
||||
BEGIN INITIAL;
|
||||
}
|
||||
yyextra->lexing_if = 0;
|
||||
yyextra->space_tokens = 1;
|
||||
yyextra->lexing_directive = 0;
|
||||
yylineno++;
|
||||
yycolumn = 0;
|
||||
return NEWLINE;
|
||||
RETURN_TOKEN_NEVER_SKIP (NEWLINE);
|
||||
}
|
||||
|
||||
/* Handle missing newline at EOF. */
|
||||
<INITIAL><<EOF>> {
|
||||
<INITIAL,COMMENT,DEFINE,HASH><<EOF>> {
|
||||
if (YY_START == COMMENT)
|
||||
glcpp_error(yylloc, yyextra, "Unterminated comment");
|
||||
BEGIN DONE; /* Don't keep matching this rule forever. */
|
||||
yyextra->lexing_if = 0;
|
||||
return NEWLINE;
|
||||
yyextra->lexing_directive = 0;
|
||||
if (! parser->last_token_was_newline)
|
||||
RETURN_TOKEN (NEWLINE);
|
||||
}
|
||||
|
||||
/* This is a catch-all to avoid the annoying default flex action which
|
||||
* matches any character and prints it. If any input ever matches this
|
||||
* rule, then we have made a mistake above and need to fix one or more
|
||||
* of the preceding patterns to match that input. */
|
||||
|
||||
<*>. {
|
||||
glcpp_error(yylloc, yyextra, "Internal compiler error: Unexpected character: %s", yytext);
|
||||
|
||||
/* We don't actually use the UNREACHABLE start condition. We
|
||||
only have this action here so that we can pretend to call some
|
||||
only have this block here so that we can pretend to call some
|
||||
generated functions, (to avoid "defined but not used"
|
||||
warnings. */
|
||||
<UNREACHABLE>. {
|
||||
unput('.');
|
||||
yy_top_state(yyextra);
|
||||
if (YY_START == UNREACHABLE) {
|
||||
unput('.');
|
||||
yy_top_state(yyextra);
|
||||
}
|
||||
}
|
||||
|
||||
%%
|
||||
|
||||
2013
3rdparty/glsl-optimizer/src/glsl/glcpp/glcpp-parse.c
vendored
2013
3rdparty/glsl-optimizer/src/glsl/glcpp/glcpp-parse.c
vendored
File diff suppressed because it is too large
Load Diff
@@ -34,7 +34,7 @@
|
||||
# define YY_GLCPP_PARSER_SRC_GLSL_GLCPP_GLCPP_PARSE_H_INCLUDED
|
||||
/* Debug traces. */
|
||||
#ifndef YYDEBUG
|
||||
# define YYDEBUG 0
|
||||
# define YYDEBUG 1
|
||||
#endif
|
||||
#if YYDEBUG
|
||||
extern int glcpp_parser_debug;
|
||||
@@ -45,41 +45,45 @@ extern int glcpp_parser_debug;
|
||||
# define YYTOKENTYPE
|
||||
enum yytokentype
|
||||
{
|
||||
COMMA_FINAL = 258,
|
||||
DEFINED = 259,
|
||||
ELIF_EXPANDED = 260,
|
||||
HASH = 261,
|
||||
HASH_DEFINE = 262,
|
||||
FUNC_IDENTIFIER = 263,
|
||||
OBJ_IDENTIFIER = 264,
|
||||
HASH_ELIF = 265,
|
||||
HASH_ELSE = 266,
|
||||
HASH_ENDIF = 267,
|
||||
HASH_IF = 268,
|
||||
HASH_IFDEF = 269,
|
||||
HASH_IFNDEF = 270,
|
||||
HASH_LINE = 271,
|
||||
HASH_UNDEF = 272,
|
||||
HASH_VERSION = 273,
|
||||
IDENTIFIER = 274,
|
||||
IF_EXPANDED = 275,
|
||||
INTEGER = 276,
|
||||
INTEGER_STRING = 277,
|
||||
LINE_EXPANDED = 278,
|
||||
NEWLINE = 279,
|
||||
OTHER = 280,
|
||||
PLACEHOLDER = 281,
|
||||
SPACE = 282,
|
||||
PASTE = 283,
|
||||
OR = 284,
|
||||
AND = 285,
|
||||
EQUAL = 286,
|
||||
NOT_EQUAL = 287,
|
||||
LESS_OR_EQUAL = 288,
|
||||
GREATER_OR_EQUAL = 289,
|
||||
LEFT_SHIFT = 290,
|
||||
RIGHT_SHIFT = 291,
|
||||
UNARY = 292
|
||||
DEFINED = 258,
|
||||
ELIF_EXPANDED = 259,
|
||||
HASH_TOKEN = 260,
|
||||
DEFINE_TOKEN = 261,
|
||||
FUNC_IDENTIFIER = 262,
|
||||
OBJ_IDENTIFIER = 263,
|
||||
ELIF = 264,
|
||||
ELSE = 265,
|
||||
ENDIF = 266,
|
||||
ERROR_TOKEN = 267,
|
||||
IF = 268,
|
||||
IFDEF = 269,
|
||||
IFNDEF = 270,
|
||||
LINE = 271,
|
||||
PRAGMA = 272,
|
||||
UNDEF = 273,
|
||||
VERSION_TOKEN = 274,
|
||||
GARBAGE = 275,
|
||||
IDENTIFIER = 276,
|
||||
IF_EXPANDED = 277,
|
||||
INTEGER = 278,
|
||||
INTEGER_STRING = 279,
|
||||
LINE_EXPANDED = 280,
|
||||
NEWLINE = 281,
|
||||
OTHER = 282,
|
||||
PLACEHOLDER = 283,
|
||||
SPACE = 284,
|
||||
PLUS_PLUS = 285,
|
||||
MINUS_MINUS = 286,
|
||||
PASTE = 287,
|
||||
OR = 288,
|
||||
AND = 289,
|
||||
EQUAL = 290,
|
||||
NOT_EQUAL = 291,
|
||||
LESS_OR_EQUAL = 292,
|
||||
GREATER_OR_EQUAL = 293,
|
||||
LEFT_SHIFT = 294,
|
||||
RIGHT_SHIFT = 295,
|
||||
UNARY = 296
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
641
3rdparty/glsl-optimizer/src/glsl/glcpp/glcpp-parse.y
vendored
641
3rdparty/glsl-optimizer/src/glsl/glcpp/glcpp-parse.y
vendored
File diff suppressed because it is too large
Load Diff
15
3rdparty/glsl-optimizer/src/glsl/glcpp/glcpp.h
vendored
15
3rdparty/glsl-optimizer/src/glsl/glcpp/glcpp.h
vendored
@@ -29,7 +29,7 @@
|
||||
|
||||
#include "main/mtypes.h"
|
||||
|
||||
#include "../ralloc.h"
|
||||
#include "util/ralloc.h"
|
||||
|
||||
#include "program/hash_table.h"
|
||||
|
||||
@@ -37,6 +37,12 @@
|
||||
|
||||
/* Some data types used for parser values. */
|
||||
|
||||
typedef struct expression_value {
|
||||
intmax_t value;
|
||||
char *undefined_macro;
|
||||
} expression_value_t;
|
||||
|
||||
|
||||
typedef struct string_node {
|
||||
const char *str;
|
||||
struct string_node *next;
|
||||
@@ -55,6 +61,7 @@ typedef union YYSTYPE
|
||||
// Could be int, but results in some bugs with parsing of #version directives
|
||||
// in Apple LLVM Compiler 4.2 when building for 32 bit.
|
||||
intmax_t ival;
|
||||
expression_value_t expression_value;
|
||||
char *str;
|
||||
string_list_t *string_list;
|
||||
token_t *token;
|
||||
@@ -170,13 +177,17 @@ struct glcpp_parser {
|
||||
yyscan_t scanner;
|
||||
struct hash_table *defines;
|
||||
active_list_t *active;
|
||||
int lexing_if;
|
||||
int lexing_directive;
|
||||
int space_tokens;
|
||||
int last_token_was_newline;
|
||||
int last_token_was_space;
|
||||
int first_non_space_token_this_line;
|
||||
int newline_as_space;
|
||||
int in_control_line;
|
||||
int paren_count;
|
||||
int commented_newlines;
|
||||
skip_node_t *skip_stack;
|
||||
int skipping;
|
||||
token_list_t *lex_from_list;
|
||||
token_node_t *lex_from_node;
|
||||
char *output;
|
||||
|
||||
96
3rdparty/glsl-optimizer/src/glsl/glcpp/pp.c
vendored
96
3rdparty/glsl-optimizer/src/glsl/glcpp/pp.c
vendored
@@ -70,6 +70,42 @@ glcpp_warning (YYLTYPE *locp, glcpp_parser_t *parser, const char *fmt, ...)
|
||||
&parser->info_log_length, "\n");
|
||||
}
|
||||
|
||||
/* Given str, (that's expected to start with a newline terminator of some
|
||||
* sort), return a pointer to the first character in str after the newline.
|
||||
*
|
||||
* A newline terminator can be any of the following sequences:
|
||||
*
|
||||
* "\r\n"
|
||||
* "\n\r"
|
||||
* "\n"
|
||||
* "\r"
|
||||
*
|
||||
* And the longest such sequence will be skipped.
|
||||
*/
|
||||
static const char *
|
||||
skip_newline (const char *str)
|
||||
{
|
||||
const char *ret = str;
|
||||
|
||||
if (ret == NULL)
|
||||
return ret;
|
||||
|
||||
if (*ret == '\0')
|
||||
return ret;
|
||||
|
||||
if (*ret == '\r') {
|
||||
ret++;
|
||||
if (*ret && *ret == '\n')
|
||||
ret++;
|
||||
} else if (*ret == '\n') {
|
||||
ret++;
|
||||
if (*ret && *ret == '\r')
|
||||
ret++;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Remove any line continuation characters in the shader, (whether in
|
||||
* preprocessing directives or in GLSL code).
|
||||
*/
|
||||
@@ -78,10 +114,49 @@ remove_line_continuations(glcpp_parser_t *ctx, const char *shader)
|
||||
{
|
||||
char *clean = ralloc_strdup(ctx, "");
|
||||
const char *backslash, *newline, *search_start;
|
||||
const char *cr, *lf;
|
||||
char newline_separator[3];
|
||||
int collapsed_newlines = 0;
|
||||
|
||||
search_start = shader;
|
||||
|
||||
/* Determine what flavor of newlines this shader is using. GLSL
|
||||
* provides for 4 different possible ways to separate lines, (using
|
||||
* one or two characters):
|
||||
*
|
||||
* "\n" (line-feed, like Linux, Unix, and new Mac OS)
|
||||
* "\r" (carriage-return, like old Mac files)
|
||||
* "\r\n" (carriage-return + line-feed, like DOS files)
|
||||
* "\n\r" (line-feed + carriage-return, like nothing, really)
|
||||
*
|
||||
* This code explicitly supports a shader that uses a mixture of
|
||||
* newline terminators and will properly handle line continuation
|
||||
* backslashes followed by any of the above.
|
||||
*
|
||||
* But, since we must also insert additional newlines in the output
|
||||
* (for any collapsed lines) we attempt to maintain consistency by
|
||||
* examining the first encountered newline terminator, and using the
|
||||
* same terminator for any newlines we insert.
|
||||
*/
|
||||
cr = strchr(search_start, '\r');
|
||||
lf = strchr(search_start, '\n');
|
||||
|
||||
newline_separator[0] = '\n';
|
||||
newline_separator[1] = '\0';
|
||||
newline_separator[2] = '\0';
|
||||
|
||||
if (cr == NULL) {
|
||||
/* Nothing to do. */
|
||||
} else if (lf == NULL) {
|
||||
newline_separator[0] = '\r';
|
||||
} else if (lf == cr + 1) {
|
||||
newline_separator[0] = '\r';
|
||||
newline_separator[1] = '\n';
|
||||
} else if (cr == lf + 1) {
|
||||
newline_separator[0] = '\n';
|
||||
newline_separator[1] = '\r';
|
||||
}
|
||||
|
||||
while (true) {
|
||||
backslash = strchr(search_start, '\\');
|
||||
|
||||
@@ -91,17 +166,24 @@ remove_line_continuations(glcpp_parser_t *ctx, const char *shader)
|
||||
* line numbers.
|
||||
*/
|
||||
if (collapsed_newlines) {
|
||||
newline = strchr(search_start, '\n');
|
||||
cr = strchr (search_start, '\r');
|
||||
lf = strchr (search_start, '\n');
|
||||
if (cr && lf)
|
||||
newline = cr < lf ? cr : lf;
|
||||
else if (cr)
|
||||
newline = cr;
|
||||
else
|
||||
newline = lf;
|
||||
if (newline &&
|
||||
(backslash == NULL || newline < backslash))
|
||||
{
|
||||
ralloc_strncat(&clean, shader,
|
||||
newline - shader + 1);
|
||||
while (collapsed_newlines) {
|
||||
ralloc_strcat(&clean, "\n");
|
||||
ralloc_strcat(&clean, newline_separator);
|
||||
collapsed_newlines--;
|
||||
}
|
||||
shader = newline + 1;
|
||||
shader = skip_newline (newline);
|
||||
search_start = shader;
|
||||
}
|
||||
}
|
||||
@@ -116,15 +198,11 @@ remove_line_continuations(glcpp_parser_t *ctx, const char *shader)
|
||||
* advance the shader pointer to the character after the
|
||||
* newline.
|
||||
*/
|
||||
if (backslash[1] == '\n' ||
|
||||
(backslash[1] == '\r' && backslash[2] == '\n'))
|
||||
if (backslash[1] == '\r' || backslash[1] == '\n')
|
||||
{
|
||||
collapsed_newlines++;
|
||||
ralloc_strncat(&clean, shader, backslash - shader);
|
||||
if (backslash[1] == '\n')
|
||||
shader = backslash + 2;
|
||||
else
|
||||
shader = backslash + 3;
|
||||
shader = skip_newline (backslash + 1);
|
||||
search_start = shader;
|
||||
}
|
||||
}
|
||||
|
||||
2098
3rdparty/glsl-optimizer/src/glsl/glsl_lexer.cpp
vendored
2098
3rdparty/glsl-optimizer/src/glsl/glsl_lexer.cpp
vendored
File diff suppressed because it is too large
Load Diff
32
3rdparty/glsl-optimizer/src/glsl/glsl_lexer.ll
vendored
32
3rdparty/glsl-optimizer/src/glsl/glsl_lexer.ll
vendored
@@ -44,8 +44,9 @@ static int classify_identifier(struct _mesa_glsl_parse_state *, const char *);
|
||||
do { \
|
||||
yylloc->source = 0; \
|
||||
yylloc->first_column = yycolumn + 1; \
|
||||
yylloc->first_line = yylineno + 1; \
|
||||
yylloc->first_line = yylloc->last_line = yylineno + 1; \
|
||||
yycolumn += yyleng; \
|
||||
yylloc->last_column = yycolumn + 1; \
|
||||
} while(0);
|
||||
|
||||
#define YY_USER_INIT yylineno = 0; yycolumn = 0;
|
||||
@@ -86,7 +87,8 @@ static int classify_identifier(struct _mesa_glsl_parse_state *, const char *);
|
||||
"illegal use of reserved word `%s'", yytext); \
|
||||
return ERROR_TOK; \
|
||||
} else { \
|
||||
yylval->identifier = strdup(yytext); \
|
||||
void *mem_ctx = yyextra; \
|
||||
yylval->identifier = ralloc_strdup(mem_ctx, yytext); \
|
||||
return classify_identifier(yyextra, yytext); \
|
||||
} \
|
||||
} while (0)
|
||||
@@ -157,7 +159,11 @@ literal_integer(char *text, int len, struct _mesa_glsl_parse_state *state,
|
||||
%option never-interactive
|
||||
%option prefix="_mesa_glsl_lexer_"
|
||||
%option extra-type="struct _mesa_glsl_parse_state *"
|
||||
%option warn nodefault
|
||||
|
||||
/* Note: When adding any start conditions to this list, you must also
|
||||
* update the "Internal compiler error" catch-all rule near the end of
|
||||
* this file. */
|
||||
%x PP PRAGMA
|
||||
|
||||
DEC_INT [1-9][0-9]*
|
||||
@@ -233,7 +239,8 @@ HASH ^{SPC}#{SPC}
|
||||
<PP>[ \t\r]* { }
|
||||
<PP>: return COLON;
|
||||
<PP>[_a-zA-Z][_a-zA-Z0-9]* {
|
||||
yylval->identifier = strdup(yytext);
|
||||
void *mem_ctx = yyextra;
|
||||
yylval->identifier = ralloc_strdup(mem_ctx, yytext);
|
||||
return IDENTIFIER;
|
||||
}
|
||||
<PP>[1-9][0-9]* {
|
||||
@@ -241,6 +248,7 @@ HASH ^{SPC}#{SPC}
|
||||
return INTCONSTANT;
|
||||
}
|
||||
<PP>\n { BEGIN 0; yylineno++; yycolumn = 0; return EOL; }
|
||||
<PP>. { return yytext[0]; }
|
||||
|
||||
\n { yylineno++; yycolumn = 0; }
|
||||
|
||||
@@ -291,11 +299,11 @@ out return OUT_TOK;
|
||||
inout return INOUT_TOK;
|
||||
uniform return UNIFORM;
|
||||
varying DEPRECATED_ES_KEYWORD(VARYING);
|
||||
centroid KEYWORD(120, 100, 120, 100, CENTROID);
|
||||
invariant KEYWORD(120, 100, 120, 100, INVARIANT);
|
||||
flat KEYWORD(120, 100, 120, 100, FLAT);
|
||||
smooth KEYWORD(120, 100, 120, 100, SMOOTH);
|
||||
noperspective KEYWORD(120, 100, 120, 100, NOPERSPECTIVE);
|
||||
centroid KEYWORD(120, 300, 120, 300, CENTROID);
|
||||
invariant KEYWORD(120, 100, 120, 100, INVARIANT);
|
||||
flat KEYWORD(130, 100, 130, 300, FLAT);
|
||||
smooth KEYWORD(130, 300, 130, 300, SMOOTH);
|
||||
noperspective KEYWORD(130, 300, 130, 0, NOPERSPECTIVE);
|
||||
|
||||
sampler1D DEPRECATED_ES_KEYWORD(SAMPLER1D);
|
||||
sampler2D return SAMPLER2D;
|
||||
@@ -343,6 +351,9 @@ samplerExternalOES {
|
||||
return IDENTIFIER;
|
||||
}
|
||||
|
||||
/* keywords available with ARB_gpu_shader5 */
|
||||
precise KEYWORD_WITH_ALT(400, 0, 400, 0, yyextra->ARB_gpu_shader5_enable, PRECISE);
|
||||
|
||||
/* keywords available with ARB_shader_image_load_store */
|
||||
image1D KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IMAGE1D);
|
||||
image2D KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IMAGE2D);
|
||||
@@ -398,13 +409,16 @@ layout {
|
||||
|| yyextra->AMD_conservative_depth_enable
|
||||
|| yyextra->ARB_conservative_depth_enable
|
||||
|| yyextra->ARB_explicit_attrib_location_enable
|
||||
|| yyextra->ARB_explicit_uniform_location_enable
|
||||
|| yyextra->has_separate_shader_objects()
|
||||
|| yyextra->ARB_uniform_buffer_object_enable
|
||||
|| yyextra->ARB_fragment_coord_conventions_enable
|
||||
|| yyextra->ARB_shading_language_420pack_enable
|
||||
|| yyextra->ARB_compute_shader_enable) {
|
||||
return LAYOUT_TOK;
|
||||
} else {
|
||||
yylval->identifier = strdup(yytext);
|
||||
void *mem_ctx = yyextra;
|
||||
yylval->identifier = ralloc_strdup(mem_ctx, yytext);
|
||||
return classify_identifier(yyextra, yytext);
|
||||
}
|
||||
}
|
||||
|
||||
266
3rdparty/glsl-optimizer/src/glsl/glsl_optimizer.cpp
vendored
266
3rdparty/glsl-optimizer/src/glsl/glsl_optimizer.cpp
vendored
@@ -3,6 +3,7 @@
|
||||
#include "glsl_parser_extras.h"
|
||||
#include "glsl_parser.h"
|
||||
#include "ir_optimization.h"
|
||||
#include "ir_print_metal_visitor.h"
|
||||
#include "ir_print_glsl_visitor.h"
|
||||
#include "ir_print_visitor.h"
|
||||
#include "ir_stats.h"
|
||||
@@ -37,6 +38,9 @@ initialize_mesa_context(struct gl_context *ctx, glslopt_target api)
|
||||
case kGlslTargetOpenGLES30:
|
||||
mesaAPI = API_OPENGL_CORE;
|
||||
break;
|
||||
case kGlslTargetMetal:
|
||||
mesaAPI = API_OPENGL_CORE;
|
||||
break;
|
||||
}
|
||||
initialize_context_to_defaults (ctx, mesaAPI);
|
||||
|
||||
@@ -50,12 +54,18 @@ initialize_mesa_context(struct gl_context *ctx, glslopt_target api)
|
||||
ctx->Extensions.OES_standard_derivatives = true;
|
||||
ctx->Extensions.EXT_shadow_samplers = true;
|
||||
ctx->Extensions.EXT_frag_depth = true;
|
||||
ctx->Extensions.EXT_shader_framebuffer_fetch = true;
|
||||
break;
|
||||
case kGlslTargetOpenGLES30:
|
||||
ctx->Extensions.ARB_ES3_compatibility = true;
|
||||
ctx->Extensions.EXT_shader_framebuffer_fetch = true;
|
||||
break;
|
||||
case kGlslTargetMetal:
|
||||
ctx->Extensions.ARB_ES3_compatibility = true;
|
||||
ctx->Extensions.EXT_shader_framebuffer_fetch = true;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// allow high amount of texcoords
|
||||
ctx->Const.MaxTextureCoordUnits = 16;
|
||||
@@ -64,6 +74,7 @@ initialize_mesa_context(struct gl_context *ctx, glslopt_target api)
|
||||
ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxTextureImageUnits = 16;
|
||||
ctx->Const.Program[MESA_SHADER_GEOMETRY].MaxTextureImageUnits = 16;
|
||||
|
||||
// For GLES2.0 this would be 1, but we do support GL_EXT_draw_buffers
|
||||
ctx->Const.MaxDrawBuffers = 8;
|
||||
|
||||
ctx->Driver.NewShader = _mesa_new_shader;
|
||||
@@ -73,16 +84,16 @@ initialize_mesa_context(struct gl_context *ctx, glslopt_target api)
|
||||
|
||||
struct glslopt_ctx {
|
||||
glslopt_ctx (glslopt_target target) {
|
||||
this->target = target;
|
||||
mem_ctx = ralloc_context (NULL);
|
||||
initialize_mesa_context (&mesa_ctx, target);
|
||||
max_unroll_iterations = 8;
|
||||
}
|
||||
~glslopt_ctx() {
|
||||
ralloc_free (mem_ctx);
|
||||
}
|
||||
struct gl_context mesa_ctx;
|
||||
void* mem_ctx;
|
||||
unsigned int max_unroll_iterations;
|
||||
glslopt_target target;
|
||||
};
|
||||
|
||||
glslopt_ctx* glslopt_initialize (glslopt_target target)
|
||||
@@ -98,12 +109,19 @@ void glslopt_cleanup (glslopt_ctx* ctx)
|
||||
|
||||
void glslopt_set_max_unroll_iterations (glslopt_ctx* ctx, unsigned iterations)
|
||||
{
|
||||
ctx->max_unroll_iterations = iterations;
|
||||
for (int i = 0; i < MESA_SHADER_STAGES; ++i)
|
||||
ctx->mesa_ctx.Const.ShaderCompilerOptions[i].MaxUnrollIterations = iterations;
|
||||
}
|
||||
|
||||
struct glslopt_shader_input
|
||||
struct glslopt_shader_var
|
||||
{
|
||||
const char* name;
|
||||
glslopt_basic_type type;
|
||||
glslopt_precision prec;
|
||||
int vectorSize;
|
||||
int matrixSize;
|
||||
int arraySize;
|
||||
int location;
|
||||
};
|
||||
|
||||
struct glslopt_shader
|
||||
@@ -124,7 +142,10 @@ struct glslopt_shader
|
||||
: rawOutput(0)
|
||||
, optimizedOutput(0)
|
||||
, status(false)
|
||||
, uniformCount(0)
|
||||
, uniformsSize(0)
|
||||
, inputCount(0)
|
||||
, textureCount(0)
|
||||
, statsMath(0)
|
||||
, statsTex(0)
|
||||
, statsFlow(0)
|
||||
@@ -157,9 +178,15 @@ struct glslopt_shader
|
||||
struct gl_shader_program* whole_program;
|
||||
struct gl_shader* shader;
|
||||
|
||||
static const int kMaxShaderUniforms = 1024;
|
||||
static const int kMaxShaderInputs = 128;
|
||||
glslopt_shader_input inputs[kMaxShaderInputs];
|
||||
static const int kMaxShaderTextures = 128;
|
||||
glslopt_shader_var uniforms[kMaxShaderUniforms];
|
||||
glslopt_shader_var inputs[kMaxShaderInputs];
|
||||
glslopt_shader_var textures[kMaxShaderInputs];
|
||||
int uniformCount, uniformsSize;
|
||||
int inputCount;
|
||||
int textureCount;
|
||||
int statsMath, statsTex, statsFlow;
|
||||
|
||||
char* rawOutput;
|
||||
@@ -172,7 +199,7 @@ static inline void debug_print_ir (const char* name, exec_list* ir, _mesa_glsl_p
|
||||
{
|
||||
#if 0
|
||||
printf("**** %s:\n", name);
|
||||
//_mesa_print_ir (ir, state);
|
||||
// _mesa_print_ir (ir, state);
|
||||
char* foobar = _mesa_print_ir_glsl(ir, state, ralloc_strdup(memctx, ""), kPrintGlslFragment);
|
||||
printf("%s\n", foobar);
|
||||
validate_ir_tree(ir);
|
||||
@@ -181,14 +208,23 @@ static inline void debug_print_ir (const char* name, exec_list* ir, _mesa_glsl_p
|
||||
|
||||
static void propagate_precision_deref(ir_instruction *ir, void *data)
|
||||
{
|
||||
// variable -> deference
|
||||
// variable deref with undefined precision: take from variable itself
|
||||
ir_dereference_variable* der = ir->as_dereference_variable();
|
||||
if (der && der->get_precision() == glsl_precision_undefined && der->var->data.precision != glsl_precision_undefined)
|
||||
{
|
||||
der->set_precision ((glsl_precision)der->var->data.precision);
|
||||
*(bool*)data = true;
|
||||
}
|
||||
// swizzle value -> swizzle
|
||||
|
||||
// array deref with undefined precision: take from array itself
|
||||
ir_dereference_array* der_arr = ir->as_dereference_array();
|
||||
if (der_arr && der_arr->get_precision() == glsl_precision_undefined && der_arr->array->get_precision() != glsl_precision_undefined)
|
||||
{
|
||||
der_arr->set_precision (der_arr->array->get_precision());
|
||||
*(bool*)data = true;
|
||||
}
|
||||
|
||||
// swizzle with undefined precision: take from swizzle argument
|
||||
ir_swizzle* swz = ir->as_swizzle();
|
||||
if (swz && swz->get_precision() == glsl_precision_undefined && swz->val->get_precision() != glsl_precision_undefined)
|
||||
{
|
||||
@@ -272,14 +308,14 @@ static void propagate_precision_call(ir_instruction *ir, void *data)
|
||||
}
|
||||
|
||||
|
||||
static bool propagate_precision(exec_list* list)
|
||||
static bool propagate_precision(exec_list* list, bool assign_high_to_undefined)
|
||||
{
|
||||
bool anyProgress = false;
|
||||
bool res;
|
||||
do {
|
||||
res = false;
|
||||
foreach_list(node, list) {
|
||||
ir_instruction* ir = (ir_instruction*)node;
|
||||
foreach_in_list(ir_instruction, ir, list)
|
||||
{
|
||||
visit_tree (ir, propagate_precision_deref, &res);
|
||||
visit_tree (ir, propagate_precision_assign, &res);
|
||||
visit_tree (ir, propagate_precision_call, &res);
|
||||
@@ -287,11 +323,30 @@ static bool propagate_precision(exec_list* list)
|
||||
}
|
||||
anyProgress |= res;
|
||||
} while (res);
|
||||
anyProgress |= res;
|
||||
|
||||
// for globals that have undefined precision, set it to highp
|
||||
if (assign_high_to_undefined)
|
||||
{
|
||||
foreach_in_list(ir_instruction, ir, list)
|
||||
{
|
||||
ir_variable* var = ir->as_variable();
|
||||
if (var)
|
||||
{
|
||||
if (var->data.precision == glsl_precision_undefined)
|
||||
{
|
||||
var->data.precision = glsl_precision_high;
|
||||
anyProgress = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return anyProgress;
|
||||
}
|
||||
|
||||
|
||||
static void do_optimization_passes(exec_list* ir, bool linked, unsigned max_unroll_iterations, _mesa_glsl_parse_state* state, void* mem_ctx)
|
||||
static void do_optimization_passes(exec_list* ir, bool linked, _mesa_glsl_parse_state* state, void* mem_ctx)
|
||||
{
|
||||
bool progress;
|
||||
do {
|
||||
@@ -305,9 +360,14 @@ static void do_optimization_passes(exec_list* ir, bool linked, unsigned max_unro
|
||||
}
|
||||
progress2 = do_if_simplification(ir); progress |= progress2; if (progress2) debug_print_ir ("After if simpl", ir, state, mem_ctx);
|
||||
progress2 = opt_flatten_nested_if_blocks(ir); progress |= progress2; if (progress2) debug_print_ir ("After if flatten", ir, state, mem_ctx);
|
||||
progress2 = propagate_precision (ir); progress |= progress2; if (progress2) debug_print_ir ("After prec propagation", ir, state, mem_ctx);
|
||||
progress2 = propagate_precision (ir, state->metal_target); progress |= progress2; if (progress2) debug_print_ir ("After prec propagation", ir, state, mem_ctx);
|
||||
progress2 = do_copy_propagation(ir); progress |= progress2; if (progress2) debug_print_ir ("After copy propagation", ir, state, mem_ctx);
|
||||
progress2 = do_copy_propagation_elements(ir); progress |= progress2; if (progress2) debug_print_ir ("After copy propagation elems", ir, state, mem_ctx);
|
||||
if (state->es_shader && linked)
|
||||
{
|
||||
progress2 = optimize_split_vectors(ir, linked, OPT_SPLIT_ONLY_LOOP_INDUCTORS); progress |= progress2; if (progress2) debug_print_ir("After split vectors", ir, state, mem_ctx);
|
||||
}
|
||||
|
||||
if (linked)
|
||||
{
|
||||
progress2 = do_vectorize(ir); progress |= progress2; if (progress2) debug_print_ir ("After vectorize", ir, state, mem_ctx);
|
||||
@@ -318,7 +378,7 @@ static void do_optimization_passes(exec_list* ir, bool linked, unsigned max_unro
|
||||
progress2 = do_dead_code_unlinked(ir); progress |= progress2; if (progress2) debug_print_ir ("After dead code unlinked", ir, state, mem_ctx);
|
||||
}
|
||||
progress2 = do_dead_code_local(ir); progress |= progress2; if (progress2) debug_print_ir ("After dead code local", ir, state, mem_ctx);
|
||||
progress2 = propagate_precision (ir); progress |= progress2; if (progress2) debug_print_ir ("After prec propagation", ir, state, mem_ctx);
|
||||
progress2 = propagate_precision (ir, state->metal_target); progress |= progress2; if (progress2) debug_print_ir ("After prec propagation", ir, state, mem_ctx);
|
||||
progress2 = do_tree_grafting(ir); progress |= progress2; if (progress2) debug_print_ir ("After tree grafting", ir, state, mem_ctx);
|
||||
progress2 = do_constant_propagation(ir); progress |= progress2; if (progress2) debug_print_ir ("After const propagation", ir, state, mem_ctx);
|
||||
if (linked) {
|
||||
@@ -327,15 +387,19 @@ static void do_optimization_passes(exec_list* ir, bool linked, unsigned max_unro
|
||||
progress2 = do_constant_variable_unlinked(ir); progress |= progress2; if (progress2) debug_print_ir ("After const variable unlinked", ir, state, mem_ctx);
|
||||
}
|
||||
progress2 = do_constant_folding(ir); progress |= progress2; if (progress2) debug_print_ir ("After const folding", ir, state, mem_ctx);
|
||||
progress2 = do_minmax_prune(ir); progress |= progress2; if (progress2) debug_print_ir ("After minmax prune", ir, state, mem_ctx);
|
||||
progress2 = do_cse(ir); progress |= progress2; if (progress2) debug_print_ir ("After CSE", ir, state, mem_ctx);
|
||||
progress2 = do_algebraic(ir); progress |= progress2; if (progress2) debug_print_ir ("After algebraic", ir, state, mem_ctx);
|
||||
progress2 = do_rebalance_tree(ir); progress |= progress2; if (progress2) debug_print_ir ("After rebalance tree", ir, state, mem_ctx);
|
||||
progress2 = do_algebraic(ir, state->ctx->Const.NativeIntegers, &state->ctx->Const.ShaderCompilerOptions[state->stage]); progress |= progress2; if (progress2) debug_print_ir ("After algebraic", ir, state, mem_ctx);
|
||||
progress2 = do_lower_jumps(ir); progress |= progress2; if (progress2) debug_print_ir ("After lower jumps", ir, state, mem_ctx);
|
||||
progress2 = do_vec_index_to_swizzle(ir); progress |= progress2; if (progress2) debug_print_ir ("After vec index to swizzle", ir, state, mem_ctx);
|
||||
progress2 = lower_vector_insert(ir, false); progress |= progress2; if (progress2) debug_print_ir ("After lower vector insert", ir, state, mem_ctx);
|
||||
progress2 = do_swizzle_swizzle(ir); progress |= progress2; if (progress2) debug_print_ir ("After swizzle swizzle", ir, state, mem_ctx);
|
||||
progress2 = do_noop_swizzle(ir); progress |= progress2; if (progress2) debug_print_ir ("After noop swizzle", ir, state, mem_ctx);
|
||||
progress2 = optimize_split_arrays(ir, linked); progress |= progress2; if (progress2) debug_print_ir ("After split arrays", ir, state, mem_ctx);
|
||||
progress2 = optimize_split_arrays(ir, linked, state->metal_target && state->stage == MESA_SHADER_FRAGMENT); progress |= progress2; if (progress2) debug_print_ir ("After split arrays", ir, state, mem_ctx);
|
||||
progress2 = optimize_split_vectors(ir, linked, OPT_SPLIT_ONLY_UNUSED); progress |= progress2; if (progress2) debug_print_ir("After split unused vectors", ir, state, mem_ctx);
|
||||
progress2 = optimize_redundant_jumps(ir); progress |= progress2; if (progress2) debug_print_ir ("After redundant jumps", ir, state, mem_ctx);
|
||||
|
||||
|
||||
// do loop stuff only when linked; otherwise causes duplicate loop induction variable
|
||||
// problems (ast-in.txt test)
|
||||
if (linked)
|
||||
@@ -343,27 +407,101 @@ static void do_optimization_passes(exec_list* ir, bool linked, unsigned max_unro
|
||||
loop_state *ls = analyze_loop_variables(ir);
|
||||
if (ls->loop_found) {
|
||||
progress2 = set_loop_controls(ir, ls); progress |= progress2; if (progress2) debug_print_ir ("After set loop", ir, state, mem_ctx);
|
||||
progress2 = unroll_loops(ir, ls, max_unroll_iterations); progress |= progress2; if (progress2) debug_print_ir ("After unroll", ir, state, mem_ctx);
|
||||
progress2 = unroll_loops(ir, ls, &state->ctx->Const.ShaderCompilerOptions[state->stage]); progress |= progress2; if (progress2) debug_print_ir ("After unroll", ir, state, mem_ctx);
|
||||
}
|
||||
delete ls;
|
||||
}
|
||||
} while (progress);
|
||||
|
||||
if (!state->metal_target)
|
||||
{
|
||||
// GLSL/ES does not have saturate, so lower it
|
||||
lower_instructions(ir, SAT_TO_CLAMP);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void find_shader_inputs(glslopt_shader* sh, exec_list* ir)
|
||||
static void glsl_type_to_optimizer_desc(const glsl_type* type, glsl_precision prec, glslopt_shader_var* out)
|
||||
{
|
||||
foreach_list(node, ir)
|
||||
out->arraySize = type->array_size();
|
||||
|
||||
// type; use element type when in array
|
||||
if (type->is_array())
|
||||
type = type->element_type();
|
||||
|
||||
if (type->is_float())
|
||||
out->type = kGlslTypeFloat;
|
||||
else if (type->is_integer())
|
||||
out->type = kGlslTypeInt;
|
||||
else if (type->is_boolean())
|
||||
out->type = kGlslTypeBool;
|
||||
else if (type->is_sampler())
|
||||
{
|
||||
ir_variable* const var = ((ir_instruction *)node)->as_variable();
|
||||
if (var == NULL || var->data.mode != ir_var_shader_in)
|
||||
if (type->sampler_dimensionality == GLSL_SAMPLER_DIM_2D)
|
||||
out->type = kGlslTypeTex2D;
|
||||
else if (type->sampler_dimensionality == GLSL_SAMPLER_DIM_3D)
|
||||
out->type = kGlslTypeTex3D;
|
||||
else if (type->sampler_dimensionality == GLSL_SAMPLER_DIM_CUBE)
|
||||
out->type = kGlslTypeTexCube;
|
||||
else
|
||||
out->type = kGlslTypeOther;
|
||||
}
|
||||
else
|
||||
out->type = kGlslTypeOther;
|
||||
|
||||
// sizes
|
||||
out->vectorSize = type->vector_elements;
|
||||
out->matrixSize = type->matrix_columns;
|
||||
|
||||
// precision
|
||||
switch (prec)
|
||||
{
|
||||
case glsl_precision_high: out->prec = kGlslPrecHigh; break;
|
||||
case glsl_precision_medium: out->prec = kGlslPrecMedium; break;
|
||||
case glsl_precision_low: out->prec = kGlslPrecLow; break;
|
||||
default: out->prec = kGlslPrecHigh; break;
|
||||
}
|
||||
}
|
||||
|
||||
static void find_shader_variables(glslopt_shader* sh, exec_list* ir)
|
||||
{
|
||||
foreach_in_list(ir_instruction, node, ir)
|
||||
{
|
||||
ir_variable* const var = node->as_variable();
|
||||
if (var == NULL)
|
||||
continue;
|
||||
if (var->data.mode == ir_var_shader_in)
|
||||
{
|
||||
if (sh->inputCount >= glslopt_shader::kMaxShaderInputs)
|
||||
continue;
|
||||
|
||||
if (sh->inputCount >= glslopt_shader::kMaxShaderInputs)
|
||||
return;
|
||||
|
||||
sh->inputs[sh->inputCount].name = ralloc_strdup(sh, var->name);
|
||||
++sh->inputCount;
|
||||
glslopt_shader_var& v = sh->inputs[sh->inputCount];
|
||||
v.name = ralloc_strdup(sh, var->name);
|
||||
glsl_type_to_optimizer_desc(var->type, (glsl_precision)var->data.precision, &v);
|
||||
v.location = var->data.explicit_location ? var->data.location : -1;
|
||||
++sh->inputCount;
|
||||
}
|
||||
if (var->data.mode == ir_var_uniform && !var->type->is_sampler())
|
||||
{
|
||||
if (sh->uniformCount >= glslopt_shader::kMaxShaderUniforms)
|
||||
continue;
|
||||
|
||||
glslopt_shader_var& v = sh->uniforms[sh->uniformCount];
|
||||
v.name = ralloc_strdup(sh, var->name);
|
||||
glsl_type_to_optimizer_desc(var->type, (glsl_precision)var->data.precision, &v);
|
||||
v.location = var->data.explicit_location ? var->data.location : -1;
|
||||
++sh->uniformCount;
|
||||
}
|
||||
if (var->data.mode == ir_var_uniform && var->type->is_sampler())
|
||||
{
|
||||
if (sh->textureCount >= glslopt_shader::kMaxShaderTextures)
|
||||
continue;
|
||||
|
||||
glslopt_shader_var& v = sh->textures[sh->textureCount];
|
||||
v.name = ralloc_strdup(sh, var->name);
|
||||
glsl_type_to_optimizer_desc(var->type, (glsl_precision)var->data.precision, &v);
|
||||
v.location = var->data.explicit_location ? var->data.location : -1;
|
||||
++sh->textureCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -397,8 +535,10 @@ glslopt_shader* glslopt_optimize (glslopt_ctx* ctx, glslopt_shader_type type, co
|
||||
shader->status = false;
|
||||
return shader;
|
||||
}
|
||||
|
||||
|
||||
_mesa_glsl_parse_state* state = new (shader) _mesa_glsl_parse_state (&ctx->mesa_ctx, shader->shader->Stage, shader);
|
||||
if (ctx->target == kGlslTargetMetal)
|
||||
state->metal_target = true;
|
||||
state->error = 0;
|
||||
|
||||
if (!(options & kGlslOptionSkipPreprocessor))
|
||||
@@ -425,7 +565,10 @@ glslopt_shader* glslopt_optimize (glslopt_ctx* ctx, glslopt_shader_type type, co
|
||||
// Un-optimized output
|
||||
if (!state->error) {
|
||||
validate_ir_tree(ir);
|
||||
shader->rawOutput = _mesa_print_ir_glsl(ir, state, ralloc_strdup(shader, ""), printMode);
|
||||
if (ctx->target == kGlslTargetMetal)
|
||||
shader->rawOutput = _mesa_print_ir_metal(ir, state, ralloc_strdup(shader, ""), printMode, &shader->uniformsSize);
|
||||
else
|
||||
shader->rawOutput = _mesa_print_ir_glsl(ir, state, ralloc_strdup(shader, ""), printMode);
|
||||
}
|
||||
|
||||
// Link built-in functions
|
||||
@@ -434,7 +577,7 @@ glslopt_shader* glslopt_optimize (glslopt_ctx* ctx, glslopt_shader_type type, co
|
||||
|
||||
struct gl_shader* linked_shader = NULL;
|
||||
|
||||
if (!state->error && !ir->is_empty())
|
||||
if (!state->error && !ir->is_empty() && !(options & kGlslOptionNotFullShader))
|
||||
{
|
||||
linked_shader = link_intrastage_shaders(shader,
|
||||
&ctx->mesa_ctx,
|
||||
@@ -456,20 +599,23 @@ glslopt_shader* glslopt_optimize (glslopt_ctx* ctx, glslopt_shader_type type, co
|
||||
if (!state->error && !ir->is_empty())
|
||||
{
|
||||
const bool linked = !(options & kGlslOptionNotFullShader);
|
||||
do_optimization_passes(ir, linked, ctx->max_unroll_iterations, state, shader);
|
||||
do_optimization_passes(ir, linked, state, shader);
|
||||
validate_ir_tree(ir);
|
||||
}
|
||||
|
||||
// Final optimized output
|
||||
if (!state->error)
|
||||
{
|
||||
shader->optimizedOutput = _mesa_print_ir_glsl(ir, state, ralloc_strdup(shader, ""), printMode);
|
||||
if (ctx->target == kGlslTargetMetal)
|
||||
shader->optimizedOutput = _mesa_print_ir_metal(ir, state, ralloc_strdup(shader, ""), printMode, &shader->uniformsSize);
|
||||
else
|
||||
shader->optimizedOutput = _mesa_print_ir_glsl(ir, state, ralloc_strdup(shader, ""), printMode);
|
||||
}
|
||||
|
||||
shader->status = !state->error;
|
||||
shader->infoLog = state->info_log;
|
||||
|
||||
find_shader_inputs(shader, ir);
|
||||
find_shader_variables (shader, ir);
|
||||
if (!state->error)
|
||||
calculate_shader_stats (ir, &shader->statsMath, &shader->statsTex, &shader->statsFlow);
|
||||
|
||||
@@ -512,9 +658,55 @@ int glslopt_shader_get_input_count (glslopt_shader* shader)
|
||||
return shader->inputCount;
|
||||
}
|
||||
|
||||
const char* glslopt_shader_get_input_name (glslopt_shader* shader, int index)
|
||||
int glslopt_shader_get_uniform_count (glslopt_shader* shader)
|
||||
{
|
||||
return shader->inputs[index].name;
|
||||
return shader->uniformCount;
|
||||
}
|
||||
|
||||
int glslopt_shader_get_uniform_total_size (glslopt_shader* shader)
|
||||
{
|
||||
return shader->uniformsSize;
|
||||
}
|
||||
|
||||
int glslopt_shader_get_texture_count (glslopt_shader* shader)
|
||||
{
|
||||
return shader->textureCount;
|
||||
}
|
||||
|
||||
void glslopt_shader_get_input_desc (glslopt_shader* shader, int index, const char** outName, glslopt_basic_type* outType, glslopt_precision* outPrec, int* outVecSize, int* outMatSize, int* outArraySize, int* outLocation)
|
||||
{
|
||||
const glslopt_shader_var& v = shader->inputs[index];
|
||||
*outName = v.name;
|
||||
*outType = v.type;
|
||||
*outPrec = v.prec;
|
||||
*outVecSize = v.vectorSize;
|
||||
*outMatSize = v.matrixSize;
|
||||
*outArraySize = v.arraySize;
|
||||
*outLocation = v.location;
|
||||
}
|
||||
|
||||
void glslopt_shader_get_uniform_desc (glslopt_shader* shader, int index, const char** outName, glslopt_basic_type* outType, glslopt_precision* outPrec, int* outVecSize, int* outMatSize, int* outArraySize, int* outLocation)
|
||||
{
|
||||
const glslopt_shader_var& v = shader->uniforms[index];
|
||||
*outName = v.name;
|
||||
*outType = v.type;
|
||||
*outPrec = v.prec;
|
||||
*outVecSize = v.vectorSize;
|
||||
*outMatSize = v.matrixSize;
|
||||
*outArraySize = v.arraySize;
|
||||
*outLocation = v.location;
|
||||
}
|
||||
|
||||
void glslopt_shader_get_texture_desc (glslopt_shader* shader, int index, const char** outName, glslopt_basic_type* outType, glslopt_precision* outPrec, int* outVecSize, int* outMatSize, int* outArraySize, int* outLocation)
|
||||
{
|
||||
const glslopt_shader_var& v = shader->textures[index];
|
||||
*outName = v.name;
|
||||
*outType = v.type;
|
||||
*outPrec = v.prec;
|
||||
*outVecSize = v.vectorSize;
|
||||
*outMatSize = v.matrixSize;
|
||||
*outArraySize = v.arraySize;
|
||||
*outLocation = v.location;
|
||||
}
|
||||
|
||||
void glslopt_shader_get_stats (glslopt_shader* shader, int* approxMath, int* approxTex, int* approxFlow)
|
||||
|
||||
@@ -40,7 +40,26 @@ enum glslopt_options {
|
||||
enum glslopt_target {
|
||||
kGlslTargetOpenGL = 0,
|
||||
kGlslTargetOpenGLES20 = 1,
|
||||
kGlslTargetOpenGLES30 = 2
|
||||
kGlslTargetOpenGLES30 = 2,
|
||||
kGlslTargetMetal = 3,
|
||||
};
|
||||
|
||||
// Type info
|
||||
enum glslopt_basic_type {
|
||||
kGlslTypeFloat = 0,
|
||||
kGlslTypeInt,
|
||||
kGlslTypeBool,
|
||||
kGlslTypeTex2D,
|
||||
kGlslTypeTex3D,
|
||||
kGlslTypeTexCube,
|
||||
kGlslTypeOther,
|
||||
kGlslTypeCount
|
||||
};
|
||||
enum glslopt_precision {
|
||||
kGlslPrecHigh = 0,
|
||||
kGlslPrecMedium,
|
||||
kGlslPrecLow,
|
||||
kGlslPrecCount
|
||||
};
|
||||
|
||||
glslopt_ctx* glslopt_initialize (glslopt_target target);
|
||||
@@ -56,7 +75,12 @@ const char* glslopt_get_log (glslopt_shader* shader);
|
||||
void glslopt_shader_delete (glslopt_shader* shader);
|
||||
|
||||
int glslopt_shader_get_input_count (glslopt_shader* shader);
|
||||
const char* glslopt_shader_get_input_name (glslopt_shader* shader, int index);
|
||||
void glslopt_shader_get_input_desc (glslopt_shader* shader, int index, const char** outName, glslopt_basic_type* outType, glslopt_precision* outPrec, int* outVecSize, int* outMatSize, int* outArraySize, int* outLocation);
|
||||
int glslopt_shader_get_uniform_count (glslopt_shader* shader);
|
||||
int glslopt_shader_get_uniform_total_size (glslopt_shader* shader);
|
||||
void glslopt_shader_get_uniform_desc (glslopt_shader* shader, int index, const char** outName, glslopt_basic_type* outType, glslopt_precision* outPrec, int* outVecSize, int* outMatSize, int* outArraySize, int* outLocation);
|
||||
int glslopt_shader_get_texture_count (glslopt_shader* shader);
|
||||
void glslopt_shader_get_texture_desc (glslopt_shader* shader, int index, const char** outName, glslopt_basic_type* outType, glslopt_precision* outPrec, int* outVecSize, int* outMatSize, int* outArraySize, int* outLocation);
|
||||
|
||||
// Get *very* approximate shader stats:
|
||||
// Number of math, texture and flow control instructions.
|
||||
|
||||
6296
3rdparty/glsl-optimizer/src/glsl/glsl_parser.cpp
vendored
6296
3rdparty/glsl-optimizer/src/glsl/glsl_parser.cpp
vendored
File diff suppressed because it is too large
Load Diff
376
3rdparty/glsl-optimizer/src/glsl/glsl_parser.h
vendored
376
3rdparty/glsl-optimizer/src/glsl/glsl_parser.h
vendored
@@ -80,193 +80,193 @@ extern int _mesa_glsl_debug;
|
||||
INOUT_TOK = 290,
|
||||
UNIFORM = 291,
|
||||
VARYING = 292,
|
||||
NOPERSPECTIVE = 293,
|
||||
FLAT = 294,
|
||||
SMOOTH = 295,
|
||||
MAT2X2 = 296,
|
||||
MAT2X3 = 297,
|
||||
MAT2X4 = 298,
|
||||
MAT3X2 = 299,
|
||||
MAT3X3 = 300,
|
||||
MAT3X4 = 301,
|
||||
MAT4X2 = 302,
|
||||
MAT4X3 = 303,
|
||||
MAT4X4 = 304,
|
||||
SAMPLER1D = 305,
|
||||
SAMPLER2D = 306,
|
||||
SAMPLER3D = 307,
|
||||
SAMPLERCUBE = 308,
|
||||
SAMPLER1DSHADOW = 309,
|
||||
SAMPLER2DSHADOW = 310,
|
||||
SAMPLERCUBESHADOW = 311,
|
||||
SAMPLER1DARRAY = 312,
|
||||
SAMPLER2DARRAY = 313,
|
||||
SAMPLER1DARRAYSHADOW = 314,
|
||||
SAMPLER2DARRAYSHADOW = 315,
|
||||
SAMPLERCUBEARRAY = 316,
|
||||
SAMPLERCUBEARRAYSHADOW = 317,
|
||||
ISAMPLER1D = 318,
|
||||
ISAMPLER2D = 319,
|
||||
ISAMPLER3D = 320,
|
||||
ISAMPLERCUBE = 321,
|
||||
ISAMPLER1DARRAY = 322,
|
||||
ISAMPLER2DARRAY = 323,
|
||||
ISAMPLERCUBEARRAY = 324,
|
||||
USAMPLER1D = 325,
|
||||
USAMPLER2D = 326,
|
||||
USAMPLER3D = 327,
|
||||
USAMPLERCUBE = 328,
|
||||
USAMPLER1DARRAY = 329,
|
||||
USAMPLER2DARRAY = 330,
|
||||
USAMPLERCUBEARRAY = 331,
|
||||
SAMPLER2DRECT = 332,
|
||||
ISAMPLER2DRECT = 333,
|
||||
USAMPLER2DRECT = 334,
|
||||
SAMPLER2DRECTSHADOW = 335,
|
||||
SAMPLERBUFFER = 336,
|
||||
ISAMPLERBUFFER = 337,
|
||||
USAMPLERBUFFER = 338,
|
||||
SAMPLER2DMS = 339,
|
||||
ISAMPLER2DMS = 340,
|
||||
USAMPLER2DMS = 341,
|
||||
SAMPLER2DMSARRAY = 342,
|
||||
ISAMPLER2DMSARRAY = 343,
|
||||
USAMPLER2DMSARRAY = 344,
|
||||
SAMPLEREXTERNALOES = 345,
|
||||
IMAGE1D = 346,
|
||||
IMAGE2D = 347,
|
||||
IMAGE3D = 348,
|
||||
IMAGE2DRECT = 349,
|
||||
IMAGECUBE = 350,
|
||||
IMAGEBUFFER = 351,
|
||||
IMAGE1DARRAY = 352,
|
||||
IMAGE2DARRAY = 353,
|
||||
IMAGECUBEARRAY = 354,
|
||||
IMAGE2DMS = 355,
|
||||
IMAGE2DMSARRAY = 356,
|
||||
IIMAGE1D = 357,
|
||||
IIMAGE2D = 358,
|
||||
IIMAGE3D = 359,
|
||||
IIMAGE2DRECT = 360,
|
||||
IIMAGECUBE = 361,
|
||||
IIMAGEBUFFER = 362,
|
||||
IIMAGE1DARRAY = 363,
|
||||
IIMAGE2DARRAY = 364,
|
||||
IIMAGECUBEARRAY = 365,
|
||||
IIMAGE2DMS = 366,
|
||||
IIMAGE2DMSARRAY = 367,
|
||||
UIMAGE1D = 368,
|
||||
UIMAGE2D = 369,
|
||||
UIMAGE3D = 370,
|
||||
UIMAGE2DRECT = 371,
|
||||
UIMAGECUBE = 372,
|
||||
UIMAGEBUFFER = 373,
|
||||
UIMAGE1DARRAY = 374,
|
||||
UIMAGE2DARRAY = 375,
|
||||
UIMAGECUBEARRAY = 376,
|
||||
UIMAGE2DMS = 377,
|
||||
UIMAGE2DMSARRAY = 378,
|
||||
IMAGE1DSHADOW = 379,
|
||||
IMAGE2DSHADOW = 380,
|
||||
IMAGE1DARRAYSHADOW = 381,
|
||||
IMAGE2DARRAYSHADOW = 382,
|
||||
COHERENT = 383,
|
||||
VOLATILE = 384,
|
||||
RESTRICT = 385,
|
||||
READONLY = 386,
|
||||
WRITEONLY = 387,
|
||||
ATOMIC_UINT = 388,
|
||||
STRUCT = 389,
|
||||
VOID_TOK = 390,
|
||||
WHILE = 391,
|
||||
IDENTIFIER = 392,
|
||||
TYPE_IDENTIFIER = 393,
|
||||
NEW_IDENTIFIER = 394,
|
||||
FLOATCONSTANT = 395,
|
||||
INTCONSTANT = 396,
|
||||
UINTCONSTANT = 397,
|
||||
BOOLCONSTANT = 398,
|
||||
FIELD_SELECTION = 399,
|
||||
LEFT_OP = 400,
|
||||
RIGHT_OP = 401,
|
||||
INC_OP = 402,
|
||||
DEC_OP = 403,
|
||||
LE_OP = 404,
|
||||
GE_OP = 405,
|
||||
EQ_OP = 406,
|
||||
NE_OP = 407,
|
||||
AND_OP = 408,
|
||||
OR_OP = 409,
|
||||
XOR_OP = 410,
|
||||
MUL_ASSIGN = 411,
|
||||
DIV_ASSIGN = 412,
|
||||
ADD_ASSIGN = 413,
|
||||
MOD_ASSIGN = 414,
|
||||
LEFT_ASSIGN = 415,
|
||||
RIGHT_ASSIGN = 416,
|
||||
AND_ASSIGN = 417,
|
||||
XOR_ASSIGN = 418,
|
||||
OR_ASSIGN = 419,
|
||||
SUB_ASSIGN = 420,
|
||||
INVARIANT = 421,
|
||||
LOWP = 422,
|
||||
MEDIUMP = 423,
|
||||
HIGHP = 424,
|
||||
SUPERP = 425,
|
||||
PRECISION = 426,
|
||||
VERSION_TOK = 427,
|
||||
EXTENSION = 428,
|
||||
LINE = 429,
|
||||
COLON = 430,
|
||||
EOL = 431,
|
||||
INTERFACE = 432,
|
||||
OUTPUT = 433,
|
||||
PRAGMA_DEBUG_ON = 434,
|
||||
PRAGMA_DEBUG_OFF = 435,
|
||||
PRAGMA_OPTIMIZE_ON = 436,
|
||||
PRAGMA_OPTIMIZE_OFF = 437,
|
||||
PRAGMA_INVARIANT_ALL = 438,
|
||||
LAYOUT_TOK = 439,
|
||||
ASM = 440,
|
||||
CLASS = 441,
|
||||
UNION = 442,
|
||||
ENUM = 443,
|
||||
TYPEDEF = 444,
|
||||
TEMPLATE = 445,
|
||||
THIS = 446,
|
||||
PACKED_TOK = 447,
|
||||
GOTO = 448,
|
||||
INLINE_TOK = 449,
|
||||
NOINLINE = 450,
|
||||
PUBLIC_TOK = 451,
|
||||
STATIC = 452,
|
||||
EXTERN = 453,
|
||||
EXTERNAL = 454,
|
||||
LONG_TOK = 455,
|
||||
SHORT_TOK = 456,
|
||||
DOUBLE_TOK = 457,
|
||||
HALF = 458,
|
||||
FIXED_TOK = 459,
|
||||
UNSIGNED = 460,
|
||||
INPUT_TOK = 461,
|
||||
OUPTUT = 462,
|
||||
HVEC2 = 463,
|
||||
HVEC3 = 464,
|
||||
HVEC4 = 465,
|
||||
DVEC2 = 466,
|
||||
DVEC3 = 467,
|
||||
DVEC4 = 468,
|
||||
FVEC2 = 469,
|
||||
FVEC3 = 470,
|
||||
FVEC4 = 471,
|
||||
SAMPLER3DRECT = 472,
|
||||
SIZEOF = 473,
|
||||
CAST = 474,
|
||||
NAMESPACE = 475,
|
||||
USING = 476,
|
||||
RESOURCE = 477,
|
||||
PATCH = 478,
|
||||
SAMPLE = 479,
|
||||
SAMPLE = 293,
|
||||
NOPERSPECTIVE = 294,
|
||||
FLAT = 295,
|
||||
SMOOTH = 296,
|
||||
MAT2X2 = 297,
|
||||
MAT2X3 = 298,
|
||||
MAT2X4 = 299,
|
||||
MAT3X2 = 300,
|
||||
MAT3X3 = 301,
|
||||
MAT3X4 = 302,
|
||||
MAT4X2 = 303,
|
||||
MAT4X3 = 304,
|
||||
MAT4X4 = 305,
|
||||
SAMPLER1D = 306,
|
||||
SAMPLER2D = 307,
|
||||
SAMPLER3D = 308,
|
||||
SAMPLERCUBE = 309,
|
||||
SAMPLER1DSHADOW = 310,
|
||||
SAMPLER2DSHADOW = 311,
|
||||
SAMPLERCUBESHADOW = 312,
|
||||
SAMPLER1DARRAY = 313,
|
||||
SAMPLER2DARRAY = 314,
|
||||
SAMPLER1DARRAYSHADOW = 315,
|
||||
SAMPLER2DARRAYSHADOW = 316,
|
||||
SAMPLERCUBEARRAY = 317,
|
||||
SAMPLERCUBEARRAYSHADOW = 318,
|
||||
ISAMPLER1D = 319,
|
||||
ISAMPLER2D = 320,
|
||||
ISAMPLER3D = 321,
|
||||
ISAMPLERCUBE = 322,
|
||||
ISAMPLER1DARRAY = 323,
|
||||
ISAMPLER2DARRAY = 324,
|
||||
ISAMPLERCUBEARRAY = 325,
|
||||
USAMPLER1D = 326,
|
||||
USAMPLER2D = 327,
|
||||
USAMPLER3D = 328,
|
||||
USAMPLERCUBE = 329,
|
||||
USAMPLER1DARRAY = 330,
|
||||
USAMPLER2DARRAY = 331,
|
||||
USAMPLERCUBEARRAY = 332,
|
||||
SAMPLER2DRECT = 333,
|
||||
ISAMPLER2DRECT = 334,
|
||||
USAMPLER2DRECT = 335,
|
||||
SAMPLER2DRECTSHADOW = 336,
|
||||
SAMPLERBUFFER = 337,
|
||||
ISAMPLERBUFFER = 338,
|
||||
USAMPLERBUFFER = 339,
|
||||
SAMPLER2DMS = 340,
|
||||
ISAMPLER2DMS = 341,
|
||||
USAMPLER2DMS = 342,
|
||||
SAMPLER2DMSARRAY = 343,
|
||||
ISAMPLER2DMSARRAY = 344,
|
||||
USAMPLER2DMSARRAY = 345,
|
||||
SAMPLEREXTERNALOES = 346,
|
||||
IMAGE1D = 347,
|
||||
IMAGE2D = 348,
|
||||
IMAGE3D = 349,
|
||||
IMAGE2DRECT = 350,
|
||||
IMAGECUBE = 351,
|
||||
IMAGEBUFFER = 352,
|
||||
IMAGE1DARRAY = 353,
|
||||
IMAGE2DARRAY = 354,
|
||||
IMAGECUBEARRAY = 355,
|
||||
IMAGE2DMS = 356,
|
||||
IMAGE2DMSARRAY = 357,
|
||||
IIMAGE1D = 358,
|
||||
IIMAGE2D = 359,
|
||||
IIMAGE3D = 360,
|
||||
IIMAGE2DRECT = 361,
|
||||
IIMAGECUBE = 362,
|
||||
IIMAGEBUFFER = 363,
|
||||
IIMAGE1DARRAY = 364,
|
||||
IIMAGE2DARRAY = 365,
|
||||
IIMAGECUBEARRAY = 366,
|
||||
IIMAGE2DMS = 367,
|
||||
IIMAGE2DMSARRAY = 368,
|
||||
UIMAGE1D = 369,
|
||||
UIMAGE2D = 370,
|
||||
UIMAGE3D = 371,
|
||||
UIMAGE2DRECT = 372,
|
||||
UIMAGECUBE = 373,
|
||||
UIMAGEBUFFER = 374,
|
||||
UIMAGE1DARRAY = 375,
|
||||
UIMAGE2DARRAY = 376,
|
||||
UIMAGECUBEARRAY = 377,
|
||||
UIMAGE2DMS = 378,
|
||||
UIMAGE2DMSARRAY = 379,
|
||||
IMAGE1DSHADOW = 380,
|
||||
IMAGE2DSHADOW = 381,
|
||||
IMAGE1DARRAYSHADOW = 382,
|
||||
IMAGE2DARRAYSHADOW = 383,
|
||||
COHERENT = 384,
|
||||
VOLATILE = 385,
|
||||
RESTRICT = 386,
|
||||
READONLY = 387,
|
||||
WRITEONLY = 388,
|
||||
ATOMIC_UINT = 389,
|
||||
STRUCT = 390,
|
||||
VOID_TOK = 391,
|
||||
WHILE = 392,
|
||||
IDENTIFIER = 393,
|
||||
TYPE_IDENTIFIER = 394,
|
||||
NEW_IDENTIFIER = 395,
|
||||
FLOATCONSTANT = 396,
|
||||
INTCONSTANT = 397,
|
||||
UINTCONSTANT = 398,
|
||||
BOOLCONSTANT = 399,
|
||||
FIELD_SELECTION = 400,
|
||||
LEFT_OP = 401,
|
||||
RIGHT_OP = 402,
|
||||
INC_OP = 403,
|
||||
DEC_OP = 404,
|
||||
LE_OP = 405,
|
||||
GE_OP = 406,
|
||||
EQ_OP = 407,
|
||||
NE_OP = 408,
|
||||
AND_OP = 409,
|
||||
OR_OP = 410,
|
||||
XOR_OP = 411,
|
||||
MUL_ASSIGN = 412,
|
||||
DIV_ASSIGN = 413,
|
||||
ADD_ASSIGN = 414,
|
||||
MOD_ASSIGN = 415,
|
||||
LEFT_ASSIGN = 416,
|
||||
RIGHT_ASSIGN = 417,
|
||||
AND_ASSIGN = 418,
|
||||
XOR_ASSIGN = 419,
|
||||
OR_ASSIGN = 420,
|
||||
SUB_ASSIGN = 421,
|
||||
INVARIANT = 422,
|
||||
PRECISE = 423,
|
||||
LOWP = 424,
|
||||
MEDIUMP = 425,
|
||||
HIGHP = 426,
|
||||
SUPERP = 427,
|
||||
PRECISION = 428,
|
||||
VERSION_TOK = 429,
|
||||
EXTENSION = 430,
|
||||
LINE = 431,
|
||||
COLON = 432,
|
||||
EOL = 433,
|
||||
INTERFACE = 434,
|
||||
OUTPUT = 435,
|
||||
PRAGMA_DEBUG_ON = 436,
|
||||
PRAGMA_DEBUG_OFF = 437,
|
||||
PRAGMA_OPTIMIZE_ON = 438,
|
||||
PRAGMA_OPTIMIZE_OFF = 439,
|
||||
PRAGMA_INVARIANT_ALL = 440,
|
||||
LAYOUT_TOK = 441,
|
||||
ASM = 442,
|
||||
CLASS = 443,
|
||||
UNION = 444,
|
||||
ENUM = 445,
|
||||
TYPEDEF = 446,
|
||||
TEMPLATE = 447,
|
||||
THIS = 448,
|
||||
PACKED_TOK = 449,
|
||||
GOTO = 450,
|
||||
INLINE_TOK = 451,
|
||||
NOINLINE = 452,
|
||||
PUBLIC_TOK = 453,
|
||||
STATIC = 454,
|
||||
EXTERN = 455,
|
||||
EXTERNAL = 456,
|
||||
LONG_TOK = 457,
|
||||
SHORT_TOK = 458,
|
||||
DOUBLE_TOK = 459,
|
||||
HALF = 460,
|
||||
FIXED_TOK = 461,
|
||||
UNSIGNED = 462,
|
||||
INPUT_TOK = 463,
|
||||
HVEC2 = 464,
|
||||
HVEC3 = 465,
|
||||
HVEC4 = 466,
|
||||
DVEC2 = 467,
|
||||
DVEC3 = 468,
|
||||
DVEC4 = 469,
|
||||
FVEC2 = 470,
|
||||
FVEC3 = 471,
|
||||
FVEC4 = 472,
|
||||
SAMPLER3DRECT = 473,
|
||||
SIZEOF = 474,
|
||||
CAST = 475,
|
||||
NAMESPACE = 476,
|
||||
USING = 477,
|
||||
RESOURCE = 478,
|
||||
PATCH = 479,
|
||||
SUBROUTINE = 480,
|
||||
ERROR_TOK = 481,
|
||||
COMMON = 482,
|
||||
@@ -283,7 +283,7 @@ extern int _mesa_glsl_debug;
|
||||
typedef union YYSTYPE YYSTYPE;
|
||||
union YYSTYPE
|
||||
{
|
||||
#line 96 "src/glsl/glsl_parser.yy" /* yacc.c:1909 */
|
||||
#line 99 "src/glsl/glsl_parser.yy" /* yacc.c:1909 */
|
||||
|
||||
int n;
|
||||
float real;
|
||||
|
||||
479
3rdparty/glsl-optimizer/src/glsl/glsl_parser.yy
vendored
479
3rdparty/glsl-optimizer/src/glsl/glsl_parser.yy
vendored
File diff suppressed because it is too large
Load Diff
@@ -30,7 +30,7 @@ extern "C" {
|
||||
#include "main/context.h"
|
||||
}
|
||||
|
||||
#include "ralloc.h"
|
||||
#include "util/ralloc.h"
|
||||
#include "ast.h"
|
||||
#include "glsl_parser_extras.h"
|
||||
#include "glsl_parser.h"
|
||||
@@ -49,7 +49,7 @@ glsl_compute_version_string(void *mem_ctx, bool is_es, unsigned version)
|
||||
}
|
||||
|
||||
|
||||
static unsigned known_desktop_glsl_versions[] =
|
||||
static const unsigned known_desktop_glsl_versions[] =
|
||||
{ 110, 120, 130, 140, 150, 330, 400, 410, 420, 430, 440 };
|
||||
|
||||
|
||||
@@ -66,10 +66,6 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx,
|
||||
this->translation_unit.make_empty();
|
||||
this->symbols = new(mem_ctx) glsl_symbol_table;
|
||||
|
||||
this->num_uniform_blocks = 0;
|
||||
this->uniform_block_array_size = 0;
|
||||
this->uniform_blocks = NULL;
|
||||
|
||||
this->info_log = ralloc_strdup(mem_ctx, "");
|
||||
this->error = false;
|
||||
this->loop_nesting_ast = NULL;
|
||||
@@ -82,6 +78,7 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx,
|
||||
this->language_version = ctx->Const.ForceGLSLVersion ?
|
||||
ctx->Const.ForceGLSLVersion : 110;
|
||||
this->es_shader = false;
|
||||
this->metal_target = false;
|
||||
this->had_version_string = false;
|
||||
this->had_float_precision = false;
|
||||
this->ARB_texture_rectangle_enable = true;
|
||||
@@ -203,13 +200,21 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx,
|
||||
this->default_uniform_qualifier->flags.q.shared = 1;
|
||||
this->default_uniform_qualifier->flags.q.column_major = 1;
|
||||
|
||||
this->fs_uses_gl_fragcoord = false;
|
||||
this->fs_redeclares_gl_fragcoord = false;
|
||||
this->fs_origin_upper_left = false;
|
||||
this->fs_pixel_center_integer = false;
|
||||
this->fs_redeclares_gl_fragcoord_with_no_layout_qualifiers = false;
|
||||
|
||||
this->gs_input_prim_type_specified = false;
|
||||
this->gs_input_prim_type = GL_POINTS;
|
||||
this->gs_input_size = 0;
|
||||
this->in_qualifier = new(this) ast_type_qualifier();
|
||||
this->out_qualifier = new(this) ast_type_qualifier();
|
||||
this->early_fragment_tests = false;
|
||||
memset(this->atomic_counter_offsets, 0,
|
||||
sizeof(this->atomic_counter_offsets));
|
||||
this->allow_extension_directive_midshader =
|
||||
ctx->Const.AllowGLSLExtensionDirectiveMidShader;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -386,8 +391,9 @@ _mesa_glsl_msg(const YYLTYPE *locp, _mesa_glsl_parse_state *state,
|
||||
/* Get the offset that the new message will be written to. */
|
||||
int msg_offset = strlen(state->info_log);
|
||||
|
||||
ralloc_asprintf_append(&state->info_log, "%u:%u(%u): %s: ",
|
||||
locp->source,
|
||||
// format:
|
||||
// (line,col): type: message
|
||||
ralloc_asprintf_append(&state->info_log, "(%u,%u): %s: ",
|
||||
locp->first_line,
|
||||
locp->first_column,
|
||||
error ? "error" : "warning");
|
||||
@@ -507,42 +513,62 @@ struct _mesa_glsl_extension {
|
||||
static const _mesa_glsl_extension _mesa_glsl_supported_extensions[] = {
|
||||
/* API availability */
|
||||
/* name GL ES supported flag */
|
||||
|
||||
/* ARB extensions go here, sorted alphabetically.
|
||||
*/
|
||||
EXT(ARB_arrays_of_arrays, true, false, ARB_arrays_of_arrays),
|
||||
EXT(ARB_compute_shader, true, false, ARB_compute_shader),
|
||||
EXT(ARB_conservative_depth, true, false, ARB_conservative_depth),
|
||||
EXT(ARB_derivative_control, true, false, ARB_derivative_control),
|
||||
EXT(ARB_draw_buffers, true, false, dummy_true),
|
||||
EXT(ARB_draw_instanced, true, false, ARB_draw_instanced),
|
||||
EXT(ARB_explicit_attrib_location, true, false, ARB_explicit_attrib_location),
|
||||
EXT(ARB_explicit_uniform_location, true, false, ARB_explicit_uniform_location),
|
||||
EXT(ARB_fragment_coord_conventions, true, false, ARB_fragment_coord_conventions),
|
||||
EXT(ARB_texture_rectangle, true, false, dummy_true),
|
||||
EXT(EXT_texture_array, true, false, EXT_texture_array),
|
||||
EXT(ARB_shader_texture_lod, true, false, ARB_shader_texture_lod),
|
||||
EXT(EXT_shader_texture_lod, false, true, ARB_shader_texture_lod),
|
||||
EXT(ARB_shader_stencil_export, true, false, ARB_shader_stencil_export),
|
||||
EXT(AMD_conservative_depth, true, false, ARB_conservative_depth),
|
||||
EXT(AMD_shader_stencil_export, true, false, ARB_shader_stencil_export),
|
||||
EXT(OES_texture_3D, false, true, EXT_texture3D),
|
||||
EXT(OES_EGL_image_external, false, true, OES_EGL_image_external),
|
||||
EXT(ARB_fragment_layer_viewport, true, false, ARB_fragment_layer_viewport),
|
||||
EXT(ARB_gpu_shader5, true, false, ARB_gpu_shader5),
|
||||
EXT(ARB_sample_shading, true, false, ARB_sample_shading),
|
||||
EXT(ARB_separate_shader_objects, true, false, dummy_true),
|
||||
EXT(ARB_shader_atomic_counters, true, false, ARB_shader_atomic_counters),
|
||||
EXT(ARB_shader_bit_encoding, true, false, ARB_shader_bit_encoding),
|
||||
EXT(ARB_uniform_buffer_object, true, false, ARB_uniform_buffer_object),
|
||||
EXT(OES_standard_derivatives, false, true, OES_standard_derivatives),
|
||||
EXT(EXT_shadow_samplers, false, true, EXT_shadow_samplers),
|
||||
EXT(EXT_frag_depth, false, true, EXT_frag_depth),
|
||||
EXT(ARB_texture_cube_map_array, true, false, ARB_texture_cube_map_array),
|
||||
EXT(ARB_shading_language_packing, true, false, ARB_shading_language_packing),
|
||||
EXT(ARB_shader_image_load_store, true, false, ARB_shader_image_load_store),
|
||||
EXT(ARB_shader_stencil_export, true, false, ARB_shader_stencil_export),
|
||||
EXT(ARB_shader_texture_lod, true, false, ARB_shader_texture_lod),
|
||||
EXT(ARB_shading_language_420pack, true, false, ARB_shading_language_420pack),
|
||||
EXT(ARB_shading_language_packing, true, false, ARB_shading_language_packing),
|
||||
EXT(ARB_texture_cube_map_array, true, false, ARB_texture_cube_map_array),
|
||||
EXT(ARB_texture_gather, true, false, ARB_texture_gather),
|
||||
EXT(ARB_texture_multisample, true, false, ARB_texture_multisample),
|
||||
EXT(ARB_texture_query_levels, true, false, ARB_texture_query_levels),
|
||||
EXT(ARB_texture_query_lod, true, false, ARB_texture_query_lod),
|
||||
EXT(ARB_gpu_shader5, true, false, ARB_gpu_shader5),
|
||||
EXT(AMD_vertex_shader_layer, true, false, AMD_vertex_shader_layer),
|
||||
EXT(EXT_shader_integer_mix, true, true, EXT_shader_integer_mix),
|
||||
EXT(ARB_texture_gather, true, false, ARB_texture_gather),
|
||||
EXT(ARB_shader_atomic_counters, true, false, ARB_shader_atomic_counters),
|
||||
EXT(ARB_sample_shading, true, false, ARB_sample_shading),
|
||||
EXT(AMD_shader_trinary_minmax, true, false, dummy_true),
|
||||
EXT(ARB_texture_rectangle, true, false, dummy_true),
|
||||
EXT(ARB_uniform_buffer_object, true, false, ARB_uniform_buffer_object),
|
||||
EXT(ARB_viewport_array, true, false, ARB_viewport_array),
|
||||
EXT(ARB_compute_shader, true, false, ARB_compute_shader),
|
||||
EXT(ARB_shader_image_load_store, true, false, ARB_shader_image_load_store),
|
||||
|
||||
/* KHR extensions go here, sorted alphabetically.
|
||||
*/
|
||||
|
||||
/* OES extensions go here, sorted alphabetically.
|
||||
*/
|
||||
EXT(OES_EGL_image_external, false, true, OES_EGL_image_external),
|
||||
EXT(OES_standard_derivatives, false, true, OES_standard_derivatives),
|
||||
EXT(OES_texture_3D, false, true, EXT_texture3D),
|
||||
|
||||
/* All other extensions go here, sorted alphabetically.
|
||||
*/
|
||||
EXT(AMD_conservative_depth, true, false, ARB_conservative_depth),
|
||||
EXT(AMD_shader_stencil_export, true, false, ARB_shader_stencil_export),
|
||||
EXT(AMD_shader_trinary_minmax, true, false, dummy_true),
|
||||
EXT(AMD_vertex_shader_layer, true, false, AMD_vertex_shader_layer),
|
||||
EXT(AMD_vertex_shader_viewport_index, true, false, AMD_vertex_shader_viewport_index),
|
||||
EXT(EXT_draw_buffers, false, true, EXT_draw_buffers),
|
||||
EXT(EXT_frag_depth, false, true, EXT_frag_depth),
|
||||
EXT(EXT_separate_shader_objects, false, true, dummy_true),
|
||||
EXT(EXT_shader_framebuffer_fetch, false, true, EXT_shader_framebuffer_fetch),
|
||||
EXT(EXT_shader_integer_mix, true, true, EXT_shader_integer_mix),
|
||||
EXT(EXT_shader_texture_lod, false, true, ARB_shader_texture_lod),
|
||||
EXT(EXT_shadow_samplers, false, true, EXT_shadow_samplers),
|
||||
EXT(EXT_texture_array, true, false, EXT_texture_array),
|
||||
};
|
||||
|
||||
#undef EXT
|
||||
@@ -646,7 +672,7 @@ _mesa_glsl_process_extension(const char *name, YYLTYPE *name_locp,
|
||||
if (extension && extension->compatible_with_state(state)) {
|
||||
extension->set_flags(state, behavior);
|
||||
} else {
|
||||
static const char *const fmt = "extension `%s' unsupported in %s shader";
|
||||
static const char fmt[] = "extension `%s' unsupported in %s shader";
|
||||
|
||||
if (behavior == extension_require) {
|
||||
_mesa_glsl_error(name_locp, state, fmt,
|
||||
@@ -812,8 +838,10 @@ ast_node::print(void) const
|
||||
ast_node::ast_node(void)
|
||||
{
|
||||
this->location.source = 0;
|
||||
this->location.line = 0;
|
||||
this->location.column = 0;
|
||||
this->location.first_line = 0;
|
||||
this->location.first_column = 0;
|
||||
this->location.last_line = 0;
|
||||
this->location.last_column = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -830,8 +858,7 @@ ast_compound_statement::print(void) const
|
||||
{
|
||||
printf("{\n");
|
||||
|
||||
foreach_list_const(n, &this->statements) {
|
||||
ast_node *ast = exec_node_data(ast_node, n, link);
|
||||
foreach_list_typed(ast_node, ast, link, &this->statements) {
|
||||
ast->print();
|
||||
}
|
||||
|
||||
@@ -910,11 +937,10 @@ ast_expression::print(void) const
|
||||
subexpressions[0]->print();
|
||||
printf("( ");
|
||||
|
||||
foreach_list_const (n, &this->expressions) {
|
||||
if (n != this->expressions.get_head())
|
||||
foreach_list_typed (ast_node, ast, link, &this->expressions) {
|
||||
if (&ast->link != this->expressions.get_head())
|
||||
printf(", ");
|
||||
|
||||
ast_node *ast = exec_node_data(ast_node, n, link);
|
||||
ast->print();
|
||||
}
|
||||
|
||||
@@ -946,11 +972,10 @@ ast_expression::print(void) const
|
||||
|
||||
case ast_sequence: {
|
||||
printf("( ");
|
||||
foreach_list_const(n, & this->expressions) {
|
||||
if (n != this->expressions.get_head())
|
||||
foreach_list_typed (ast_node, ast, link, & this->expressions) {
|
||||
if (&ast->link != this->expressions.get_head())
|
||||
printf(", ");
|
||||
|
||||
ast_node *ast = exec_node_data(ast_node, n, link);
|
||||
ast->print();
|
||||
}
|
||||
printf(") ");
|
||||
@@ -959,11 +984,10 @@ ast_expression::print(void) const
|
||||
|
||||
case ast_aggregate: {
|
||||
printf("{ ");
|
||||
foreach_list_const(n, & this->expressions) {
|
||||
if (n != this->expressions.get_head())
|
||||
foreach_list_typed (ast_node, ast, link, & this->expressions) {
|
||||
if (&ast->link != this->expressions.get_head())
|
||||
printf(", ");
|
||||
|
||||
ast_node *ast = exec_node_data(ast_node, n, link);
|
||||
ast->print();
|
||||
}
|
||||
printf("} ");
|
||||
@@ -1013,8 +1037,7 @@ ast_function::print(void) const
|
||||
return_type->print();
|
||||
printf(" %s (", identifier);
|
||||
|
||||
foreach_list_const(n, & this->parameters) {
|
||||
ast_node *ast = exec_node_data(ast_node, n, link);
|
||||
foreach_list_typed(ast_node, ast, link, & this->parameters) {
|
||||
ast->print();
|
||||
}
|
||||
|
||||
@@ -1086,14 +1109,15 @@ ast_declarator_list::print(void) const
|
||||
|
||||
if (type)
|
||||
type->print();
|
||||
else
|
||||
else if (invariant)
|
||||
printf("invariant ");
|
||||
else
|
||||
printf("precise ");
|
||||
|
||||
foreach_list_const (ptr, & this->declarations) {
|
||||
if (ptr != this->declarations.get_head())
|
||||
foreach_list_typed (ast_node, ast, link, & this->declarations) {
|
||||
if (&ast->link != this->declarations.get_head())
|
||||
printf(", ");
|
||||
|
||||
ast_node *ast = exec_node_data(ast_node, ptr, link);
|
||||
ast->print();
|
||||
}
|
||||
|
||||
@@ -1105,6 +1129,7 @@ ast_declarator_list::ast_declarator_list(ast_fully_specified_type *type)
|
||||
{
|
||||
this->type = type;
|
||||
this->invariant = false;
|
||||
this->precise = false;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1224,8 +1249,7 @@ ast_case_label::ast_case_label(ast_expression *test_value)
|
||||
|
||||
void ast_case_label_list::print(void) const
|
||||
{
|
||||
foreach_list_const(n, & this->labels) {
|
||||
ast_node *ast = exec_node_data(ast_node, n, link);
|
||||
foreach_list_typed(ast_node, ast, link, & this->labels) {
|
||||
ast->print();
|
||||
}
|
||||
printf("\n");
|
||||
@@ -1240,8 +1264,7 @@ ast_case_label_list::ast_case_label_list(void)
|
||||
void ast_case_statement::print(void) const
|
||||
{
|
||||
labels->print();
|
||||
foreach_list_const(n, & this->stmts) {
|
||||
ast_node *ast = exec_node_data(ast_node, n, link);
|
||||
foreach_list_typed(ast_node, ast, link, & this->stmts) {
|
||||
ast->print();
|
||||
printf("\n");
|
||||
}
|
||||
@@ -1256,8 +1279,7 @@ ast_case_statement::ast_case_statement(ast_case_label_list *labels)
|
||||
|
||||
void ast_case_statement_list::print(void) const
|
||||
{
|
||||
foreach_list_const(n, & this->cases) {
|
||||
ast_node *ast = exec_node_data(ast_node, n, link);
|
||||
foreach_list_typed(ast_node, ast, link, & this->cases) {
|
||||
ast->print();
|
||||
}
|
||||
}
|
||||
@@ -1327,8 +1349,7 @@ void
|
||||
ast_struct_specifier::print(void) const
|
||||
{
|
||||
printf("struct %s { ", name);
|
||||
foreach_list_const(n, &this->declarations) {
|
||||
ast_node *ast = exec_node_data(ast_node, n, link);
|
||||
foreach_list_typed(ast_node, ast, link, &this->declarations) {
|
||||
ast->print();
|
||||
}
|
||||
printf("} ");
|
||||
@@ -1354,7 +1375,7 @@ set_shader_inout_layout(struct gl_shader *shader,
|
||||
{
|
||||
if (shader->Stage != MESA_SHADER_GEOMETRY) {
|
||||
/* Should have been prevented by the parser. */
|
||||
assert(!state->gs_input_prim_type_specified);
|
||||
assert(!state->in_qualifier->flags.i);
|
||||
assert(!state->out_qualifier->flags.i);
|
||||
}
|
||||
|
||||
@@ -1363,6 +1384,14 @@ set_shader_inout_layout(struct gl_shader *shader,
|
||||
assert(!state->cs_input_local_size_specified);
|
||||
}
|
||||
|
||||
if (shader->Stage != MESA_SHADER_FRAGMENT) {
|
||||
/* Should have been prevented by the parser. */
|
||||
assert(!state->fs_uses_gl_fragcoord);
|
||||
assert(!state->fs_redeclares_gl_fragcoord);
|
||||
assert(!state->fs_pixel_center_integer);
|
||||
assert(!state->fs_origin_upper_left);
|
||||
}
|
||||
|
||||
switch (shader->Stage) {
|
||||
case MESA_SHADER_GEOMETRY:
|
||||
shader->Geom.VerticesOut = 0;
|
||||
@@ -1370,7 +1399,7 @@ set_shader_inout_layout(struct gl_shader *shader,
|
||||
shader->Geom.VerticesOut = state->out_qualifier->max_vertices;
|
||||
|
||||
if (state->gs_input_prim_type_specified) {
|
||||
shader->Geom.InputType = state->gs_input_prim_type;
|
||||
shader->Geom.InputType = state->in_qualifier->prim_type;
|
||||
} else {
|
||||
shader->Geom.InputType = PRIM_UNKNOWN;
|
||||
}
|
||||
@@ -1380,6 +1409,10 @@ set_shader_inout_layout(struct gl_shader *shader,
|
||||
} else {
|
||||
shader->Geom.OutputType = PRIM_UNKNOWN;
|
||||
}
|
||||
|
||||
shader->Geom.Invocations = 0;
|
||||
if (state->in_qualifier->flags.q.invocations)
|
||||
shader->Geom.Invocations = state->in_qualifier->invocations;
|
||||
break;
|
||||
|
||||
case MESA_SHADER_COMPUTE:
|
||||
@@ -1392,6 +1425,15 @@ set_shader_inout_layout(struct gl_shader *shader,
|
||||
}
|
||||
break;
|
||||
|
||||
case MESA_SHADER_FRAGMENT:
|
||||
shader->redeclares_gl_fragcoord = state->fs_redeclares_gl_fragcoord;
|
||||
shader->uses_gl_fragcoord = state->fs_uses_gl_fragcoord;
|
||||
shader->pixel_center_integer = state->fs_pixel_center_integer;
|
||||
shader->origin_upper_left = state->fs_origin_upper_left;
|
||||
shader->ARB_fragment_coord_conventions_enable =
|
||||
state->ARB_fragment_coord_conventions_enable;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Nothing to do. */
|
||||
break;
|
||||
@@ -1408,6 +1450,9 @@ _mesa_glsl_compile_shader(struct gl_context *ctx, struct gl_shader *shader,
|
||||
new(shader) _mesa_glsl_parse_state(ctx, shader->Stage, shader);
|
||||
const char *source = shader->Source;
|
||||
|
||||
if (ctx->Const.GenerateTemporaryNames)
|
||||
ir_variable::temporaries_allocate_names = true;
|
||||
|
||||
state->error = !!glcpp_preprocess(state, &source, &state->info_log,
|
||||
&ctx->Extensions, ctx);
|
||||
|
||||
@@ -1418,8 +1463,7 @@ _mesa_glsl_compile_shader(struct gl_context *ctx, struct gl_shader *shader,
|
||||
}
|
||||
|
||||
if (dump_ast) {
|
||||
foreach_list_const(n, &state->translation_unit) {
|
||||
ast_node *ast = exec_node_data(ast_node, n, link);
|
||||
foreach_list_typed(ast_node, ast, link, &state->translation_unit) {
|
||||
ast->print();
|
||||
}
|
||||
printf("\n\n");
|
||||
@@ -1435,46 +1479,89 @@ _mesa_glsl_compile_shader(struct gl_context *ctx, struct gl_shader *shader,
|
||||
|
||||
/* Print out the unoptimized IR. */
|
||||
if (dump_hir) {
|
||||
_mesa_print_ir(shader->ir, state);
|
||||
_mesa_print_ir(stdout, shader->ir, state);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!state->error && !shader->ir->is_empty()) {
|
||||
struct gl_shader_compiler_options *options =
|
||||
&ctx->ShaderCompilerOptions[shader->Stage];
|
||||
&ctx->Const.ShaderCompilerOptions[shader->Stage];
|
||||
|
||||
/* Do some optimization at compile time to reduce shader IR size
|
||||
* and reduce later work if the same shader is linked multiple times
|
||||
*/
|
||||
while (do_common_optimization(shader->ir, false, false, 32, options))
|
||||
while (do_common_optimization(shader->ir, false, false, options,
|
||||
ctx->Const.NativeIntegers))
|
||||
;
|
||||
|
||||
validate_ir_tree(shader->ir);
|
||||
|
||||
enum ir_variable_mode other;
|
||||
switch (shader->Stage) {
|
||||
case MESA_SHADER_VERTEX:
|
||||
other = ir_var_shader_in;
|
||||
break;
|
||||
case MESA_SHADER_FRAGMENT:
|
||||
other = ir_var_shader_out;
|
||||
break;
|
||||
default:
|
||||
/* Something invalid to ensure optimize_dead_builtin_uniforms
|
||||
* doesn't remove anything other than uniforms or constants.
|
||||
*/
|
||||
other = ir_var_mode_count;
|
||||
break;
|
||||
}
|
||||
|
||||
optimize_dead_builtin_variables(shader->ir, other);
|
||||
|
||||
validate_ir_tree(shader->ir);
|
||||
}
|
||||
|
||||
if (shader->InfoLog)
|
||||
ralloc_free(shader->InfoLog);
|
||||
|
||||
shader->symbols = state->symbols;
|
||||
shader->symbols = new(shader->ir) glsl_symbol_table;
|
||||
shader->CompileStatus = !state->error;
|
||||
shader->InfoLog = state->info_log;
|
||||
shader->Version = state->language_version;
|
||||
shader->IsES = state->es_shader;
|
||||
shader->uses_builtin_functions = state->uses_builtin_functions;
|
||||
|
||||
if (shader->UniformBlocks)
|
||||
ralloc_free(shader->UniformBlocks);
|
||||
shader->NumUniformBlocks = state->num_uniform_blocks;
|
||||
shader->UniformBlocks = state->uniform_blocks;
|
||||
ralloc_steal(shader, shader->UniformBlocks);
|
||||
|
||||
if (!state->error)
|
||||
set_shader_inout_layout(shader, state);
|
||||
|
||||
/* Retain any live IR, but trash the rest. */
|
||||
reparent_ir(shader->ir, shader->ir);
|
||||
|
||||
/* Destroy the symbol table. Create a new symbol table that contains only
|
||||
* the variables and functions that still exist in the IR. The symbol
|
||||
* table will be used later during linking.
|
||||
*
|
||||
* There must NOT be any freed objects still referenced by the symbol
|
||||
* table. That could cause the linker to dereference freed memory.
|
||||
*
|
||||
* We don't have to worry about types or interface-types here because those
|
||||
* are fly-weights that are looked up by glsl_type.
|
||||
*/
|
||||
foreach_in_list (ir_instruction, ir, shader->ir) {
|
||||
switch (ir->ir_type) {
|
||||
case ir_type_function:
|
||||
shader->symbols->add_function((ir_function *) ir);
|
||||
break;
|
||||
case ir_type_variable: {
|
||||
ir_variable *const var = (ir_variable *) ir;
|
||||
|
||||
if (var->data.mode != ir_var_temporary)
|
||||
shader->symbols->add_variable(var);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
delete state->symbols;
|
||||
ralloc_free(state);
|
||||
}
|
||||
|
||||
@@ -1500,8 +1587,8 @@ _mesa_glsl_compile_shader(struct gl_context *ctx, struct gl_shader *shader,
|
||||
bool
|
||||
do_common_optimization(exec_list *ir, bool linked,
|
||||
bool uniform_locations_assigned,
|
||||
unsigned max_unroll_iterations,
|
||||
const struct gl_shader_compiler_options *options)
|
||||
const struct gl_shader_compiler_options *options,
|
||||
bool native_integers)
|
||||
{
|
||||
GLboolean progress = GL_FALSE;
|
||||
|
||||
@@ -1536,21 +1623,23 @@ do_common_optimization(exec_list *ir, bool linked,
|
||||
else
|
||||
progress = do_constant_variable_unlinked(ir) || progress;
|
||||
progress = do_constant_folding(ir) || progress;
|
||||
progress = do_minmax_prune(ir) || progress;
|
||||
progress = do_cse(ir) || progress;
|
||||
progress = do_algebraic(ir) || progress;
|
||||
progress = do_rebalance_tree(ir) || progress;
|
||||
progress = do_algebraic(ir, native_integers, options) || progress;
|
||||
progress = do_lower_jumps(ir) || progress;
|
||||
progress = do_vec_index_to_swizzle(ir) || progress;
|
||||
progress = lower_vector_insert(ir, false) || progress;
|
||||
progress = do_swizzle_swizzle(ir) || progress;
|
||||
progress = do_noop_swizzle(ir) || progress;
|
||||
|
||||
progress = optimize_split_arrays(ir, linked) || progress;
|
||||
progress = optimize_split_arrays(ir, linked, false) || progress;
|
||||
progress = optimize_redundant_jumps(ir) || progress;
|
||||
|
||||
loop_state *ls = analyze_loop_variables(ir);
|
||||
if (ls->loop_found) {
|
||||
progress = set_loop_controls(ir, ls) || progress;
|
||||
progress = unroll_loops(ir, ls, max_unroll_iterations) || progress;
|
||||
progress = unroll_loops(ir, ls, options) || progress;
|
||||
}
|
||||
delete ls;
|
||||
|
||||
|
||||
@@ -43,6 +43,9 @@ struct glsl_switch_state {
|
||||
ir_variable *is_break_var;
|
||||
class ast_switch_statement *switch_nesting_ast;
|
||||
|
||||
/** Used to set condition if 'default' label should be chosen. */
|
||||
ir_variable *run_default;
|
||||
|
||||
/** Table of constant values already used in case labels */
|
||||
struct hash_table *labels_ht;
|
||||
class ast_case_label *previous_default;
|
||||
@@ -119,6 +122,19 @@ struct _mesa_glsl_parse_state {
|
||||
return check_version(130, 300, locp, "bit-wise operations are forbidden");
|
||||
}
|
||||
|
||||
bool check_explicit_attrib_stream_allowed(YYLTYPE *locp)
|
||||
{
|
||||
if (!this->has_explicit_attrib_stream()) {
|
||||
const char *const requirement = "GL_ARB_gpu_shader5 extension or GLSL 400";
|
||||
|
||||
_mesa_glsl_error(locp, this, "explicit stream requires %s",
|
||||
requirement);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool check_explicit_attrib_location_allowed(YYLTYPE *locp,
|
||||
const ir_variable *var)
|
||||
{
|
||||
@@ -135,6 +151,42 @@ struct _mesa_glsl_parse_state {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool check_separate_shader_objects_allowed(YYLTYPE *locp,
|
||||
const ir_variable *var)
|
||||
{
|
||||
if (!this->has_separate_shader_objects()) {
|
||||
const char *const requirement = this->es_shader
|
||||
? "GL_EXT_separate_shader_objects extension"
|
||||
: "GL_ARB_separate_shader_objects extension or GLSL 420";
|
||||
|
||||
_mesa_glsl_error(locp, this, "%s explicit location requires %s",
|
||||
mode_string(var), requirement);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool check_explicit_uniform_location_allowed(YYLTYPE *locp,
|
||||
const ir_variable *)
|
||||
{
|
||||
if (!this->has_explicit_attrib_location() ||
|
||||
!this->ARB_explicit_uniform_location_enable) {
|
||||
_mesa_glsl_error(locp, this,
|
||||
"uniform explicit location requires "
|
||||
"GL_ARB_explicit_uniform_location and either "
|
||||
"GL_ARB_explicit_attrib_location or GLSL 330.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool has_explicit_attrib_stream() const
|
||||
{
|
||||
return ARB_gpu_shader5_enable || is_version(400, 0);
|
||||
}
|
||||
|
||||
bool has_explicit_attrib_location() const
|
||||
{
|
||||
return ARB_explicit_attrib_location_enable || is_version(330, 300);
|
||||
@@ -145,6 +197,12 @@ struct _mesa_glsl_parse_state {
|
||||
return ARB_uniform_buffer_object_enable || is_version(140, 300);
|
||||
}
|
||||
|
||||
bool has_separate_shader_objects() const
|
||||
{
|
||||
return ARB_separate_shader_objects_enable || is_version(410, 0)
|
||||
|| EXT_separate_shader_objects_enable;
|
||||
}
|
||||
|
||||
void process_version_directive(YYLTYPE *locp, int version,
|
||||
const char *ident);
|
||||
|
||||
@@ -153,10 +211,6 @@ struct _mesa_glsl_parse_state {
|
||||
exec_list translation_unit;
|
||||
glsl_symbol_table *symbols;
|
||||
|
||||
unsigned num_uniform_blocks;
|
||||
unsigned uniform_block_array_size;
|
||||
struct gl_uniform_block *uniform_blocks;
|
||||
|
||||
unsigned num_supported_versions;
|
||||
struct {
|
||||
unsigned ver;
|
||||
@@ -164,6 +218,7 @@ struct _mesa_glsl_parse_state {
|
||||
} supported_versions[12];
|
||||
|
||||
bool es_shader;
|
||||
bool metal_target;
|
||||
unsigned language_version;
|
||||
bool had_version_string;
|
||||
bool had_float_precision;
|
||||
@@ -172,7 +227,7 @@ struct _mesa_glsl_parse_state {
|
||||
/**
|
||||
* Number of nested struct_specifier levels
|
||||
*
|
||||
* Outside a struct_specifer, this is zero.
|
||||
* Outside a struct_specifier, this is zero.
|
||||
*/
|
||||
unsigned struct_specifier_depth;
|
||||
|
||||
@@ -183,6 +238,18 @@ struct _mesa_glsl_parse_state {
|
||||
*/
|
||||
struct ast_type_qualifier *default_uniform_qualifier;
|
||||
|
||||
/**
|
||||
* Variables to track different cases if a fragment shader redeclares
|
||||
* built-in variable gl_FragCoord.
|
||||
*
|
||||
* Note: These values are computed at ast_to_hir time rather than at parse
|
||||
* time.
|
||||
*/
|
||||
bool fs_redeclares_gl_fragcoord;
|
||||
bool fs_origin_upper_left;
|
||||
bool fs_pixel_center_integer;
|
||||
bool fs_redeclares_gl_fragcoord_with_no_layout_qualifiers;
|
||||
|
||||
/**
|
||||
* True if a geometry shader input primitive type was specified using a
|
||||
* layout directive.
|
||||
@@ -192,11 +259,8 @@ struct _mesa_glsl_parse_state {
|
||||
*/
|
||||
bool gs_input_prim_type_specified;
|
||||
|
||||
/**
|
||||
* If gs_input_prim_type_specified is true, the primitive type that was
|
||||
* specified. Otherwise ignored.
|
||||
*/
|
||||
GLenum gs_input_prim_type;
|
||||
/** Input layout qualifiers from GLSL 1.50. (geometry shader controls)*/
|
||||
struct ast_type_qualifier *in_qualifier;
|
||||
|
||||
/**
|
||||
* True if a compute shader input local size was specified using a layout
|
||||
@@ -324,84 +388,113 @@ struct _mesa_glsl_parse_state {
|
||||
* \name Enable bits for GLSL extensions
|
||||
*/
|
||||
/*@{*/
|
||||
/* ARB extensions go here, sorted alphabetically.
|
||||
*/
|
||||
bool ARB_arrays_of_arrays_enable;
|
||||
bool ARB_arrays_of_arrays_warn;
|
||||
bool ARB_compute_shader_enable;
|
||||
bool ARB_compute_shader_warn;
|
||||
bool ARB_conservative_depth_enable;
|
||||
bool ARB_conservative_depth_warn;
|
||||
bool ARB_derivative_control_enable;
|
||||
bool ARB_derivative_control_warn;
|
||||
bool ARB_draw_buffers_enable;
|
||||
bool ARB_draw_buffers_warn;
|
||||
bool ARB_draw_instanced_enable;
|
||||
bool ARB_draw_instanced_warn;
|
||||
bool ARB_explicit_attrib_location_enable;
|
||||
bool ARB_explicit_attrib_location_warn;
|
||||
bool ARB_explicit_uniform_location_enable;
|
||||
bool ARB_explicit_uniform_location_warn;
|
||||
bool ARB_fragment_coord_conventions_enable;
|
||||
bool ARB_fragment_coord_conventions_warn;
|
||||
bool ARB_texture_rectangle_enable;
|
||||
bool ARB_texture_rectangle_warn;
|
||||
bool ARB_texture_gather_enable;
|
||||
bool ARB_texture_gather_warn;
|
||||
bool EXT_texture_array_enable;
|
||||
bool EXT_texture_array_warn;
|
||||
bool ARB_shader_texture_lod_enable;
|
||||
bool ARB_shader_texture_lod_warn;
|
||||
bool EXT_shader_texture_lod_enable;
|
||||
bool EXT_shader_texture_lod_warn;
|
||||
bool EXT_shadow_samplers_enable;
|
||||
bool EXT_shadow_samplers_warn;
|
||||
bool EXT_frag_depth_enable;
|
||||
bool EXT_frag_depth_warn;
|
||||
bool ARB_shader_stencil_export_enable;
|
||||
bool ARB_shader_stencil_export_warn;
|
||||
bool AMD_conservative_depth_enable;
|
||||
bool AMD_conservative_depth_warn;
|
||||
bool ARB_conservative_depth_enable;
|
||||
bool ARB_conservative_depth_warn;
|
||||
bool AMD_shader_stencil_export_enable;
|
||||
bool AMD_shader_stencil_export_warn;
|
||||
bool OES_texture_3D_enable;
|
||||
bool OES_texture_3D_warn;
|
||||
bool OES_EGL_image_external_enable;
|
||||
bool OES_EGL_image_external_warn;
|
||||
bool ARB_fragment_layer_viewport_enable;
|
||||
bool ARB_fragment_layer_viewport_warn;
|
||||
bool ARB_gpu_shader5_enable;
|
||||
bool ARB_gpu_shader5_warn;
|
||||
bool ARB_sample_shading_enable;
|
||||
bool ARB_sample_shading_warn;
|
||||
bool ARB_separate_shader_objects_enable;
|
||||
bool ARB_separate_shader_objects_warn;
|
||||
bool ARB_shader_atomic_counters_enable;
|
||||
bool ARB_shader_atomic_counters_warn;
|
||||
bool ARB_shader_bit_encoding_enable;
|
||||
bool ARB_shader_bit_encoding_warn;
|
||||
bool ARB_uniform_buffer_object_enable;
|
||||
bool ARB_uniform_buffer_object_warn;
|
||||
bool OES_standard_derivatives_enable;
|
||||
bool OES_standard_derivatives_warn;
|
||||
bool ARB_texture_cube_map_array_enable;
|
||||
bool ARB_texture_cube_map_array_warn;
|
||||
bool ARB_shader_image_load_store_enable;
|
||||
bool ARB_shader_image_load_store_warn;
|
||||
bool ARB_shader_stencil_export_enable;
|
||||
bool ARB_shader_stencil_export_warn;
|
||||
bool ARB_shader_texture_lod_enable;
|
||||
bool ARB_shader_texture_lod_warn;
|
||||
bool ARB_shading_language_420pack_enable;
|
||||
bool ARB_shading_language_420pack_warn;
|
||||
bool ARB_shading_language_packing_enable;
|
||||
bool ARB_shading_language_packing_warn;
|
||||
bool ARB_texture_cube_map_array_enable;
|
||||
bool ARB_texture_cube_map_array_warn;
|
||||
bool ARB_texture_gather_enable;
|
||||
bool ARB_texture_gather_warn;
|
||||
bool ARB_texture_multisample_enable;
|
||||
bool ARB_texture_multisample_warn;
|
||||
bool ARB_texture_query_levels_enable;
|
||||
bool ARB_texture_query_levels_warn;
|
||||
bool ARB_texture_query_lod_enable;
|
||||
bool ARB_texture_query_lod_warn;
|
||||
bool ARB_gpu_shader5_enable;
|
||||
bool ARB_gpu_shader5_warn;
|
||||
bool AMD_vertex_shader_layer_enable;
|
||||
bool AMD_vertex_shader_layer_warn;
|
||||
bool ARB_shading_language_420pack_enable;
|
||||
bool ARB_shading_language_420pack_warn;
|
||||
bool ARB_sample_shading_enable;
|
||||
bool ARB_sample_shading_warn;
|
||||
bool EXT_shader_integer_mix_enable;
|
||||
bool EXT_shader_integer_mix_warn;
|
||||
bool ARB_shader_atomic_counters_enable;
|
||||
bool ARB_shader_atomic_counters_warn;
|
||||
bool AMD_shader_trinary_minmax_enable;
|
||||
bool AMD_shader_trinary_minmax_warn;
|
||||
bool ARB_texture_rectangle_enable;
|
||||
bool ARB_texture_rectangle_warn;
|
||||
bool ARB_uniform_buffer_object_enable;
|
||||
bool ARB_uniform_buffer_object_warn;
|
||||
bool ARB_viewport_array_enable;
|
||||
bool ARB_viewport_array_warn;
|
||||
bool ARB_compute_shader_enable;
|
||||
bool ARB_compute_shader_warn;
|
||||
bool ARB_shader_image_load_store_enable;
|
||||
bool ARB_shader_image_load_store_warn;
|
||||
|
||||
/* KHR extensions go here, sorted alphabetically.
|
||||
*/
|
||||
|
||||
/* OES extensions go here, sorted alphabetically.
|
||||
*/
|
||||
bool OES_EGL_image_external_enable;
|
||||
bool OES_EGL_image_external_warn;
|
||||
bool OES_standard_derivatives_enable;
|
||||
bool OES_standard_derivatives_warn;
|
||||
bool OES_texture_3D_enable;
|
||||
bool OES_texture_3D_warn;
|
||||
|
||||
/* All other extensions go here, sorted alphabetically.
|
||||
*/
|
||||
bool AMD_conservative_depth_enable;
|
||||
bool AMD_conservative_depth_warn;
|
||||
bool AMD_shader_stencil_export_enable;
|
||||
bool AMD_shader_stencil_export_warn;
|
||||
bool AMD_shader_trinary_minmax_enable;
|
||||
bool AMD_shader_trinary_minmax_warn;
|
||||
bool AMD_vertex_shader_layer_enable;
|
||||
bool AMD_vertex_shader_layer_warn;
|
||||
bool AMD_vertex_shader_viewport_index_enable;
|
||||
bool AMD_vertex_shader_viewport_index_warn;
|
||||
bool EXT_draw_buffers_enable;
|
||||
bool EXT_draw_buffers_warn;
|
||||
bool EXT_frag_depth_enable;
|
||||
bool EXT_frag_depth_warn;
|
||||
bool EXT_separate_shader_objects_enable;
|
||||
bool EXT_separate_shader_objects_warn;
|
||||
bool EXT_shader_framebuffer_fetch_enable;
|
||||
bool EXT_shader_framebuffer_fetch_warn;
|
||||
bool EXT_shader_integer_mix_enable;
|
||||
bool EXT_shader_integer_mix_warn;
|
||||
bool EXT_shader_texture_lod_enable;
|
||||
bool EXT_shader_texture_lod_warn;
|
||||
bool EXT_shadow_samplers_enable;
|
||||
bool EXT_shadow_samplers_warn;
|
||||
bool EXT_texture_array_enable;
|
||||
bool EXT_texture_array_warn;
|
||||
|
||||
/*@}*/
|
||||
|
||||
/** Extensions supported by the OpenGL implementation. */
|
||||
const struct gl_extensions *extensions;
|
||||
|
||||
bool uses_builtin_functions;
|
||||
bool fs_uses_gl_fragcoord;
|
||||
|
||||
/**
|
||||
* For geometry shaders, size of the most recently seen input declaration
|
||||
@@ -416,6 +509,8 @@ struct _mesa_glsl_parse_state {
|
||||
|
||||
/** Atomic counter offsets by binding */
|
||||
unsigned atomic_counter_offsets[MAX_COMBINED_ATOMIC_BUFFERS];
|
||||
|
||||
bool allow_extension_directive_midshader;
|
||||
};
|
||||
|
||||
# define YYLLOC_DEFAULT(Current, Rhs, N) \
|
||||
|
||||
@@ -124,6 +124,8 @@ bool glsl_symbol_table::name_declared_this_scope(const char *name)
|
||||
|
||||
bool glsl_symbol_table::add_variable(ir_variable *v)
|
||||
{
|
||||
assert(v->data.mode != ir_var_temporary);
|
||||
|
||||
if (this->separate_function_namespace) {
|
||||
/* In 1.10, functions and variables have separate namespaces. */
|
||||
symbol_table_entry *existing = get_entry(v->name);
|
||||
@@ -162,23 +164,6 @@ bool glsl_symbol_table::add_type(const char *name, const glsl_type *t)
|
||||
return _mesa_symbol_table_add_symbol(table, -1, name, entry) == 0;
|
||||
}
|
||||
|
||||
static char *make_ast_name(const char *name)
|
||||
{
|
||||
char *ast_name = new char[strlen("#ast.") + strlen(name) + 1];
|
||||
strcpy(ast_name, "#ast.");
|
||||
strcat(ast_name + strlen("#ast."), name);
|
||||
return ast_name;
|
||||
}
|
||||
|
||||
bool glsl_symbol_table::add_type_ast(const char *name, const class ast_type_specifier *a)
|
||||
{
|
||||
symbol_table_entry *entry = new(mem_ctx) symbol_table_entry(a);
|
||||
char *ast_name = make_ast_name(name);
|
||||
bool ret = _mesa_symbol_table_add_symbol(table, -1, ast_name, entry) == 0;
|
||||
delete [] ast_name;
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool glsl_symbol_table::add_interface(const char *name, const glsl_type *i,
|
||||
enum ir_variable_mode mode)
|
||||
{
|
||||
@@ -230,14 +215,6 @@ const glsl_type *glsl_symbol_table::get_type(const char *name)
|
||||
return entry != NULL ? entry->t : NULL;
|
||||
}
|
||||
|
||||
const class ast_type_specifier *glsl_symbol_table::get_type_ast(const char *name)
|
||||
{
|
||||
char *ast_name = make_ast_name(name);
|
||||
symbol_table_entry *entry = get_entry(ast_name);
|
||||
delete [] ast_name;
|
||||
return entry != NULL ? entry->a : NULL;
|
||||
}
|
||||
|
||||
const glsl_type *glsl_symbol_table::get_interface(const char *name,
|
||||
enum ir_variable_mode mode)
|
||||
{
|
||||
|
||||
@@ -32,9 +32,9 @@ extern "C" {
|
||||
#include "program/symbol_table.h"
|
||||
}
|
||||
#include "ir.h"
|
||||
#include "glsl_types.h"
|
||||
|
||||
class symbol_table_entry;
|
||||
struct glsl_type;
|
||||
|
||||
/**
|
||||
* Facade class for _mesa_symbol_table
|
||||
@@ -43,37 +43,8 @@ class symbol_table_entry;
|
||||
* type safe and some symbol table invariants.
|
||||
*/
|
||||
struct glsl_symbol_table {
|
||||
private:
|
||||
static void
|
||||
_glsl_symbol_table_destructor (glsl_symbol_table *table)
|
||||
{
|
||||
table->~glsl_symbol_table();
|
||||
}
|
||||
DECLARE_RALLOC_CXX_OPERATORS(glsl_symbol_table)
|
||||
|
||||
public:
|
||||
/* Callers of this ralloc-based new need not call delete. It's
|
||||
* easier to just ralloc_free 'ctx' (or any of its ancestors). */
|
||||
static void* operator new(size_t size, void *ctx)
|
||||
{
|
||||
void *table;
|
||||
|
||||
table = ralloc_size(ctx, size);
|
||||
assert(table != NULL);
|
||||
|
||||
ralloc_set_destructor(table, (void (*)(void*)) _glsl_symbol_table_destructor);
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
/* If the user *does* call delete, that's OK, we will just
|
||||
* ralloc_free in that case. Here, C++ will have already called the
|
||||
* destructor so tell ralloc not to do that again. */
|
||||
static void operator delete(void *table)
|
||||
{
|
||||
ralloc_set_destructor(table, NULL);
|
||||
ralloc_free(table);
|
||||
}
|
||||
|
||||
glsl_symbol_table();
|
||||
~glsl_symbol_table();
|
||||
|
||||
@@ -98,7 +69,6 @@ public:
|
||||
/*@{*/
|
||||
bool add_variable(ir_variable *v);
|
||||
bool add_type(const char *name, const glsl_type *t);
|
||||
bool add_type_ast(const char *name, const class ast_type_specifier *t);
|
||||
bool add_function(ir_function *f);
|
||||
bool add_interface(const char *name, const glsl_type *i,
|
||||
enum ir_variable_mode mode);
|
||||
@@ -115,7 +85,6 @@ public:
|
||||
/*@{*/
|
||||
ir_variable *get_variable(const char *name);
|
||||
const glsl_type *get_type(const char *name);
|
||||
const class ast_type_specifier *get_type_ast(const char *name);
|
||||
ir_function *get_function(const char *name);
|
||||
const glsl_type *get_interface(const char *name,
|
||||
enum ir_variable_mode mode);
|
||||
|
||||
111
3rdparty/glsl-optimizer/src/glsl/glsl_types.cpp
vendored
111
3rdparty/glsl-optimizer/src/glsl/glsl_types.cpp
vendored
@@ -22,9 +22,7 @@
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "main/core.h" /* for Elements */
|
||||
#include "glsl_symbol_table.h"
|
||||
#include "main/core.h" /* for Elements, MAX2 */
|
||||
#include "glsl_parser_extras.h"
|
||||
#include "glsl_types.h"
|
||||
#include "main/glminimal.h"
|
||||
@@ -112,7 +110,7 @@ glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields,
|
||||
this->fields.structure[i].interpolation = fields[i].interpolation;
|
||||
this->fields.structure[i].centroid = fields[i].centroid;
|
||||
this->fields.structure[i].sample = fields[i].sample;
|
||||
this->fields.structure[i].row_major = fields[i].row_major;
|
||||
this->fields.structure[i].matrix_layout = fields[i].matrix_layout;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,7 +139,7 @@ glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields,
|
||||
this->fields.structure[i].interpolation = fields[i].interpolation;
|
||||
this->fields.structure[i].centroid = fields[i].centroid;
|
||||
this->fields.structure[i].sample = fields[i].sample;
|
||||
this->fields.structure[i].row_major = fields[i].row_major;
|
||||
this->fields.structure[i].matrix_layout = fields[i].matrix_layout;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -495,14 +493,28 @@ glsl_type::record_compare(const glsl_type *b) const
|
||||
if (this->interface_packing != b->interface_packing)
|
||||
return false;
|
||||
|
||||
/* From the GLSL 4.20 specification (Sec 4.2):
|
||||
*
|
||||
* "Structures must have the same name, sequence of type names, and
|
||||
* type definitions, and field names to be considered the same type."
|
||||
*
|
||||
* GLSL ES behaves the same (Ver 1.00 Sec 4.2.4, Ver 3.00 Sec 4.2.5).
|
||||
*
|
||||
* Note that we cannot force type name check when comparing unnamed
|
||||
* structure types, these have a unique name assigned during parsing.
|
||||
*/
|
||||
if (!this->is_anonymous() && !b->is_anonymous())
|
||||
if (strcmp(this->name, b->name) != 0)
|
||||
return false;
|
||||
|
||||
for (unsigned i = 0; i < this->length; i++) {
|
||||
if (this->fields.structure[i].type != b->fields.structure[i].type)
|
||||
return false;
|
||||
if (strcmp(this->fields.structure[i].name,
|
||||
b->fields.structure[i].name) != 0)
|
||||
return false;
|
||||
if (this->fields.structure[i].row_major
|
||||
!= b->fields.structure[i].row_major)
|
||||
if (this->fields.structure[i].matrix_layout
|
||||
!= b->fields.structure[i].matrix_layout)
|
||||
return false;
|
||||
if (this->fields.structure[i].location
|
||||
!= b->fields.structure[i].location)
|
||||
@@ -697,8 +709,35 @@ glsl_type::component_slots() const
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned
|
||||
glsl_type::uniform_locations() const
|
||||
{
|
||||
unsigned size = 0;
|
||||
|
||||
switch (this->base_type) {
|
||||
case GLSL_TYPE_UINT:
|
||||
case GLSL_TYPE_INT:
|
||||
case GLSL_TYPE_FLOAT:
|
||||
case GLSL_TYPE_BOOL:
|
||||
case GLSL_TYPE_SAMPLER:
|
||||
case GLSL_TYPE_IMAGE:
|
||||
return 1;
|
||||
|
||||
case GLSL_TYPE_STRUCT:
|
||||
case GLSL_TYPE_INTERFACE:
|
||||
for (unsigned i = 0; i < this->length; i++)
|
||||
size += this->fields.structure[i].type->uniform_locations();
|
||||
return size;
|
||||
case GLSL_TYPE_ARRAY:
|
||||
return this->length * this->fields.array->uniform_locations();
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
glsl_type::can_implicitly_convert_to(const glsl_type *desired) const
|
||||
glsl_type::can_implicitly_convert_to(const glsl_type *desired,
|
||||
_mesa_glsl_parse_state *state) const
|
||||
{
|
||||
if (this == desired)
|
||||
return true;
|
||||
@@ -707,10 +746,23 @@ glsl_type::can_implicitly_convert_to(const glsl_type *desired) const
|
||||
if (this->matrix_columns > 1 || desired->matrix_columns > 1)
|
||||
return false;
|
||||
|
||||
/* Vector size must match. */
|
||||
if (this->vector_elements != desired->vector_elements)
|
||||
return false;
|
||||
|
||||
/* int and uint can be converted to float. */
|
||||
return desired->is_float()
|
||||
&& this->is_integer()
|
||||
&& this->vector_elements == desired->vector_elements;
|
||||
if (desired->is_float() && this->is_integer())
|
||||
return true;
|
||||
|
||||
/* With GLSL 4.0 / ARB_gpu_shader5, int can be converted to uint.
|
||||
* Note that state may be NULL here, when resolving function calls in the
|
||||
* linker. By this time, all the state-dependent checks have already
|
||||
* happened though, so allow anything that's allowed in any shader version. */
|
||||
if ((!state || state->is_version(400, 0) || state->ARB_gpu_shader5_enable) &&
|
||||
desired->base_type == GLSL_TYPE_UINT && this->base_type == GLSL_TYPE_INT)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned
|
||||
@@ -808,9 +860,18 @@ glsl_type::std140_base_alignment(bool row_major) const
|
||||
if (this->is_record()) {
|
||||
unsigned base_alignment = 16;
|
||||
for (unsigned i = 0; i < this->length; i++) {
|
||||
bool field_row_major = row_major;
|
||||
const enum glsl_matrix_layout matrix_layout =
|
||||
glsl_matrix_layout(this->fields.structure[i].matrix_layout);
|
||||
if (matrix_layout == GLSL_MATRIX_LAYOUT_ROW_MAJOR) {
|
||||
field_row_major = true;
|
||||
} else if (matrix_layout == GLSL_MATRIX_LAYOUT_COLUMN_MAJOR) {
|
||||
field_row_major = false;
|
||||
}
|
||||
|
||||
const struct glsl_type *field_type = this->fields.structure[i].type;
|
||||
base_alignment = MAX2(base_alignment,
|
||||
field_type->std140_base_alignment(row_major));
|
||||
field_type->std140_base_alignment(field_row_major));
|
||||
}
|
||||
return base_alignment;
|
||||
}
|
||||
@@ -854,8 +915,7 @@ glsl_type::std140_size(bool row_major) const
|
||||
* and <R> rows, the matrix is stored identically to a row of <S>*<R>
|
||||
* row vectors with <C> components each, according to rule (4).
|
||||
*/
|
||||
if (this->is_matrix() || (this->is_array() &&
|
||||
this->fields.array->is_matrix())) {
|
||||
if (this->without_array()->is_matrix()) {
|
||||
const struct glsl_type *element_type;
|
||||
const struct glsl_type *vec_type;
|
||||
unsigned int array_len;
|
||||
@@ -917,14 +977,29 @@ glsl_type::std140_size(bool row_major) const
|
||||
*/
|
||||
if (this->is_record()) {
|
||||
unsigned size = 0;
|
||||
unsigned max_align = 0;
|
||||
|
||||
for (unsigned i = 0; i < this->length; i++) {
|
||||
bool field_row_major = row_major;
|
||||
const enum glsl_matrix_layout matrix_layout =
|
||||
glsl_matrix_layout(this->fields.structure[i].matrix_layout);
|
||||
if (matrix_layout == GLSL_MATRIX_LAYOUT_ROW_MAJOR) {
|
||||
field_row_major = true;
|
||||
} else if (matrix_layout == GLSL_MATRIX_LAYOUT_COLUMN_MAJOR) {
|
||||
field_row_major = false;
|
||||
}
|
||||
|
||||
const struct glsl_type *field_type = this->fields.structure[i].type;
|
||||
unsigned align = field_type->std140_base_alignment(row_major);
|
||||
unsigned align = field_type->std140_base_alignment(field_row_major);
|
||||
size = glsl_align(size, align);
|
||||
size += field_type->std140_size(row_major);
|
||||
size += field_type->std140_size(field_row_major);
|
||||
|
||||
max_align = MAX2(align, max_align);
|
||||
|
||||
if (field_type->is_record() && (i + 1 < this->length))
|
||||
size = glsl_align(size, 16);
|
||||
}
|
||||
size = glsl_align(size,
|
||||
this->fields.structure[0].type->std140_base_alignment(row_major));
|
||||
size = glsl_align(size, MAX2(max_align, 16));
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
69
3rdparty/glsl-optimizer/src/glsl/glsl_types.h
vendored
69
3rdparty/glsl-optimizer/src/glsl/glsl_types.h
vendored
@@ -86,9 +86,30 @@ enum glsl_precision {
|
||||
glsl_precision_undefined,
|
||||
};
|
||||
|
||||
enum glsl_matrix_layout {
|
||||
/**
|
||||
* The layout of the matrix is inherited from the object containing the
|
||||
* matrix (the top level structure or the uniform block).
|
||||
*/
|
||||
GLSL_MATRIX_LAYOUT_INHERITED,
|
||||
|
||||
/**
|
||||
* Explicit column-major layout
|
||||
*
|
||||
* If a uniform block doesn't have an explicit layout set, it will default
|
||||
* to this layout.
|
||||
*/
|
||||
GLSL_MATRIX_LAYOUT_COLUMN_MAJOR,
|
||||
|
||||
/**
|
||||
* Row-major layout
|
||||
*/
|
||||
GLSL_MATRIX_LAYOUT_ROW_MAJOR
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include "../mesa/main/glminimal.h"
|
||||
#include "ralloc.h"
|
||||
#include "util/ralloc.h"
|
||||
|
||||
struct glsl_type {
|
||||
GLenum gl_type;
|
||||
@@ -187,7 +208,7 @@ struct glsl_type {
|
||||
/**@}*/
|
||||
|
||||
/**
|
||||
* For numeric and boolean derrived types returns the basic scalar type
|
||||
* For numeric and boolean derived types returns the basic scalar type
|
||||
*
|
||||
* If the type is a numeric or boolean scalar, vector, or matrix type,
|
||||
* this function gets the scalar type of the individual components. For
|
||||
@@ -262,6 +283,15 @@ struct glsl_type {
|
||||
*/
|
||||
unsigned component_slots() const;
|
||||
|
||||
/**
|
||||
* Calculate the number of unique values from glGetUniformLocation for the
|
||||
* elements of the type.
|
||||
*
|
||||
* This is used to allocate slots in the UniformRemapTable, the amount of
|
||||
* locations may not match with actual used storage space by the driver.
|
||||
*/
|
||||
unsigned uniform_locations() const;
|
||||
|
||||
/**
|
||||
* Calculate the number of attribute slots required to hold this type
|
||||
*
|
||||
@@ -321,7 +351,8 @@ struct glsl_type {
|
||||
* integers.
|
||||
* \endverbatim
|
||||
*/
|
||||
bool can_implicitly_convert_to(const glsl_type *desired) const;
|
||||
bool can_implicitly_convert_to(const glsl_type *desired,
|
||||
_mesa_glsl_parse_state *state) const;
|
||||
|
||||
/**
|
||||
* Query whether or not a type is a scalar (non-vector and non-matrix).
|
||||
@@ -464,6 +495,26 @@ struct glsl_type {
|
||||
return base_type == GLSL_TYPE_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* Query if a type is unnamed/anonymous (named by the parser)
|
||||
*/
|
||||
bool is_anonymous() const
|
||||
{
|
||||
return !strncmp(name, "#anon", 5);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the type stripped of any arrays
|
||||
*
|
||||
* \return
|
||||
* Pointer to the type of elements of the first non-array type for array
|
||||
* types, or pointer to itself for non-array types.
|
||||
*/
|
||||
const glsl_type *without_array() const
|
||||
{
|
||||
return this->is_array() ? this->fields.array : this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the amount of atomic counter storage required for a type.
|
||||
*/
|
||||
@@ -646,7 +697,6 @@ private:
|
||||
struct glsl_struct_field {
|
||||
const struct glsl_type *type;
|
||||
const char *name;
|
||||
bool row_major;
|
||||
glsl_precision precision;
|
||||
|
||||
/**
|
||||
@@ -675,6 +725,17 @@ struct glsl_struct_field {
|
||||
* in ir_variable::sample). 0 otherwise.
|
||||
*/
|
||||
unsigned sample:1;
|
||||
|
||||
/**
|
||||
* Layout of the matrix. Uses glsl_matrix_layout values.
|
||||
*/
|
||||
unsigned matrix_layout:2;
|
||||
|
||||
/**
|
||||
* For interface blocks, it has a value if this variable uses multiple vertex
|
||||
* streams (as in ir_variable::stream). -1 otherwise.
|
||||
*/
|
||||
int stream;
|
||||
};
|
||||
|
||||
static inline unsigned int
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
*/
|
||||
|
||||
#include "ir.h"
|
||||
#include "program/symbol_table.h"
|
||||
#include "glsl_parser_extras.h"
|
||||
#include "ast.h"
|
||||
#include "glsl_types.h"
|
||||
|
||||
218
3rdparty/glsl-optimizer/src/glsl/ir.cpp
vendored
218
3rdparty/glsl-optimizer/src/glsl/ir.cpp
vendored
@@ -23,7 +23,6 @@
|
||||
#include <string.h>
|
||||
#include "main/core.h" /* for MAX2 */
|
||||
#include "ir.h"
|
||||
#include "ir_visitor.h"
|
||||
#include "glsl_types.h"
|
||||
|
||||
glsl_precision higher_precision (ir_instruction* a, ir_instruction* b)
|
||||
@@ -38,8 +37,9 @@ glsl_precision higher_precision (ir_instruction* a, ir_instruction* b)
|
||||
}
|
||||
|
||||
|
||||
ir_rvalue::ir_rvalue(glsl_precision precision)
|
||||
: precision(precision)
|
||||
ir_rvalue::ir_rvalue(enum ir_node_type t, glsl_precision precision)
|
||||
: ir_instruction(t)
|
||||
, precision(precision)
|
||||
{
|
||||
this->type = glsl_type::error_type;
|
||||
}
|
||||
@@ -166,8 +166,8 @@ ir_assignment::whole_variable_written()
|
||||
|
||||
ir_assignment::ir_assignment(ir_dereference *lhs, ir_rvalue *rhs,
|
||||
ir_rvalue *condition, unsigned write_mask)
|
||||
: ir_instruction(ir_type_assignment)
|
||||
{
|
||||
this->ir_type = ir_type_assignment;
|
||||
this->condition = condition;
|
||||
this->rhs = rhs;
|
||||
this->lhs = lhs;
|
||||
@@ -186,8 +186,8 @@ ir_assignment::ir_assignment(ir_dereference *lhs, ir_rvalue *rhs,
|
||||
|
||||
ir_assignment::ir_assignment(ir_rvalue *lhs, ir_rvalue *rhs,
|
||||
ir_rvalue *condition)
|
||||
: ir_instruction(ir_type_assignment)
|
||||
{
|
||||
this->ir_type = ir_type_assignment;
|
||||
this->condition = condition;
|
||||
this->rhs = rhs;
|
||||
|
||||
@@ -211,9 +211,8 @@ ir_assignment::ir_assignment(ir_rvalue *lhs, ir_rvalue *rhs,
|
||||
ir_expression::ir_expression(int op, const struct glsl_type *type,
|
||||
ir_rvalue *op0, ir_rvalue *op1,
|
||||
ir_rvalue *op2, ir_rvalue *op3)
|
||||
: ir_rvalue(higher_precision(higher_precision(op0,op1), higher_precision(op2,op3)))
|
||||
: ir_rvalue(ir_type_expression, higher_precision(higher_precision(op0,op1), higher_precision(op2,op3)))
|
||||
{
|
||||
this->ir_type = ir_type_expression;
|
||||
this->type = type;
|
||||
this->operation = ir_expression_operation(op);
|
||||
this->operands[0] = op0;
|
||||
@@ -229,10 +228,8 @@ ir_expression::ir_expression(int op, const struct glsl_type *type,
|
||||
}
|
||||
|
||||
ir_expression::ir_expression(int op, ir_rvalue *op0)
|
||||
: ir_rvalue(precision_from_ir(op0))
|
||||
: ir_rvalue(ir_type_expression, precision_from_ir(op0))
|
||||
{
|
||||
this->ir_type = ir_type_expression;
|
||||
|
||||
this->operation = ir_expression_operation(op);
|
||||
this->operands[0] = op0;
|
||||
this->operands[1] = NULL;
|
||||
@@ -265,8 +262,14 @@ ir_expression::ir_expression(int op, ir_rvalue *op0)
|
||||
case ir_unop_sin_reduced:
|
||||
case ir_unop_cos_reduced:
|
||||
case ir_unop_dFdx:
|
||||
case ir_unop_dFdx_coarse:
|
||||
case ir_unop_dFdx_fine:
|
||||
case ir_unop_dFdy:
|
||||
case ir_unop_dFdy_coarse:
|
||||
case ir_unop_dFdy_fine:
|
||||
case ir_unop_bitfield_reverse:
|
||||
case ir_unop_interpolate_at_centroid:
|
||||
case ir_unop_saturate:
|
||||
this->type = op0->type;
|
||||
break;
|
||||
|
||||
@@ -340,10 +343,8 @@ ir_expression::ir_expression(int op, ir_rvalue *op0)
|
||||
}
|
||||
|
||||
ir_expression::ir_expression(int op, ir_rvalue *op0, ir_rvalue *op1)
|
||||
: ir_rvalue(higher_precision(op0,op1))
|
||||
: ir_rvalue(ir_type_expression, higher_precision(op0,op1))
|
||||
{
|
||||
this->ir_type = ir_type_expression;
|
||||
|
||||
this->operation = ir_expression_operation(op);
|
||||
this->operands[0] = op0;
|
||||
this->operands[1] = op1;
|
||||
@@ -422,6 +423,8 @@ ir_expression::ir_expression(int op, ir_rvalue *op0, ir_rvalue *op1)
|
||||
case ir_binop_rshift:
|
||||
case ir_binop_bfm:
|
||||
case ir_binop_ldexp:
|
||||
case ir_binop_interpolate_at_offset:
|
||||
case ir_binop_interpolate_at_sample:
|
||||
this->type = op0->type;
|
||||
this->set_precision(op0->get_precision());
|
||||
break;
|
||||
@@ -439,10 +442,8 @@ ir_expression::ir_expression(int op, ir_rvalue *op0, ir_rvalue *op1)
|
||||
|
||||
ir_expression::ir_expression(int op, ir_rvalue *op0, ir_rvalue *op1,
|
||||
ir_rvalue *op2)
|
||||
: ir_rvalue(higher_precision(precision_from_ir(op0),higher_precision(op1,op2)))
|
||||
: ir_rvalue(ir_type_expression, higher_precision(precision_from_ir(op0),higher_precision(op1,op2)))
|
||||
{
|
||||
this->ir_type = ir_type_expression;
|
||||
|
||||
this->operation = ir_expression_operation(op);
|
||||
this->operands[0] = op0;
|
||||
this->operands[1] = op1;
|
||||
@@ -531,7 +532,11 @@ static const char *const operator_strs[] = {
|
||||
"sin_reduced",
|
||||
"cos_reduced",
|
||||
"dFdx",
|
||||
"dFdxCoarse",
|
||||
"dFdxFine",
|
||||
"dFdy",
|
||||
"dFdyCoarse",
|
||||
"dFdyFine",
|
||||
"packSnorm2x16",
|
||||
"packSnorm4x8",
|
||||
"packUnorm2x16",
|
||||
@@ -548,7 +553,9 @@ static const char *const operator_strs[] = {
|
||||
"bit_count",
|
||||
"find_msb",
|
||||
"find_lsb",
|
||||
"sat",
|
||||
"noise",
|
||||
"interpolate_at_centroid",
|
||||
"+",
|
||||
"-",
|
||||
"*",
|
||||
@@ -582,6 +589,8 @@ static const char *const operator_strs[] = {
|
||||
"ubo_load",
|
||||
"ldexp",
|
||||
"vector_extract",
|
||||
"interpolate_at_offset",
|
||||
"interpolate_at_sample",
|
||||
"fma",
|
||||
"clamp",
|
||||
"lrp",
|
||||
@@ -633,28 +642,25 @@ ir_expression::get_operator(const char *str)
|
||||
}
|
||||
|
||||
ir_constant::ir_constant()
|
||||
: ir_rvalue(glsl_precision_undefined)
|
||||
: ir_rvalue(ir_type_constant, glsl_precision_undefined)
|
||||
{
|
||||
this->ir_type = ir_type_constant;
|
||||
}
|
||||
|
||||
ir_constant::ir_constant(const struct glsl_type *type,
|
||||
const ir_constant_data *data)
|
||||
: ir_rvalue(glsl_precision_undefined)
|
||||
: ir_rvalue(ir_type_constant, glsl_precision_undefined)
|
||||
{
|
||||
assert((type->base_type >= GLSL_TYPE_UINT)
|
||||
&& (type->base_type <= GLSL_TYPE_BOOL));
|
||||
|
||||
this->ir_type = ir_type_constant;
|
||||
this->type = type;
|
||||
memcpy(& this->value, data, sizeof(this->value));
|
||||
}
|
||||
|
||||
ir_constant::ir_constant(float f, unsigned vector_elements)
|
||||
: ir_rvalue(glsl_precision_undefined)
|
||||
: ir_rvalue(ir_type_constant, glsl_precision_undefined)
|
||||
{
|
||||
assert(vector_elements <= 4);
|
||||
this->ir_type = ir_type_constant;
|
||||
this->type = glsl_type::get_instance(GLSL_TYPE_FLOAT, vector_elements, 1);
|
||||
for (unsigned i = 0; i < vector_elements; i++) {
|
||||
this->value.f[i] = f;
|
||||
@@ -665,10 +671,9 @@ ir_constant::ir_constant(float f, unsigned vector_elements)
|
||||
}
|
||||
|
||||
ir_constant::ir_constant(unsigned int u, unsigned vector_elements)
|
||||
: ir_rvalue(glsl_precision_undefined)
|
||||
: ir_rvalue(ir_type_constant, glsl_precision_undefined)
|
||||
{
|
||||
assert(vector_elements <= 4);
|
||||
this->ir_type = ir_type_constant;
|
||||
this->type = glsl_type::get_instance(GLSL_TYPE_UINT, vector_elements, 1);
|
||||
for (unsigned i = 0; i < vector_elements; i++) {
|
||||
this->value.u[i] = u;
|
||||
@@ -679,10 +684,9 @@ ir_constant::ir_constant(unsigned int u, unsigned vector_elements)
|
||||
}
|
||||
|
||||
ir_constant::ir_constant(int integer, unsigned vector_elements)
|
||||
: ir_rvalue(glsl_precision_undefined)
|
||||
: ir_rvalue(ir_type_constant, glsl_precision_undefined)
|
||||
{
|
||||
assert(vector_elements <= 4);
|
||||
this->ir_type = ir_type_constant;
|
||||
this->type = glsl_type::get_instance(GLSL_TYPE_INT, vector_elements, 1);
|
||||
for (unsigned i = 0; i < vector_elements; i++) {
|
||||
this->value.i[i] = integer;
|
||||
@@ -693,10 +697,9 @@ ir_constant::ir_constant(int integer, unsigned vector_elements)
|
||||
}
|
||||
|
||||
ir_constant::ir_constant(bool b, unsigned vector_elements)
|
||||
: ir_rvalue(glsl_precision_undefined)
|
||||
: ir_rvalue(ir_type_constant, glsl_precision_undefined)
|
||||
{
|
||||
assert(vector_elements <= 4);
|
||||
this->ir_type = ir_type_constant;
|
||||
this->type = glsl_type::get_instance(GLSL_TYPE_BOOL, vector_elements, 1);
|
||||
for (unsigned i = 0; i < vector_elements; i++) {
|
||||
this->value.b[i] = b;
|
||||
@@ -707,9 +710,8 @@ ir_constant::ir_constant(bool b, unsigned vector_elements)
|
||||
}
|
||||
|
||||
ir_constant::ir_constant(const ir_constant *c, unsigned i)
|
||||
: ir_rvalue(c->precision)
|
||||
: ir_rvalue(ir_type_constant, c->precision)
|
||||
{
|
||||
this->ir_type = ir_type_constant;
|
||||
this->type = c->type->get_base_type();
|
||||
|
||||
switch (this->type->base_type) {
|
||||
@@ -722,9 +724,8 @@ ir_constant::ir_constant(const ir_constant *c, unsigned i)
|
||||
}
|
||||
|
||||
ir_constant::ir_constant(const struct glsl_type *type, exec_list *value_list)
|
||||
: ir_rvalue(glsl_precision_undefined)
|
||||
: ir_rvalue(ir_type_constant, glsl_precision_undefined)
|
||||
{
|
||||
this->ir_type = ir_type_constant;
|
||||
this->type = type;
|
||||
|
||||
assert(type->is_scalar() || type->is_vector() || type->is_matrix()
|
||||
@@ -733,8 +734,7 @@ ir_constant::ir_constant(const struct glsl_type *type, exec_list *value_list)
|
||||
if (type->is_array()) {
|
||||
this->array_elements = ralloc_array(this, ir_constant *, type->length);
|
||||
unsigned i = 0;
|
||||
foreach_list(node, value_list) {
|
||||
ir_constant *value = (ir_constant *) node;
|
||||
foreach_in_list(ir_constant, value, value_list) {
|
||||
assert(value->as_constant() != NULL);
|
||||
|
||||
this->array_elements[i++] = value;
|
||||
@@ -1035,9 +1035,7 @@ ir_constant::copy_offset(ir_constant *src, int offset)
|
||||
case GLSL_TYPE_STRUCT: {
|
||||
assert (src->type == this->type);
|
||||
this->components.make_empty();
|
||||
foreach_list(node, &src->components) {
|
||||
ir_constant *const orig = (ir_constant *) node;
|
||||
|
||||
foreach_in_list(ir_constant, orig, &src->components) {
|
||||
this->components.push_tail(orig->clone(this, NULL));
|
||||
}
|
||||
break;
|
||||
@@ -1254,18 +1252,26 @@ ir_constant::is_basis() const
|
||||
return ones == 1;
|
||||
}
|
||||
|
||||
ir_loop::ir_loop()
|
||||
bool
|
||||
ir_constant::is_uint16_constant() const
|
||||
{
|
||||
if (!type->is_integer())
|
||||
return false;
|
||||
|
||||
return value.u[0] < (1 << 16);
|
||||
}
|
||||
|
||||
ir_loop::ir_loop()
|
||||
: ir_instruction(ir_type_loop)
|
||||
{
|
||||
this->ir_type = ir_type_loop;
|
||||
}
|
||||
|
||||
|
||||
ir_dereference_variable::ir_dereference_variable(ir_variable *var)
|
||||
: ir_dereference(precision_from_ir(var))
|
||||
: ir_dereference(ir_type_dereference_variable, precision_from_ir(var))
|
||||
{
|
||||
assert(var != NULL);
|
||||
|
||||
this->ir_type = ir_type_dereference_variable;
|
||||
this->var = var;
|
||||
this->type = var->type;
|
||||
}
|
||||
@@ -1273,9 +1279,8 @@ ir_dereference_variable::ir_dereference_variable(ir_variable *var)
|
||||
|
||||
ir_dereference_array::ir_dereference_array(ir_rvalue *value,
|
||||
ir_rvalue *array_index)
|
||||
: ir_dereference(precision_from_ir(value))
|
||||
: ir_dereference(ir_type_dereference_array, precision_from_ir(value))
|
||||
{
|
||||
this->ir_type = ir_type_dereference_array;
|
||||
this->array_index = array_index;
|
||||
this->set_array(value);
|
||||
}
|
||||
@@ -1283,11 +1288,10 @@ ir_dereference_array::ir_dereference_array(ir_rvalue *value,
|
||||
|
||||
ir_dereference_array::ir_dereference_array(ir_variable *var,
|
||||
ir_rvalue *array_index)
|
||||
: ir_dereference(precision_from_ir(var))
|
||||
: ir_dereference(ir_type_dereference_array, precision_from_ir(var))
|
||||
{
|
||||
void *ctx = ralloc_parent(var);
|
||||
|
||||
this->ir_type = ir_type_dereference_array;
|
||||
this->array_index = array_index;
|
||||
this->set_array(new(ctx) ir_dereference_variable(var));
|
||||
}
|
||||
@@ -1314,11 +1318,10 @@ ir_dereference_array::set_array(ir_rvalue *value)
|
||||
|
||||
ir_dereference_record::ir_dereference_record(ir_rvalue *value,
|
||||
const char *field)
|
||||
: ir_dereference(precision_from_ir(value))
|
||||
: ir_dereference(ir_type_dereference_record, precision_from_ir(value))
|
||||
{
|
||||
assert(value != NULL);
|
||||
|
||||
this->ir_type = ir_type_dereference_record;
|
||||
this->record = value;
|
||||
this->field = ralloc_strdup(this, field);
|
||||
this->type = this->record->type->field_type(field);
|
||||
@@ -1329,11 +1332,10 @@ ir_dereference_record::ir_dereference_record(ir_rvalue *value,
|
||||
|
||||
ir_dereference_record::ir_dereference_record(ir_variable *var,
|
||||
const char *field)
|
||||
: ir_dereference(precision_from_ir(var))
|
||||
: ir_dereference(ir_type_dereference_record, precision_from_ir(var))
|
||||
{
|
||||
void *ctx = ralloc_parent(var);
|
||||
|
||||
this->ir_type = ir_type_dereference_record;
|
||||
this->record = new(ctx) ir_dereference_variable(var);
|
||||
this->field = ralloc_strdup(this, field);
|
||||
this->type = this->record->type->field_type(field);
|
||||
@@ -1364,7 +1366,7 @@ ir_dereference::is_lvalue() const
|
||||
}
|
||||
|
||||
|
||||
static const char *tex_opcode_strs[] = { "tex", "txb", "txl", "txd", "txf", "txf_ms", "txs", "lod", "tg4", "query_levels" };
|
||||
static const char * const tex_opcode_strs[] = { "tex", "txb", "txl", "txd", "txf", "txf_ms", "txs", "lod", "tg4", "query_levels" };
|
||||
|
||||
const char *ir_texture::opcode_string()
|
||||
{
|
||||
@@ -1452,25 +1454,22 @@ ir_swizzle::init_mask(const unsigned *comp, unsigned count)
|
||||
|
||||
ir_swizzle::ir_swizzle(ir_rvalue *val, unsigned x, unsigned y, unsigned z,
|
||||
unsigned w, unsigned count)
|
||||
: ir_rvalue(precision_from_ir(val)), val(val)
|
||||
: ir_rvalue(ir_type_swizzle, precision_from_ir(val)), val(val)
|
||||
{
|
||||
const unsigned components[4] = { x, y, z, w };
|
||||
this->ir_type = ir_type_swizzle;
|
||||
this->init_mask(components, count);
|
||||
}
|
||||
|
||||
ir_swizzle::ir_swizzle(ir_rvalue *val, const unsigned *comp,
|
||||
unsigned count)
|
||||
: ir_rvalue(precision_from_ir(val)), val(val)
|
||||
: ir_rvalue(ir_type_swizzle, precision_from_ir(val)), val(val)
|
||||
{
|
||||
this->ir_type = ir_type_swizzle;
|
||||
this->init_mask(comp, count);
|
||||
}
|
||||
|
||||
ir_swizzle::ir_swizzle(ir_rvalue *val, ir_swizzle_mask mask)
|
||||
: ir_rvalue(precision_from_ir(val))
|
||||
: ir_rvalue(ir_type_swizzle, precision_from_ir(val))
|
||||
{
|
||||
this->ir_type = ir_type_swizzle;
|
||||
this->val = val;
|
||||
this->mask = mask;
|
||||
this->type = glsl_type::get_instance(val->type->base_type,
|
||||
@@ -1566,18 +1565,45 @@ ir_swizzle::variable_referenced() const
|
||||
return this->val->variable_referenced();
|
||||
}
|
||||
|
||||
|
||||
bool ir_variable::temporaries_allocate_names = false;
|
||||
|
||||
const char ir_variable::tmp_name[] = "compiler_temp";
|
||||
|
||||
ir_variable::ir_variable(const struct glsl_type *type, const char *name,
|
||||
ir_variable_mode mode, glsl_precision precision)
|
||||
: max_ifc_array_access(NULL)
|
||||
: ir_instruction(ir_type_variable)
|
||||
{
|
||||
this->ir_type = ir_type_variable;
|
||||
this->type = type;
|
||||
this->name = ralloc_strdup(this, name);
|
||||
|
||||
if (mode == ir_var_temporary && !ir_variable::temporaries_allocate_names)
|
||||
name = NULL;
|
||||
|
||||
/* The ir_variable clone method may call this constructor with name set to
|
||||
* tmp_name.
|
||||
*/
|
||||
assert(name != NULL
|
||||
|| mode == ir_var_temporary
|
||||
|| mode == ir_var_function_in
|
||||
|| mode == ir_var_function_out
|
||||
|| mode == ir_var_function_inout);
|
||||
assert(name != ir_variable::tmp_name
|
||||
|| mode == ir_var_temporary);
|
||||
if (mode == ir_var_temporary
|
||||
&& (name == NULL || name == ir_variable::tmp_name)) {
|
||||
this->name = ir_variable::tmp_name;
|
||||
} else {
|
||||
this->name = ralloc_strdup(this, name);
|
||||
}
|
||||
|
||||
this->u.max_ifc_array_access = NULL;
|
||||
|
||||
this->data.explicit_location = false;
|
||||
this->data.has_initializer = false;
|
||||
this->data.location = -1;
|
||||
this->data.location_frac = 0;
|
||||
this->warn_extension = NULL;
|
||||
this->data.binding = 0;
|
||||
this->data.warn_extension_index = 0;
|
||||
this->constant_value = NULL;
|
||||
this->constant_initializer = NULL;
|
||||
this->data.origin_upper_left = false;
|
||||
@@ -1593,13 +1619,12 @@ ir_variable::ir_variable(const struct glsl_type *type, const char *name,
|
||||
this->data.precision = precision;
|
||||
this->data.interpolation = INTERP_QUALIFIER_NONE;
|
||||
this->data.max_array_access = 0;
|
||||
this->data.atomic.buffer_index = 0;
|
||||
this->data.atomic.offset = 0;
|
||||
this->data.image.read_only = false;
|
||||
this->data.image.write_only = false;
|
||||
this->data.image.coherent = false;
|
||||
this->data.image._volatile = false;
|
||||
this->data.image.restrict_flag = false;
|
||||
this->data.image_read_only = false;
|
||||
this->data.image_write_only = false;
|
||||
this->data.image_coherent = false;
|
||||
this->data.image_volatile = false;
|
||||
this->data.image_restrict = false;
|
||||
|
||||
if (type != NULL) {
|
||||
if (type->base_type == GLSL_TYPE_SAMPLER)
|
||||
@@ -1642,13 +1667,39 @@ ir_variable::determine_interpolation_mode(bool flat_shade)
|
||||
return INTERP_QUALIFIER_SMOOTH;
|
||||
}
|
||||
|
||||
const char *const ir_variable::warn_extension_table[] = {
|
||||
"",
|
||||
"GL_ARB_shader_stencil_export",
|
||||
"GL_AMD_shader_stencil_export",
|
||||
};
|
||||
|
||||
void
|
||||
ir_variable::enable_extension_warning(const char *extension)
|
||||
{
|
||||
for (unsigned i = 0; i < Elements(warn_extension_table); i++) {
|
||||
if (strcmp(warn_extension_table[i], extension) == 0) {
|
||||
this->data.warn_extension_index = i;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
assert(!"Should not get here.");
|
||||
this->data.warn_extension_index = 0;
|
||||
}
|
||||
|
||||
const char *
|
||||
ir_variable::get_extension_warning() const
|
||||
{
|
||||
return this->data.warn_extension_index == 0
|
||||
? NULL : warn_extension_table[this->data.warn_extension_index];
|
||||
}
|
||||
|
||||
ir_function_signature::ir_function_signature(const glsl_type *return_type,
|
||||
glsl_precision precision, builtin_available_predicate b)
|
||||
: return_type(return_type), precision(precision), is_defined(false), is_intrinsic(false),
|
||||
: ir_instruction(ir_type_function_signature),
|
||||
return_type(return_type), precision(precision), is_defined(false), is_intrinsic(false),
|
||||
builtin_avail(b), _function(NULL)
|
||||
{
|
||||
this->ir_type = ir_type_function_signature;
|
||||
this->origin = NULL;
|
||||
}
|
||||
|
||||
@@ -1706,11 +1757,11 @@ ir_function_signature::qualifiers_match(exec_list *params)
|
||||
a->data.interpolation != b->data.interpolation ||
|
||||
a->data.centroid != b->data.centroid ||
|
||||
a->data.sample != b->data.sample ||
|
||||
a->data.image.read_only != b->data.image.read_only ||
|
||||
a->data.image.write_only != b->data.image.write_only ||
|
||||
a->data.image.coherent != b->data.image.coherent ||
|
||||
a->data.image._volatile != b->data.image._volatile ||
|
||||
a->data.image.restrict_flag != b->data.image.restrict_flag) {
|
||||
a->data.image_read_only != b->data.image_read_only ||
|
||||
a->data.image_write_only != b->data.image_write_only ||
|
||||
a->data.image_coherent != b->data.image_coherent ||
|
||||
a->data.image_volatile != b->data.image_volatile ||
|
||||
a->data.image_restrict != b->data.image_restrict) {
|
||||
|
||||
/* parameter a's qualifiers don't match */
|
||||
return a->name;
|
||||
@@ -1732,8 +1783,8 @@ ir_function_signature::replace_parameters(exec_list *new_params)
|
||||
|
||||
|
||||
ir_function::ir_function(const char *name)
|
||||
: ir_instruction(ir_type_function)
|
||||
{
|
||||
this->ir_type = ir_type_function;
|
||||
this->name = ralloc_strdup(this, name);
|
||||
}
|
||||
|
||||
@@ -1741,8 +1792,7 @@ ir_function::ir_function(const char *name)
|
||||
bool
|
||||
ir_function::has_user_signature()
|
||||
{
|
||||
foreach_list(n, &this->signatures) {
|
||||
ir_function_signature *const sig = (ir_function_signature *) n;
|
||||
foreach_in_list(ir_function_signature, sig, &this->signatures) {
|
||||
if (!sig->is_builtin())
|
||||
return true;
|
||||
}
|
||||
@@ -1753,7 +1803,7 @@ ir_function::has_user_signature()
|
||||
ir_rvalue *
|
||||
ir_rvalue::error_value(void *mem_ctx)
|
||||
{
|
||||
ir_rvalue *v = new(mem_ctx) ir_rvalue(glsl_precision_undefined);
|
||||
ir_rvalue *v = new(mem_ctx) ir_rvalue(ir_type_unset, glsl_precision_undefined);
|
||||
|
||||
v->type = glsl_type::error_type;
|
||||
return v;
|
||||
@@ -1763,8 +1813,8 @@ ir_rvalue::error_value(void *mem_ctx)
|
||||
void
|
||||
visit_exec_list(exec_list *list, ir_visitor *visitor)
|
||||
{
|
||||
foreach_list_safe(n, list) {
|
||||
((ir_instruction *) n)->accept(visitor);
|
||||
foreach_in_list_safe(ir_instruction, node, list) {
|
||||
node->accept(visitor);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1785,8 +1835,7 @@ steal_memory(ir_instruction *ir, void *new_ctx)
|
||||
*/
|
||||
if (constant != NULL) {
|
||||
if (constant->type->is_record()) {
|
||||
foreach_list(n, &constant->components) {
|
||||
ir_constant *field = (ir_constant *) n;
|
||||
foreach_in_list(ir_constant, field, &constant->components) {
|
||||
steal_memory(field, ir);
|
||||
}
|
||||
} else if (constant->type->is_array()) {
|
||||
@@ -1803,8 +1852,8 @@ steal_memory(ir_instruction *ir, void *new_ctx)
|
||||
void
|
||||
reparent_ir(exec_list *list, void *mem_ctx)
|
||||
{
|
||||
foreach_list(node, list) {
|
||||
visit_tree((ir_instruction *) node, steal_memory, mem_ctx);
|
||||
foreach_in_list(ir_instruction, node, list) {
|
||||
visit_tree(node, steal_memory, mem_ctx);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1926,6 +1975,9 @@ mode_string(const ir_variable *var)
|
||||
case ir_var_shader_out:
|
||||
return "shader output";
|
||||
|
||||
case ir_var_shader_inout:
|
||||
return "shader inout";
|
||||
|
||||
case ir_var_function_in:
|
||||
case ir_var_const_in:
|
||||
return "function input";
|
||||
|
||||
633
3rdparty/glsl-optimizer/src/glsl/ir.h
vendored
633
3rdparty/glsl-optimizer/src/glsl/ir.h
vendored
File diff suppressed because it is too large
Load Diff
@@ -28,9 +28,7 @@
|
||||
*/
|
||||
|
||||
#include "ir.h"
|
||||
#include "ir_visitor.h"
|
||||
#include "ir_basic_block.h"
|
||||
#include "glsl_types.h"
|
||||
|
||||
|
||||
static ir_if* as_if_skip_discard (ir_instruction* ir)
|
||||
@@ -43,8 +41,7 @@ static ir_if* as_if_skip_discard (ir_instruction* ir)
|
||||
|
||||
bool only_discards = true;
|
||||
int count = 0;
|
||||
foreach_list(node, &irif->then_instructions) {
|
||||
ir_instruction *iir = (ir_instruction *)node;
|
||||
foreach_in_list(ir_instruction, iir, &irif->then_instructions) {
|
||||
if (!iir->as_discard())
|
||||
{
|
||||
only_discards = false;
|
||||
@@ -85,8 +82,7 @@ void call_for_basic_blocks(exec_list *instructions,
|
||||
ir_instruction *leader = NULL;
|
||||
ir_instruction *last = NULL;
|
||||
|
||||
foreach_list(n, instructions) {
|
||||
ir_instruction *ir = (ir_instruction *) n;
|
||||
foreach_in_list(ir_instruction, ir, instructions) {
|
||||
ir_if *ir_if;
|
||||
ir_loop *ir_loop;
|
||||
ir_function *ir_function;
|
||||
@@ -117,9 +113,7 @@ void call_for_basic_blocks(exec_list *instructions,
|
||||
* and the body of main(). Perhaps those instructions ought
|
||||
* to live inside of main().
|
||||
*/
|
||||
foreach_list(func_node, &ir_function->signatures) {
|
||||
ir_function_signature *ir_sig = (ir_function_signature *) func_node;
|
||||
|
||||
foreach_in_list(ir_function_signature, ir_sig, &ir_function->signatures) {
|
||||
call_for_basic_blocks(&ir_sig->body, callback, data);
|
||||
}
|
||||
}
|
||||
|
||||
35
3rdparty/glsl-optimizer/src/glsl/ir_builder.cpp
vendored
35
3rdparty/glsl-optimizer/src/glsl/ir_builder.cpp
vendored
@@ -35,11 +35,11 @@ ir_factory::emit(ir_instruction *ir)
|
||||
}
|
||||
|
||||
ir_variable *
|
||||
ir_factory::make_temp(const glsl_type *type, const char *name)
|
||||
ir_factory::make_temp(const glsl_type *type, const char *name, glsl_precision prec)
|
||||
{
|
||||
ir_variable *var;
|
||||
|
||||
var = new(mem_ctx) ir_variable(type, name, ir_var_temporary, glsl_precision_undefined);
|
||||
var = new(mem_ctx) ir_variable(type, name, ir_var_temporary, prec);
|
||||
emit(var);
|
||||
|
||||
return var;
|
||||
@@ -251,13 +251,8 @@ ir_expression *round_even(operand a)
|
||||
return expr(ir_unop_round_even, a);
|
||||
}
|
||||
|
||||
ir_expression *dot(operand a, operand b)
|
||||
{
|
||||
return expr(ir_binop_dot, a, b);
|
||||
}
|
||||
|
||||
/* dot for vectors, mul for scalars */
|
||||
ir_expression *dotlike(operand a, operand b)
|
||||
ir_expression *dot(operand a, operand b)
|
||||
{
|
||||
assert(a.val->type == b.val->type);
|
||||
|
||||
@@ -276,11 +271,7 @@ clamp(operand a, operand b, operand c)
|
||||
ir_expression *
|
||||
saturate(operand a)
|
||||
{
|
||||
void *mem_ctx = ralloc_parent(a.val);
|
||||
|
||||
return expr(ir_binop_max,
|
||||
expr(ir_binop_min, a, new(mem_ctx) ir_constant(1.0f)),
|
||||
new(mem_ctx) ir_constant(0.0f));
|
||||
return expr(ir_unop_saturate, a);
|
||||
}
|
||||
|
||||
ir_expression *
|
||||
@@ -505,6 +496,24 @@ b2f(operand a)
|
||||
return expr(ir_unop_b2f, a);
|
||||
}
|
||||
|
||||
ir_expression *
|
||||
interpolate_at_centroid(operand a)
|
||||
{
|
||||
return expr(ir_unop_interpolate_at_centroid, a);
|
||||
}
|
||||
|
||||
ir_expression *
|
||||
interpolate_at_offset(operand a, operand b)
|
||||
{
|
||||
return expr(ir_binop_interpolate_at_offset, a, b);
|
||||
}
|
||||
|
||||
ir_expression *
|
||||
interpolate_at_sample(operand a, operand b)
|
||||
{
|
||||
return expr(ir_binop_interpolate_at_sample, a, b);
|
||||
}
|
||||
|
||||
ir_expression *
|
||||
fma(operand a, operand b, operand c)
|
||||
{
|
||||
|
||||
@@ -90,7 +90,7 @@ public:
|
||||
}
|
||||
|
||||
void emit(ir_instruction *ir);
|
||||
ir_variable *make_temp(const glsl_type *type, const char *name);
|
||||
ir_variable *make_temp(const glsl_type *type, const char *name, glsl_precision prec = glsl_precision_undefined);
|
||||
|
||||
ir_constant*
|
||||
constant(float f)
|
||||
@@ -139,7 +139,6 @@ ir_expression *carry(operand a, operand b);
|
||||
ir_expression *borrow(operand a, operand b);
|
||||
ir_expression *round_even(operand a);
|
||||
ir_expression *dot(operand a, operand b);
|
||||
ir_expression *dotlike(operand a, operand b);
|
||||
ir_expression *clamp(operand a, operand b, operand c);
|
||||
ir_expression *saturate(operand a);
|
||||
ir_expression *abs(operand a);
|
||||
@@ -187,6 +186,10 @@ ir_expression *b2f(operand a);
|
||||
ir_expression *min2(operand a, operand b);
|
||||
ir_expression *max2(operand a, operand b);
|
||||
|
||||
ir_expression *interpolate_at_centroid(operand a);
|
||||
ir_expression *interpolate_at_offset(operand a, operand b);
|
||||
ir_expression *interpolate_at_sample(operand a, operand b);
|
||||
|
||||
ir_expression *fma(operand a, operand b, operand c);
|
||||
ir_expression *lrp(operand x, operand y, operand a);
|
||||
ir_expression *csel(operand a, operand b, operand c);
|
||||
|
||||
59
3rdparty/glsl-optimizer/src/glsl/ir_clone.cpp
vendored
59
3rdparty/glsl-optimizer/src/glsl/ir_clone.cpp
vendored
@@ -28,7 +28,7 @@
|
||||
#include "program/hash_table.h"
|
||||
|
||||
ir_rvalue *
|
||||
ir_rvalue::clone(void *mem_ctx, struct hash_table *ht) const
|
||||
ir_rvalue::clone(void *mem_ctx, struct hash_table *) const
|
||||
{
|
||||
/* The only possible instantiation is the generic error value. */
|
||||
return error_value(mem_ctx);
|
||||
@@ -45,25 +45,18 @@ ir_variable::clone(void *mem_ctx, struct hash_table *ht) const
|
||||
|
||||
var->data.max_array_access = this->data.max_array_access;
|
||||
if (this->is_interface_instance()) {
|
||||
var->max_ifc_array_access =
|
||||
var->u.max_ifc_array_access =
|
||||
rzalloc_array(var, unsigned, this->interface_type->length);
|
||||
memcpy(var->max_ifc_array_access, this->max_ifc_array_access,
|
||||
memcpy(var->u.max_ifc_array_access, this->u.max_ifc_array_access,
|
||||
this->interface_type->length * sizeof(unsigned));
|
||||
}
|
||||
|
||||
memcpy(&var->data, &this->data, sizeof(var->data));
|
||||
|
||||
var->warn_extension = this->warn_extension;
|
||||
|
||||
var->num_state_slots = this->num_state_slots;
|
||||
if (this->state_slots) {
|
||||
/* FINISHME: This really wants to use something like talloc_reference, but
|
||||
* FINISHME: ralloc doesn't have any similar function.
|
||||
*/
|
||||
var->state_slots = ralloc_array(var, ir_state_slot,
|
||||
this->num_state_slots);
|
||||
memcpy(var->state_slots, this->state_slots,
|
||||
sizeof(this->state_slots[0]) * var->num_state_slots);
|
||||
if (this->get_state_slots()) {
|
||||
ir_state_slot *s = var->allocate_state_slots(this->get_num_state_slots());
|
||||
memcpy(s, this->get_state_slots(),
|
||||
sizeof(s[0]) * var->get_num_state_slots());
|
||||
}
|
||||
|
||||
if (this->constant_value)
|
||||
@@ -125,13 +118,11 @@ ir_if::clone(void *mem_ctx, struct hash_table *ht) const
|
||||
{
|
||||
ir_if *new_if = new(mem_ctx) ir_if(this->condition->clone(mem_ctx, ht));
|
||||
|
||||
foreach_list(n, &this->then_instructions) {
|
||||
ir_instruction *ir = (ir_instruction *) n;
|
||||
foreach_in_list(ir_instruction, ir, &this->then_instructions) {
|
||||
new_if->then_instructions.push_tail(ir->clone(mem_ctx, ht));
|
||||
}
|
||||
|
||||
foreach_list(n, &this->else_instructions) {
|
||||
ir_instruction *ir = (ir_instruction *) n;
|
||||
foreach_in_list(ir_instruction, ir, &this->else_instructions) {
|
||||
new_if->else_instructions.push_tail(ir->clone(mem_ctx, ht));
|
||||
}
|
||||
|
||||
@@ -143,8 +134,7 @@ ir_loop::clone(void *mem_ctx, struct hash_table *ht) const
|
||||
{
|
||||
ir_loop *new_loop = new(mem_ctx) ir_loop();
|
||||
|
||||
foreach_list(n, &this->body_instructions) {
|
||||
ir_instruction *ir = (ir_instruction *) n;
|
||||
foreach_in_list(ir_instruction, ir, &this->body_instructions) {
|
||||
new_loop->body_instructions.push_tail(ir->clone(mem_ctx, ht));
|
||||
}
|
||||
|
||||
@@ -160,8 +150,7 @@ ir_call::clone(void *mem_ctx, struct hash_table *ht) const
|
||||
|
||||
exec_list new_parameters;
|
||||
|
||||
foreach_list(n, &this->actual_parameters) {
|
||||
ir_instruction *ir = (ir_instruction *) n;
|
||||
foreach_in_list(ir_instruction, ir, &this->actual_parameters) {
|
||||
new_parameters.push_tail(ir->clone(mem_ctx, ht));
|
||||
}
|
||||
|
||||
@@ -267,10 +256,12 @@ ir_assignment::clone(void *mem_ctx, struct hash_table *ht) const
|
||||
if (this->condition)
|
||||
new_condition = this->condition->clone(mem_ctx, ht);
|
||||
|
||||
return new(mem_ctx) ir_assignment(this->lhs->clone(mem_ctx, ht),
|
||||
this->rhs->clone(mem_ctx, ht),
|
||||
new_condition,
|
||||
this->write_mask);
|
||||
ir_assignment *cloned =
|
||||
new(mem_ctx) ir_assignment(this->lhs->clone(mem_ctx, ht),
|
||||
this->rhs->clone(mem_ctx, ht),
|
||||
new_condition);
|
||||
cloned->write_mask = this->write_mask;
|
||||
return cloned;
|
||||
}
|
||||
|
||||
ir_function *
|
||||
@@ -278,10 +269,7 @@ ir_function::clone(void *mem_ctx, struct hash_table *ht) const
|
||||
{
|
||||
ir_function *copy = new(mem_ctx) ir_function(this->name);
|
||||
|
||||
foreach_list_const(node, &this->signatures) {
|
||||
const ir_function_signature *const sig =
|
||||
(const ir_function_signature *const) node;
|
||||
|
||||
foreach_in_list(const ir_function_signature, sig, &this->signatures) {
|
||||
ir_function_signature *sig_copy = sig->clone(mem_ctx, ht);
|
||||
copy->add_signature(sig_copy);
|
||||
|
||||
@@ -302,9 +290,7 @@ ir_function_signature::clone(void *mem_ctx, struct hash_table *ht) const
|
||||
|
||||
/* Clone the instruction list.
|
||||
*/
|
||||
foreach_list_const(node, &this->body) {
|
||||
const ir_instruction *const inst = (const ir_instruction *) node;
|
||||
|
||||
foreach_in_list(const ir_instruction, inst, &this->body) {
|
||||
ir_instruction *const inst_copy = inst->clone(mem_ctx, ht);
|
||||
copy->body.push_tail(inst_copy);
|
||||
}
|
||||
@@ -324,9 +310,7 @@ ir_function_signature::clone_prototype(void *mem_ctx, struct hash_table *ht) con
|
||||
|
||||
/* Clone the parameter list, but NOT the body.
|
||||
*/
|
||||
foreach_list_const(node, &this->parameters) {
|
||||
const ir_variable *const param = (const ir_variable *) node;
|
||||
|
||||
foreach_in_list(const ir_variable, param, &this->parameters) {
|
||||
assert(const_cast<ir_variable *>(param)->as_variable() != NULL);
|
||||
|
||||
ir_variable *const param_copy = param->clone(mem_ctx, ht);
|
||||
@@ -444,8 +428,7 @@ clone_ir_list(void *mem_ctx, exec_list *out, const exec_list *in)
|
||||
struct hash_table *ht =
|
||||
hash_table_ctor(0, hash_table_pointer_hash, hash_table_pointer_compare);
|
||||
|
||||
foreach_list_const(node, in) {
|
||||
const ir_instruction *const original = (ir_instruction *) node;
|
||||
foreach_in_list(const ir_instruction, original, in) {
|
||||
ir_instruction *copy = original->clone(mem_ctx, ht);
|
||||
|
||||
out->push_tail(copy);
|
||||
|
||||
@@ -36,7 +36,6 @@
|
||||
#include <math.h>
|
||||
#include "main/core.h" /* for MAX2, MIN2, CLAMP */
|
||||
#include "ir.h"
|
||||
#include "ir_visitor.h"
|
||||
#include "glsl_types.h"
|
||||
#include "program/hash_table.h"
|
||||
|
||||
@@ -53,7 +52,7 @@ static int isnormal(double x)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1800
|
||||
static double copysign(double x, double y)
|
||||
{
|
||||
return _copysign(x, y);
|
||||
@@ -386,8 +385,104 @@ unpack_half_1x16(uint16_t u)
|
||||
return _mesa_half_to_float(u);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the constant that is ultimately referenced by an r-value, in a constant
|
||||
* expression evaluation context.
|
||||
*
|
||||
* The offset is used when the reference is to a specific column of a matrix.
|
||||
*/
|
||||
static bool
|
||||
constant_referenced(const ir_dereference *deref,
|
||||
struct hash_table *variable_context,
|
||||
ir_constant *&store, int &offset)
|
||||
{
|
||||
store = NULL;
|
||||
offset = 0;
|
||||
|
||||
if (variable_context == NULL)
|
||||
return false;
|
||||
|
||||
switch (deref->ir_type) {
|
||||
case ir_type_dereference_array: {
|
||||
const ir_dereference_array *const da =
|
||||
(const ir_dereference_array *) deref;
|
||||
|
||||
ir_constant *const index_c =
|
||||
da->array_index->constant_expression_value(variable_context);
|
||||
|
||||
if (!index_c || !index_c->type->is_scalar() || !index_c->type->is_integer())
|
||||
break;
|
||||
|
||||
const int index = index_c->type->base_type == GLSL_TYPE_INT ?
|
||||
index_c->get_int_component(0) :
|
||||
index_c->get_uint_component(0);
|
||||
|
||||
ir_constant *substore;
|
||||
int suboffset;
|
||||
|
||||
const ir_dereference *const deref = da->array->as_dereference();
|
||||
if (!deref)
|
||||
break;
|
||||
|
||||
if (!constant_referenced(deref, variable_context, substore, suboffset))
|
||||
break;
|
||||
|
||||
const glsl_type *const vt = da->array->type;
|
||||
if (vt->is_array()) {
|
||||
store = substore->get_array_element(index);
|
||||
offset = 0;
|
||||
} else if (vt->is_matrix()) {
|
||||
store = substore;
|
||||
offset = index * vt->vector_elements;
|
||||
} else if (vt->is_vector()) {
|
||||
store = substore;
|
||||
offset = suboffset + index;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case ir_type_dereference_record: {
|
||||
const ir_dereference_record *const dr =
|
||||
(const ir_dereference_record *) deref;
|
||||
|
||||
const ir_dereference *const deref = dr->record->as_dereference();
|
||||
if (!deref)
|
||||
break;
|
||||
|
||||
ir_constant *substore;
|
||||
int suboffset;
|
||||
|
||||
if (!constant_referenced(deref, variable_context, substore, suboffset))
|
||||
break;
|
||||
|
||||
/* Since we're dropping it on the floor...
|
||||
*/
|
||||
assert(suboffset == 0);
|
||||
|
||||
store = substore->get_record_field(dr->field);
|
||||
break;
|
||||
}
|
||||
|
||||
case ir_type_dereference_variable: {
|
||||
const ir_dereference_variable *const dv =
|
||||
(const ir_dereference_variable *) deref;
|
||||
|
||||
store = (ir_constant *) hash_table_find(variable_context, dv->var);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
assert(!"Should not get here.");
|
||||
break;
|
||||
}
|
||||
|
||||
return store != NULL;
|
||||
}
|
||||
|
||||
|
||||
ir_constant *
|
||||
ir_rvalue::constant_expression_value(struct hash_table *variable_context)
|
||||
ir_rvalue::constant_expression_value(struct hash_table *)
|
||||
{
|
||||
assert(this->type->is_error());
|
||||
return NULL;
|
||||
@@ -415,6 +510,8 @@ ir_expression::constant_expression_value(struct hash_table *variable_context)
|
||||
case ir_binop_lshift:
|
||||
case ir_binop_rshift:
|
||||
case ir_binop_ldexp:
|
||||
case ir_binop_interpolate_at_offset:
|
||||
case ir_binop_interpolate_at_sample:
|
||||
case ir_binop_vector_extract:
|
||||
case ir_triop_csel:
|
||||
case ir_triop_bitfield_extract:
|
||||
@@ -771,7 +868,11 @@ ir_expression::constant_expression_value(struct hash_table *variable_context)
|
||||
break;
|
||||
|
||||
case ir_unop_dFdx:
|
||||
case ir_unop_dFdx_coarse:
|
||||
case ir_unop_dFdx_fine:
|
||||
case ir_unop_dFdy:
|
||||
case ir_unop_dFdy_coarse:
|
||||
case ir_unop_dFdy_fine:
|
||||
assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
|
||||
for (unsigned c = 0; c < op[0]->type->components(); c++) {
|
||||
data.f[c] = 0.0;
|
||||
@@ -1385,6 +1486,12 @@ ir_expression::constant_expression_value(struct hash_table *variable_context)
|
||||
}
|
||||
break;
|
||||
|
||||
case ir_unop_saturate:
|
||||
for (unsigned c = 0; c < components; c++) {
|
||||
data.f[c] = CLAMP(op[0]->value.f[c], 0.0f, 1.0f);
|
||||
}
|
||||
break;
|
||||
|
||||
case ir_triop_bitfield_extract: {
|
||||
int offset = op[1]->value.i[0];
|
||||
int bits = op[2]->value.i[0];
|
||||
@@ -1551,7 +1658,7 @@ ir_expression::constant_expression_value(struct hash_table *variable_context)
|
||||
|
||||
|
||||
ir_constant *
|
||||
ir_texture::constant_expression_value(struct hash_table *variable_context)
|
||||
ir_texture::constant_expression_value(struct hash_table *)
|
||||
{
|
||||
/* texture lookups aren't constant expressions */
|
||||
return NULL;
|
||||
@@ -1587,19 +1694,6 @@ ir_swizzle::constant_expression_value(struct hash_table *variable_context)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ir_dereference_variable::constant_referenced(struct hash_table *variable_context,
|
||||
ir_constant *&store, int &offset) const
|
||||
{
|
||||
if (variable_context) {
|
||||
store = (ir_constant *)hash_table_find(variable_context, var);
|
||||
offset = 0;
|
||||
} else {
|
||||
store = NULL;
|
||||
offset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
ir_constant *
|
||||
ir_dereference_variable::constant_expression_value(struct hash_table *variable_context)
|
||||
{
|
||||
@@ -1627,60 +1721,6 @@ ir_dereference_variable::constant_expression_value(struct hash_table *variable_c
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ir_dereference_array::constant_referenced(struct hash_table *variable_context,
|
||||
ir_constant *&store, int &offset) const
|
||||
{
|
||||
ir_constant *index_c = array_index->constant_expression_value(variable_context);
|
||||
|
||||
if (!index_c || !index_c->type->is_scalar() || !index_c->type->is_integer()) {
|
||||
store = 0;
|
||||
offset = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
int index = index_c->type->base_type == GLSL_TYPE_INT ?
|
||||
index_c->get_int_component(0) :
|
||||
index_c->get_uint_component(0);
|
||||
|
||||
ir_constant *substore;
|
||||
int suboffset;
|
||||
const ir_dereference *deref = array->as_dereference();
|
||||
if (!deref) {
|
||||
store = 0;
|
||||
offset = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
deref->constant_referenced(variable_context, substore, suboffset);
|
||||
|
||||
if (!substore) {
|
||||
store = 0;
|
||||
offset = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
const glsl_type *vt = array->type;
|
||||
if (vt->is_array()) {
|
||||
store = substore->get_array_element(index);
|
||||
offset = 0;
|
||||
return;
|
||||
}
|
||||
if (vt->is_matrix()) {
|
||||
store = substore;
|
||||
offset = index * vt->vector_elements;
|
||||
return;
|
||||
}
|
||||
if (vt->is_vector()) {
|
||||
store = substore;
|
||||
offset = suboffset + index;
|
||||
return;
|
||||
}
|
||||
|
||||
store = 0;
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
ir_constant *
|
||||
ir_dereference_array::constant_expression_value(struct hash_table *variable_context)
|
||||
{
|
||||
@@ -1736,33 +1776,8 @@ ir_dereference_array::constant_expression_value(struct hash_table *variable_cont
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ir_dereference_record::constant_referenced(struct hash_table *variable_context,
|
||||
ir_constant *&store, int &offset) const
|
||||
{
|
||||
ir_constant *substore;
|
||||
int suboffset;
|
||||
const ir_dereference *deref = record->as_dereference();
|
||||
if (!deref) {
|
||||
store = 0;
|
||||
offset = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
deref->constant_referenced(variable_context, substore, suboffset);
|
||||
|
||||
if (!substore) {
|
||||
store = 0;
|
||||
offset = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
store = substore->get_record_field(field);
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
ir_constant *
|
||||
ir_dereference_record::constant_expression_value(struct hash_table *variable_context)
|
||||
ir_dereference_record::constant_expression_value(struct hash_table *)
|
||||
{
|
||||
ir_constant *v = this->record->constant_expression_value();
|
||||
|
||||
@@ -1771,7 +1786,7 @@ ir_dereference_record::constant_expression_value(struct hash_table *variable_con
|
||||
|
||||
|
||||
ir_constant *
|
||||
ir_assignment::constant_expression_value(struct hash_table *variable_context)
|
||||
ir_assignment::constant_expression_value(struct hash_table *)
|
||||
{
|
||||
/* FINISHME: Handle CEs involving assignment (return RHS) */
|
||||
return NULL;
|
||||
@@ -1779,7 +1794,7 @@ ir_assignment::constant_expression_value(struct hash_table *variable_context)
|
||||
|
||||
|
||||
ir_constant *
|
||||
ir_constant::constant_expression_value(struct hash_table *variable_context)
|
||||
ir_constant::constant_expression_value(struct hash_table *)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
@@ -1796,8 +1811,7 @@ bool ir_function_signature::constant_expression_evaluate_expression_list(const s
|
||||
struct hash_table *variable_context,
|
||||
ir_constant **result)
|
||||
{
|
||||
foreach_list(n, &body) {
|
||||
ir_instruction *inst = (ir_instruction *)n;
|
||||
foreach_in_list(ir_instruction, inst, &body) {
|
||||
switch(inst->ir_type) {
|
||||
|
||||
/* (declare () type symbol) */
|
||||
@@ -1820,9 +1834,8 @@ bool ir_function_signature::constant_expression_evaluate_expression_list(const s
|
||||
|
||||
ir_constant *store = NULL;
|
||||
int offset = 0;
|
||||
asg->lhs->constant_referenced(variable_context, store, offset);
|
||||
|
||||
if (!store)
|
||||
if (!constant_referenced(asg->lhs, variable_context, store, offset))
|
||||
return false;
|
||||
|
||||
ir_constant *value = asg->rhs->constant_expression_value(variable_context);
|
||||
@@ -1853,9 +1866,9 @@ bool ir_function_signature::constant_expression_evaluate_expression_list(const s
|
||||
|
||||
ir_constant *store = NULL;
|
||||
int offset = 0;
|
||||
call->return_deref->constant_referenced(variable_context, store, offset);
|
||||
|
||||
if (!store)
|
||||
if (!constant_referenced(call->return_deref, variable_context,
|
||||
store, offset))
|
||||
return false;
|
||||
|
||||
ir_constant *value = call->constant_expression_value(variable_context);
|
||||
@@ -1937,8 +1950,8 @@ ir_function_signature::constant_expression_value(exec_list *actual_parameters, s
|
||||
*/
|
||||
const exec_node *parameter_info = origin ? origin->parameters.head : parameters.head;
|
||||
|
||||
foreach_list(n, actual_parameters) {
|
||||
ir_constant *constant = ((ir_rvalue *) n)->constant_expression_value(variable_context);
|
||||
foreach_in_list(ir_rvalue, n, actual_parameters) {
|
||||
ir_constant *constant = n->constant_expression_value(variable_context);
|
||||
if (constant == NULL) {
|
||||
hash_table_dtor(deref_hash);
|
||||
return NULL;
|
||||
|
||||
@@ -41,13 +41,13 @@ possibly_null_equals(ir_instruction *a, ir_instruction *b, enum ir_node_type ign
|
||||
* about.
|
||||
*/
|
||||
bool
|
||||
ir_instruction::equals(ir_instruction *ir, enum ir_node_type)
|
||||
ir_instruction::equals(ir_instruction *, enum ir_node_type)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
ir_constant::equals(ir_instruction *ir, enum ir_node_type ignore)
|
||||
ir_constant::equals(ir_instruction *ir, enum ir_node_type)
|
||||
{
|
||||
const ir_constant *other = ir->as_constant();
|
||||
if (!other)
|
||||
@@ -65,7 +65,7 @@ ir_constant::equals(ir_instruction *ir, enum ir_node_type ignore)
|
||||
}
|
||||
|
||||
bool
|
||||
ir_dereference_variable::equals(ir_instruction *ir, enum ir_node_type ignore)
|
||||
ir_dereference_variable::equals(ir_instruction *ir, enum ir_node_type)
|
||||
{
|
||||
const ir_dereference_variable *other = ir->as_dereference_variable();
|
||||
if (!other)
|
||||
|
||||
@@ -32,10 +32,8 @@
|
||||
*/
|
||||
|
||||
#include "ir.h"
|
||||
#include "ir_visitor.h"
|
||||
#include "ir_rvalue_visitor.h"
|
||||
#include "ir_expression_flattening.h"
|
||||
#include "glsl_types.h"
|
||||
|
||||
class ir_expression_flattening_visitor : public ir_rvalue_visitor {
|
||||
public:
|
||||
@@ -59,9 +57,7 @@ do_expression_flattening(exec_list *instructions,
|
||||
{
|
||||
ir_expression_flattening_visitor v(predicate);
|
||||
|
||||
foreach_list(n, instructions) {
|
||||
ir_instruction *ir = (ir_instruction *) n;
|
||||
|
||||
foreach_in_list(ir_instruction, ir, instructions) {
|
||||
ir->accept(&v);
|
||||
}
|
||||
}
|
||||
|
||||
224
3rdparty/glsl-optimizer/src/glsl/ir_function.cpp
vendored
224
3rdparty/glsl-optimizer/src/glsl/ir_function.cpp
vendored
@@ -23,6 +23,8 @@
|
||||
|
||||
#include "glsl_types.h"
|
||||
#include "ir.h"
|
||||
#include "glsl_parser_extras.h"
|
||||
#include "main/errors.h"
|
||||
|
||||
typedef enum {
|
||||
PARAMETER_LIST_NO_MATCH,
|
||||
@@ -38,7 +40,8 @@ typedef enum {
|
||||
* \see matching_signature()
|
||||
*/
|
||||
static parameter_list_match_t
|
||||
parameter_lists_match(const exec_list *list_a, const exec_list *list_b)
|
||||
parameter_lists_match(_mesa_glsl_parse_state *state,
|
||||
const exec_list *list_a, const exec_list *list_b)
|
||||
{
|
||||
const exec_node *node_a = list_a->head;
|
||||
const exec_node *node_b = list_b->head;
|
||||
@@ -79,12 +82,12 @@ parameter_lists_match(const exec_list *list_a, const exec_list *list_b)
|
||||
|
||||
case ir_var_const_in:
|
||||
case ir_var_function_in:
|
||||
if (!actual->type->can_implicitly_convert_to(param->type))
|
||||
if (!actual->type->can_implicitly_convert_to(param->type, state))
|
||||
return PARAMETER_LIST_NO_MATCH;
|
||||
break;
|
||||
|
||||
case ir_var_function_out:
|
||||
if (!param->type->can_implicitly_convert_to(actual->type))
|
||||
if (!param->type->can_implicitly_convert_to(actual->type, state))
|
||||
return PARAMETER_LIST_NO_MATCH;
|
||||
break;
|
||||
|
||||
@@ -115,21 +118,188 @@ parameter_lists_match(const exec_list *list_a, const exec_list *list_b)
|
||||
}
|
||||
|
||||
|
||||
/* Classes of parameter match, sorted (mostly) best matches first.
|
||||
* See is_better_parameter_match() below for the exceptions.
|
||||
* */
|
||||
typedef enum {
|
||||
PARAMETER_EXACT_MATCH,
|
||||
PARAMETER_FLOAT_TO_DOUBLE,
|
||||
PARAMETER_INT_TO_FLOAT,
|
||||
PARAMETER_INT_TO_DOUBLE,
|
||||
PARAMETER_OTHER_CONVERSION,
|
||||
} parameter_match_t;
|
||||
|
||||
|
||||
static parameter_match_t
|
||||
get_parameter_match_type(const ir_variable *param,
|
||||
const ir_rvalue *actual)
|
||||
{
|
||||
const glsl_type *from_type;
|
||||
const glsl_type *to_type;
|
||||
|
||||
if (param->data.mode == ir_var_function_out) {
|
||||
from_type = param->type;
|
||||
to_type = actual->type;
|
||||
} else {
|
||||
from_type = actual->type;
|
||||
to_type = param->type;
|
||||
}
|
||||
|
||||
if (from_type == to_type)
|
||||
return PARAMETER_EXACT_MATCH;
|
||||
|
||||
/* XXX: When ARB_gpu_shader_fp64 support is added, check for float->double,
|
||||
* and int/uint->double conversions
|
||||
*/
|
||||
|
||||
if (to_type->base_type == GLSL_TYPE_FLOAT)
|
||||
return PARAMETER_INT_TO_FLOAT;
|
||||
|
||||
/* int -> uint and any other oddball conversions */
|
||||
return PARAMETER_OTHER_CONVERSION;
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
is_better_parameter_match(parameter_match_t a_match,
|
||||
parameter_match_t b_match)
|
||||
{
|
||||
/* From section 6.1 of the GLSL 4.00 spec (and the ARB_gpu_shader5 spec):
|
||||
*
|
||||
* 1. An exact match is better than a match involving any implicit
|
||||
* conversion.
|
||||
*
|
||||
* 2. A match involving an implicit conversion from float to double
|
||||
* is better than match involving any other implicit conversion.
|
||||
*
|
||||
* [XXX: Not in GLSL 4.0: Only in ARB_gpu_shader5:
|
||||
* 3. A match involving an implicit conversion from either int or uint
|
||||
* to float is better than a match involving an implicit conversion
|
||||
* from either int or uint to double.]
|
||||
*
|
||||
* If none of the rules above apply to a particular pair of conversions,
|
||||
* neither conversion is considered better than the other.
|
||||
*
|
||||
* --
|
||||
*
|
||||
* Notably, the int->uint conversion is *not* considered to be better
|
||||
* or worse than int/uint->float or int/uint->double.
|
||||
*/
|
||||
|
||||
if (a_match >= PARAMETER_INT_TO_FLOAT && b_match == PARAMETER_OTHER_CONVERSION)
|
||||
return false;
|
||||
|
||||
return a_match < b_match;
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
is_best_inexact_overload(const exec_list *actual_parameters,
|
||||
ir_function_signature **matches,
|
||||
int num_matches,
|
||||
ir_function_signature *sig)
|
||||
{
|
||||
/* From section 6.1 of the GLSL 4.00 spec (and the ARB_gpu_shader5 spec):
|
||||
*
|
||||
* "A function definition A is considered a better
|
||||
* match than function definition B if:
|
||||
*
|
||||
* * for at least one function argument, the conversion for that argument
|
||||
* in A is better than the corresponding conversion in B; and
|
||||
*
|
||||
* * there is no function argument for which the conversion in B is better
|
||||
* than the corresponding conversion in A.
|
||||
*
|
||||
* If a single function definition is considered a better match than every
|
||||
* other matching function definition, it will be used. Otherwise, a
|
||||
* semantic error occurs and the shader will fail to compile."
|
||||
*/
|
||||
for (ir_function_signature **other = matches;
|
||||
other < matches + num_matches; other++) {
|
||||
if (*other == sig)
|
||||
continue;
|
||||
|
||||
const exec_node *node_a = sig->parameters.head;
|
||||
const exec_node *node_b = (*other)->parameters.head;
|
||||
const exec_node *node_p = actual_parameters->head;
|
||||
|
||||
bool better_for_some_parameter = false;
|
||||
|
||||
for (/* empty */
|
||||
; !node_a->is_tail_sentinel()
|
||||
; node_a = node_a->next,
|
||||
node_b = node_b->next,
|
||||
node_p = node_p->next) {
|
||||
parameter_match_t a_match = get_parameter_match_type(
|
||||
(const ir_variable *)node_a,
|
||||
(const ir_rvalue *)node_p);
|
||||
parameter_match_t b_match = get_parameter_match_type(
|
||||
(const ir_variable *)node_b,
|
||||
(const ir_rvalue *)node_p);
|
||||
|
||||
if (is_better_parameter_match(a_match, b_match))
|
||||
better_for_some_parameter = true;
|
||||
|
||||
if (is_better_parameter_match(b_match, a_match))
|
||||
return false; /* B is better for this parameter */
|
||||
}
|
||||
|
||||
if (!better_for_some_parameter)
|
||||
return false; /* A must be better than B for some parameter */
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static ir_function_signature *
|
||||
choose_best_inexact_overload(_mesa_glsl_parse_state *state,
|
||||
const exec_list *actual_parameters,
|
||||
ir_function_signature **matches,
|
||||
int num_matches)
|
||||
{
|
||||
if (num_matches == 0)
|
||||
return NULL;
|
||||
|
||||
if (num_matches == 1)
|
||||
return *matches;
|
||||
|
||||
/* Without GLSL 4.0 / ARB_gpu_shader5, there is no overload resolution
|
||||
* among multiple inexact matches. Note that state may be NULL here if
|
||||
* called from the linker; in that case we assume everything supported in
|
||||
* any GLSL version is available. */
|
||||
if (!state || state->is_version(400, 0) || state->ARB_gpu_shader5_enable) {
|
||||
for (ir_function_signature **sig = matches; sig < matches + num_matches; sig++) {
|
||||
if (is_best_inexact_overload(actual_parameters, matches, num_matches, *sig))
|
||||
return *sig;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL; /* no best candidate */
|
||||
}
|
||||
|
||||
|
||||
ir_function_signature *
|
||||
ir_function::matching_signature(_mesa_glsl_parse_state *state,
|
||||
const exec_list *actual_parameters)
|
||||
const exec_list *actual_parameters,
|
||||
bool allow_builtins)
|
||||
{
|
||||
bool is_exact;
|
||||
return matching_signature(state, actual_parameters, &is_exact);
|
||||
return matching_signature(state, actual_parameters, allow_builtins,
|
||||
&is_exact);
|
||||
}
|
||||
|
||||
ir_function_signature *
|
||||
ir_function::matching_signature(_mesa_glsl_parse_state *state,
|
||||
const exec_list *actual_parameters,
|
||||
bool *is_exact)
|
||||
bool allow_builtins,
|
||||
bool *is_exact)
|
||||
{
|
||||
ir_function_signature **inexact_matches = NULL;
|
||||
ir_function_signature **inexact_matches_temp;
|
||||
ir_function_signature *match = NULL;
|
||||
bool multiple_inexact_matches = false;
|
||||
int num_inexact_matches = 0;
|
||||
|
||||
/* From page 42 (page 49 of the PDF) of the GLSL 1.20 spec:
|
||||
*
|
||||
@@ -141,23 +311,30 @@ ir_function::matching_signature(_mesa_glsl_parse_state *state,
|
||||
* multiple ways to apply these conversions to the actual arguments of a
|
||||
* call such that the call can be made to match multiple signatures."
|
||||
*/
|
||||
foreach_list(n, &this->signatures) {
|
||||
ir_function_signature *const sig = (ir_function_signature *) n;
|
||||
|
||||
foreach_in_list(ir_function_signature, sig, &this->signatures) {
|
||||
/* Skip over any built-ins that aren't available in this shader. */
|
||||
if (sig->is_builtin() && !sig->is_builtin_available(state))
|
||||
if (sig->is_builtin() && (!allow_builtins ||
|
||||
!sig->is_builtin_available(state)))
|
||||
continue;
|
||||
|
||||
switch (parameter_lists_match(& sig->parameters, actual_parameters)) {
|
||||
switch (parameter_lists_match(state, & sig->parameters, actual_parameters)) {
|
||||
case PARAMETER_LIST_EXACT_MATCH:
|
||||
*is_exact = true;
|
||||
return sig;
|
||||
*is_exact = true;
|
||||
free(inexact_matches);
|
||||
return sig;
|
||||
case PARAMETER_LIST_INEXACT_MATCH:
|
||||
if (match == NULL)
|
||||
match = sig;
|
||||
else
|
||||
multiple_inexact_matches = true;
|
||||
continue;
|
||||
inexact_matches_temp = (ir_function_signature **)
|
||||
realloc(inexact_matches,
|
||||
sizeof(*inexact_matches) *
|
||||
(num_inexact_matches + 1));
|
||||
if (inexact_matches_temp == NULL) {
|
||||
_mesa_error_no_memory(__func__);
|
||||
free(inexact_matches);
|
||||
return NULL;
|
||||
}
|
||||
inexact_matches = inexact_matches_temp;
|
||||
inexact_matches[num_inexact_matches++] = sig;
|
||||
continue;
|
||||
case PARAMETER_LIST_NO_MATCH:
|
||||
continue;
|
||||
default:
|
||||
@@ -175,9 +352,10 @@ ir_function::matching_signature(_mesa_glsl_parse_state *state,
|
||||
*/
|
||||
*is_exact = false;
|
||||
|
||||
if (multiple_inexact_matches)
|
||||
return NULL;
|
||||
match = choose_best_inexact_overload(state, actual_parameters,
|
||||
inexact_matches, num_inexact_matches);
|
||||
|
||||
free(inexact_matches);
|
||||
return match;
|
||||
}
|
||||
|
||||
@@ -211,9 +389,7 @@ ir_function_signature *
|
||||
ir_function::exact_matching_signature(_mesa_glsl_parse_state *state,
|
||||
const exec_list *actual_parameters)
|
||||
{
|
||||
foreach_list(n, &this->signatures) {
|
||||
ir_function_signature *const sig = (ir_function_signature *) n;
|
||||
|
||||
foreach_in_list(ir_function_signature, sig, &this->signatures) {
|
||||
/* Skip over any built-ins that aren't available in this shader. */
|
||||
if (sig->is_builtin() && !sig->is_builtin_available(state))
|
||||
continue;
|
||||
|
||||
@@ -229,15 +229,13 @@ public:
|
||||
static void
|
||||
destroy_links(exec_list *list, function *f)
|
||||
{
|
||||
foreach_list_safe(node, list) {
|
||||
struct call_node *n = (struct call_node *) node;
|
||||
|
||||
foreach_in_list_safe(call_node, node, list) {
|
||||
/* If this is the right function, remove it. Note that the loop cannot
|
||||
* terminate now. There can be multiple links to a function if it is
|
||||
* either called multiple times or calls multiple times.
|
||||
*/
|
||||
if (n->func == f)
|
||||
n->remove();
|
||||
if (node->func == f)
|
||||
node->remove();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,16 +27,18 @@
|
||||
ir_hierarchical_visitor::ir_hierarchical_visitor()
|
||||
{
|
||||
this->base_ir = NULL;
|
||||
this->callback = NULL;
|
||||
this->data = NULL;
|
||||
this->callback_enter = NULL;
|
||||
this->callback_leave = NULL;
|
||||
this->data_enter = NULL;
|
||||
this->data_leave = NULL;
|
||||
this->in_assignee = false;
|
||||
}
|
||||
|
||||
ir_visitor_status
|
||||
ir_hierarchical_visitor::visit(ir_rvalue *ir)
|
||||
{
|
||||
if (this->callback != NULL)
|
||||
this->callback(ir, this->data);
|
||||
if (this->callback_enter != NULL)
|
||||
this->callback_enter(ir, this->data_enter);
|
||||
|
||||
return visit_continue;
|
||||
}
|
||||
@@ -44,8 +46,8 @@ ir_hierarchical_visitor::visit(ir_rvalue *ir)
|
||||
ir_visitor_status
|
||||
ir_hierarchical_visitor::visit(ir_variable *ir)
|
||||
{
|
||||
if (this->callback != NULL)
|
||||
this->callback(ir, this->data);
|
||||
if (this->callback_enter != NULL)
|
||||
this->callback_enter(ir, this->data_enter);
|
||||
|
||||
return visit_continue;
|
||||
}
|
||||
@@ -53,8 +55,8 @@ ir_hierarchical_visitor::visit(ir_variable *ir)
|
||||
ir_visitor_status
|
||||
ir_hierarchical_visitor::visit(ir_constant *ir)
|
||||
{
|
||||
if (this->callback != NULL)
|
||||
this->callback(ir, this->data);
|
||||
if (this->callback_enter != NULL)
|
||||
this->callback_enter(ir, this->data_enter);
|
||||
|
||||
return visit_continue;
|
||||
}
|
||||
@@ -62,8 +64,8 @@ ir_hierarchical_visitor::visit(ir_constant *ir)
|
||||
ir_visitor_status
|
||||
ir_hierarchical_visitor::visit(ir_loop_jump *ir)
|
||||
{
|
||||
if (this->callback != NULL)
|
||||
this->callback(ir, this->data);
|
||||
if (this->callback_enter != NULL)
|
||||
this->callback_enter(ir, this->data_enter);
|
||||
|
||||
return visit_continue;
|
||||
}
|
||||
@@ -71,8 +73,8 @@ ir_hierarchical_visitor::visit(ir_loop_jump *ir)
|
||||
ir_visitor_status
|
||||
ir_hierarchical_visitor::visit(ir_precision_statement *ir)
|
||||
{
|
||||
if (this->callback != NULL)
|
||||
this->callback(ir, this->data);
|
||||
if (this->callback_enter != NULL)
|
||||
this->callback_enter(ir, this->data_enter);
|
||||
|
||||
return visit_continue;
|
||||
}
|
||||
@@ -80,26 +82,8 @@ ir_hierarchical_visitor::visit(ir_precision_statement *ir)
|
||||
ir_visitor_status
|
||||
ir_hierarchical_visitor::visit(ir_typedecl_statement *ir)
|
||||
{
|
||||
if (this->callback != NULL)
|
||||
this->callback(ir, this->data);
|
||||
|
||||
return visit_continue;
|
||||
}
|
||||
|
||||
ir_visitor_status
|
||||
ir_hierarchical_visitor::visit(ir_emit_vertex *ir)
|
||||
{
|
||||
if (this->callback != NULL)
|
||||
this->callback(ir, this->data);
|
||||
|
||||
return visit_continue;
|
||||
}
|
||||
|
||||
ir_visitor_status
|
||||
ir_hierarchical_visitor::visit(ir_end_primitive *ir)
|
||||
{
|
||||
if (this->callback != NULL)
|
||||
this->callback(ir, this->data);
|
||||
if (this->callback_enter != NULL)
|
||||
this->callback_enter(ir, this->data_enter);
|
||||
|
||||
return visit_continue;
|
||||
}
|
||||
@@ -107,8 +91,8 @@ ir_hierarchical_visitor::visit(ir_end_primitive *ir)
|
||||
ir_visitor_status
|
||||
ir_hierarchical_visitor::visit(ir_dereference_variable *ir)
|
||||
{
|
||||
if (this->callback != NULL)
|
||||
this->callback(ir, this->data);
|
||||
if (this->callback_enter != NULL)
|
||||
this->callback_enter(ir, this->data_enter);
|
||||
|
||||
return visit_continue;
|
||||
}
|
||||
@@ -116,8 +100,8 @@ ir_hierarchical_visitor::visit(ir_dereference_variable *ir)
|
||||
ir_visitor_status
|
||||
ir_hierarchical_visitor::visit_enter(ir_loop *ir)
|
||||
{
|
||||
if (this->callback != NULL)
|
||||
this->callback(ir, this->data);
|
||||
if (this->callback_enter != NULL)
|
||||
this->callback_enter(ir, this->data_enter);
|
||||
|
||||
return visit_continue;
|
||||
}
|
||||
@@ -125,15 +109,17 @@ ir_hierarchical_visitor::visit_enter(ir_loop *ir)
|
||||
ir_visitor_status
|
||||
ir_hierarchical_visitor::visit_leave(ir_loop *ir)
|
||||
{
|
||||
(void) ir;
|
||||
if (this->callback_leave != NULL)
|
||||
this->callback_leave(ir, this->data_leave);
|
||||
|
||||
return visit_continue;
|
||||
}
|
||||
|
||||
ir_visitor_status
|
||||
ir_hierarchical_visitor::visit_enter(ir_function_signature *ir)
|
||||
{
|
||||
if (this->callback != NULL)
|
||||
this->callback(ir, this->data);
|
||||
if (this->callback_enter != NULL)
|
||||
this->callback_enter(ir, this->data_enter);
|
||||
|
||||
return visit_continue;
|
||||
}
|
||||
@@ -141,15 +127,17 @@ ir_hierarchical_visitor::visit_enter(ir_function_signature *ir)
|
||||
ir_visitor_status
|
||||
ir_hierarchical_visitor::visit_leave(ir_function_signature *ir)
|
||||
{
|
||||
(void) ir;
|
||||
if (this->callback_leave != NULL)
|
||||
this->callback_leave(ir, this->data_leave);
|
||||
|
||||
return visit_continue;
|
||||
}
|
||||
|
||||
ir_visitor_status
|
||||
ir_hierarchical_visitor::visit_enter(ir_function *ir)
|
||||
{
|
||||
if (this->callback != NULL)
|
||||
this->callback(ir, this->data);
|
||||
if (this->callback_enter != NULL)
|
||||
this->callback_enter(ir, this->data_enter);
|
||||
|
||||
return visit_continue;
|
||||
}
|
||||
@@ -157,15 +145,17 @@ ir_hierarchical_visitor::visit_enter(ir_function *ir)
|
||||
ir_visitor_status
|
||||
ir_hierarchical_visitor::visit_leave(ir_function *ir)
|
||||
{
|
||||
(void) ir;
|
||||
if (this->callback_leave != NULL)
|
||||
this->callback_leave(ir, this->data_leave);
|
||||
|
||||
return visit_continue;
|
||||
}
|
||||
|
||||
ir_visitor_status
|
||||
ir_hierarchical_visitor::visit_enter(ir_expression *ir)
|
||||
{
|
||||
if (this->callback != NULL)
|
||||
this->callback(ir, this->data);
|
||||
if (this->callback_enter != NULL)
|
||||
this->callback_enter(ir, this->data_enter);
|
||||
|
||||
return visit_continue;
|
||||
}
|
||||
@@ -173,15 +163,17 @@ ir_hierarchical_visitor::visit_enter(ir_expression *ir)
|
||||
ir_visitor_status
|
||||
ir_hierarchical_visitor::visit_leave(ir_expression *ir)
|
||||
{
|
||||
(void) ir;
|
||||
if (this->callback_leave != NULL)
|
||||
this->callback_leave(ir, this->data_leave);
|
||||
|
||||
return visit_continue;
|
||||
}
|
||||
|
||||
ir_visitor_status
|
||||
ir_hierarchical_visitor::visit_enter(ir_texture *ir)
|
||||
{
|
||||
if (this->callback != NULL)
|
||||
this->callback(ir, this->data);
|
||||
if (this->callback_enter != NULL)
|
||||
this->callback_enter(ir, this->data_enter);
|
||||
|
||||
return visit_continue;
|
||||
}
|
||||
@@ -189,15 +181,17 @@ ir_hierarchical_visitor::visit_enter(ir_texture *ir)
|
||||
ir_visitor_status
|
||||
ir_hierarchical_visitor::visit_leave(ir_texture *ir)
|
||||
{
|
||||
(void) ir;
|
||||
if (this->callback_leave != NULL)
|
||||
this->callback_leave(ir, this->data_leave);
|
||||
|
||||
return visit_continue;
|
||||
}
|
||||
|
||||
ir_visitor_status
|
||||
ir_hierarchical_visitor::visit_enter(ir_swizzle *ir)
|
||||
{
|
||||
if (this->callback != NULL)
|
||||
this->callback(ir, this->data);
|
||||
if (this->callback_enter != NULL)
|
||||
this->callback_enter(ir, this->data_enter);
|
||||
|
||||
return visit_continue;
|
||||
}
|
||||
@@ -205,15 +199,17 @@ ir_hierarchical_visitor::visit_enter(ir_swizzle *ir)
|
||||
ir_visitor_status
|
||||
ir_hierarchical_visitor::visit_leave(ir_swizzle *ir)
|
||||
{
|
||||
(void) ir;
|
||||
if (this->callback_leave != NULL)
|
||||
this->callback_leave(ir, this->data_leave);
|
||||
|
||||
return visit_continue;
|
||||
}
|
||||
|
||||
ir_visitor_status
|
||||
ir_hierarchical_visitor::visit_enter(ir_dereference_array *ir)
|
||||
{
|
||||
if (this->callback != NULL)
|
||||
this->callback(ir, this->data);
|
||||
if (this->callback_enter != NULL)
|
||||
this->callback_enter(ir, this->data_enter);
|
||||
|
||||
return visit_continue;
|
||||
}
|
||||
@@ -221,15 +217,17 @@ ir_hierarchical_visitor::visit_enter(ir_dereference_array *ir)
|
||||
ir_visitor_status
|
||||
ir_hierarchical_visitor::visit_leave(ir_dereference_array *ir)
|
||||
{
|
||||
(void) ir;
|
||||
if (this->callback_leave != NULL)
|
||||
this->callback_leave(ir, this->data_leave);
|
||||
|
||||
return visit_continue;
|
||||
}
|
||||
|
||||
ir_visitor_status
|
||||
ir_hierarchical_visitor::visit_enter(ir_dereference_record *ir)
|
||||
{
|
||||
if (this->callback != NULL)
|
||||
this->callback(ir, this->data);
|
||||
if (this->callback_enter != NULL)
|
||||
this->callback_enter(ir, this->data_enter);
|
||||
|
||||
return visit_continue;
|
||||
}
|
||||
@@ -237,15 +235,17 @@ ir_hierarchical_visitor::visit_enter(ir_dereference_record *ir)
|
||||
ir_visitor_status
|
||||
ir_hierarchical_visitor::visit_leave(ir_dereference_record *ir)
|
||||
{
|
||||
(void) ir;
|
||||
if (this->callback_leave != NULL)
|
||||
this->callback_leave(ir, this->data_leave);
|
||||
|
||||
return visit_continue;
|
||||
}
|
||||
|
||||
ir_visitor_status
|
||||
ir_hierarchical_visitor::visit_enter(ir_assignment *ir)
|
||||
{
|
||||
if (this->callback != NULL)
|
||||
this->callback(ir, this->data);
|
||||
if (this->callback_enter != NULL)
|
||||
this->callback_enter(ir, this->data_enter);
|
||||
|
||||
return visit_continue;
|
||||
}
|
||||
@@ -253,15 +253,17 @@ ir_hierarchical_visitor::visit_enter(ir_assignment *ir)
|
||||
ir_visitor_status
|
||||
ir_hierarchical_visitor::visit_leave(ir_assignment *ir)
|
||||
{
|
||||
(void) ir;
|
||||
if (this->callback_leave != NULL)
|
||||
this->callback_leave(ir, this->data_leave);
|
||||
|
||||
return visit_continue;
|
||||
}
|
||||
|
||||
ir_visitor_status
|
||||
ir_hierarchical_visitor::visit_enter(ir_call *ir)
|
||||
{
|
||||
if (this->callback != NULL)
|
||||
this->callback(ir, this->data);
|
||||
if (this->callback_enter != NULL)
|
||||
this->callback_enter(ir, this->data_enter);
|
||||
|
||||
return visit_continue;
|
||||
}
|
||||
@@ -269,15 +271,17 @@ ir_hierarchical_visitor::visit_enter(ir_call *ir)
|
||||
ir_visitor_status
|
||||
ir_hierarchical_visitor::visit_leave(ir_call *ir)
|
||||
{
|
||||
(void) ir;
|
||||
if (this->callback_leave != NULL)
|
||||
this->callback_leave(ir, this->data_leave);
|
||||
|
||||
return visit_continue;
|
||||
}
|
||||
|
||||
ir_visitor_status
|
||||
ir_hierarchical_visitor::visit_enter(ir_return *ir)
|
||||
{
|
||||
if (this->callback != NULL)
|
||||
this->callback(ir, this->data);
|
||||
if (this->callback_enter != NULL)
|
||||
this->callback_enter(ir, this->data_enter);
|
||||
|
||||
return visit_continue;
|
||||
}
|
||||
@@ -285,15 +289,17 @@ ir_hierarchical_visitor::visit_enter(ir_return *ir)
|
||||
ir_visitor_status
|
||||
ir_hierarchical_visitor::visit_leave(ir_return *ir)
|
||||
{
|
||||
(void) ir;
|
||||
if (this->callback_leave != NULL)
|
||||
this->callback_leave(ir, this->data_leave);
|
||||
|
||||
return visit_continue;
|
||||
}
|
||||
|
||||
ir_visitor_status
|
||||
ir_hierarchical_visitor::visit_enter(ir_discard *ir)
|
||||
{
|
||||
if (this->callback != NULL)
|
||||
this->callback(ir, this->data);
|
||||
if (this->callback_enter != NULL)
|
||||
this->callback_enter(ir, this->data_enter);
|
||||
|
||||
return visit_continue;
|
||||
}
|
||||
@@ -301,15 +307,17 @@ ir_hierarchical_visitor::visit_enter(ir_discard *ir)
|
||||
ir_visitor_status
|
||||
ir_hierarchical_visitor::visit_leave(ir_discard *ir)
|
||||
{
|
||||
(void) ir;
|
||||
if (this->callback_leave != NULL)
|
||||
this->callback_leave(ir, this->data_leave);
|
||||
|
||||
return visit_continue;
|
||||
}
|
||||
|
||||
ir_visitor_status
|
||||
ir_hierarchical_visitor::visit_enter(ir_if *ir)
|
||||
{
|
||||
if (this->callback != NULL)
|
||||
this->callback(ir, this->data);
|
||||
if (this->callback_enter != NULL)
|
||||
this->callback_enter(ir, this->data_enter);
|
||||
|
||||
return visit_continue;
|
||||
}
|
||||
@@ -317,7 +325,45 @@ ir_hierarchical_visitor::visit_enter(ir_if *ir)
|
||||
ir_visitor_status
|
||||
ir_hierarchical_visitor::visit_leave(ir_if *ir)
|
||||
{
|
||||
(void) ir;
|
||||
if (this->callback_leave != NULL)
|
||||
this->callback_leave(ir, this->data_leave);
|
||||
|
||||
return visit_continue;
|
||||
}
|
||||
|
||||
ir_visitor_status
|
||||
ir_hierarchical_visitor::visit_enter(ir_emit_vertex *ir)
|
||||
{
|
||||
if (this->callback_enter != NULL)
|
||||
this->callback_enter(ir, this->data_enter);
|
||||
|
||||
return visit_continue;
|
||||
}
|
||||
|
||||
ir_visitor_status
|
||||
ir_hierarchical_visitor::visit_leave(ir_emit_vertex *ir)
|
||||
{
|
||||
if (this->callback_leave != NULL)
|
||||
this->callback_leave(ir, this->data_leave);
|
||||
|
||||
return visit_continue;
|
||||
}
|
||||
|
||||
ir_visitor_status
|
||||
ir_hierarchical_visitor::visit_enter(ir_end_primitive *ir)
|
||||
{
|
||||
if (this->callback_enter != NULL)
|
||||
this->callback_enter(ir, this->data_enter);
|
||||
|
||||
return visit_continue;
|
||||
}
|
||||
|
||||
ir_visitor_status
|
||||
ir_hierarchical_visitor::visit_leave(ir_end_primitive *ir)
|
||||
{
|
||||
if (this->callback_leave != NULL)
|
||||
this->callback_leave(ir, this->data_leave);
|
||||
|
||||
return visit_continue;
|
||||
}
|
||||
|
||||
@@ -330,13 +376,17 @@ ir_hierarchical_visitor::run(exec_list *instructions)
|
||||
|
||||
void
|
||||
visit_tree(ir_instruction *ir,
|
||||
void (*callback)(class ir_instruction *ir, void *data),
|
||||
void *data)
|
||||
void (*callback_enter)(class ir_instruction *ir, void *data),
|
||||
void *data_enter,
|
||||
void (*callback_leave)(class ir_instruction *ir, void *data),
|
||||
void *data_leave)
|
||||
{
|
||||
ir_hierarchical_visitor v;
|
||||
|
||||
v.callback = callback;
|
||||
v.data = data;
|
||||
v.callback_enter = callback_enter;
|
||||
v.callback_leave = callback_leave;
|
||||
v.data_enter = data_enter;
|
||||
v.data_leave = data_leave;
|
||||
|
||||
ir->accept(&v);
|
||||
}
|
||||
|
||||
@@ -89,8 +89,6 @@ public:
|
||||
virtual ir_visitor_status visit(class ir_loop_jump *);
|
||||
virtual ir_visitor_status visit(class ir_precision_statement *);
|
||||
virtual ir_visitor_status visit(class ir_typedecl_statement *);
|
||||
virtual ir_visitor_status visit(class ir_emit_vertex *);
|
||||
virtual ir_visitor_status visit(class ir_end_primitive *);
|
||||
|
||||
/**
|
||||
* ir_dereference_variable isn't technically a leaf, but it is treated as a
|
||||
@@ -139,6 +137,10 @@ public:
|
||||
virtual ir_visitor_status visit_leave(class ir_discard *);
|
||||
virtual ir_visitor_status visit_enter(class ir_if *);
|
||||
virtual ir_visitor_status visit_leave(class ir_if *);
|
||||
virtual ir_visitor_status visit_enter(class ir_emit_vertex *);
|
||||
virtual ir_visitor_status visit_leave(class ir_emit_vertex *);
|
||||
virtual ir_visitor_status visit_enter(class ir_end_primitive *);
|
||||
virtual ir_visitor_status visit_leave(class ir_end_primitive *);
|
||||
/*@}*/
|
||||
|
||||
|
||||
@@ -163,14 +165,29 @@ public:
|
||||
* \warning
|
||||
* Visitor classes derived from \c ir_hierarchical_visitor \b may \b not
|
||||
* invoke this function. This can be used, for example, to cause the
|
||||
* callback to be invoked on every node type execpt one.
|
||||
* callback to be invoked on every node type except one.
|
||||
*/
|
||||
void (*callback)(class ir_instruction *ir, void *data);
|
||||
void (*callback_enter)(class ir_instruction *ir, void *data);
|
||||
|
||||
/**
|
||||
* Extra data parameter passed to the per-node callback function
|
||||
* Callback function that is invoked on exit of each node visited.
|
||||
*
|
||||
* \warning
|
||||
* Visitor classes derived from \c ir_hierarchical_visitor \b may \b not
|
||||
* invoke this function. This can be used, for example, to cause the
|
||||
* callback to be invoked on every node type except one.
|
||||
*/
|
||||
void *data;
|
||||
void (*callback_leave)(class ir_instruction *ir, void *data);
|
||||
|
||||
/**
|
||||
* Extra data parameter passed to the per-node callback_enter function
|
||||
*/
|
||||
void *data_enter;
|
||||
|
||||
/**
|
||||
* Extra data parameter passed to the per-node callback_leave function
|
||||
*/
|
||||
void *data_leave;
|
||||
|
||||
/**
|
||||
* Currently in the LHS of an assignment?
|
||||
@@ -181,8 +198,10 @@ public:
|
||||
};
|
||||
|
||||
void visit_tree(ir_instruction *ir,
|
||||
void (*callback)(class ir_instruction *ir, void *data),
|
||||
void *data);
|
||||
void (*callback_enter)(class ir_instruction *ir, void *data),
|
||||
void *data_enter,
|
||||
void (*callback_leave)(class ir_instruction *ir, void *data) = NULL,
|
||||
void *data_leave = NULL);
|
||||
|
||||
ir_visitor_status visit_list_elements(ir_hierarchical_visitor *v, exec_list *l,
|
||||
bool statement_list = true);
|
||||
|
||||
@@ -49,8 +49,7 @@ visit_list_elements(ir_hierarchical_visitor *v, exec_list *l,
|
||||
{
|
||||
ir_instruction *prev_base_ir = v->base_ir;
|
||||
|
||||
foreach_list_safe(n, l) {
|
||||
ir_instruction *const ir = (ir_instruction *) n;
|
||||
foreach_in_list_safe(ir_instruction, ir, l) {
|
||||
if (statement_list)
|
||||
v->base_ir = ir;
|
||||
ir_visitor_status s = ir->accept(v);
|
||||
@@ -393,7 +392,7 @@ ir_if::accept(ir_hierarchical_visitor *v)
|
||||
ir_visitor_status
|
||||
ir_precision_statement::accept(ir_hierarchical_visitor *v)
|
||||
{
|
||||
return v->visit(this);
|
||||
return v->visit(this);
|
||||
}
|
||||
|
||||
ir_visitor_status
|
||||
@@ -405,11 +404,27 @@ ir_typedecl_statement::accept(ir_hierarchical_visitor *v)
|
||||
ir_visitor_status
|
||||
ir_emit_vertex::accept(ir_hierarchical_visitor *v)
|
||||
{
|
||||
return v->visit(this);
|
||||
ir_visitor_status s = v->visit_enter(this);
|
||||
if (s != visit_continue)
|
||||
return (s == visit_continue_with_parent) ? visit_continue : s;
|
||||
|
||||
s = this->stream->accept(v);
|
||||
if (s != visit_continue)
|
||||
return (s == visit_continue_with_parent) ? visit_continue : s;
|
||||
|
||||
return (s == visit_stop) ? s : v->visit_leave(this);
|
||||
}
|
||||
|
||||
ir_visitor_status
|
||||
ir_end_primitive::accept(ir_hierarchical_visitor *v)
|
||||
{
|
||||
return v->visit(this);
|
||||
ir_visitor_status s = v->visit_enter(this);
|
||||
if (s != visit_continue)
|
||||
return (s == visit_continue_with_parent) ? visit_continue : s;
|
||||
|
||||
s = this->stream->accept(v);
|
||||
if (s != visit_continue)
|
||||
return (s == visit_continue_with_parent) ? visit_continue : s;
|
||||
|
||||
return (s == visit_stop) ? s : v->visit_leave(this);
|
||||
}
|
||||
|
||||
@@ -36,9 +36,11 @@
|
||||
#define LOG_TO_LOG2 0x10
|
||||
#define MOD_TO_FRACT 0x20
|
||||
#define INT_DIV_TO_MUL_RCP 0x40
|
||||
#define LRP_TO_ARITH 0x80
|
||||
#define BITFIELD_INSERT_TO_BFM_BFI 0x100
|
||||
#define LDEXP_TO_ARITH 0x200
|
||||
#define BITFIELD_INSERT_TO_BFM_BFI 0x80
|
||||
#define LDEXP_TO_ARITH 0x100
|
||||
#define CARRY_TO_ARITH 0x200
|
||||
#define BORROW_TO_ARITH 0x400
|
||||
#define SAT_TO_CLAMP 0x800
|
||||
|
||||
/**
|
||||
* \see class lower_packing_builtins_visitor
|
||||
@@ -67,10 +69,12 @@ enum lower_packing_builtins_op {
|
||||
|
||||
bool do_common_optimization(exec_list *ir, bool linked,
|
||||
bool uniform_locations_assigned,
|
||||
unsigned max_unroll_iterations,
|
||||
const struct gl_shader_compiler_options *options);
|
||||
const struct gl_shader_compiler_options *options,
|
||||
bool native_integers);
|
||||
|
||||
bool do_algebraic(exec_list *instructions);
|
||||
bool do_rebalance_tree(exec_list *instructions);
|
||||
bool do_algebraic(exec_list *instructions, bool native_integers,
|
||||
const struct gl_shader_compiler_options *options);
|
||||
bool do_constant_folding(exec_list *instructions);
|
||||
bool do_constant_variable(exec_list *instructions);
|
||||
bool do_constant_variable_unlinked(exec_list *instructions);
|
||||
@@ -94,6 +98,7 @@ bool opt_flatten_nested_if_blocks(exec_list *instructions);
|
||||
bool do_discard_simplification(exec_list *instructions);
|
||||
bool lower_if_to_cond_assign(exec_list *instructions, unsigned max_depth = 0);
|
||||
bool do_mat_op_to_vec(exec_list *instructions);
|
||||
bool do_minmax_prune(exec_list *instructions);
|
||||
bool do_noop_swizzle(exec_list *instructions);
|
||||
bool do_structure_splitting(exec_list *instructions);
|
||||
bool do_swizzle_swizzle(exec_list *instructions);
|
||||
@@ -112,13 +117,27 @@ bool lower_clip_distance(gl_shader *shader);
|
||||
void lower_output_reads(exec_list *instructions);
|
||||
bool lower_packing_builtins(exec_list *instructions, int op_mask);
|
||||
void lower_ubo_reference(struct gl_shader *shader, exec_list *instructions);
|
||||
void lower_packed_varyings(void *mem_ctx, unsigned location_base,
|
||||
void lower_packed_varyings(void *mem_ctx,
|
||||
unsigned locations_used, ir_variable_mode mode,
|
||||
unsigned gs_input_vertices, gl_shader *shader);
|
||||
bool lower_vector_insert(exec_list *instructions, bool lower_nonconstant_index);
|
||||
void lower_named_interface_blocks(void *mem_ctx, gl_shader *shader);
|
||||
bool optimize_redundant_jumps(exec_list *instructions);
|
||||
bool optimize_split_arrays(exec_list *instructions, bool linked);
|
||||
|
||||
typedef enum {
|
||||
OPT_SPLIT_ONLY_LOOP_INDUCTORS = 0, //< only split vectors that are used as loop inductors (and are not used by any vector operation)
|
||||
OPT_SPLIT_ONLY_UNUSED = 1, //< only split vectors that have unused components (and are not used by any vector operation)
|
||||
OPT_SPLIT_ANY_POSSIBLE = 2, //< Split all vectors that are only accessed by their components
|
||||
} glsl_vector_splitting_mode;
|
||||
|
||||
bool optimize_split_vectors(exec_list *instructions, bool linked, glsl_vector_splitting_mode mode);
|
||||
|
||||
bool optimize_split_arrays(exec_list *instructions, bool linked, bool split_shader_outputs);
|
||||
bool lower_offset_arrays(exec_list *instructions);
|
||||
void optimize_dead_builtin_variables(exec_list *instructions,
|
||||
enum ir_variable_mode other);
|
||||
|
||||
bool lower_vertex_id(gl_shader *shader);
|
||||
|
||||
ir_rvalue *
|
||||
compare_index_block(exec_list *instructions, ir_variable *index,
|
||||
|
||||
@@ -29,63 +29,7 @@
|
||||
#include "loop_analysis.h"
|
||||
#include "program/hash_table.h"
|
||||
#include <math.h>
|
||||
|
||||
|
||||
class string_buffer
|
||||
{
|
||||
public:
|
||||
string_buffer(void* mem_ctx)
|
||||
{
|
||||
m_Capacity = 512;
|
||||
m_Ptr = (char*)ralloc_size(mem_ctx, m_Capacity);
|
||||
m_Size = 0;
|
||||
m_Ptr[0] = 0;
|
||||
}
|
||||
|
||||
~string_buffer()
|
||||
{
|
||||
ralloc_free(m_Ptr);
|
||||
}
|
||||
|
||||
const char* c_str() const { return m_Ptr; }
|
||||
|
||||
void asprintf_append(const char *fmt, ...) PRINTFLIKE(2, 3)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
vasprintf_append(fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void vasprintf_append(const char *fmt, va_list args)
|
||||
{
|
||||
assert (m_Ptr != NULL);
|
||||
vasprintf_rewrite_tail (&m_Size, fmt, args);
|
||||
}
|
||||
|
||||
void vasprintf_rewrite_tail (size_t *start, const char *fmt, va_list args)
|
||||
{
|
||||
assert (m_Ptr != NULL);
|
||||
|
||||
size_t new_length = printf_length(fmt, args);
|
||||
size_t needed_length = m_Size + new_length + 1;
|
||||
|
||||
if (m_Capacity < needed_length)
|
||||
{
|
||||
m_Capacity = MAX2 (m_Capacity + m_Capacity/2, needed_length);
|
||||
m_Ptr = (char*)reralloc_size(ralloc_parent(m_Ptr), m_Ptr, m_Capacity);
|
||||
}
|
||||
|
||||
vsnprintf(m_Ptr + m_Size, new_length+1, fmt, args);
|
||||
m_Size += new_length;
|
||||
assert (m_Capacity >= m_Size);
|
||||
}
|
||||
|
||||
private:
|
||||
char* m_Ptr;
|
||||
size_t m_Size;
|
||||
size_t m_Capacity;
|
||||
};
|
||||
#include <limits>
|
||||
|
||||
|
||||
static void print_type(string_buffer& buffer, const glsl_type *t, bool arraySize);
|
||||
@@ -186,6 +130,7 @@ public:
|
||||
virtual void visit(ir_end_primitive *);
|
||||
|
||||
void emit_assignment_part (ir_dereference* lhs, ir_rvalue* rhs, unsigned write_mask, ir_rvalue* dstIndex);
|
||||
bool can_emit_canonical_for (loop_variable_state *ls);
|
||||
bool emit_canonical_for (ir_loop* ir);
|
||||
bool try_print_array_assignment (ir_dereference* lhs, ir_rvalue* rhs);
|
||||
|
||||
@@ -229,6 +174,13 @@ _mesa_print_ir_glsl(exec_list *instructions,
|
||||
str.asprintf_append ("#extension GL_EXT_shadow_samplers : enable\n");
|
||||
if (state->EXT_frag_depth_enable)
|
||||
str.asprintf_append ("#extension GL_EXT_frag_depth : enable\n");
|
||||
if (state->es_shader && state->language_version < 300)
|
||||
{
|
||||
if (state->EXT_draw_buffers_enable)
|
||||
str.asprintf_append ("#extension GL_EXT_draw_buffers : require\n");
|
||||
}
|
||||
if (state->EXT_shader_framebuffer_fetch_enable)
|
||||
str.asprintf_append ("#extension GL_EXT_shader_framebuffer_fetch : enable\n");
|
||||
}
|
||||
|
||||
// remove unused struct declarations
|
||||
@@ -240,9 +192,8 @@ _mesa_print_ir_glsl(exec_list *instructions,
|
||||
if (ls->loop_found)
|
||||
set_loop_controls(instructions, ls);
|
||||
|
||||
foreach_list(node, instructions)
|
||||
foreach_in_list(ir_instruction, ir, instructions)
|
||||
{
|
||||
ir_instruction *ir = (ir_instruction *)node;
|
||||
if (ir->ir_type == ir_type_variable) {
|
||||
ir_variable *var = static_cast<ir_variable*>(ir);
|
||||
if ((strstr(var->name, "gl_") == var->name)
|
||||
@@ -344,13 +295,13 @@ void ir_print_glsl_visitor::print_precision (ir_instruction* ir, const glsl_type
|
||||
// this->state->stage == MESA_SHADER_FRAGMENT &&
|
||||
!this->state->had_float_precision)
|
||||
{
|
||||
prec = glsl_precision_medium;
|
||||
}
|
||||
|
||||
prec = glsl_precision_high;
|
||||
}
|
||||
|
||||
// skip precision for samplers that end up being lowp (default anyway) or undefined;
|
||||
// except always emit it for shadowmap samplers (some drivers don't implement
|
||||
// default EXT_shadow_samplers precision)
|
||||
if (type && type->is_sampler() && !type->sampler_shadow)
|
||||
// default EXT_shadow_samplers precision) and 3D textures (they always require precision)
|
||||
if (type && type->is_sampler() && !type->sampler_shadow && !(type->sampler_dimensionality > GLSL_SAMPLER_DIM_2D))
|
||||
{
|
||||
if (prec == glsl_precision_low || prec == glsl_precision_undefined)
|
||||
return;
|
||||
@@ -394,9 +345,9 @@ void ir_print_glsl_visitor::visit(ir_variable *ir)
|
||||
const char *const inv = (ir->data.invariant) ? "invariant " : "";
|
||||
const char *const mode[3][ir_var_mode_count] =
|
||||
{
|
||||
{ "", "uniform ", "in ", "out ", "in ", "out ", "inout ", "", "", "" },
|
||||
{ "", "uniform ", "attribute ", "varying ", "in ", "out ", "inout ", "", "", "" },
|
||||
{ "", "uniform ", "varying ", "out ", "in ", "out ", "inout ", "", "", "" },
|
||||
{ "", "uniform ", "in ", "out ", "inout ", "in ", "out ", "inout ", "", "", "" },
|
||||
{ "", "uniform ", "attribute ", "varying ", "inout ", "in ", "out ", "inout ", "", "", "" },
|
||||
{ "", "uniform ", "varying ", "out ", "inout ", "in ", "out ", "inout ", "", "", "" },
|
||||
};
|
||||
|
||||
const char *const interp[] = { "", "smooth ", "flat ", "noperspective " };
|
||||
@@ -431,7 +382,8 @@ void ir_print_glsl_visitor::visit(ir_variable *ir)
|
||||
if (!inside_loop_body)
|
||||
{
|
||||
loop_variable_state* inductor_state = loopstate->get_for_inductor(ir);
|
||||
if (inductor_state && inductor_state->private_induction_variable_count == 1)
|
||||
if (inductor_state && inductor_state->private_induction_variable_count == 1 &&
|
||||
can_emit_canonical_for(inductor_state))
|
||||
{
|
||||
skipped_this_ir = true;
|
||||
return;
|
||||
@@ -456,6 +408,7 @@ void ir_print_glsl_visitor::visit(ir_variable *ir)
|
||||
if (ir->constant_value &&
|
||||
ir->data.mode != ir_var_shader_in &&
|
||||
ir->data.mode != ir_var_shader_out &&
|
||||
ir->data.mode != ir_var_shader_inout &&
|
||||
ir->data.mode != ir_var_function_in &&
|
||||
ir->data.mode != ir_var_function_out &&
|
||||
ir->data.mode != ir_var_function_inout)
|
||||
@@ -478,9 +431,7 @@ void ir_print_glsl_visitor::visit(ir_function_signature *ir)
|
||||
|
||||
indentation++; previous_skipped = false;
|
||||
bool first = true;
|
||||
foreach_list(node, &ir->parameters) {
|
||||
ir_variable *const inst = (ir_variable *)node;
|
||||
|
||||
foreach_in_list(ir_variable, inst, &ir->parameters) {
|
||||
if (!first)
|
||||
buffer.asprintf_append (",\n");
|
||||
indent();
|
||||
@@ -510,17 +461,15 @@ void ir_print_glsl_visitor::visit(ir_function_signature *ir)
|
||||
{
|
||||
assert (!globals->main_function_done);
|
||||
globals->main_function_done = true;
|
||||
foreach_list(node, &globals->global_assignements)
|
||||
foreach_in_list(ga_entry, node, &globals->global_assignements)
|
||||
{
|
||||
ir_instruction* as = ((ga_entry *)node)->ir;
|
||||
ir_instruction* as = node->ir;
|
||||
as->accept(this);
|
||||
buffer.asprintf_append(";\n");
|
||||
}
|
||||
}
|
||||
|
||||
foreach_list(node, &ir->body) {
|
||||
ir_instruction *const inst = (ir_instruction *)node;
|
||||
|
||||
foreach_in_list(ir_instruction, inst, &ir->body) {
|
||||
indent();
|
||||
inst->accept(this);
|
||||
end_statement_line();
|
||||
@@ -534,8 +483,7 @@ void ir_print_glsl_visitor::visit(ir_function *ir)
|
||||
{
|
||||
bool found_non_builtin_proto = false;
|
||||
|
||||
foreach_list(node, &ir->signatures) {
|
||||
ir_function_signature *const sig = (ir_function_signature *)node;
|
||||
foreach_in_list(ir_function_signature, sig, &ir->signatures) {
|
||||
if (!sig->is_builtin())
|
||||
found_non_builtin_proto = true;
|
||||
}
|
||||
@@ -545,9 +493,7 @@ void ir_print_glsl_visitor::visit(ir_function *ir)
|
||||
PrintGlslMode oldMode = this->mode;
|
||||
this->mode = kPrintGlslNone;
|
||||
|
||||
foreach_list(node, &ir->signatures) {
|
||||
ir_function_signature *const sig = (ir_function_signature *)node;
|
||||
|
||||
foreach_in_list(ir_function_signature, sig, &ir->signatures) {
|
||||
indent();
|
||||
sig->accept(this);
|
||||
buffer.asprintf_append ("\n");
|
||||
@@ -598,7 +544,11 @@ static const char *const operator_glsl_strs[] = {
|
||||
"sin", // reduced
|
||||
"cos", // reduced
|
||||
"dFdx",
|
||||
"dFdxCoarse",
|
||||
"dFdxFine",
|
||||
"dFdy",
|
||||
"dFdyCoarse",
|
||||
"dFdyFine",
|
||||
"packSnorm2x16",
|
||||
"packSnorm4x8",
|
||||
"packUnorm2x16",
|
||||
@@ -615,7 +565,9 @@ static const char *const operator_glsl_strs[] = {
|
||||
"bitCount",
|
||||
"findMSB",
|
||||
"findLSB",
|
||||
"saturate",
|
||||
"noise",
|
||||
"interpolateAtCentroid",
|
||||
"+",
|
||||
"-",
|
||||
"*",
|
||||
@@ -649,6 +601,8 @@ static const char *const operator_glsl_strs[] = {
|
||||
"uboloadTODO",
|
||||
"ldexp_TODO",
|
||||
"vectorExtract_TODO",
|
||||
"interpolateAtOffset",
|
||||
"interpolateAtSample",
|
||||
"fma",
|
||||
"clamp",
|
||||
"mix",
|
||||
@@ -916,7 +870,7 @@ void ir_print_glsl_visitor::visit(ir_swizzle *ir)
|
||||
ir->mask.w,
|
||||
};
|
||||
|
||||
if (ir->val->type == glsl_type::float_type || ir->val->type == glsl_type::int_type)
|
||||
if (ir->val->type == glsl_type::float_type || ir->val->type == glsl_type::int_type || ir->val->type == glsl_type::uint_type)
|
||||
{
|
||||
if (ir->mask.num_components != 1)
|
||||
{
|
||||
@@ -927,7 +881,7 @@ void ir_print_glsl_visitor::visit(ir_swizzle *ir)
|
||||
|
||||
ir->val->accept(this);
|
||||
|
||||
if (ir->val->type == glsl_type::float_type || ir->val->type == glsl_type::int_type)
|
||||
if (ir->val->type == glsl_type::float_type || ir->val->type == glsl_type::int_type || ir->val->type == glsl_type::uint_type)
|
||||
{
|
||||
if (ir->mask.num_components != 1)
|
||||
{
|
||||
@@ -1126,7 +1080,8 @@ void ir_print_glsl_visitor::visit(ir_assignment *ir)
|
||||
if (!ir->condition && whole_var)
|
||||
{
|
||||
loop_variable_state* inductor_state = loopstate->get_for_inductor(whole_var);
|
||||
if (inductor_state && inductor_state->private_induction_variable_count == 1)
|
||||
if (inductor_state && inductor_state->private_induction_variable_count == 1 &&
|
||||
can_emit_canonical_for(inductor_state))
|
||||
{
|
||||
skipped_this_ir = true;
|
||||
return;
|
||||
@@ -1200,6 +1155,18 @@ static void print_float (string_buffer& buffer, float f)
|
||||
if (!posE)
|
||||
posE = strchr(tmp, 'E');
|
||||
|
||||
// snprintf formats infinity as inf.0 or -inf.0, which isn't useful here.
|
||||
// GLSL has no infinity constant so print an equivalent expression instead.
|
||||
if (f == std::numeric_limits<float>::infinity())
|
||||
strcpy(tmp, "(1.0/0.0)");
|
||||
|
||||
if (f == -std::numeric_limits<float>::infinity())
|
||||
strcpy(tmp, "(-1.0/0.0)");
|
||||
|
||||
// Do similar thing for NaN
|
||||
if (f != f)
|
||||
strcpy(tmp, "(0.0/0.0)");
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
// While gcc would print something like 1.0e+07, MSVC will print 1.0e+007 -
|
||||
// only for exponential notation, it seems, will add one extra useless zero. Let's try to remove
|
||||
@@ -1241,7 +1208,12 @@ void ir_print_glsl_visitor::visit(ir_constant *ir)
|
||||
}
|
||||
else if (type == glsl_type::uint_type)
|
||||
{
|
||||
buffer.asprintf_append ("%u", ir->value.u[0]);
|
||||
// ES 2.0 doesn't support uints, neither does GLSL < 130
|
||||
if ((state->es_shader && (state->language_version < 300))
|
||||
|| (state->language_version < 130))
|
||||
buffer.asprintf_append("%u", ir->value.u[0]);
|
||||
else
|
||||
buffer.asprintf_append("%uu", ir->value.u[0]);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1259,11 +1231,10 @@ void ir_print_glsl_visitor::visit(ir_constant *ir)
|
||||
}
|
||||
} else if (ir->type->is_record()) {
|
||||
bool first = true;
|
||||
foreach_list(n, &ir->components) {
|
||||
foreach_in_list(ir_constant, inst, &ir->components) {
|
||||
if (!first)
|
||||
buffer.asprintf_append (", ");
|
||||
first = false;
|
||||
ir_constant* inst = (ir_constant*)n;
|
||||
inst->accept(this);
|
||||
}
|
||||
}else {
|
||||
@@ -1273,7 +1244,16 @@ void ir_print_glsl_visitor::visit(ir_constant *ir)
|
||||
buffer.asprintf_append (", ");
|
||||
first = false;
|
||||
switch (base_type->base_type) {
|
||||
case GLSL_TYPE_UINT: buffer.asprintf_append ("%u", ir->value.u[i]); break;
|
||||
case GLSL_TYPE_UINT:
|
||||
{
|
||||
// ES 2.0 doesn't support uints, neither does GLSL < 130
|
||||
if ((state->es_shader && (state->language_version < 300))
|
||||
|| (state->language_version < 130))
|
||||
buffer.asprintf_append("%u", ir->value.u[i]);
|
||||
else
|
||||
buffer.asprintf_append("%uu", ir->value.u[i]);
|
||||
break;
|
||||
}
|
||||
case GLSL_TYPE_INT: buffer.asprintf_append ("%d", ir->value.i[i]); break;
|
||||
case GLSL_TYPE_FLOAT: print_float(buffer, ir->value.f[i]); break;
|
||||
case GLSL_TYPE_BOOL: buffer.asprintf_append ("%d", ir->value.b[i]); break;
|
||||
@@ -1305,8 +1285,7 @@ ir_print_glsl_visitor::visit(ir_call *ir)
|
||||
|
||||
buffer.asprintf_append ("%s (", ir->callee_name());
|
||||
bool first = true;
|
||||
foreach_list(node, &ir->actual_parameters) {
|
||||
ir_instruction *const inst = (ir_instruction *)node;
|
||||
foreach_in_list(ir_instruction, inst, &ir->actual_parameters) {
|
||||
if (!first)
|
||||
buffer.asprintf_append (", ");
|
||||
inst->accept(this);
|
||||
@@ -1351,9 +1330,7 @@ ir_print_glsl_visitor::visit(ir_if *ir)
|
||||
indentation++; previous_skipped = false;
|
||||
|
||||
|
||||
foreach_list(n, &ir->then_instructions) {
|
||||
ir_instruction *const inst = (ir_instruction *)n;
|
||||
|
||||
foreach_in_list(ir_instruction, inst, &ir->then_instructions) {
|
||||
indent();
|
||||
inst->accept(this);
|
||||
end_statement_line();
|
||||
@@ -1368,9 +1345,7 @@ ir_print_glsl_visitor::visit(ir_if *ir)
|
||||
buffer.asprintf_append (" else {\n");
|
||||
indentation++; previous_skipped = false;
|
||||
|
||||
foreach_list(n, &ir->else_instructions) {
|
||||
ir_instruction *const inst = (ir_instruction *)n;
|
||||
|
||||
foreach_in_list(ir_instruction, inst, &ir->else_instructions) {
|
||||
indent();
|
||||
inst->accept(this);
|
||||
end_statement_line();
|
||||
@@ -1381,10 +1356,8 @@ ir_print_glsl_visitor::visit(ir_if *ir)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool ir_print_glsl_visitor::emit_canonical_for (ir_loop* ir)
|
||||
bool ir_print_glsl_visitor::can_emit_canonical_for (loop_variable_state *ls)
|
||||
{
|
||||
loop_variable_state* const ls = this->loopstate->get(ir);
|
||||
if (ls == NULL)
|
||||
return false;
|
||||
|
||||
@@ -1395,12 +1368,19 @@ bool ir_print_glsl_visitor::emit_canonical_for (ir_loop* ir)
|
||||
return false;
|
||||
|
||||
// only support for loops with one terminator condition
|
||||
int terminatorCount = 0;
|
||||
foreach_list(node, &ls->terminators) {
|
||||
++terminatorCount;
|
||||
}
|
||||
int terminatorCount = ls->terminators.length();
|
||||
if (terminatorCount != 1)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ir_print_glsl_visitor::emit_canonical_for (ir_loop* ir)
|
||||
{
|
||||
loop_variable_state* const ls = this->loopstate->get(ir);
|
||||
|
||||
if (!can_emit_canonical_for(ls))
|
||||
return false;
|
||||
|
||||
hash_table* terminator_hash = hash_table_ctor(0, hash_table_pointer_hash, hash_table_pointer_compare);
|
||||
hash_table* induction_hash = hash_table_ctor(0, hash_table_pointer_hash, hash_table_pointer_compare);
|
||||
@@ -1412,9 +1392,8 @@ bool ir_print_glsl_visitor::emit_canonical_for (ir_loop* ir)
|
||||
// only for loops with single induction variable, to avoid cases of different types of them
|
||||
if (ls->private_induction_variable_count == 1)
|
||||
{
|
||||
foreach_list(node, &ls->induction_variables)
|
||||
foreach_in_list(loop_variable, indvar, &ls->induction_variables)
|
||||
{
|
||||
loop_variable* indvar = (loop_variable *) node;
|
||||
if (!this->loopstate->get_for_inductor(indvar->var))
|
||||
continue;
|
||||
|
||||
@@ -1434,9 +1413,8 @@ bool ir_print_glsl_visitor::emit_canonical_for (ir_loop* ir)
|
||||
buffer.asprintf_append("; ");
|
||||
|
||||
// emit loop terminating conditions
|
||||
foreach_list(node, &ls->terminators)
|
||||
foreach_in_list(loop_terminator, term, &ls->terminators)
|
||||
{
|
||||
loop_terminator* term = (loop_terminator *) node;
|
||||
hash_table_insert(terminator_hash, term, term->ir);
|
||||
|
||||
// IR has conditions in the form of "if (x) break",
|
||||
@@ -1487,9 +1465,8 @@ bool ir_print_glsl_visitor::emit_canonical_for (ir_loop* ir)
|
||||
|
||||
// emit loop induction variable updates
|
||||
bool first = true;
|
||||
foreach_list(node, &ls->induction_variables)
|
||||
foreach_in_list(loop_variable, indvar, &ls->induction_variables)
|
||||
{
|
||||
loop_variable* indvar = (loop_variable *) node;
|
||||
hash_table_insert(induction_hash, indvar, indvar->first_assignment);
|
||||
if (!first)
|
||||
buffer.asprintf_append(", ");
|
||||
@@ -1502,9 +1479,8 @@ bool ir_print_glsl_visitor::emit_canonical_for (ir_loop* ir)
|
||||
|
||||
// emit loop body
|
||||
indentation++; previous_skipped = false;
|
||||
foreach_list(node, &ir->body_instructions) {
|
||||
ir_instruction *const inst = (ir_instruction *)node;
|
||||
|
||||
foreach_in_list(ir_instruction, inst, &ir->body_instructions) {
|
||||
|
||||
// skip termination & induction statements,
|
||||
// they are part of "for" clause
|
||||
if (hash_table_find(terminator_hash, inst))
|
||||
@@ -1536,8 +1512,7 @@ ir_print_glsl_visitor::visit(ir_loop *ir)
|
||||
|
||||
buffer.asprintf_append ("while (true) {\n");
|
||||
indentation++; previous_skipped = false;
|
||||
foreach_list(n, &ir->body_instructions) {
|
||||
ir_instruction *const inst = (ir_instruction *)n;
|
||||
foreach_in_list(ir_instruction, inst, &ir->body_instructions) {
|
||||
indent();
|
||||
inst->accept(this);
|
||||
end_statement_line();
|
||||
|
||||
@@ -38,4 +38,65 @@ extern char* _mesa_print_ir_glsl(exec_list *instructions,
|
||||
struct _mesa_glsl_parse_state *state,
|
||||
char* buf, PrintGlslMode mode);
|
||||
|
||||
|
||||
|
||||
class string_buffer
|
||||
{
|
||||
public:
|
||||
string_buffer(void* mem_ctx)
|
||||
{
|
||||
m_Capacity = 512;
|
||||
m_Ptr = (char*)ralloc_size(mem_ctx, m_Capacity);
|
||||
m_Size = 0;
|
||||
m_Ptr[0] = 0;
|
||||
}
|
||||
|
||||
~string_buffer()
|
||||
{
|
||||
ralloc_free(m_Ptr);
|
||||
}
|
||||
|
||||
bool empty() const { return m_Size == 0; }
|
||||
|
||||
const char* c_str() const { return m_Ptr; }
|
||||
|
||||
void asprintf_append(const char *fmt, ...) PRINTFLIKE(2, 3)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
vasprintf_append(fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void vasprintf_append(const char *fmt, va_list args)
|
||||
{
|
||||
assert (m_Ptr != NULL);
|
||||
vasprintf_rewrite_tail (&m_Size, fmt, args);
|
||||
}
|
||||
|
||||
void vasprintf_rewrite_tail (size_t *start, const char *fmt, va_list args)
|
||||
{
|
||||
assert (m_Ptr != NULL);
|
||||
|
||||
size_t new_length = printf_length(fmt, args);
|
||||
size_t needed_length = m_Size + new_length + 1;
|
||||
|
||||
if (m_Capacity < needed_length)
|
||||
{
|
||||
m_Capacity = MAX2 (m_Capacity + m_Capacity/2, needed_length);
|
||||
m_Ptr = (char*)reralloc_size(ralloc_parent(m_Ptr), m_Ptr, m_Capacity);
|
||||
}
|
||||
|
||||
vsnprintf(m_Ptr + m_Size, new_length+1, fmt, args);
|
||||
m_Size += new_length;
|
||||
assert (m_Capacity >= m_Size);
|
||||
}
|
||||
|
||||
private:
|
||||
char* m_Ptr;
|
||||
size_t m_Size;
|
||||
size_t m_Capacity;
|
||||
};
|
||||
|
||||
|
||||
#endif /* IR_PRINT_GLSL_VISITOR_H */
|
||||
|
||||
1914
3rdparty/glsl-optimizer/src/glsl/ir_print_metal_visitor.cpp
vendored
Normal file
1914
3rdparty/glsl-optimizer/src/glsl/ir_print_metal_visitor.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
36
3rdparty/glsl-optimizer/src/glsl/ir_print_metal_visitor.h
vendored
Normal file
36
3rdparty/glsl-optimizer/src/glsl/ir_print_metal_visitor.h
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
/* -*- c++ -*- */
|
||||
/*
|
||||
* Copyright © 2014 Unity Technologies
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef IR_PRINT_METAL_VISITOR_H
|
||||
#define IR_PRINT_METAL_VISITOR_H
|
||||
|
||||
#include "ir.h"
|
||||
#include "ir_print_glsl_visitor.h"
|
||||
|
||||
extern char* _mesa_print_ir_metal(exec_list *instructions,
|
||||
struct _mesa_glsl_parse_state *state,
|
||||
char* buf, PrintGlslMode mode, int* outUniformsSize);
|
||||
|
||||
#endif /* IR_PRINT_GLSL_VISITOR_H */
|
||||
@@ -27,52 +27,65 @@
|
||||
#include "main/macros.h"
|
||||
#include "program/hash_table.h"
|
||||
|
||||
static void print_type(const glsl_type *t);
|
||||
static void print_type(FILE *f, const glsl_type *t);
|
||||
|
||||
void
|
||||
ir_instruction::print(void) const
|
||||
{
|
||||
this->fprint(stdout);
|
||||
}
|
||||
|
||||
void
|
||||
ir_instruction::fprint(FILE *f) const
|
||||
{
|
||||
ir_instruction *deconsted = const_cast<ir_instruction *>(this);
|
||||
|
||||
ir_print_visitor v;
|
||||
ir_print_visitor v(f);
|
||||
deconsted->accept(&v);
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
void
|
||||
_mesa_print_ir(exec_list *instructions,
|
||||
_mesa_print_ir(FILE *f, exec_list *instructions,
|
||||
struct _mesa_glsl_parse_state *state)
|
||||
{
|
||||
if (state) {
|
||||
for (unsigned i = 0; i < state->num_user_structures; i++) {
|
||||
const glsl_type *const s = state->user_structures[i];
|
||||
|
||||
printf("(structure (%s) (%s@%p) (%u) (\n",
|
||||
s->name, s->name, (void *) s, s->length);
|
||||
fprintf(f, "(structure (%s) (%s@%p) (%u) (\n",
|
||||
s->name, s->name, (void *) s, s->length);
|
||||
|
||||
for (unsigned j = 0; j < s->length; j++) {
|
||||
printf("\t((");
|
||||
print_type(s->fields.structure[j].type);
|
||||
printf(")(%s))\n", s->fields.structure[j].name);
|
||||
fprintf(f, "\t((");
|
||||
print_type(f, s->fields.structure[j].type);
|
||||
fprintf(f, ")(%s))\n", s->fields.structure[j].name);
|
||||
}
|
||||
|
||||
printf(")\n");
|
||||
fprintf(f, ")\n");
|
||||
}
|
||||
}
|
||||
|
||||
printf("(\n");
|
||||
foreach_list(n, instructions) {
|
||||
ir_instruction *ir = (ir_instruction *) n;
|
||||
ir->print();
|
||||
fprintf(f, "(\n");
|
||||
foreach_in_list(ir_instruction, ir, instructions) {
|
||||
ir->fprint(f);
|
||||
if (ir->ir_type != ir_type_function)
|
||||
printf("\n");
|
||||
fprintf(f, "\n");
|
||||
}
|
||||
printf("\n)");
|
||||
fprintf(f, "\n)");
|
||||
}
|
||||
|
||||
void
|
||||
fprint_ir(FILE *f, const void *instruction)
|
||||
{
|
||||
const ir_instruction *ir = (const ir_instruction *)instruction;
|
||||
ir->fprint(f);
|
||||
}
|
||||
|
||||
} /* extern "C" */
|
||||
|
||||
ir_print_visitor::ir_print_visitor()
|
||||
ir_print_visitor::ir_print_visitor(FILE *f)
|
||||
: f(f)
|
||||
{
|
||||
indentation = 0;
|
||||
printable_names =
|
||||
@@ -91,7 +104,7 @@ ir_print_visitor::~ir_print_visitor()
|
||||
void ir_print_visitor::indent(void)
|
||||
{
|
||||
for (int i = 0; i < indentation; i++)
|
||||
printf(" ");
|
||||
fprintf(f, " ");
|
||||
}
|
||||
|
||||
const char *
|
||||
@@ -125,87 +138,86 @@ ir_print_visitor::unique_name(ir_variable *var)
|
||||
}
|
||||
|
||||
static void
|
||||
print_type(const glsl_type *t)
|
||||
print_type(FILE *f, const glsl_type *t)
|
||||
{
|
||||
if (t->base_type == GLSL_TYPE_ARRAY) {
|
||||
printf("(array ");
|
||||
print_type(t->fields.array);
|
||||
printf(" %u)", t->length);
|
||||
fprintf(f, "(array ");
|
||||
print_type(f, t->fields.array);
|
||||
fprintf(f, " %u)", t->length);
|
||||
} else if ((t->base_type == GLSL_TYPE_STRUCT)
|
||||
&& (strncmp("gl_", t->name, 3) != 0)) {
|
||||
printf("%s@%p", t->name, (void *) t);
|
||||
&& !is_gl_identifier(t->name)) {
|
||||
fprintf(f, "%s@%p", t->name, (void *) t);
|
||||
} else {
|
||||
printf("%s", t->name);
|
||||
fprintf(f, "%s", t->name);
|
||||
}
|
||||
}
|
||||
|
||||
void ir_print_visitor::visit(ir_rvalue *ir)
|
||||
void ir_print_visitor::visit(ir_rvalue *)
|
||||
{
|
||||
printf("error");
|
||||
fprintf(f, "error");
|
||||
}
|
||||
|
||||
void ir_print_visitor::visit(ir_variable *ir)
|
||||
{
|
||||
printf("(declare ");
|
||||
fprintf(f, "(declare ");
|
||||
|
||||
const char *const cent = (ir->data.centroid) ? "centroid " : "";
|
||||
const char *const samp = (ir->data.sample) ? "sample " : "";
|
||||
const char *const inv = (ir->data.invariant) ? "invariant " : "";
|
||||
const char *const mode[] = { "", "uniform ", "shader_in ", "shader_out ",
|
||||
const char *const mode[] = { "", "uniform ", "shader_in ", "shader_out ", "shader_inout ",
|
||||
"in ", "out ", "inout ",
|
||||
"const_in ", "sys ", "temporary " };
|
||||
STATIC_ASSERT(ARRAY_SIZE(mode) == ir_var_mode_count);
|
||||
const char *const stream [] = {"", "stream1 ", "stream2 ", "stream3 "};
|
||||
const char *const interp[] = { "", "smooth", "flat", "noperspective" };
|
||||
STATIC_ASSERT(ARRAY_SIZE(interp) == INTERP_QUALIFIER_COUNT);
|
||||
|
||||
printf("(%s%s%s%s%s) ",
|
||||
cent, samp, inv, mode[ir->data.mode], interp[ir->data.interpolation]);
|
||||
fprintf(f, "(%s%s%s%s%s%s) ",
|
||||
cent, samp, inv, mode[ir->data.mode],
|
||||
stream[ir->data.stream],
|
||||
interp[ir->data.interpolation]);
|
||||
|
||||
print_type(ir->type);
|
||||
printf(" %s)", unique_name(ir));
|
||||
print_type(f, ir->type);
|
||||
fprintf(f, " %s)", unique_name(ir));
|
||||
}
|
||||
|
||||
|
||||
void ir_print_visitor::visit(ir_function_signature *ir)
|
||||
{
|
||||
_mesa_symbol_table_push_scope(symbols);
|
||||
printf("(signature ");
|
||||
fprintf(f, "(signature ");
|
||||
indentation++;
|
||||
|
||||
print_type(ir->return_type);
|
||||
printf("\n");
|
||||
print_type(f, ir->return_type);
|
||||
fprintf(f, "\n");
|
||||
indent();
|
||||
|
||||
printf("(parameters\n");
|
||||
fprintf(f, "(parameters\n");
|
||||
indentation++;
|
||||
|
||||
foreach_list(n, &ir->parameters) {
|
||||
ir_variable *const inst = (ir_variable *) n;
|
||||
|
||||
foreach_in_list(ir_variable, inst, &ir->parameters) {
|
||||
indent();
|
||||
inst->accept(this);
|
||||
printf("\n");
|
||||
fprintf(f, "\n");
|
||||
}
|
||||
indentation--;
|
||||
|
||||
indent();
|
||||
printf(")\n");
|
||||
fprintf(f, ")\n");
|
||||
|
||||
indent();
|
||||
|
||||
printf("(\n");
|
||||
fprintf(f, "(\n");
|
||||
indentation++;
|
||||
|
||||
foreach_list(n, &ir->body) {
|
||||
ir_instruction *const inst = (ir_instruction *) n;
|
||||
|
||||
foreach_in_list(ir_instruction, inst, &ir->body) {
|
||||
indent();
|
||||
inst->accept(this);
|
||||
printf("\n");
|
||||
fprintf(f, "\n");
|
||||
}
|
||||
indentation--;
|
||||
indent();
|
||||
printf("))\n");
|
||||
fprintf(f, "))\n");
|
||||
indentation--;
|
||||
_mesa_symbol_table_pop_scope(symbols);
|
||||
}
|
||||
@@ -213,61 +225,60 @@ void ir_print_visitor::visit(ir_function_signature *ir)
|
||||
|
||||
void ir_print_visitor::visit(ir_function *ir)
|
||||
{
|
||||
printf("(function %s\n", ir->name);
|
||||
fprintf(f, "(function %s\n", ir->name);
|
||||
indentation++;
|
||||
foreach_list(n, &ir->signatures) {
|
||||
ir_function_signature *const sig = (ir_function_signature *) n;
|
||||
foreach_in_list(ir_function_signature, sig, &ir->signatures) {
|
||||
indent();
|
||||
sig->accept(this);
|
||||
printf("\n");
|
||||
fprintf(f, "\n");
|
||||
}
|
||||
indentation--;
|
||||
indent();
|
||||
printf(")\n\n");
|
||||
fprintf(f, ")\n\n");
|
||||
}
|
||||
|
||||
|
||||
void ir_print_visitor::visit(ir_expression *ir)
|
||||
{
|
||||
printf("(expression ");
|
||||
fprintf(f, "(expression ");
|
||||
|
||||
print_type(ir->type);
|
||||
print_type(f, ir->type);
|
||||
|
||||
printf(" %s ", ir->operator_string());
|
||||
fprintf(f, " %s ", ir->operator_string());
|
||||
|
||||
for (unsigned i = 0; i < ir->get_num_operands(); i++) {
|
||||
ir->operands[i]->accept(this);
|
||||
}
|
||||
|
||||
printf(") ");
|
||||
fprintf(f, ") ");
|
||||
}
|
||||
|
||||
|
||||
void ir_print_visitor::visit(ir_texture *ir)
|
||||
{
|
||||
printf("(%s ", ir->opcode_string());
|
||||
fprintf(f, "(%s ", ir->opcode_string());
|
||||
|
||||
print_type(ir->type);
|
||||
printf(" ");
|
||||
print_type(f, ir->type);
|
||||
fprintf(f, " ");
|
||||
|
||||
ir->sampler->accept(this);
|
||||
printf(" ");
|
||||
fprintf(f, " ");
|
||||
|
||||
if (ir->op != ir_txs && ir->op != ir_query_levels) {
|
||||
ir->coordinate->accept(this);
|
||||
|
||||
printf(" ");
|
||||
fprintf(f, " ");
|
||||
|
||||
if (ir->offset != NULL) {
|
||||
ir->offset->accept(this);
|
||||
} else {
|
||||
printf("0");
|
||||
fprintf(f, "0");
|
||||
}
|
||||
|
||||
printf(" ");
|
||||
fprintf(f, " ");
|
||||
}
|
||||
|
||||
printf(" ");
|
||||
fprintf(f, " ");
|
||||
switch (ir->op)
|
||||
{
|
||||
case ir_tex:
|
||||
@@ -286,17 +297,17 @@ void ir_print_visitor::visit(ir_texture *ir)
|
||||
ir->lod_info.sample_index->accept(this);
|
||||
break;
|
||||
case ir_txd:
|
||||
printf("(");
|
||||
fprintf(f, "(");
|
||||
ir->lod_info.grad.dPdx->accept(this);
|
||||
printf(" ");
|
||||
fprintf(f, " ");
|
||||
ir->lod_info.grad.dPdy->accept(this);
|
||||
printf(")");
|
||||
fprintf(f, ")");
|
||||
break;
|
||||
case ir_tg4:
|
||||
ir->lod_info.component->accept(this);
|
||||
break;
|
||||
};
|
||||
printf(")");
|
||||
fprintf(f, ")");
|
||||
}
|
||||
|
||||
|
||||
@@ -309,43 +320,43 @@ void ir_print_visitor::visit(ir_swizzle *ir)
|
||||
ir->mask.w,
|
||||
};
|
||||
|
||||
printf("(swiz ");
|
||||
fprintf(f, "(swiz ");
|
||||
for (unsigned i = 0; i < ir->mask.num_components; i++) {
|
||||
printf("%c", "xyzw"[swiz[i]]);
|
||||
fprintf(f, "%c", "xyzw"[swiz[i]]);
|
||||
}
|
||||
printf(" ");
|
||||
fprintf(f, " ");
|
||||
ir->val->accept(this);
|
||||
printf(")");
|
||||
fprintf(f, ")");
|
||||
}
|
||||
|
||||
|
||||
void ir_print_visitor::visit(ir_dereference_variable *ir)
|
||||
{
|
||||
ir_variable *var = ir->variable_referenced();
|
||||
printf("(var_ref %s) ", unique_name(var));
|
||||
fprintf(f, "(var_ref %s) ", unique_name(var));
|
||||
}
|
||||
|
||||
|
||||
void ir_print_visitor::visit(ir_dereference_array *ir)
|
||||
{
|
||||
printf("(array_ref ");
|
||||
fprintf(f, "(array_ref ");
|
||||
ir->array->accept(this);
|
||||
ir->array_index->accept(this);
|
||||
printf(") ");
|
||||
fprintf(f, ") ");
|
||||
}
|
||||
|
||||
|
||||
void ir_print_visitor::visit(ir_dereference_record *ir)
|
||||
{
|
||||
printf("(record_ref ");
|
||||
fprintf(f, "(record_ref ");
|
||||
ir->record->accept(this);
|
||||
printf(" %s) ", ir->field);
|
||||
fprintf(f, " %s) ", ir->field);
|
||||
}
|
||||
|
||||
|
||||
void ir_print_visitor::visit(ir_assignment *ir)
|
||||
{
|
||||
printf("(assign ");
|
||||
fprintf(f, "(assign ");
|
||||
|
||||
if (ir->condition)
|
||||
ir->condition->accept(this);
|
||||
@@ -361,22 +372,22 @@ void ir_print_visitor::visit(ir_assignment *ir)
|
||||
}
|
||||
mask[j] = '\0';
|
||||
|
||||
printf(" (%s) ", mask);
|
||||
fprintf(f, " (%s) ", mask);
|
||||
|
||||
ir->lhs->accept(this);
|
||||
|
||||
printf(" ");
|
||||
fprintf(f, " ");
|
||||
|
||||
ir->rhs->accept(this);
|
||||
printf(") ");
|
||||
fprintf(f, ") ");
|
||||
}
|
||||
|
||||
|
||||
void ir_print_visitor::visit(ir_constant *ir)
|
||||
{
|
||||
printf("(constant ");
|
||||
print_type(ir->type);
|
||||
printf(" (");
|
||||
fprintf(f, "(constant ");
|
||||
print_type(f, ir->type);
|
||||
fprintf(f, " (");
|
||||
|
||||
if (ir->type->is_array()) {
|
||||
for (unsigned i = 0; i < ir->type->length; i++)
|
||||
@@ -384,122 +395,116 @@ void ir_print_visitor::visit(ir_constant *ir)
|
||||
} else if (ir->type->is_record()) {
|
||||
ir_constant *value = (ir_constant *) ir->components.get_head();
|
||||
for (unsigned i = 0; i < ir->type->length; i++) {
|
||||
printf("(%s ", ir->type->fields.structure[i].name);
|
||||
fprintf(f, "(%s ", ir->type->fields.structure[i].name);
|
||||
value->accept(this);
|
||||
printf(")");
|
||||
fprintf(f, ")");
|
||||
|
||||
value = (ir_constant *) value->next;
|
||||
}
|
||||
} else {
|
||||
for (unsigned i = 0; i < ir->type->components(); i++) {
|
||||
if (i != 0)
|
||||
printf(" ");
|
||||
fprintf(f, " ");
|
||||
switch (ir->type->base_type) {
|
||||
case GLSL_TYPE_UINT: printf("%u", ir->value.u[i]); break;
|
||||
case GLSL_TYPE_INT: printf("%d", ir->value.i[i]); break;
|
||||
case GLSL_TYPE_UINT: fprintf(f, "%u", ir->value.u[i]); break;
|
||||
case GLSL_TYPE_INT: fprintf(f, "%d", ir->value.i[i]); break;
|
||||
case GLSL_TYPE_FLOAT:
|
||||
if (ir->value.f[i] == 0.0f)
|
||||
/* 0.0 == -0.0, so print with %f to get the proper sign. */
|
||||
printf("%.1f", ir->value.f[i]);
|
||||
fprintf(f, "%f", ir->value.f[i]);
|
||||
else if (fabs(ir->value.f[i]) < 0.000001f)
|
||||
printf("%a", ir->value.f[i]);
|
||||
fprintf(f, "%a", ir->value.f[i]);
|
||||
else if (fabs(ir->value.f[i]) > 1000000.0f)
|
||||
printf("%e", ir->value.f[i]);
|
||||
fprintf(f, "%e", ir->value.f[i]);
|
||||
else
|
||||
printf("%f", ir->value.f[i]);
|
||||
fprintf(f, "%f", ir->value.f[i]);
|
||||
break;
|
||||
case GLSL_TYPE_BOOL: printf("%d", ir->value.b[i]); break;
|
||||
case GLSL_TYPE_BOOL: fprintf(f, "%d", ir->value.b[i]); break;
|
||||
default: assert(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
printf(")) ");
|
||||
fprintf(f, ")) ");
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ir_print_visitor::visit(ir_call *ir)
|
||||
{
|
||||
printf("(call %s ", ir->callee_name());
|
||||
fprintf(f, "(call %s ", ir->callee_name());
|
||||
if (ir->return_deref)
|
||||
ir->return_deref->accept(this);
|
||||
printf(" (");
|
||||
foreach_list(n, &ir->actual_parameters) {
|
||||
ir_rvalue *const param = (ir_rvalue *) n;
|
||||
|
||||
fprintf(f, " (");
|
||||
foreach_in_list(ir_rvalue, param, &ir->actual_parameters) {
|
||||
param->accept(this);
|
||||
}
|
||||
printf("))\n");
|
||||
fprintf(f, "))\n");
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ir_print_visitor::visit(ir_return *ir)
|
||||
{
|
||||
printf("(return");
|
||||
fprintf(f, "(return");
|
||||
|
||||
ir_rvalue *const value = ir->get_value();
|
||||
if (value) {
|
||||
printf(" ");
|
||||
fprintf(f, " ");
|
||||
value->accept(this);
|
||||
}
|
||||
|
||||
printf(")");
|
||||
fprintf(f, ")");
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ir_print_visitor::visit(ir_discard *ir)
|
||||
{
|
||||
printf("(discard ");
|
||||
fprintf(f, "(discard ");
|
||||
|
||||
if (ir->condition != NULL) {
|
||||
printf(" ");
|
||||
fprintf(f, " ");
|
||||
ir->condition->accept(this);
|
||||
}
|
||||
|
||||
printf(")");
|
||||
fprintf(f, ")");
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ir_print_visitor::visit(ir_if *ir)
|
||||
{
|
||||
printf("(if ");
|
||||
fprintf(f, "(if ");
|
||||
ir->condition->accept(this);
|
||||
|
||||
printf("(\n");
|
||||
fprintf(f, "(\n");
|
||||
indentation++;
|
||||
|
||||
foreach_list(n, &ir->then_instructions) {
|
||||
ir_instruction *const inst = (ir_instruction *) n;
|
||||
|
||||
foreach_in_list(ir_instruction, inst, &ir->then_instructions) {
|
||||
indent();
|
||||
inst->accept(this);
|
||||
printf("\n");
|
||||
fprintf(f, "\n");
|
||||
}
|
||||
|
||||
indentation--;
|
||||
indent();
|
||||
printf(")\n");
|
||||
fprintf(f, ")\n");
|
||||
|
||||
indent();
|
||||
if (!ir->else_instructions.is_empty()) {
|
||||
printf("(\n");
|
||||
fprintf(f, "(\n");
|
||||
indentation++;
|
||||
|
||||
foreach_list(n, &ir->else_instructions) {
|
||||
ir_instruction *const inst = (ir_instruction *) n;
|
||||
|
||||
foreach_in_list(ir_instruction, inst, &ir->else_instructions) {
|
||||
indent();
|
||||
inst->accept(this);
|
||||
printf("\n");
|
||||
fprintf(f, "\n");
|
||||
}
|
||||
indentation--;
|
||||
indent();
|
||||
printf("))\n");
|
||||
fprintf(f, "))\n");
|
||||
} else {
|
||||
printf("())\n");
|
||||
fprintf(f, "())\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -507,26 +512,24 @@ ir_print_visitor::visit(ir_if *ir)
|
||||
void
|
||||
ir_print_visitor::visit(ir_loop *ir)
|
||||
{
|
||||
printf("(loop (\n");
|
||||
fprintf(f, "(loop (\n");
|
||||
indentation++;
|
||||
|
||||
foreach_list(n, &ir->body_instructions) {
|
||||
ir_instruction *const inst = (ir_instruction *) n;
|
||||
|
||||
foreach_in_list(ir_instruction, inst, &ir->body_instructions) {
|
||||
indent();
|
||||
inst->accept(this);
|
||||
printf("\n");
|
||||
fprintf(f, "\n");
|
||||
}
|
||||
indentation--;
|
||||
indent();
|
||||
printf("))\n");
|
||||
fprintf(f, "))\n");
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ir_print_visitor::visit(ir_loop_jump *ir)
|
||||
{
|
||||
printf("%s", ir->is_break() ? "break" : "continue");
|
||||
fprintf(f, "%s", ir->is_break() ? "break" : "continue");
|
||||
}
|
||||
|
||||
void
|
||||
@@ -543,11 +546,16 @@ ir_print_visitor::visit(ir_typedecl_statement *ir)
|
||||
void
|
||||
ir_print_visitor::visit(ir_emit_vertex *ir)
|
||||
{
|
||||
printf("(emit-vertex)");
|
||||
fprintf(f, "(emit-vertex ");
|
||||
ir->stream->accept(this);
|
||||
fprintf(f, ")\n");
|
||||
}
|
||||
|
||||
void
|
||||
ir_print_visitor::visit(ir_end_primitive *ir)
|
||||
{
|
||||
printf("(end-primitive)");
|
||||
fprintf(f, "(end-primitive ");
|
||||
ir->stream->accept(this);
|
||||
fprintf(f, ")\n");
|
||||
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ extern "C" {
|
||||
*/
|
||||
class ir_print_visitor : public ir_visitor {
|
||||
public:
|
||||
ir_print_visitor();
|
||||
ir_print_visitor(FILE *f);
|
||||
virtual ~ir_print_visitor();
|
||||
|
||||
void indent(void);
|
||||
@@ -89,6 +89,7 @@ private:
|
||||
_mesa_symbol_table *symbols;
|
||||
|
||||
void *mem_ctx;
|
||||
FILE *f;
|
||||
|
||||
int indentation;
|
||||
};
|
||||
|
||||
@@ -121,8 +121,7 @@ ir_rvalue_base_visitor::rvalue_visit(ir_assignment *ir)
|
||||
ir_visitor_status
|
||||
ir_rvalue_base_visitor::rvalue_visit(ir_call *ir)
|
||||
{
|
||||
foreach_list_safe(n, &ir->actual_parameters) {
|
||||
ir_rvalue *param = (ir_rvalue *) n;
|
||||
foreach_in_list_safe(ir_rvalue, param, &ir->actual_parameters) {
|
||||
ir_rvalue *new_param = param;
|
||||
handle_rvalue(&new_param);
|
||||
|
||||
@@ -147,6 +146,19 @@ ir_rvalue_base_visitor::rvalue_visit(ir_if *ir)
|
||||
return visit_continue;
|
||||
}
|
||||
|
||||
ir_visitor_status
|
||||
ir_rvalue_base_visitor::rvalue_visit(ir_emit_vertex *ir)
|
||||
{
|
||||
handle_rvalue(&ir->stream);
|
||||
return visit_continue;
|
||||
}
|
||||
|
||||
ir_visitor_status
|
||||
ir_rvalue_base_visitor::rvalue_visit(ir_end_primitive *ir)
|
||||
{
|
||||
handle_rvalue(&ir->stream);
|
||||
return visit_continue;
|
||||
}
|
||||
|
||||
ir_visitor_status
|
||||
ir_rvalue_visitor::visit_leave(ir_expression *ir)
|
||||
@@ -202,6 +214,18 @@ ir_rvalue_visitor::visit_leave(ir_if *ir)
|
||||
return rvalue_visit(ir);
|
||||
}
|
||||
|
||||
ir_visitor_status
|
||||
ir_rvalue_visitor::visit_leave(ir_emit_vertex *ir)
|
||||
{
|
||||
return rvalue_visit(ir);
|
||||
}
|
||||
|
||||
ir_visitor_status
|
||||
ir_rvalue_visitor::visit_leave(ir_end_primitive *ir)
|
||||
{
|
||||
return rvalue_visit(ir);
|
||||
}
|
||||
|
||||
ir_visitor_status
|
||||
ir_rvalue_enter_visitor::visit_enter(ir_expression *ir)
|
||||
{
|
||||
@@ -255,3 +279,15 @@ ir_rvalue_enter_visitor::visit_enter(ir_if *ir)
|
||||
{
|
||||
return rvalue_visit(ir);
|
||||
}
|
||||
|
||||
ir_visitor_status
|
||||
ir_rvalue_enter_visitor::visit_enter(ir_emit_vertex *ir)
|
||||
{
|
||||
return rvalue_visit(ir);
|
||||
}
|
||||
|
||||
ir_visitor_status
|
||||
ir_rvalue_enter_visitor::visit_enter(ir_end_primitive *ir)
|
||||
{
|
||||
return rvalue_visit(ir);
|
||||
}
|
||||
|
||||
@@ -41,6 +41,8 @@ public:
|
||||
ir_visitor_status rvalue_visit(ir_return *);
|
||||
ir_visitor_status rvalue_visit(ir_swizzle *);
|
||||
ir_visitor_status rvalue_visit(ir_texture *);
|
||||
ir_visitor_status rvalue_visit(ir_emit_vertex *);
|
||||
ir_visitor_status rvalue_visit(ir_end_primitive *);
|
||||
|
||||
virtual void handle_rvalue(ir_rvalue **rvalue) = 0;
|
||||
};
|
||||
@@ -57,6 +59,8 @@ public:
|
||||
virtual ir_visitor_status visit_leave(ir_return *);
|
||||
virtual ir_visitor_status visit_leave(ir_swizzle *);
|
||||
virtual ir_visitor_status visit_leave(ir_texture *);
|
||||
virtual ir_visitor_status visit_leave(ir_emit_vertex *);
|
||||
virtual ir_visitor_status visit_leave(ir_end_primitive *);
|
||||
};
|
||||
|
||||
class ir_rvalue_enter_visitor : public ir_rvalue_base_visitor {
|
||||
@@ -71,4 +75,6 @@ public:
|
||||
virtual ir_visitor_status visit_enter(ir_return *);
|
||||
virtual ir_visitor_status visit_enter(ir_swizzle *);
|
||||
virtual ir_visitor_status visit_enter(ir_texture *);
|
||||
virtual ir_visitor_status visit_enter(ir_emit_vertex *);
|
||||
virtual ir_visitor_status visit_enter(ir_end_primitive *);
|
||||
};
|
||||
|
||||
18
3rdparty/glsl-optimizer/src/glsl/ir_uniform.h
vendored
18
3rdparty/glsl-optimizer/src/glsl/ir_uniform.h
vendored
@@ -32,12 +32,17 @@
|
||||
|
||||
#include "program/prog_parameter.h" /* For union gl_constant_value. */
|
||||
|
||||
/**
|
||||
* Used by GL_ARB_explicit_uniform_location extension code in the linker
|
||||
* and glUniform* functions to identify inactive explicit uniform locations.
|
||||
*/
|
||||
#define INACTIVE_UNIFORM_EXPLICIT_LOCATION ((gl_uniform_storage *) -1)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
enum gl_uniform_driver_format {
|
||||
enum PACKED gl_uniform_driver_format {
|
||||
uniform_native = 0, /**< Store data in the native format. */
|
||||
uniform_int_float, /**< Store integer data as floats. */
|
||||
uniform_bool_float, /**< Store boolean data as floats. */
|
||||
@@ -66,11 +71,8 @@ struct gl_uniform_driver_storage {
|
||||
|
||||
/**
|
||||
* Base format of the stored data.
|
||||
*
|
||||
* This field must have a value from \c GLSL_TYPE_UINT through \c
|
||||
* GLSL_TYPE_SAMPLER.
|
||||
*/
|
||||
uint8_t format;
|
||||
enum gl_uniform_driver_format format;
|
||||
|
||||
/**
|
||||
* Pointer to the base of the data.
|
||||
@@ -178,6 +180,12 @@ struct gl_uniform_storage {
|
||||
* an atomic counter.
|
||||
*/
|
||||
int atomic_buffer_index;
|
||||
|
||||
/**
|
||||
* The 'base location' for this uniform in the uniform remap table. For
|
||||
* arrays this is the first element in the array.
|
||||
*/
|
||||
unsigned remap_location;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -71,8 +71,7 @@ bool
|
||||
ir_struct_usage_visitor::has_struct_entry(const glsl_type *t) const
|
||||
{
|
||||
assert(t);
|
||||
foreach_list(node, &this->struct_list) {
|
||||
struct_entry *entry = (struct_entry *)node;
|
||||
foreach_in_list(struct_entry, entry, &this->struct_list) {
|
||||
if (entry->type == t)
|
||||
return true;
|
||||
}
|
||||
@@ -119,8 +118,8 @@ ir_struct_usage_visitor::ir_struct_usage_visitor()
|
||||
{
|
||||
this->mem_ctx = ralloc_context(NULL);
|
||||
this->struct_list.make_empty();
|
||||
this->callback = visit_variable;
|
||||
this->data = this;
|
||||
this->callback_enter = visit_variable;
|
||||
this->data_enter = this;
|
||||
}
|
||||
|
||||
ir_struct_usage_visitor::~ir_struct_usage_visitor(void)
|
||||
|
||||
68
3rdparty/glsl-optimizer/src/glsl/ir_validate.cpp
vendored
68
3rdparty/glsl-optimizer/src/glsl/ir_validate.cpp
vendored
@@ -49,8 +49,8 @@ public:
|
||||
|
||||
this->current_function = NULL;
|
||||
|
||||
this->callback = ir_validate::validate_ir;
|
||||
this->data = ht;
|
||||
this->callback_enter = ir_validate::validate_ir;
|
||||
this->data_enter = ht;
|
||||
}
|
||||
|
||||
~ir_validate()
|
||||
@@ -100,7 +100,7 @@ ir_validate::visit(ir_dereference_variable *ir)
|
||||
abort();
|
||||
}
|
||||
|
||||
this->validate_ir(ir, this->data);
|
||||
this->validate_ir(ir, this->data_enter);
|
||||
|
||||
return visit_continue;
|
||||
}
|
||||
@@ -167,14 +167,12 @@ ir_validate::visit_enter(ir_function *ir)
|
||||
*/
|
||||
this->current_function = ir;
|
||||
|
||||
this->validate_ir(ir, this->data);
|
||||
this->validate_ir(ir, this->data_enter);
|
||||
|
||||
/* Verify that all of the things stored in the list of signatures are,
|
||||
* in fact, function signatures.
|
||||
*/
|
||||
foreach_list(node, &ir->signatures) {
|
||||
ir_instruction *sig = (ir_instruction *) node;
|
||||
|
||||
foreach_in_list(ir_instruction, sig, &ir->signatures) {
|
||||
if (sig->ir_type != ir_type_function_signature) {
|
||||
printf("Non-signature in signature list of function `%s'\n",
|
||||
ir->name);
|
||||
@@ -213,7 +211,7 @@ ir_validate::visit_enter(ir_function_signature *ir)
|
||||
abort();
|
||||
}
|
||||
|
||||
this->validate_ir(ir, this->data);
|
||||
this->validate_ir(ir, this->data_enter);
|
||||
|
||||
return visit_continue;
|
||||
}
|
||||
@@ -246,6 +244,7 @@ ir_validate::visit_leave(ir_expression *ir)
|
||||
case ir_unop_log:
|
||||
case ir_unop_exp2:
|
||||
case ir_unop_log2:
|
||||
case ir_unop_saturate:
|
||||
assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT);
|
||||
assert(ir->type == ir->operands[0]->type);
|
||||
break;
|
||||
@@ -322,7 +321,11 @@ ir_validate::visit_leave(ir_expression *ir)
|
||||
case ir_unop_sin_reduced:
|
||||
case ir_unop_cos_reduced:
|
||||
case ir_unop_dFdx:
|
||||
case ir_unop_dFdx_coarse:
|
||||
case ir_unop_dFdx_fine:
|
||||
case ir_unop_dFdy:
|
||||
case ir_unop_dFdy_coarse:
|
||||
case ir_unop_dFdy_fine:
|
||||
assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT);
|
||||
assert(ir->operands[0]->type == ir->type);
|
||||
break;
|
||||
@@ -376,6 +379,11 @@ ir_validate::visit_leave(ir_expression *ir)
|
||||
/* XXX what can we assert here? */
|
||||
break;
|
||||
|
||||
case ir_unop_interpolate_at_centroid:
|
||||
assert(ir->operands[0]->type == ir->type);
|
||||
assert(ir->operands[0]->type->is_float());
|
||||
break;
|
||||
|
||||
case ir_binop_add:
|
||||
case ir_binop_sub:
|
||||
case ir_binop_mul:
|
||||
@@ -384,6 +392,9 @@ ir_validate::visit_leave(ir_expression *ir)
|
||||
case ir_binop_min:
|
||||
case ir_binop_max:
|
||||
case ir_binop_pow:
|
||||
assert(ir->operands[0]->type->base_type ==
|
||||
ir->operands[1]->type->base_type);
|
||||
|
||||
if (ir->operands[0]->type->is_scalar())
|
||||
assert(ir->operands[1]->type == ir->type);
|
||||
else if (ir->operands[1]->type->is_scalar())
|
||||
@@ -492,7 +503,6 @@ ir_validate::visit_leave(ir_expression *ir)
|
||||
break;
|
||||
|
||||
case ir_binop_ubo_load:
|
||||
assert(ir->operands[0]->as_constant());
|
||||
assert(ir->operands[0]->type == glsl_type::uint_type);
|
||||
|
||||
assert(ir->operands[1]->type == glsl_type::uint_type);
|
||||
@@ -512,6 +522,19 @@ ir_validate::visit_leave(ir_expression *ir)
|
||||
&& ir->operands[1]->type->is_integer());
|
||||
break;
|
||||
|
||||
case ir_binop_interpolate_at_offset:
|
||||
assert(ir->operands[0]->type == ir->type);
|
||||
assert(ir->operands[0]->type->is_float());
|
||||
assert(ir->operands[1]->type->components() == 2);
|
||||
assert(ir->operands[1]->type->is_float());
|
||||
break;
|
||||
|
||||
case ir_binop_interpolate_at_sample:
|
||||
assert(ir->operands[0]->type == ir->type);
|
||||
assert(ir->operands[0]->type->is_float());
|
||||
assert(ir->operands[1]->type == glsl_type::int_type);
|
||||
break;
|
||||
|
||||
case ir_triop_fma:
|
||||
assert(ir->type->base_type == GLSL_TYPE_FLOAT);
|
||||
assert(ir->type == ir->operands[0]->type);
|
||||
@@ -634,7 +657,7 @@ ir_validate::visit(ir_variable *ir)
|
||||
* in the ir_dereference_variable handler to ensure that a variable is
|
||||
* declared before it is dereferenced.
|
||||
*/
|
||||
if (ir->name)
|
||||
if (ir->name && ir->is_name_ralloced())
|
||||
assert(ralloc_parent(ir->name) == ir);
|
||||
|
||||
hash_table_insert(ht, ir, ir);
|
||||
@@ -662,10 +685,15 @@ ir_validate::visit(ir_variable *ir)
|
||||
ir->get_interface_type()->fields.structure;
|
||||
for (unsigned i = 0; i < ir->get_interface_type()->length; i++) {
|
||||
if (fields[i].type->array_size() > 0) {
|
||||
if (ir->max_ifc_array_access[i] >= fields[i].type->length) {
|
||||
const unsigned *const max_ifc_array_access =
|
||||
ir->get_max_ifc_array_access();
|
||||
|
||||
assert(max_ifc_array_access != NULL);
|
||||
|
||||
if (max_ifc_array_access[i] >= fields[i].type->length) {
|
||||
printf("ir_variable has maximum access out of bounds for "
|
||||
"field %s (%d vs %d)\n", fields[i].name,
|
||||
ir->max_ifc_array_access[i], fields[i].type->length);
|
||||
max_ifc_array_access[i], fields[i].type->length);
|
||||
ir->print();
|
||||
abort();
|
||||
}
|
||||
@@ -680,6 +708,14 @@ ir_validate::visit(ir_variable *ir)
|
||||
abort();
|
||||
}
|
||||
|
||||
if (ir->data.mode == ir_var_uniform
|
||||
&& strncmp(ir->name, "gl_", 3) == 0
|
||||
&& ir->get_state_slots() == NULL) {
|
||||
printf("built-in uniform has no state\n");
|
||||
ir->print();
|
||||
abort();
|
||||
}
|
||||
|
||||
return visit_continue;
|
||||
}
|
||||
|
||||
@@ -710,7 +746,7 @@ ir_validate::visit_enter(ir_assignment *ir)
|
||||
}
|
||||
}
|
||||
|
||||
this->validate_ir(ir, this->data);
|
||||
this->validate_ir(ir, this->data_enter);
|
||||
|
||||
return visit_continue;
|
||||
}
|
||||
@@ -795,7 +831,7 @@ check_node_type(ir_instruction *ir, void *data)
|
||||
{
|
||||
(void) data;
|
||||
|
||||
if (ir->ir_type <= ir_type_unset || ir->ir_type >= ir_type_max) {
|
||||
if (ir->ir_type >= ir_type_max) {
|
||||
printf("Instruction node with unset type\n");
|
||||
ir->print(); printf("\n");
|
||||
}
|
||||
@@ -816,9 +852,7 @@ validate_ir_tree(exec_list *instructions)
|
||||
|
||||
v.run(instructions);
|
||||
|
||||
foreach_list(n, instructions) {
|
||||
ir_instruction *ir = (ir_instruction *) n;
|
||||
|
||||
foreach_in_list(ir_instruction, ir, instructions) {
|
||||
visit_tree(ir, check_node_type, NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -33,12 +33,13 @@
|
||||
#include "ir_visitor.h"
|
||||
#include "ir_variable_refcount.h"
|
||||
#include "glsl_types.h"
|
||||
#include "main/hash_table.h"
|
||||
#include "util/hash_table.h"
|
||||
|
||||
ir_variable_refcount_visitor::ir_variable_refcount_visitor()
|
||||
{
|
||||
this->mem_ctx = ralloc_context(NULL);
|
||||
this->ht = _mesa_hash_table_create(NULL, _mesa_key_pointer_equal);
|
||||
this->current_lhs = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -62,6 +63,7 @@ ir_variable_refcount_entry::ir_variable_refcount_entry(ir_variable *var)
|
||||
assigned_count = 0;
|
||||
declaration = false;
|
||||
referenced_count = 0;
|
||||
referenced_count_noself = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -114,10 +116,11 @@ ir_variable_refcount_visitor::visit(ir_dereference_variable *ir)
|
||||
{
|
||||
ir_variable *const var = ir->variable_referenced();
|
||||
ir_variable_refcount_entry *entry = this->get_variable_entry(var);
|
||||
|
||||
if (entry)
|
||||
if (entry) {
|
||||
entry->referenced_count++;
|
||||
|
||||
if (this->in_assignee || var != this->current_lhs)
|
||||
entry->referenced_count_noself++;
|
||||
}
|
||||
return visit_continue;
|
||||
}
|
||||
|
||||
@@ -132,10 +135,19 @@ ir_variable_refcount_visitor::visit_enter(ir_function_signature *ir)
|
||||
return visit_continue_with_parent;
|
||||
}
|
||||
|
||||
ir_visitor_status
|
||||
ir_variable_refcount_visitor::visit_enter(ir_assignment *ir)
|
||||
{
|
||||
assert(this->current_lhs == NULL);
|
||||
this->current_lhs = ir->lhs->variable_referenced();
|
||||
return visit_continue;
|
||||
}
|
||||
|
||||
|
||||
ir_visitor_status
|
||||
ir_variable_refcount_visitor::visit_leave(ir_assignment *ir)
|
||||
{
|
||||
this->current_lhs = NULL;
|
||||
ir_variable_refcount_entry *entry;
|
||||
entry = this->get_variable_entry(ir->lhs->variable_referenced());
|
||||
if (entry) {
|
||||
|
||||
@@ -44,6 +44,10 @@ public:
|
||||
/** Number of times the variable is referenced, including assignments. */
|
||||
unsigned referenced_count;
|
||||
|
||||
/** Number of times the variable was referenced, excluding cases when it was on RHS
|
||||
* of assignment of the same variable. */
|
||||
unsigned referenced_count_noself;
|
||||
|
||||
/** Number of times the variable is assigned. */
|
||||
unsigned assigned_count;
|
||||
|
||||
@@ -59,12 +63,14 @@ public:
|
||||
virtual ir_visitor_status visit(ir_dereference_variable *);
|
||||
|
||||
virtual ir_visitor_status visit_enter(ir_function_signature *);
|
||||
virtual ir_visitor_status visit_enter(ir_assignment *);
|
||||
virtual ir_visitor_status visit_leave(ir_assignment *);
|
||||
|
||||
ir_variable_refcount_entry *get_variable_entry(ir_variable *var);
|
||||
ir_variable_refcount_entry *find_variable_entry(ir_variable *var);
|
||||
|
||||
struct hash_table *ht;
|
||||
ir_variable* current_lhs;
|
||||
|
||||
void *mem_ctx;
|
||||
};
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "ir_uniform.h"
|
||||
#include "linker.h"
|
||||
#include "program/hash_table.h"
|
||||
#include "main/errors.h"
|
||||
#include "main/macros.h"
|
||||
|
||||
namespace {
|
||||
@@ -54,9 +55,18 @@ namespace {
|
||||
|
||||
void push_back(unsigned id, ir_variable *var)
|
||||
{
|
||||
counters = (active_atomic_counter *)
|
||||
realloc(counters, sizeof(active_atomic_counter) * (num_counters + 1));
|
||||
active_atomic_counter *new_counters;
|
||||
|
||||
new_counters = (active_atomic_counter *)
|
||||
realloc(counters, sizeof(active_atomic_counter) *
|
||||
(num_counters + 1));
|
||||
|
||||
if (new_counters == NULL) {
|
||||
_mesa_error_no_memory(__func__);
|
||||
return;
|
||||
}
|
||||
|
||||
counters = new_counters;
|
||||
counters[num_counters].id = id;
|
||||
counters[num_counters].var = var;
|
||||
num_counters++;
|
||||
@@ -101,8 +111,8 @@ namespace {
|
||||
if (sh == NULL)
|
||||
continue;
|
||||
|
||||
foreach_list(node, sh->ir) {
|
||||
ir_variable *var = ((ir_instruction *)node)->as_variable();
|
||||
foreach_in_list(ir_instruction, node, sh->ir) {
|
||||
ir_variable *var = node->as_variable();
|
||||
|
||||
if (var && var->type->contains_atomic()) {
|
||||
unsigned id = 0;
|
||||
@@ -192,7 +202,9 @@ link_assign_atomic_counter_resources(struct gl_context *ctx,
|
||||
gl_uniform_storage *const storage = &prog->UniformStorage[id];
|
||||
|
||||
mab.Uniforms[j] = id;
|
||||
var->data.atomic.buffer_index = i;
|
||||
if (!var->data.explicit_binding)
|
||||
var->data.binding = i;
|
||||
|
||||
storage->atomic_buffer_index = i;
|
||||
storage->offset = var->data.atomic.offset;
|
||||
storage->array_stride = (var->type->is_array() ?
|
||||
|
||||
@@ -145,8 +145,7 @@ public:
|
||||
struct hash_table *ht = hash_table_ctor(0, hash_table_pointer_hash,
|
||||
hash_table_pointer_compare);
|
||||
exec_list formal_parameters;
|
||||
foreach_list_const(node, &sig->parameters) {
|
||||
const ir_instruction *const original = (ir_instruction *) node;
|
||||
foreach_in_list(const ir_instruction, original, &sig->parameters) {
|
||||
assert(const_cast<ir_instruction *>(original)->as_variable());
|
||||
|
||||
ir_instruction *copy = original->clone(linked, ht);
|
||||
@@ -155,10 +154,10 @@ public:
|
||||
|
||||
linked_sig->replace_parameters(&formal_parameters);
|
||||
|
||||
if (sig->is_defined) {
|
||||
foreach_list_const(node, &sig->body) {
|
||||
const ir_instruction *const original = (ir_instruction *) node;
|
||||
linked_sig->is_intrinsic = sig->is_intrinsic;
|
||||
|
||||
if (sig->is_defined) {
|
||||
foreach_in_list(const ir_instruction, original, &sig->body) {
|
||||
ir_instruction *copy = original->clone(linked, ht);
|
||||
linked_sig->body.push_tail(copy);
|
||||
}
|
||||
@@ -246,11 +245,19 @@ public:
|
||||
/* Similarly, we need implicit sizes of arrays within interface
|
||||
* blocks to be sized by the maximal access in *any* shader.
|
||||
*/
|
||||
unsigned *const linked_max_ifc_array_access =
|
||||
var->get_max_ifc_array_access();
|
||||
unsigned *const ir_max_ifc_array_access =
|
||||
ir->var->get_max_ifc_array_access();
|
||||
|
||||
assert(linked_max_ifc_array_access != NULL);
|
||||
assert(ir_max_ifc_array_access != NULL);
|
||||
|
||||
for (unsigned i = 0; i < var->get_interface_type()->length;
|
||||
i++) {
|
||||
var->max_ifc_array_access[i] =
|
||||
MAX2(var->max_ifc_array_access[i],
|
||||
ir->var->max_ifc_array_access[i]);
|
||||
linked_max_ifc_array_access[i] =
|
||||
MAX2(linked_max_ifc_array_access[i],
|
||||
ir_max_ifc_array_access[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -310,7 +317,7 @@ find_matching_signature(const char *name, const exec_list *actual_parameters,
|
||||
continue;
|
||||
|
||||
ir_function_signature *sig =
|
||||
f->matching_signature(NULL, actual_parameters);
|
||||
f->matching_signature(NULL, actual_parameters, use_builtin);
|
||||
|
||||
if ((sig == NULL) ||
|
||||
(!sig->is_defined && !sig->is_intrinsic))
|
||||
|
||||
@@ -259,8 +259,8 @@ validate_intrastage_interface_blocks(struct gl_shader_program *prog,
|
||||
if (shader_list[i] == NULL)
|
||||
continue;
|
||||
|
||||
foreach_list(node, shader_list[i]->ir) {
|
||||
ir_variable *var = ((ir_instruction *) node)->as_variable();
|
||||
foreach_in_list(ir_instruction, node, shader_list[i]->ir) {
|
||||
ir_variable *var = node->as_variable();
|
||||
if (!var)
|
||||
continue;
|
||||
|
||||
@@ -316,8 +316,8 @@ validate_interstage_inout_blocks(struct gl_shader_program *prog,
|
||||
const bool extra_array_level = consumer->Stage == MESA_SHADER_GEOMETRY;
|
||||
|
||||
/* Add input interfaces from the consumer to the symbol table. */
|
||||
foreach_list(node, consumer->ir) {
|
||||
ir_variable *var = ((ir_instruction *) node)->as_variable();
|
||||
foreach_in_list(ir_instruction, node, consumer->ir) {
|
||||
ir_variable *var = node->as_variable();
|
||||
if (!var || !var->get_interface_type() || var->data.mode != ir_var_shader_in)
|
||||
continue;
|
||||
|
||||
@@ -325,8 +325,8 @@ validate_interstage_inout_blocks(struct gl_shader_program *prog,
|
||||
}
|
||||
|
||||
/* Verify that the producer's output interfaces match. */
|
||||
foreach_list(node, producer->ir) {
|
||||
ir_variable *var = ((ir_instruction *) node)->as_variable();
|
||||
foreach_in_list(ir_instruction, node, producer->ir) {
|
||||
ir_variable *var = node->as_variable();
|
||||
if (!var || !var->get_interface_type() || var->data.mode != ir_var_shader_out)
|
||||
continue;
|
||||
|
||||
@@ -359,8 +359,8 @@ validate_interstage_uniform_blocks(struct gl_shader_program *prog,
|
||||
continue;
|
||||
|
||||
const gl_shader *stage = stages[i];
|
||||
foreach_list(node, stage->ir) {
|
||||
ir_variable *var = ((ir_instruction *) node)->as_variable();
|
||||
foreach_in_list(ir_instruction, node, stage->ir) {
|
||||
ir_variable *var = node->as_variable();
|
||||
if (!var || !var->get_interface_type() || var->data.mode != ir_var_uniform)
|
||||
continue;
|
||||
|
||||
|
||||
@@ -46,6 +46,14 @@ process_block(void *mem_ctx, struct hash_table *ht, ir_variable *var)
|
||||
b->type = block_type;
|
||||
b->has_instance_name = var->is_interface_instance();
|
||||
|
||||
if (var->data.explicit_binding) {
|
||||
b->has_binding = true;
|
||||
b->binding = var->data.binding;
|
||||
} else {
|
||||
b->has_binding = false;
|
||||
b->binding = 0;
|
||||
}
|
||||
|
||||
_mesa_hash_table_insert(ht, h, var->get_interface_type()->name,
|
||||
(void *) b);
|
||||
return b;
|
||||
@@ -64,6 +72,45 @@ process_block(void *mem_ctx, struct hash_table *ht, ir_variable *var)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ir_visitor_status
|
||||
link_uniform_block_active_visitor::visit(ir_variable *var)
|
||||
{
|
||||
if (!var->is_in_uniform_block())
|
||||
return visit_continue;
|
||||
|
||||
const glsl_type *const block_type = var->is_interface_instance()
|
||||
? var->type : var->get_interface_type();
|
||||
|
||||
/* Section 2.11.6 (Uniform Variables) of the OpenGL ES 3.0.3 spec says:
|
||||
*
|
||||
* "All members of a named uniform block declared with a shared or
|
||||
* std140 layout qualifier are considered active, even if they are not
|
||||
* referenced in any shader in the program. The uniform block itself is
|
||||
* also considered active, even if no member of the block is
|
||||
* referenced."
|
||||
*/
|
||||
if (block_type->interface_packing == GLSL_INTERFACE_PACKING_PACKED)
|
||||
return visit_continue;
|
||||
|
||||
/* Process the block. Bail if there was an error.
|
||||
*/
|
||||
link_uniform_block_active *const b =
|
||||
process_block(this->mem_ctx, this->ht, var);
|
||||
if (b == NULL) {
|
||||
linker_error(this->prog,
|
||||
"uniform block `%s' has mismatching definitions",
|
||||
var->get_interface_type()->name);
|
||||
this->success = false;
|
||||
return visit_stop;
|
||||
}
|
||||
|
||||
assert(b->num_array_elements == 0);
|
||||
assert(b->array_elements == NULL);
|
||||
assert(b->type != NULL);
|
||||
|
||||
return visit_continue;
|
||||
}
|
||||
|
||||
ir_visitor_status
|
||||
link_uniform_block_active_visitor::visit_enter(ir_dereference_array *ir)
|
||||
{
|
||||
@@ -101,32 +148,44 @@ link_uniform_block_active_visitor::visit_enter(ir_dereference_array *ir)
|
||||
assert((b->num_array_elements == 0) == (b->array_elements == NULL));
|
||||
assert(b->type != NULL);
|
||||
|
||||
/* Determine whether or not this array index has already been added to the
|
||||
* list of active array indices. At this point all constant folding must
|
||||
* have occured, and the array index must be a constant.
|
||||
*/
|
||||
ir_constant *c = ir->array_index->as_constant();
|
||||
assert(c != NULL);
|
||||
|
||||
const unsigned idx = c->get_uint_component(0);
|
||||
if (c) {
|
||||
/* Index is a constant, so mark just that element used, if not already */
|
||||
const unsigned idx = c->get_uint_component(0);
|
||||
|
||||
unsigned i;
|
||||
for (i = 0; i < b->num_array_elements; i++) {
|
||||
if (b->array_elements[i] == idx)
|
||||
break;
|
||||
}
|
||||
unsigned i;
|
||||
for (i = 0; i < b->num_array_elements; i++) {
|
||||
if (b->array_elements[i] == idx)
|
||||
break;
|
||||
}
|
||||
|
||||
assert(i <= b->num_array_elements);
|
||||
assert(i <= b->num_array_elements);
|
||||
|
||||
if (i == b->num_array_elements) {
|
||||
b->array_elements = reralloc(this->mem_ctx,
|
||||
b->array_elements,
|
||||
unsigned,
|
||||
b->num_array_elements + 1);
|
||||
if (i == b->num_array_elements) {
|
||||
b->array_elements = reralloc(this->mem_ctx,
|
||||
b->array_elements,
|
||||
unsigned,
|
||||
b->num_array_elements + 1);
|
||||
|
||||
b->array_elements[b->num_array_elements] = idx;
|
||||
b->array_elements[b->num_array_elements] = idx;
|
||||
|
||||
b->num_array_elements++;
|
||||
b->num_array_elements++;
|
||||
}
|
||||
} else {
|
||||
/* The array index is not a constant, so mark the entire array used. */
|
||||
assert(b->type->is_array());
|
||||
if (b->num_array_elements < b->type->length) {
|
||||
b->num_array_elements = b->type->length;
|
||||
b->array_elements = reralloc(this->mem_ctx,
|
||||
b->array_elements,
|
||||
unsigned,
|
||||
b->num_array_elements);
|
||||
|
||||
for (unsigned i = 0; i < b->num_array_elements; i++) {
|
||||
b->array_elements[i] = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return visit_continue_with_parent;
|
||||
|
||||
@@ -26,9 +26,7 @@
|
||||
#define LINK_UNIFORM_BLOCK_ACTIVE_VISITOR_H
|
||||
|
||||
#include "ir.h"
|
||||
#include "ir_visitor.h"
|
||||
#include "glsl_types.h"
|
||||
#include "main/hash_table.h"
|
||||
#include "util/hash_table.h"
|
||||
|
||||
struct link_uniform_block_active {
|
||||
const glsl_type *type;
|
||||
@@ -36,7 +34,10 @@ struct link_uniform_block_active {
|
||||
unsigned *array_elements;
|
||||
unsigned num_array_elements;
|
||||
|
||||
unsigned binding;
|
||||
|
||||
bool has_instance_name;
|
||||
bool has_binding;
|
||||
};
|
||||
|
||||
class link_uniform_block_active_visitor : public ir_hierarchical_visitor {
|
||||
@@ -50,6 +51,7 @@ public:
|
||||
|
||||
virtual ir_visitor_status visit_enter(ir_dereference_array *);
|
||||
virtual ir_visitor_status visit(ir_dereference_variable *);
|
||||
virtual ir_visitor_status visit(ir_variable *);
|
||||
|
||||
bool success;
|
||||
|
||||
|
||||
@@ -22,11 +22,12 @@
|
||||
*/
|
||||
|
||||
#include "main/core.h"
|
||||
#include "main/errors.h"
|
||||
#include "ir.h"
|
||||
#include "linker.h"
|
||||
#include "ir_uniform.h"
|
||||
#include "link_uniform_block_active_visitor.h"
|
||||
#include "main/hash_table.h"
|
||||
#include "util/hash_table.h"
|
||||
#include "program.h"
|
||||
|
||||
namespace {
|
||||
@@ -68,7 +69,8 @@ private:
|
||||
}
|
||||
|
||||
virtual void visit_field(const glsl_type *type, const char *name,
|
||||
bool row_major, const glsl_type *record_type)
|
||||
bool row_major, const glsl_type *record_type,
|
||||
bool last_field)
|
||||
{
|
||||
assert(this->index < this->num_variables);
|
||||
|
||||
@@ -76,7 +78,7 @@ private:
|
||||
|
||||
v->Name = ralloc_strdup(mem_ctx, name);
|
||||
v->Type = type;
|
||||
v->RowMajor = row_major;
|
||||
v->RowMajor = type->without_array()->is_matrix() && row_major;
|
||||
|
||||
if (this->is_array_instance) {
|
||||
v->IndexName = ralloc_strdup(mem_ctx, name);
|
||||
@@ -92,18 +94,31 @@ private:
|
||||
unsigned len = strlen(close_bracket + 1) + 1;
|
||||
|
||||
memmove(open_bracket, close_bracket + 1, len);
|
||||
} else {
|
||||
} else {
|
||||
v->IndexName = v->Name;
|
||||
}
|
||||
|
||||
const unsigned alignment = record_type
|
||||
? record_type->std140_base_alignment(!!v->RowMajor)
|
||||
: type->std140_base_alignment(!!v->RowMajor);
|
||||
? record_type->std140_base_alignment(!!v->RowMajor)
|
||||
: type->std140_base_alignment(!!v->RowMajor);
|
||||
unsigned size = type->std140_size(!!v->RowMajor);
|
||||
|
||||
this->offset = glsl_align(this->offset, alignment);
|
||||
v->Offset = this->offset;
|
||||
|
||||
/* If this is the last field of a structure, apply rule #9. The
|
||||
* GL_ARB_uniform_buffer_object spec says:
|
||||
*
|
||||
* "The structure may have padding at the end; the base offset of
|
||||
* the member following the sub-structure is rounded up to the next
|
||||
* multiple of the base alignment of the structure."
|
||||
*
|
||||
* last_field won't be set if this is the last field of a UBO that is
|
||||
* not a named instance.
|
||||
*/
|
||||
this->offset += size;
|
||||
if (last_field)
|
||||
this->offset = glsl_align(this->offset, 16);
|
||||
|
||||
/* From the GL_ARB_uniform_buffer_object spec:
|
||||
*
|
||||
@@ -170,6 +185,12 @@ link_uniform_blocks(void *mem_ctx,
|
||||
struct hash_table *block_hash =
|
||||
_mesa_hash_table_create(mem_ctx, _mesa_key_string_equal);
|
||||
|
||||
if (block_hash == NULL) {
|
||||
_mesa_error_no_memory(__func__);
|
||||
linker_error(prog, "out of memory\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Determine which uniform blocks are active.
|
||||
*/
|
||||
link_uniform_block_active_visitor v(mem_ctx, block_hash, prog);
|
||||
@@ -251,7 +272,17 @@ link_uniform_blocks(void *mem_ctx,
|
||||
blocks[i].Name = ralloc_asprintf(blocks, "%s[%u]", name,
|
||||
b->array_elements[j]);
|
||||
blocks[i].Uniforms = &variables[parcel.index];
|
||||
blocks[i].Binding = 0;
|
||||
|
||||
/* The GL_ARB_shading_language_420pack spec says:
|
||||
*
|
||||
* "If the binding identifier is used with a uniform block
|
||||
* instanced as an array then the first element of the array
|
||||
* takes the specified block binding and each subsequent
|
||||
* element takes the next consecutive uniform block binding
|
||||
* point."
|
||||
*/
|
||||
blocks[i].Binding = (b->has_binding) ? b->binding + j : 0;
|
||||
|
||||
blocks[i].UniformBufferSize = 0;
|
||||
blocks[i]._Packing =
|
||||
gl_uniform_block_packing(block_type->interface_packing);
|
||||
@@ -269,7 +300,7 @@ link_uniform_blocks(void *mem_ctx,
|
||||
} else {
|
||||
blocks[i].Name = ralloc_strdup(blocks, block_type->name);
|
||||
blocks[i].Uniforms = &variables[parcel.index];
|
||||
blocks[i].Binding = 0;
|
||||
blocks[i].Binding = (b->has_binding) ? b->binding : 0;
|
||||
blocks[i].UniformBufferSize = 0;
|
||||
blocks[i]._Packing =
|
||||
gl_uniform_block_packing(block_type->interface_packing);
|
||||
|
||||
@@ -25,8 +25,6 @@
|
||||
#include "ir.h"
|
||||
#include "linker.h"
|
||||
#include "ir_uniform.h"
|
||||
#include "glsl_symbol_table.h"
|
||||
#include "program/hash_table.h"
|
||||
|
||||
/* These functions are put in a "private" namespace instead of being marked
|
||||
* static so that the unit tests can access them. See
|
||||
@@ -46,11 +44,24 @@ get_storage(gl_uniform_storage *storage, unsigned num_storage,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static unsigned
|
||||
get_uniform_block_index(const gl_shader_program *shProg,
|
||||
const char *uniformBlockName)
|
||||
{
|
||||
for (unsigned i = 0; i < shProg->NumUniformBlocks; i++) {
|
||||
if (!strcmp(shProg->UniformBlocks[i].Name, uniformBlockName))
|
||||
return i;
|
||||
}
|
||||
|
||||
return GL_INVALID_INDEX;
|
||||
}
|
||||
|
||||
void
|
||||
copy_constant_to_storage(union gl_constant_value *storage,
|
||||
const ir_constant *val,
|
||||
const enum glsl_base_type base_type,
|
||||
const unsigned int elements)
|
||||
const unsigned int elements,
|
||||
unsigned int boolean_true)
|
||||
{
|
||||
for (unsigned int i = 0; i < elements; i++) {
|
||||
switch (base_type) {
|
||||
@@ -65,7 +76,7 @@ copy_constant_to_storage(union gl_constant_value *storage,
|
||||
storage[i].f = val->value.f[i];
|
||||
break;
|
||||
case GLSL_TYPE_BOOL:
|
||||
storage[i].b = int(val->value.b[i]);
|
||||
storage[i].b = val->value.b[i] ? boolean_true : 0;
|
||||
break;
|
||||
case GLSL_TYPE_ARRAY:
|
||||
case GLSL_TYPE_STRUCT:
|
||||
@@ -84,8 +95,7 @@ copy_constant_to_storage(union gl_constant_value *storage,
|
||||
}
|
||||
|
||||
void
|
||||
set_uniform_binding(void *mem_ctx, gl_shader_program *prog,
|
||||
const char *name, const glsl_type *type, int binding)
|
||||
set_sampler_binding(gl_shader_program *prog, const char *name, int binding)
|
||||
{
|
||||
struct gl_uniform_storage *const storage =
|
||||
get_storage(prog->UniformStorage, prog->NumUserUniformStorage, name);
|
||||
@@ -95,37 +105,27 @@ set_uniform_binding(void *mem_ctx, gl_shader_program *prog,
|
||||
return;
|
||||
}
|
||||
|
||||
if (storage->type->is_sampler()) {
|
||||
unsigned elements = MAX2(storage->array_elements, 1);
|
||||
const unsigned elements = MAX2(storage->array_elements, 1);
|
||||
|
||||
/* From section 4.4.4 of the GLSL 4.20 specification:
|
||||
* "If the binding identifier is used with an array, the first element
|
||||
* of the array takes the specified unit and each subsequent element
|
||||
* takes the next consecutive unit."
|
||||
*/
|
||||
for (unsigned int i = 0; i < elements; i++) {
|
||||
storage->storage[i].i = binding + i;
|
||||
}
|
||||
/* Section 4.4.4 (Opaque-Uniform Layout Qualifiers) of the GLSL 4.20 spec
|
||||
* says:
|
||||
*
|
||||
* "If the binding identifier is used with an array, the first element
|
||||
* of the array takes the specified unit and each subsequent element
|
||||
* takes the next consecutive unit."
|
||||
*/
|
||||
for (unsigned int i = 0; i < elements; i++) {
|
||||
storage->storage[i].i = binding + i;
|
||||
}
|
||||
|
||||
for (int sh = 0; sh < MESA_SHADER_STAGES; sh++) {
|
||||
gl_shader *shader = prog->_LinkedShaders[sh];
|
||||
for (int sh = 0; sh < MESA_SHADER_STAGES; sh++) {
|
||||
gl_shader *shader = prog->_LinkedShaders[sh];
|
||||
|
||||
if (shader && storage->sampler[sh].active) {
|
||||
for (unsigned i = 0; i < elements; i++) {
|
||||
unsigned index = storage->sampler[sh].index + i;
|
||||
if (shader && storage->sampler[sh].active) {
|
||||
for (unsigned i = 0; i < elements; i++) {
|
||||
unsigned index = storage->sampler[sh].index + i;
|
||||
|
||||
shader->SamplerUnits[index] = storage->storage[i].i;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (storage->block_index != -1) {
|
||||
/* This is a field of a UBO. val is the binding index. */
|
||||
for (int i = 0; i < MESA_SHADER_STAGES; i++) {
|
||||
int stage_index = prog->UniformBlockStageIndex[i][storage->block_index];
|
||||
|
||||
if (stage_index != -1) {
|
||||
struct gl_shader *sh = prog->_LinkedShaders[i];
|
||||
sh->UniformBlocks[stage_index].Binding = binding;
|
||||
shader->SamplerUnits[index] = storage->storage[i].i;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -133,10 +133,31 @@ set_uniform_binding(void *mem_ctx, gl_shader_program *prog,
|
||||
storage->initialized = true;
|
||||
}
|
||||
|
||||
void
|
||||
set_block_binding(gl_shader_program *prog, const char *block_name, int binding)
|
||||
{
|
||||
const unsigned block_index = get_uniform_block_index(prog, block_name);
|
||||
|
||||
if (block_index == GL_INVALID_INDEX) {
|
||||
assert(block_index != GL_INVALID_INDEX);
|
||||
return;
|
||||
}
|
||||
|
||||
/* This is a field of a UBO. val is the binding index. */
|
||||
for (int i = 0; i < MESA_SHADER_STAGES; i++) {
|
||||
int stage_index = prog->UniformBlockStageIndex[i][block_index];
|
||||
|
||||
if (stage_index != -1) {
|
||||
struct gl_shader *sh = prog->_LinkedShaders[i];
|
||||
sh->UniformBlocks[stage_index].Binding = binding;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
set_uniform_initializer(void *mem_ctx, gl_shader_program *prog,
|
||||
const char *name, const glsl_type *type,
|
||||
ir_constant *val)
|
||||
ir_constant *val, unsigned int boolean_true)
|
||||
{
|
||||
if (type->is_record()) {
|
||||
ir_constant *field_constant;
|
||||
@@ -148,7 +169,7 @@ set_uniform_initializer(void *mem_ctx, gl_shader_program *prog,
|
||||
const char *field_name = ralloc_asprintf(mem_ctx, "%s.%s", name,
|
||||
type->fields.structure[i].name);
|
||||
set_uniform_initializer(mem_ctx, prog, field_name,
|
||||
field_type, field_constant);
|
||||
field_type, field_constant, boolean_true);
|
||||
field_constant = (ir_constant *)field_constant->next;
|
||||
}
|
||||
return;
|
||||
@@ -159,7 +180,8 @@ set_uniform_initializer(void *mem_ctx, gl_shader_program *prog,
|
||||
const char *element_name = ralloc_asprintf(mem_ctx, "%s[%d]", name, i);
|
||||
|
||||
set_uniform_initializer(mem_ctx, prog, element_name,
|
||||
element_type, val->array_elements[i]);
|
||||
element_type, val->array_elements[i],
|
||||
boolean_true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -184,7 +206,8 @@ set_uniform_initializer(void *mem_ctx, gl_shader_program *prog,
|
||||
copy_constant_to_storage(& storage->storage[idx],
|
||||
val->array_elements[i],
|
||||
base_type,
|
||||
elements);
|
||||
elements,
|
||||
boolean_true);
|
||||
|
||||
idx += elements;
|
||||
}
|
||||
@@ -192,7 +215,8 @@ set_uniform_initializer(void *mem_ctx, gl_shader_program *prog,
|
||||
copy_constant_to_storage(storage->storage,
|
||||
val,
|
||||
val->type->base_type,
|
||||
val->type->components());
|
||||
val->type->components(),
|
||||
boolean_true);
|
||||
|
||||
if (storage->type->is_sampler()) {
|
||||
for (int sh = 0; sh < MESA_SHADER_STAGES; sh++) {
|
||||
@@ -212,7 +236,8 @@ set_uniform_initializer(void *mem_ctx, gl_shader_program *prog,
|
||||
}
|
||||
|
||||
void
|
||||
link_set_uniform_initializers(struct gl_shader_program *prog)
|
||||
link_set_uniform_initializers(struct gl_shader_program *prog,
|
||||
unsigned int boolean_true)
|
||||
{
|
||||
void *mem_ctx = NULL;
|
||||
|
||||
@@ -222,8 +247,8 @@ link_set_uniform_initializers(struct gl_shader_program *prog)
|
||||
if (shader == NULL)
|
||||
continue;
|
||||
|
||||
foreach_list(node, shader->ir) {
|
||||
ir_variable *const var = ((ir_instruction *) node)->as_variable();
|
||||
foreach_in_list(ir_instruction, node, shader->ir) {
|
||||
ir_variable *const var = node->as_variable();
|
||||
|
||||
if (!var || var->data.mode != ir_var_uniform)
|
||||
continue;
|
||||
@@ -232,11 +257,56 @@ link_set_uniform_initializers(struct gl_shader_program *prog)
|
||||
mem_ctx = ralloc_context(NULL);
|
||||
|
||||
if (var->data.explicit_binding) {
|
||||
linker::set_uniform_binding(mem_ctx, prog, var->name,
|
||||
var->type, var->data.binding);
|
||||
const glsl_type *const type = var->type;
|
||||
|
||||
if (type->without_array()->is_sampler()) {
|
||||
linker::set_sampler_binding(prog, var->name, var->data.binding);
|
||||
} else if (var->is_in_uniform_block()) {
|
||||
const glsl_type *const iface_type = var->get_interface_type();
|
||||
|
||||
/* If the variable is an array and it is an interface instance,
|
||||
* we need to set the binding for each array element. Just
|
||||
* checking that the variable is an array is not sufficient.
|
||||
* The variable could be an array element of a uniform block
|
||||
* that lacks an instance name. For example:
|
||||
*
|
||||
* uniform U {
|
||||
* float f[4];
|
||||
* };
|
||||
*
|
||||
* In this case "f" would pass is_in_uniform_block (above) and
|
||||
* type->is_array(), but it will fail is_interface_instance().
|
||||
*/
|
||||
if (var->is_interface_instance() && var->type->is_array()) {
|
||||
for (unsigned i = 0; i < var->type->length; i++) {
|
||||
const char *name =
|
||||
ralloc_asprintf(mem_ctx, "%s[%u]", iface_type->name, i);
|
||||
|
||||
/* Section 4.4.3 (Uniform Block Layout Qualifiers) of the
|
||||
* GLSL 4.20 spec says:
|
||||
*
|
||||
* "If the binding identifier is used with a uniform
|
||||
* block instanced as an array then the first element
|
||||
* of the array takes the specified block binding and
|
||||
* each subsequent element takes the next consecutive
|
||||
* uniform block binding point."
|
||||
*/
|
||||
linker::set_block_binding(prog, name,
|
||||
var->data.binding + i);
|
||||
}
|
||||
} else {
|
||||
linker::set_block_binding(prog, iface_type->name,
|
||||
var->data.binding);
|
||||
}
|
||||
} else if (type->contains_atomic()) {
|
||||
/* we don't actually need to do anything. */
|
||||
} else {
|
||||
assert(!"Explicit binding not on a sampler, UBO or atomic.");
|
||||
}
|
||||
} else if (var->constant_value) {
|
||||
linker::set_uniform_initializer(mem_ctx, prog, var->name,
|
||||
var->type, var->constant_value);
|
||||
var->type, var->constant_value,
|
||||
boolean_true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
244
3rdparty/glsl-optimizer/src/glsl/link_uniforms.cpp
vendored
244
3rdparty/glsl-optimizer/src/glsl/link_uniforms.cpp
vendored
@@ -36,6 +36,11 @@
|
||||
* \author Ian Romanick <ian.d.romanick@intel.com>
|
||||
*/
|
||||
|
||||
/**
|
||||
* Used by linker to indicate uniforms that have no location set.
|
||||
*/
|
||||
#define UNMAPPED_UNIFORM_LOC ~0u
|
||||
|
||||
/**
|
||||
* Count the backing storage requirements for a type
|
||||
*/
|
||||
@@ -54,13 +59,11 @@ values_for_type(const glsl_type *type)
|
||||
void
|
||||
program_resource_visitor::process(const glsl_type *type, const char *name)
|
||||
{
|
||||
assert(type->is_record()
|
||||
|| (type->is_array() && type->fields.array->is_record())
|
||||
|| type->is_interface()
|
||||
|| (type->is_array() && type->fields.array->is_interface()));
|
||||
assert(type->without_array()->is_record()
|
||||
|| type->without_array()->is_interface());
|
||||
|
||||
char *name_copy = ralloc_strdup(NULL, name);
|
||||
recursion(type, &name_copy, strlen(name), false, NULL);
|
||||
recursion(type, &name_copy, strlen(name), false, NULL, false);
|
||||
ralloc_free(name_copy);
|
||||
}
|
||||
|
||||
@@ -68,6 +71,8 @@ void
|
||||
program_resource_visitor::process(ir_variable *var)
|
||||
{
|
||||
const glsl_type *t = var->type;
|
||||
const bool row_major =
|
||||
var->data.matrix_layout == GLSL_MATRIX_LAYOUT_ROW_MAJOR;
|
||||
|
||||
/* false is always passed for the row_major parameter to the other
|
||||
* processing functions because no information is available to do
|
||||
@@ -105,7 +110,7 @@ program_resource_visitor::process(ir_variable *var)
|
||||
* lowering is only applied to non-uniform interface blocks, so we
|
||||
* can safely pass false for row_major.
|
||||
*/
|
||||
recursion(var->type, &name, new_length, false, NULL);
|
||||
recursion(var->type, &name, new_length, row_major, NULL, false);
|
||||
}
|
||||
ralloc_free(name);
|
||||
} else if (var->data.from_named_ifc_block_nonarray) {
|
||||
@@ -129,29 +134,30 @@ program_resource_visitor::process(ir_variable *var)
|
||||
* is only applied to non-uniform interface blocks, so we can safely
|
||||
* pass false for row_major.
|
||||
*/
|
||||
recursion(var->type, &name, strlen(name), false, NULL);
|
||||
recursion(var->type, &name, strlen(name), row_major, NULL, false);
|
||||
ralloc_free(name);
|
||||
} else if (t->is_record() || (t->is_array() && t->fields.array->is_record())) {
|
||||
} else if (t->without_array()->is_record()) {
|
||||
char *name = ralloc_strdup(NULL, var->name);
|
||||
recursion(var->type, &name, strlen(name), false, NULL);
|
||||
recursion(var->type, &name, strlen(name), row_major, NULL, false);
|
||||
ralloc_free(name);
|
||||
} else if (t->is_interface()) {
|
||||
char *name = ralloc_strdup(NULL, var->type->name);
|
||||
recursion(var->type, &name, strlen(name), false, NULL);
|
||||
recursion(var->type, &name, strlen(name), row_major, NULL, false);
|
||||
ralloc_free(name);
|
||||
} else if (t->is_array() && t->fields.array->is_interface()) {
|
||||
char *name = ralloc_strdup(NULL, var->type->fields.array->name);
|
||||
recursion(var->type, &name, strlen(name), false, NULL);
|
||||
recursion(var->type, &name, strlen(name), row_major, NULL, false);
|
||||
ralloc_free(name);
|
||||
} else {
|
||||
this->visit_field(t, var->name, false, NULL);
|
||||
this->visit_field(t, var->name, row_major, NULL, false);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
program_resource_visitor::recursion(const glsl_type *t, char **name,
|
||||
size_t name_length, bool row_major,
|
||||
const glsl_type *record_type)
|
||||
const glsl_type *record_type,
|
||||
bool last_field)
|
||||
{
|
||||
/* Records need to have each field processed individually.
|
||||
*
|
||||
@@ -177,8 +183,25 @@ program_resource_visitor::recursion(const glsl_type *t, char **name,
|
||||
ralloc_asprintf_rewrite_tail(name, &new_length, ".%s", field);
|
||||
}
|
||||
|
||||
/* The layout of structures at the top level of the block is set
|
||||
* during parsing. For matrices contained in multiple levels of
|
||||
* structures in the block, the inner structures have no layout.
|
||||
* These cases must potentially inherit the layout from the outer
|
||||
* levels.
|
||||
*/
|
||||
bool field_row_major = row_major;
|
||||
const enum glsl_matrix_layout matrix_layout =
|
||||
glsl_matrix_layout(t->fields.structure[i].matrix_layout);
|
||||
if (matrix_layout == GLSL_MATRIX_LAYOUT_ROW_MAJOR) {
|
||||
field_row_major = true;
|
||||
} else if (matrix_layout == GLSL_MATRIX_LAYOUT_COLUMN_MAJOR) {
|
||||
field_row_major = false;
|
||||
}
|
||||
|
||||
recursion(t->fields.structure[i].type, name, new_length,
|
||||
t->fields.structure[i].row_major, record_type);
|
||||
field_row_major,
|
||||
record_type,
|
||||
(i + 1) == t->length);
|
||||
|
||||
/* Only the first leaf-field of the record gets called with the
|
||||
* record type pointer.
|
||||
@@ -197,7 +220,8 @@ program_resource_visitor::recursion(const glsl_type *t, char **name,
|
||||
ralloc_asprintf_rewrite_tail(name, &new_length, "[%u]", i);
|
||||
|
||||
recursion(t->fields.array, name, new_length, row_major,
|
||||
record_type);
|
||||
record_type,
|
||||
(i + 1) == t->length);
|
||||
|
||||
/* Only the first leaf-field of the record gets called with the
|
||||
* record type pointer.
|
||||
@@ -205,14 +229,15 @@ program_resource_visitor::recursion(const glsl_type *t, char **name,
|
||||
record_type = NULL;
|
||||
}
|
||||
} else {
|
||||
this->visit_field(t, *name, row_major, record_type);
|
||||
this->visit_field(t, *name, row_major, record_type, last_field);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
program_resource_visitor::visit_field(const glsl_type *type, const char *name,
|
||||
bool row_major,
|
||||
const glsl_type *record_type)
|
||||
const glsl_type *,
|
||||
bool /* last_field */)
|
||||
{
|
||||
visit_field(type, name, row_major);
|
||||
}
|
||||
@@ -294,10 +319,8 @@ private:
|
||||
virtual void visit_field(const glsl_type *type, const char *name,
|
||||
bool row_major)
|
||||
{
|
||||
assert(!type->is_record());
|
||||
assert(!(type->is_array() && type->fields.array->is_record()));
|
||||
assert(!type->is_interface());
|
||||
assert(!(type->is_array() && type->fields.array->is_interface()));
|
||||
assert(!type->without_array()->is_record());
|
||||
assert(!type->without_array()->is_interface());
|
||||
|
||||
(void) row_major;
|
||||
|
||||
@@ -308,8 +331,7 @@ private:
|
||||
*/
|
||||
const unsigned values = values_for_type(type);
|
||||
if (type->contains_sampler()) {
|
||||
this->num_shader_samplers +=
|
||||
type->is_array() ? type->array_size() : 1;
|
||||
this->num_shader_samplers += values;
|
||||
} else if (type->contains_image()) {
|
||||
this->num_shader_images += values;
|
||||
|
||||
@@ -387,6 +409,9 @@ public:
|
||||
void set_and_process(struct gl_shader_program *prog,
|
||||
ir_variable *var)
|
||||
{
|
||||
current_var = var;
|
||||
field_counter = 0;
|
||||
|
||||
ubo_block_index = -1;
|
||||
if (var->is_in_uniform_block()) {
|
||||
if (var->is_interface_instance() && var->type->is_array()) {
|
||||
@@ -420,7 +445,6 @@ public:
|
||||
*/
|
||||
if (var->is_interface_instance()) {
|
||||
ubo_byte_offset = 0;
|
||||
ubo_row_major = false;
|
||||
} else {
|
||||
const struct gl_uniform_block *const block =
|
||||
&prog->UniformBlocks[ubo_block_index];
|
||||
@@ -430,7 +454,6 @@ public:
|
||||
const struct gl_uniform_buffer_variable *const ubo_var =
|
||||
&block->Uniforms[var->data.location];
|
||||
|
||||
ubo_row_major = !!ubo_var->RowMajor;
|
||||
ubo_byte_offset = ubo_var->Offset;
|
||||
}
|
||||
|
||||
@@ -445,7 +468,6 @@ public:
|
||||
|
||||
int ubo_block_index;
|
||||
int ubo_byte_offset;
|
||||
bool ubo_row_major;
|
||||
gl_shader_stage shader_type;
|
||||
|
||||
private:
|
||||
@@ -505,14 +527,11 @@ private:
|
||||
}
|
||||
|
||||
virtual void visit_field(const glsl_type *type, const char *name,
|
||||
bool row_major, const glsl_type *record_type)
|
||||
bool row_major, const glsl_type *record_type,
|
||||
bool last_field)
|
||||
{
|
||||
assert(!type->is_record());
|
||||
assert(!(type->is_array() && type->fields.array->is_record()));
|
||||
assert(!type->is_interface());
|
||||
assert(!(type->is_array() && type->fields.array->is_interface()));
|
||||
|
||||
(void) row_major;
|
||||
assert(!type->without_array()->is_record());
|
||||
assert(!type->without_array()->is_interface());
|
||||
|
||||
unsigned id;
|
||||
bool found = this->map->get(id, name);
|
||||
@@ -543,6 +562,22 @@ private:
|
||||
return;
|
||||
}
|
||||
|
||||
/* Assign explicit locations. */
|
||||
if (current_var->data.explicit_location) {
|
||||
/* Set sequential locations for struct fields. */
|
||||
if (record_type != NULL) {
|
||||
const unsigned entries = MAX2(1, this->uniforms[id].array_elements);
|
||||
this->uniforms[id].remap_location =
|
||||
current_var->data.location + field_counter;
|
||||
field_counter += entries;
|
||||
} else {
|
||||
this->uniforms[id].remap_location = current_var->data.location;
|
||||
}
|
||||
} else {
|
||||
/* Initialize to to indicate that no location is set */
|
||||
this->uniforms[id].remap_location = UNMAPPED_UNIFORM_LOC;
|
||||
}
|
||||
|
||||
this->uniforms[id].name = ralloc_strdup(this->uniforms, name);
|
||||
this->uniforms[id].type = base_type;
|
||||
this->uniforms[id].initialized = 0;
|
||||
@@ -554,23 +589,25 @@ private:
|
||||
this->uniforms[id].block_index = this->ubo_block_index;
|
||||
|
||||
const unsigned alignment = record_type
|
||||
? record_type->std140_base_alignment(ubo_row_major)
|
||||
: type->std140_base_alignment(ubo_row_major);
|
||||
? record_type->std140_base_alignment(row_major)
|
||||
: type->std140_base_alignment(row_major);
|
||||
this->ubo_byte_offset = glsl_align(this->ubo_byte_offset, alignment);
|
||||
this->uniforms[id].offset = this->ubo_byte_offset;
|
||||
this->ubo_byte_offset += type->std140_size(ubo_row_major);
|
||||
this->ubo_byte_offset += type->std140_size(row_major);
|
||||
|
||||
if (last_field)
|
||||
this->ubo_byte_offset = glsl_align(this->ubo_byte_offset, 16);
|
||||
|
||||
if (type->is_array()) {
|
||||
this->uniforms[id].array_stride =
|
||||
glsl_align(type->fields.array->std140_size(ubo_row_major), 16);
|
||||
glsl_align(type->fields.array->std140_size(row_major), 16);
|
||||
} else {
|
||||
this->uniforms[id].array_stride = 0;
|
||||
}
|
||||
|
||||
if (type->is_matrix() ||
|
||||
(type->is_array() && type->fields.array->is_matrix())) {
|
||||
if (type->without_array()->is_matrix()) {
|
||||
this->uniforms[id].matrix_stride = 16;
|
||||
this->uniforms[id].row_major = ubo_row_major;
|
||||
this->uniforms[id].row_major = row_major;
|
||||
} else {
|
||||
this->uniforms[id].matrix_stride = 0;
|
||||
this->uniforms[id].row_major = false;
|
||||
@@ -597,6 +634,17 @@ public:
|
||||
|
||||
gl_texture_index targets[MAX_SAMPLERS];
|
||||
|
||||
/**
|
||||
* Current variable being processed.
|
||||
*/
|
||||
ir_variable *current_var;
|
||||
|
||||
/**
|
||||
* Field counter is used to take care that uniform structures
|
||||
* with explicit locations get sequential locations.
|
||||
*/
|
||||
unsigned field_counter;
|
||||
|
||||
/**
|
||||
* Mask of samplers used by the current shader stage.
|
||||
*/
|
||||
@@ -668,8 +716,8 @@ link_cross_validate_uniform_block(void *mem_ctx,
|
||||
static void
|
||||
link_update_uniform_buffer_variables(struct gl_shader *shader)
|
||||
{
|
||||
foreach_list(node, shader->ir) {
|
||||
ir_variable *const var = ((ir_instruction *) node)->as_variable();
|
||||
foreach_in_list(ir_instruction, node, shader->ir) {
|
||||
ir_variable *const var = node->as_variable();
|
||||
|
||||
if ((var == NULL) || !var->is_in_uniform_block())
|
||||
continue;
|
||||
@@ -701,7 +749,7 @@ link_update_uniform_buffer_variables(struct gl_shader *shader)
|
||||
if (end == NULL)
|
||||
continue;
|
||||
|
||||
if (l != (end - begin))
|
||||
if ((ptrdiff_t) l != (end - begin))
|
||||
continue;
|
||||
|
||||
if (strncmp(var->name, begin, l) == 0) {
|
||||
@@ -723,39 +771,6 @@ link_update_uniform_buffer_variables(struct gl_shader *shader)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
link_assign_uniform_block_offsets(struct gl_shader *shader)
|
||||
{
|
||||
for (unsigned b = 0; b < shader->NumUniformBlocks; b++) {
|
||||
struct gl_uniform_block *block = &shader->UniformBlocks[b];
|
||||
|
||||
unsigned offset = 0;
|
||||
for (unsigned int i = 0; i < block->NumUniforms; i++) {
|
||||
struct gl_uniform_buffer_variable *ubo_var = &block->Uniforms[i];
|
||||
const struct glsl_type *type = ubo_var->Type;
|
||||
|
||||
unsigned alignment = type->std140_base_alignment(!!ubo_var->RowMajor);
|
||||
unsigned size = type->std140_size(!!ubo_var->RowMajor);
|
||||
|
||||
offset = glsl_align(offset, alignment);
|
||||
ubo_var->Offset = offset;
|
||||
offset += size;
|
||||
}
|
||||
|
||||
/* From the GL_ARB_uniform_buffer_object spec:
|
||||
*
|
||||
* "For uniform blocks laid out according to [std140] rules,
|
||||
* the minimum buffer object size returned by the
|
||||
* UNIFORM_BLOCK_DATA_SIZE query is derived by taking the
|
||||
* offset of the last basic machine unit consumed by the
|
||||
* last uniform of the uniform block (including any
|
||||
* end-of-array or end-of-structure padding), adding one,
|
||||
* and rounding up to the next multiple of the base
|
||||
* alignment required for a vec4."
|
||||
*/
|
||||
block->UniformBufferSize = glsl_align(offset, 16);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scan the program for image uniforms and store image unit access
|
||||
@@ -770,18 +785,19 @@ link_set_image_access_qualifiers(struct gl_shader_program *prog)
|
||||
if (sh == NULL)
|
||||
continue;
|
||||
|
||||
foreach_list(node, sh->ir) {
|
||||
ir_variable *var = ((ir_instruction *) node)->as_variable();
|
||||
foreach_in_list(ir_instruction, node, sh->ir) {
|
||||
ir_variable *var = node->as_variable();
|
||||
|
||||
if (var && var->data.mode == ir_var_uniform &&
|
||||
var->type->contains_image()) {
|
||||
unsigned id;
|
||||
unsigned id = 0;
|
||||
bool found = prog->UniformHash->get(id, var->name);
|
||||
assert(found);
|
||||
(void) found;
|
||||
const gl_uniform_storage *storage = &prog->UniformStorage[id];
|
||||
const unsigned index = storage->image[i].index;
|
||||
const GLenum access = (var->data.image.read_only ? GL_READ_ONLY :
|
||||
var->data.image.write_only ? GL_WRITE_ONLY :
|
||||
const GLenum access = (var->data.image_read_only ? GL_READ_ONLY :
|
||||
var->data.image_write_only ? GL_WRITE_ONLY :
|
||||
GL_READ_WRITE);
|
||||
|
||||
for (unsigned j = 0; j < MAX2(1, storage->array_elements); ++j)
|
||||
@@ -792,7 +808,8 @@ link_set_image_access_qualifiers(struct gl_shader_program *prog)
|
||||
}
|
||||
|
||||
void
|
||||
link_assign_uniform_locations(struct gl_shader_program *prog)
|
||||
link_assign_uniform_locations(struct gl_shader_program *prog,
|
||||
unsigned int boolean_true)
|
||||
{
|
||||
ralloc_free(prog->UniformStorage);
|
||||
prog->UniformStorage = NULL;
|
||||
@@ -836,15 +853,15 @@ link_assign_uniform_locations(struct gl_shader_program *prog)
|
||||
*/
|
||||
uniform_size.start_shader();
|
||||
|
||||
foreach_list(node, sh->ir) {
|
||||
ir_variable *const var = ((ir_instruction *) node)->as_variable();
|
||||
foreach_in_list(ir_instruction, node, sh->ir) {
|
||||
ir_variable *const var = node->as_variable();
|
||||
|
||||
if ((var == NULL) || (var->data.mode != ir_var_uniform))
|
||||
continue;
|
||||
|
||||
/* FINISHME: Update code to process built-in uniforms!
|
||||
*/
|
||||
if (strncmp("gl_", var->name, 3) == 0) {
|
||||
if (is_gl_identifier(var->name)) {
|
||||
uniform_size.num_shader_uniform_components +=
|
||||
var->type->component_slots();
|
||||
continue;
|
||||
@@ -888,15 +905,15 @@ link_assign_uniform_locations(struct gl_shader_program *prog)
|
||||
|
||||
parcel.start_shader((gl_shader_stage)i);
|
||||
|
||||
foreach_list(node, prog->_LinkedShaders[i]->ir) {
|
||||
ir_variable *const var = ((ir_instruction *) node)->as_variable();
|
||||
foreach_in_list(ir_instruction, node, prog->_LinkedShaders[i]->ir) {
|
||||
ir_variable *const var = node->as_variable();
|
||||
|
||||
if ((var == NULL) || (var->data.mode != ir_var_uniform))
|
||||
continue;
|
||||
|
||||
/* FINISHME: Update code to process built-in uniforms!
|
||||
*/
|
||||
if (strncmp("gl_", var->name, 3) == 0)
|
||||
if (is_gl_identifier(var->name))
|
||||
continue;
|
||||
|
||||
parcel.set_and_process(prog, var);
|
||||
@@ -910,19 +927,48 @@ link_assign_uniform_locations(struct gl_shader_program *prog)
|
||||
sizeof(prog->_LinkedShaders[i]->SamplerTargets));
|
||||
}
|
||||
|
||||
/* Determine the size of the largest uniform array queryable via
|
||||
* glGetUniformLocation. Using this as the location scale guarantees that
|
||||
* there is enough "room" for the array index to be stored in the low order
|
||||
* part of the uniform location. It also makes the locations be more
|
||||
* tightly packed.
|
||||
*/
|
||||
unsigned max_array_size = 1;
|
||||
/* Reserve all the explicit locations of the active uniforms. */
|
||||
for (unsigned i = 0; i < num_user_uniforms; i++) {
|
||||
if (uniforms[i].array_elements > max_array_size)
|
||||
max_array_size = uniforms[i].array_elements;
|
||||
if (uniforms[i].remap_location != UNMAPPED_UNIFORM_LOC) {
|
||||
/* How many new entries for this uniform? */
|
||||
const unsigned entries = MAX2(1, uniforms[i].array_elements);
|
||||
|
||||
/* Set remap table entries point to correct gl_uniform_storage. */
|
||||
for (unsigned j = 0; j < entries; j++) {
|
||||
unsigned element_loc = uniforms[i].remap_location + j;
|
||||
assert(prog->UniformRemapTable[element_loc] ==
|
||||
INACTIVE_UNIFORM_EXPLICIT_LOCATION);
|
||||
prog->UniformRemapTable[element_loc] = &uniforms[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
prog->UniformLocationBaseScale = max_array_size;
|
||||
/* Reserve locations for rest of the uniforms. */
|
||||
for (unsigned i = 0; i < num_user_uniforms; i++) {
|
||||
|
||||
/* Explicit ones have been set already. */
|
||||
if (uniforms[i].remap_location != UNMAPPED_UNIFORM_LOC)
|
||||
continue;
|
||||
|
||||
/* how many new entries for this uniform? */
|
||||
const unsigned entries = MAX2(1, uniforms[i].array_elements);
|
||||
|
||||
/* resize remap table to fit new entries */
|
||||
prog->UniformRemapTable =
|
||||
reralloc(prog,
|
||||
prog->UniformRemapTable,
|
||||
gl_uniform_storage *,
|
||||
prog->NumUniformRemapTable + entries);
|
||||
|
||||
/* set pointers for this uniform */
|
||||
for (unsigned j = 0; j < entries; j++)
|
||||
prog->UniformRemapTable[prog->NumUniformRemapTable+j] = &uniforms[i];
|
||||
|
||||
/* set the base location in remap table for the uniform */
|
||||
uniforms[i].remap_location = prog->NumUniformRemapTable;
|
||||
|
||||
prog->NumUniformRemapTable += entries;
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
for (unsigned i = 0; i < num_user_uniforms; i++) {
|
||||
@@ -936,7 +982,7 @@ link_assign_uniform_locations(struct gl_shader_program *prog)
|
||||
prog->UniformStorage = uniforms;
|
||||
|
||||
link_set_image_access_qualifiers(prog);
|
||||
link_set_uniform_initializers(prog);
|
||||
link_set_uniform_initializers(prog, boolean_true);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
464
3rdparty/glsl-optimizer/src/glsl/link_varyings.cpp
vendored
464
3rdparty/glsl-optimizer/src/glsl/link_varyings.cpp
vendored
@@ -29,6 +29,7 @@
|
||||
*/
|
||||
|
||||
|
||||
#include "main/errors.h"
|
||||
#include "main/mtypes.h"
|
||||
#include "glsl_symbol_table.h"
|
||||
#include "glsl_parser_extras.h"
|
||||
@@ -77,8 +78,7 @@ cross_validate_types_and_qualifiers(struct gl_shader_program *prog,
|
||||
* correspondence between the vertex language and the
|
||||
* fragment language."
|
||||
*/
|
||||
if (!output->type->is_array()
|
||||
|| (strncmp("gl_", output->name, 3) != 0)) {
|
||||
if (!output->type->is_array() || !is_gl_identifier(output->name)) {
|
||||
linker_error(prog,
|
||||
"%s shader output `%s' declared as type `%s', "
|
||||
"but %s shader input declared as type `%s'\n",
|
||||
@@ -172,16 +172,36 @@ cross_validate_outputs_to_inputs(struct gl_shader_program *prog,
|
||||
gl_shader *producer, gl_shader *consumer)
|
||||
{
|
||||
glsl_symbol_table parameters;
|
||||
ir_variable *explicit_locations[MAX_VARYING] = { NULL, };
|
||||
|
||||
/* Find all shader outputs in the "producer" stage.
|
||||
*/
|
||||
foreach_list(node, producer->ir) {
|
||||
ir_variable *const var = ((ir_instruction *) node)->as_variable();
|
||||
foreach_in_list(ir_instruction, node, producer->ir) {
|
||||
ir_variable *const var = node->as_variable();
|
||||
|
||||
if ((var == NULL) || (var->data.mode != ir_var_shader_out))
|
||||
continue;
|
||||
|
||||
parameters.add_variable(var);
|
||||
if (!var->data.explicit_location
|
||||
|| var->data.location < VARYING_SLOT_VAR0)
|
||||
parameters.add_variable(var);
|
||||
else {
|
||||
/* User-defined varyings with explicit locations are handled
|
||||
* differently because they do not need to have matching names.
|
||||
*/
|
||||
const unsigned idx = var->data.location - VARYING_SLOT_VAR0;
|
||||
|
||||
if (explicit_locations[idx] != NULL) {
|
||||
linker_error(prog,
|
||||
"%s shader has multiple outputs explicitly "
|
||||
"assigned to location %d\n",
|
||||
_mesa_shader_stage_to_string(producer->Stage),
|
||||
idx);
|
||||
return;
|
||||
}
|
||||
|
||||
explicit_locations[idx] = var;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -193,8 +213,8 @@ cross_validate_outputs_to_inputs(struct gl_shader_program *prog,
|
||||
* should be arrays and the type of the array element should match the type
|
||||
* of the corresponding producer output.
|
||||
*/
|
||||
foreach_list(node, consumer->ir) {
|
||||
ir_variable *const input = ((ir_instruction *) node)->as_variable();
|
||||
foreach_in_list(ir_instruction, node, consumer->ir) {
|
||||
ir_variable *const input = node->as_variable();
|
||||
|
||||
if ((input == NULL) || (input->data.mode != ir_var_shader_in))
|
||||
continue;
|
||||
@@ -220,7 +240,27 @@ cross_validate_outputs_to_inputs(struct gl_shader_program *prog,
|
||||
front_color, back_color,
|
||||
consumer->Stage, producer->Stage);
|
||||
} else {
|
||||
ir_variable *const output = parameters.get_variable(input->name);
|
||||
/* The rules for connecting inputs and outputs change in the presence
|
||||
* of explicit locations. In this case, we no longer care about the
|
||||
* names of the variables. Instead, we care only about the
|
||||
* explicitly assigned location.
|
||||
*/
|
||||
ir_variable *output = NULL;
|
||||
if (input->data.explicit_location
|
||||
&& input->data.location >= VARYING_SLOT_VAR0) {
|
||||
output = explicit_locations[input->data.location - VARYING_SLOT_VAR0];
|
||||
|
||||
if (output == NULL) {
|
||||
linker_error(prog,
|
||||
"%s shader input `%s' with explicit location "
|
||||
"has no matching output\n",
|
||||
_mesa_shader_stage_to_string(consumer->Stage),
|
||||
input->name);
|
||||
}
|
||||
} else {
|
||||
output = parameters.get_variable(input->name);
|
||||
}
|
||||
|
||||
if (output != NULL) {
|
||||
cross_validate_types_and_qualifiers(prog, input, output,
|
||||
consumer->Stage, producer->Stage);
|
||||
@@ -252,6 +292,7 @@ tfeedback_decl::init(struct gl_context *ctx, const void *mem_ctx,
|
||||
this->skip_components = 0;
|
||||
this->next_buffer_separator = false;
|
||||
this->matched_candidate = NULL;
|
||||
this->stream_id = 0;
|
||||
|
||||
if (ctx->Extensions.ARB_transform_feedback3) {
|
||||
/* Parse gl_NextBuffer. */
|
||||
@@ -278,6 +319,11 @@ tfeedback_decl::init(struct gl_context *ctx, const void *mem_ctx,
|
||||
const char *base_name_end;
|
||||
long subscript = parse_program_resource_name(input, &base_name_end);
|
||||
this->var_name = ralloc_strndup(mem_ctx, input, base_name_end - input);
|
||||
if (this->var_name == NULL) {
|
||||
_mesa_error_no_memory(__func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (subscript >= 0) {
|
||||
this->array_subscript = subscript;
|
||||
this->is_subscripted = true;
|
||||
@@ -289,7 +335,7 @@ tfeedback_decl::init(struct gl_context *ctx, const void *mem_ctx,
|
||||
* class must behave specially to account for the fact that gl_ClipDistance
|
||||
* is converted from a float[8] to a vec4[2].
|
||||
*/
|
||||
if (ctx->ShaderCompilerOptions[MESA_SHADER_VERTEX].LowerClipDistance &&
|
||||
if (ctx->Const.ShaderCompilerOptions[MESA_SHADER_VERTEX].LowerClipDistance &&
|
||||
strcmp(this->var_name, "gl_ClipDistance") == 0) {
|
||||
this->is_clip_distance_mesa = true;
|
||||
}
|
||||
@@ -316,8 +362,8 @@ tfeedback_decl::is_same(const tfeedback_decl &x, const tfeedback_decl &y)
|
||||
|
||||
|
||||
/**
|
||||
* Assign a location for this tfeedback_decl object based on the transform
|
||||
* feedback candidate found by find_candidate.
|
||||
* Assign a location and stream ID for this tfeedback_decl object based on the
|
||||
* transform feedback candidate found by find_candidate.
|
||||
*
|
||||
* If an error occurs, the error is reported through linker_error() and false
|
||||
* is returned.
|
||||
@@ -398,6 +444,11 @@ tfeedback_decl::assign_location(struct gl_context *ctx,
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Only transform feedback varyings can be assigned to non-zero streams,
|
||||
* so assign the stream id here.
|
||||
*/
|
||||
this->stream_id = this->matched_candidate->toplevel_var->data.stream;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -456,6 +507,7 @@ tfeedback_decl::store(struct gl_context *ctx, struct gl_shader_program *prog,
|
||||
info->Outputs[info->NumOutputs].ComponentOffset = location_frac;
|
||||
info->Outputs[info->NumOutputs].OutputRegister = location;
|
||||
info->Outputs[info->NumOutputs].NumComponents = output_size;
|
||||
info->Outputs[info->NumOutputs].StreamId = stream_id;
|
||||
info->Outputs[info->NumOutputs].OutputBuffer = buffer;
|
||||
info->Outputs[info->NumOutputs].DstOffset = info->BufferStride[buffer];
|
||||
++info->NumOutputs;
|
||||
@@ -589,10 +641,27 @@ store_tfeedback_info(struct gl_context *ctx, struct gl_shader_program *prog,
|
||||
}
|
||||
else {
|
||||
/* GL_INVERLEAVED_ATTRIBS */
|
||||
int buffer_stream_id = -1;
|
||||
for (unsigned i = 0; i < num_tfeedback_decls; ++i) {
|
||||
if (tfeedback_decls[i].is_next_buffer_separator()) {
|
||||
num_buffers++;
|
||||
buffer_stream_id = -1;
|
||||
continue;
|
||||
} else if (buffer_stream_id == -1) {
|
||||
/* First varying writing to this buffer: remember its stream */
|
||||
buffer_stream_id = (int) tfeedback_decls[i].get_stream_id();
|
||||
} else if (buffer_stream_id !=
|
||||
(int) tfeedback_decls[i].get_stream_id()) {
|
||||
/* Varying writes to the same buffer from a different stream */
|
||||
linker_error(prog,
|
||||
"Transform feedback can't capture varyings belonging "
|
||||
"to different vertex streams in a single buffer. "
|
||||
"Varying %s writes to buffer from stream %u, other "
|
||||
"varyings in the same buffer write from stream %u.",
|
||||
tfeedback_decls[i].name(),
|
||||
tfeedback_decls[i].get_stream_id(),
|
||||
buffer_stream_id);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!tfeedback_decls[i].store(ctx, prog,
|
||||
@@ -622,7 +691,7 @@ public:
|
||||
~varying_matches();
|
||||
void record(ir_variable *producer_var, ir_variable *consumer_var);
|
||||
unsigned assign_locations();
|
||||
void store_locations(unsigned producer_base, unsigned consumer_base) const;
|
||||
void store_locations() const;
|
||||
|
||||
private:
|
||||
/**
|
||||
@@ -648,8 +717,8 @@ private:
|
||||
PACKING_ORDER_VEC3,
|
||||
};
|
||||
|
||||
static unsigned compute_packing_class(ir_variable *var);
|
||||
static packing_order_enum compute_packing_order(ir_variable *var);
|
||||
static unsigned compute_packing_class(const ir_variable *var);
|
||||
static packing_order_enum compute_packing_order(const ir_variable *var);
|
||||
static int match_comparator(const void *x_generic, const void *y_generic);
|
||||
|
||||
/**
|
||||
@@ -746,7 +815,10 @@ varying_matches::~varying_matches()
|
||||
void
|
||||
varying_matches::record(ir_variable *producer_var, ir_variable *consumer_var)
|
||||
{
|
||||
if (!producer_var->data.is_unmatched_generic_inout) {
|
||||
assert(producer_var != NULL || consumer_var != NULL);
|
||||
|
||||
if ((producer_var && !producer_var->data.is_unmatched_generic_inout)
|
||||
|| (consumer_var && !consumer_var->data.is_unmatched_generic_inout)) {
|
||||
/* Either a location already exists for this variable (since it is part
|
||||
* of fixed functionality), or it has already been recorded as part of a
|
||||
* previous match.
|
||||
@@ -781,24 +853,28 @@ varying_matches::record(ir_variable *producer_var, ir_variable *consumer_var)
|
||||
realloc(this->matches,
|
||||
sizeof(*this->matches) * this->matches_capacity);
|
||||
}
|
||||
|
||||
const ir_variable *const var = (producer_var != NULL)
|
||||
? producer_var : consumer_var;
|
||||
|
||||
this->matches[this->num_matches].packing_class
|
||||
= this->compute_packing_class(producer_var);
|
||||
= this->compute_packing_class(var);
|
||||
this->matches[this->num_matches].packing_order
|
||||
= this->compute_packing_order(producer_var);
|
||||
= this->compute_packing_order(var);
|
||||
if (this->disable_varying_packing) {
|
||||
unsigned slots = producer_var->type->is_array()
|
||||
? (producer_var->type->length
|
||||
* producer_var->type->fields.array->matrix_columns)
|
||||
: producer_var->type->matrix_columns;
|
||||
unsigned slots = var->type->is_array()
|
||||
? (var->type->length * var->type->fields.array->matrix_columns)
|
||||
: var->type->matrix_columns;
|
||||
this->matches[this->num_matches].num_components = 4 * slots;
|
||||
} else {
|
||||
this->matches[this->num_matches].num_components
|
||||
= producer_var->type->component_slots();
|
||||
= var->type->component_slots();
|
||||
}
|
||||
this->matches[this->num_matches].producer_var = producer_var;
|
||||
this->matches[this->num_matches].consumer_var = consumer_var;
|
||||
this->num_matches++;
|
||||
producer_var->data.is_unmatched_generic_inout = 0;
|
||||
if (producer_var)
|
||||
producer_var->data.is_unmatched_generic_inout = 0;
|
||||
if (consumer_var)
|
||||
consumer_var->data.is_unmatched_generic_inout = 0;
|
||||
}
|
||||
@@ -842,8 +918,7 @@ varying_matches::assign_locations()
|
||||
* assignments that were made by varying_matches::assign_locations().
|
||||
*/
|
||||
void
|
||||
varying_matches::store_locations(unsigned producer_base,
|
||||
unsigned consumer_base) const
|
||||
varying_matches::store_locations() const
|
||||
{
|
||||
for (unsigned i = 0; i < this->num_matches; i++) {
|
||||
ir_variable *producer_var = this->matches[i].producer_var;
|
||||
@@ -852,11 +927,14 @@ varying_matches::store_locations(unsigned producer_base,
|
||||
unsigned slot = generic_location / 4;
|
||||
unsigned offset = generic_location % 4;
|
||||
|
||||
producer_var->data.location = producer_base + slot;
|
||||
producer_var->data.location_frac = offset;
|
||||
if (producer_var) {
|
||||
producer_var->data.location = VARYING_SLOT_VAR0 + slot;
|
||||
producer_var->data.location_frac = offset;
|
||||
}
|
||||
|
||||
if (consumer_var) {
|
||||
assert(consumer_var->data.location == -1);
|
||||
consumer_var->data.location = consumer_base + slot;
|
||||
consumer_var->data.location = VARYING_SLOT_VAR0 + slot;
|
||||
consumer_var->data.location_frac = offset;
|
||||
}
|
||||
}
|
||||
@@ -869,7 +947,7 @@ varying_matches::store_locations(unsigned producer_base,
|
||||
* be safely backed into the same vec4.
|
||||
*/
|
||||
unsigned
|
||||
varying_matches::compute_packing_class(ir_variable *var)
|
||||
varying_matches::compute_packing_class(const ir_variable *var)
|
||||
{
|
||||
/* Without help from the back-end, there is no way to pack together
|
||||
* variables with different interpolation types, because
|
||||
@@ -900,7 +978,7 @@ varying_matches::compute_packing_class(ir_variable *var)
|
||||
* other varyings in the same packing class.
|
||||
*/
|
||||
varying_matches::packing_order_enum
|
||||
varying_matches::compute_packing_order(ir_variable *var)
|
||||
varying_matches::compute_packing_order(const ir_variable *var)
|
||||
{
|
||||
const glsl_type *element_type = var->type;
|
||||
|
||||
@@ -943,7 +1021,7 @@ varying_matches::match_comparator(const void *x_generic, const void *y_generic)
|
||||
* varyings, but excludes variables such as gl_FrontFacing and gl_FragCoord.
|
||||
*/
|
||||
static bool
|
||||
is_varying_var(gl_shader_stage stage, const ir_variable *var)
|
||||
var_counts_against_varying_limit(gl_shader_stage stage, const ir_variable *var)
|
||||
{
|
||||
/* Only fragment shaders will take a varying variable as an input */
|
||||
if (stage == MESA_SHADER_FRAGMENT &&
|
||||
@@ -996,10 +1074,8 @@ private:
|
||||
virtual void visit_field(const glsl_type *type, const char *name,
|
||||
bool row_major)
|
||||
{
|
||||
assert(!type->is_record());
|
||||
assert(!(type->is_array() && type->fields.array->is_record()));
|
||||
assert(!type->is_interface());
|
||||
assert(!(type->is_array() && type->fields.array->is_interface()));
|
||||
assert(!type->without_array()->is_record());
|
||||
assert(!type->without_array()->is_interface());
|
||||
|
||||
(void) row_major;
|
||||
|
||||
@@ -1037,6 +1113,157 @@ private:
|
||||
};
|
||||
|
||||
|
||||
namespace linker {
|
||||
|
||||
bool
|
||||
populate_consumer_input_sets(void *mem_ctx, exec_list *ir,
|
||||
hash_table *consumer_inputs,
|
||||
hash_table *consumer_interface_inputs,
|
||||
ir_variable *consumer_inputs_with_locations[VARYING_SLOT_MAX])
|
||||
{
|
||||
memset(consumer_inputs_with_locations,
|
||||
0,
|
||||
sizeof(consumer_inputs_with_locations[0]) * VARYING_SLOT_MAX);
|
||||
|
||||
foreach_in_list(ir_instruction, node, ir) {
|
||||
ir_variable *const input_var = node->as_variable();
|
||||
|
||||
if ((input_var != NULL) && (input_var->data.mode == ir_var_shader_in)) {
|
||||
if (input_var->type->is_interface())
|
||||
return false;
|
||||
|
||||
if (input_var->data.explicit_location) {
|
||||
/* assign_varying_locations only cares about finding the
|
||||
* ir_variable at the start of a contiguous location block.
|
||||
*
|
||||
* - For !producer, consumer_inputs_with_locations isn't used.
|
||||
*
|
||||
* - For !consumer, consumer_inputs_with_locations is empty.
|
||||
*
|
||||
* For consumer && producer, if you were trying to set some
|
||||
* ir_variable to the middle of a location block on the other side
|
||||
* of producer/consumer, cross_validate_outputs_to_inputs() should
|
||||
* be link-erroring due to either type mismatch or location
|
||||
* overlaps. If the variables do match up, then they've got a
|
||||
* matching data.location and you only looked at
|
||||
* consumer_inputs_with_locations[var->data.location], not any
|
||||
* following entries for the array/structure.
|
||||
*/
|
||||
consumer_inputs_with_locations[input_var->data.location] =
|
||||
input_var;
|
||||
} else if (input_var->get_interface_type() != NULL) {
|
||||
char *const iface_field_name =
|
||||
ralloc_asprintf(mem_ctx, "%s.%s",
|
||||
input_var->get_interface_type()->name,
|
||||
input_var->name);
|
||||
hash_table_insert(consumer_interface_inputs, input_var,
|
||||
iface_field_name);
|
||||
} else {
|
||||
hash_table_insert(consumer_inputs, input_var,
|
||||
ralloc_strdup(mem_ctx, input_var->name));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a variable from the consumer that "matches" the specified variable
|
||||
*
|
||||
* This function only finds inputs with names that match. There is no
|
||||
* validation (here) that the types, etc. are compatible.
|
||||
*/
|
||||
ir_variable *
|
||||
get_matching_input(void *mem_ctx,
|
||||
const ir_variable *output_var,
|
||||
hash_table *consumer_inputs,
|
||||
hash_table *consumer_interface_inputs,
|
||||
ir_variable *consumer_inputs_with_locations[VARYING_SLOT_MAX])
|
||||
{
|
||||
ir_variable *input_var;
|
||||
|
||||
if (output_var->data.explicit_location) {
|
||||
input_var = consumer_inputs_with_locations[output_var->data.location];
|
||||
} else if (output_var->get_interface_type() != NULL) {
|
||||
char *const iface_field_name =
|
||||
ralloc_asprintf(mem_ctx, "%s.%s",
|
||||
output_var->get_interface_type()->name,
|
||||
output_var->name);
|
||||
input_var =
|
||||
(ir_variable *) hash_table_find(consumer_interface_inputs,
|
||||
iface_field_name);
|
||||
} else {
|
||||
input_var =
|
||||
(ir_variable *) hash_table_find(consumer_inputs, output_var->name);
|
||||
}
|
||||
|
||||
return (input_var == NULL || input_var->data.mode != ir_var_shader_in)
|
||||
? NULL : input_var;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static int
|
||||
io_variable_cmp(const void *_a, const void *_b)
|
||||
{
|
||||
const ir_variable *const a = *(const ir_variable **) _a;
|
||||
const ir_variable *const b = *(const ir_variable **) _b;
|
||||
|
||||
if (a->data.explicit_location && b->data.explicit_location)
|
||||
return b->data.location - a->data.location;
|
||||
|
||||
if (a->data.explicit_location && !b->data.explicit_location)
|
||||
return 1;
|
||||
|
||||
if (!a->data.explicit_location && b->data.explicit_location)
|
||||
return -1;
|
||||
|
||||
return -strcmp(a->name, b->name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort the shader IO variables into canonical order
|
||||
*/
|
||||
static void
|
||||
canonicalize_shader_io(exec_list *ir, enum ir_variable_mode io_mode)
|
||||
{
|
||||
ir_variable *var_table[MAX_PROGRAM_OUTPUTS * 4];
|
||||
unsigned num_variables = 0;
|
||||
|
||||
foreach_in_list(ir_instruction, node, ir) {
|
||||
ir_variable *const var = node->as_variable();
|
||||
|
||||
if (var == NULL || var->data.mode != io_mode)
|
||||
continue;
|
||||
|
||||
/* If we have already encountered more I/O variables that could
|
||||
* successfully link, bail.
|
||||
*/
|
||||
if (num_variables == ARRAY_SIZE(var_table))
|
||||
return;
|
||||
|
||||
var_table[num_variables++] = var;
|
||||
}
|
||||
|
||||
if (num_variables == 0)
|
||||
return;
|
||||
|
||||
/* Sort the list in reverse order (io_variable_cmp handles this). Later
|
||||
* we're going to push the variables on to the IR list as a stack, so we
|
||||
* want the last variable (in canonical order) to be first in the list.
|
||||
*/
|
||||
qsort(var_table, num_variables, sizeof(var_table[0]), io_variable_cmp);
|
||||
|
||||
/* Remove the variable from it's current location in the IR, and put it at
|
||||
* the front.
|
||||
*/
|
||||
for (unsigned i = 0; i < num_variables; i++) {
|
||||
var_table[i]->remove();
|
||||
ir->push_head(var_table[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign locations for all variables that are produced in one pipeline stage
|
||||
* (the "producer") and consumed in the next stage (the "consumer").
|
||||
@@ -1069,8 +1296,6 @@ assign_varying_locations(struct gl_context *ctx,
|
||||
tfeedback_decl *tfeedback_decls,
|
||||
unsigned gs_input_vertices)
|
||||
{
|
||||
const unsigned producer_base = VARYING_SLOT_VAR0;
|
||||
const unsigned consumer_base = VARYING_SLOT_VAR0;
|
||||
varying_matches matches(!!ctx->Const.DisableVaryingPacking,
|
||||
consumer && consumer->Stage == MESA_SHADER_FRAGMENT);
|
||||
hash_table *tfeedback_candidates
|
||||
@@ -1079,67 +1304,96 @@ assign_varying_locations(struct gl_context *ctx,
|
||||
= hash_table_ctor(0, hash_table_string_hash, hash_table_string_compare);
|
||||
hash_table *consumer_interface_inputs
|
||||
= hash_table_ctor(0, hash_table_string_hash, hash_table_string_compare);
|
||||
ir_variable *consumer_inputs_with_locations[VARYING_SLOT_MAX] = {
|
||||
NULL,
|
||||
};
|
||||
|
||||
/* Operate in a total of three passes.
|
||||
/* Operate in a total of four passes.
|
||||
*
|
||||
* 1. Assign locations for any matching inputs and outputs.
|
||||
* 1. Sort inputs / outputs into a canonical order. This is necessary so
|
||||
* that inputs / outputs of separable shaders will be assigned
|
||||
* predictable locations regardless of the order in which declarations
|
||||
* appeared in the shader source.
|
||||
*
|
||||
* 2. Mark output variables in the producer that do not have locations as
|
||||
* 2. Assign locations for any matching inputs and outputs.
|
||||
*
|
||||
* 3. Mark output variables in the producer that do not have locations as
|
||||
* not being outputs. This lets the optimizer eliminate them.
|
||||
*
|
||||
* 3. Mark input variables in the consumer that do not have locations as
|
||||
* 4. Mark input variables in the consumer that do not have locations as
|
||||
* not being inputs. This lets the optimizer eliminate them.
|
||||
*/
|
||||
if (consumer)
|
||||
canonicalize_shader_io(consumer->ir, ir_var_shader_in);
|
||||
|
||||
if (consumer) {
|
||||
foreach_list(node, consumer->ir) {
|
||||
ir_variable *const input_var =
|
||||
((ir_instruction *) node)->as_variable();
|
||||
if (producer)
|
||||
canonicalize_shader_io(producer->ir, ir_var_shader_out);
|
||||
|
||||
if ((input_var != NULL) && (input_var->data.mode == ir_var_shader_in)) {
|
||||
if (input_var->get_interface_type() != NULL) {
|
||||
char *const iface_field_name =
|
||||
ralloc_asprintf(mem_ctx, "%s.%s",
|
||||
input_var->get_interface_type()->name,
|
||||
input_var->name);
|
||||
hash_table_insert(consumer_interface_inputs, input_var,
|
||||
iface_field_name);
|
||||
} else {
|
||||
hash_table_insert(consumer_inputs, input_var,
|
||||
ralloc_strdup(mem_ctx, input_var->name));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (consumer
|
||||
&& !linker::populate_consumer_input_sets(mem_ctx,
|
||||
consumer->ir,
|
||||
consumer_inputs,
|
||||
consumer_interface_inputs,
|
||||
consumer_inputs_with_locations)) {
|
||||
assert(!"populate_consumer_input_sets failed");
|
||||
hash_table_dtor(tfeedback_candidates);
|
||||
hash_table_dtor(consumer_inputs);
|
||||
hash_table_dtor(consumer_interface_inputs);
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach_list(node, producer->ir) {
|
||||
ir_variable *const output_var = ((ir_instruction *) node)->as_variable();
|
||||
if (producer) {
|
||||
foreach_in_list(ir_instruction, node, producer->ir) {
|
||||
ir_variable *const output_var = node->as_variable();
|
||||
|
||||
if ((output_var == NULL) || (output_var->data.mode != ir_var_shader_out))
|
||||
continue;
|
||||
if ((output_var == NULL) ||
|
||||
(output_var->data.mode != ir_var_shader_out))
|
||||
continue;
|
||||
|
||||
tfeedback_candidate_generator g(mem_ctx, tfeedback_candidates);
|
||||
g.process(output_var);
|
||||
/* Only geometry shaders can use non-zero streams */
|
||||
assert(output_var->data.stream == 0 ||
|
||||
(output_var->data.stream < MAX_VERTEX_STREAMS &&
|
||||
producer->Stage == MESA_SHADER_GEOMETRY));
|
||||
|
||||
ir_variable *input_var;
|
||||
if (output_var->get_interface_type() != NULL) {
|
||||
char *const iface_field_name =
|
||||
ralloc_asprintf(mem_ctx, "%s.%s",
|
||||
output_var->get_interface_type()->name,
|
||||
output_var->name);
|
||||
input_var =
|
||||
(ir_variable *) hash_table_find(consumer_interface_inputs,
|
||||
iface_field_name);
|
||||
} else {
|
||||
input_var =
|
||||
(ir_variable *) hash_table_find(consumer_inputs, output_var->name);
|
||||
tfeedback_candidate_generator g(mem_ctx, tfeedback_candidates);
|
||||
g.process(output_var);
|
||||
|
||||
ir_variable *const input_var =
|
||||
linker::get_matching_input(mem_ctx, output_var, consumer_inputs,
|
||||
consumer_interface_inputs,
|
||||
consumer_inputs_with_locations);
|
||||
|
||||
/* If a matching input variable was found, add this ouptut (and the
|
||||
* input) to the set. If this is a separable program and there is no
|
||||
* consumer stage, add the output.
|
||||
*/
|
||||
if (input_var || (prog->SeparateShader && consumer == NULL)) {
|
||||
matches.record(output_var, input_var);
|
||||
}
|
||||
|
||||
/* Only stream 0 outputs can be consumed in the next stage */
|
||||
if (input_var && output_var->data.stream != 0) {
|
||||
linker_error(prog, "output %s is assigned to stream=%d but "
|
||||
"is linked to an input, which requires stream=0",
|
||||
output_var->name, output_var->data.stream);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* If there's no producer stage, then this must be a separable program.
|
||||
* For example, we may have a program that has just a fragment shader.
|
||||
* Later this program will be used with some arbitrary vertex (or
|
||||
* geometry) shader program. This means that locations must be assigned
|
||||
* for all the inputs.
|
||||
*/
|
||||
foreach_in_list(ir_instruction, node, consumer->ir) {
|
||||
ir_variable *const input_var = node->as_variable();
|
||||
|
||||
if (input_var && input_var->data.mode != ir_var_shader_in)
|
||||
input_var = NULL;
|
||||
if ((input_var == NULL) ||
|
||||
(input_var->data.mode != ir_var_shader_in))
|
||||
continue;
|
||||
|
||||
if (input_var) {
|
||||
matches.record(output_var, input_var);
|
||||
matches.record(NULL, input_var);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1162,7 +1416,7 @@ assign_varying_locations(struct gl_context *ctx,
|
||||
}
|
||||
|
||||
const unsigned slots_used = matches.assign_locations();
|
||||
matches.store_locations(producer_base, consumer_base);
|
||||
matches.store_locations();
|
||||
|
||||
for (unsigned i = 0; i < num_tfeedback_decls; ++i) {
|
||||
if (!tfeedback_decls[i].is_varying())
|
||||
@@ -1187,21 +1441,38 @@ assign_varying_locations(struct gl_context *ctx,
|
||||
*/
|
||||
assert(!ctx->Extensions.EXT_transform_feedback);
|
||||
} else {
|
||||
lower_packed_varyings(mem_ctx, producer_base, slots_used,
|
||||
ir_var_shader_out, 0, producer);
|
||||
if (producer) {
|
||||
lower_packed_varyings(mem_ctx, slots_used, ir_var_shader_out,
|
||||
0, producer);
|
||||
}
|
||||
if (consumer) {
|
||||
lower_packed_varyings(mem_ctx, consumer_base, slots_used,
|
||||
ir_var_shader_in, gs_input_vertices, consumer);
|
||||
lower_packed_varyings(mem_ctx, slots_used, ir_var_shader_in,
|
||||
gs_input_vertices, consumer);
|
||||
}
|
||||
}
|
||||
|
||||
if (consumer) {
|
||||
foreach_list(node, consumer->ir) {
|
||||
ir_variable *const var = ((ir_instruction *) node)->as_variable();
|
||||
if (consumer && producer) {
|
||||
foreach_in_list(ir_instruction, node, consumer->ir) {
|
||||
ir_variable *const var = node->as_variable();
|
||||
|
||||
if (var && var->data.mode == ir_var_shader_in &&
|
||||
var->data.is_unmatched_generic_inout) {
|
||||
if (prog->Version <= 120) {
|
||||
if (prog->IsES) {
|
||||
/*
|
||||
* On Page 91 (Page 97 of the PDF) of the GLSL ES 1.0 spec:
|
||||
*
|
||||
* If the vertex shader declares but doesn't write to a
|
||||
* varying and the fragment shader declares and reads it,
|
||||
* is this an error?
|
||||
*
|
||||
* RESOLUTION: No.
|
||||
*/
|
||||
linker_warning(prog, "%s shader varying %s not written "
|
||||
"by %s shader\n.",
|
||||
_mesa_shader_stage_to_string(consumer->Stage),
|
||||
var->name,
|
||||
_mesa_shader_stage_to_string(producer->Stage));
|
||||
} else if (prog->Version <= 120) {
|
||||
/* On page 25 (page 31 of the PDF) of the GLSL 1.20 spec:
|
||||
*
|
||||
* Only those varying variables used (i.e. read) in
|
||||
@@ -1214,7 +1485,6 @@ assign_varying_locations(struct gl_context *ctx,
|
||||
* write the variable for the FS to read it. See
|
||||
* "glsl1-varying read but not written" in piglit.
|
||||
*/
|
||||
|
||||
linker_error(prog, "%s shader varying %s not written "
|
||||
"by %s shader\n.",
|
||||
_mesa_shader_stage_to_string(consumer->Stage),
|
||||
@@ -1240,11 +1510,11 @@ check_against_output_limit(struct gl_context *ctx,
|
||||
{
|
||||
unsigned output_vectors = 0;
|
||||
|
||||
foreach_list(node, producer->ir) {
|
||||
ir_variable *const var = ((ir_instruction *) node)->as_variable();
|
||||
foreach_in_list(ir_instruction, node, producer->ir) {
|
||||
ir_variable *const var = node->as_variable();
|
||||
|
||||
if (var && var->data.mode == ir_var_shader_out &&
|
||||
is_varying_var(producer->Stage, var)) {
|
||||
var_counts_against_varying_limit(producer->Stage, var)) {
|
||||
output_vectors += var->type->count_attribute_slots();
|
||||
}
|
||||
}
|
||||
@@ -1279,11 +1549,11 @@ check_against_input_limit(struct gl_context *ctx,
|
||||
{
|
||||
unsigned input_vectors = 0;
|
||||
|
||||
foreach_list(node, consumer->ir) {
|
||||
ir_variable *const var = ((ir_instruction *) node)->as_variable();
|
||||
foreach_in_list(ir_instruction, node, consumer->ir) {
|
||||
ir_variable *const var = node->as_variable();
|
||||
|
||||
if (var && var->data.mode == ir_var_shader_in &&
|
||||
is_varying_var(consumer->Stage, var)) {
|
||||
var_counts_against_varying_limit(consumer->Stage, var)) {
|
||||
input_vectors += var->type->count_attribute_slots();
|
||||
}
|
||||
}
|
||||
|
||||
17
3rdparty/glsl-optimizer/src/glsl/link_varyings.h
vendored
17
3rdparty/glsl-optimizer/src/glsl/link_varyings.h
vendored
@@ -112,6 +112,16 @@ public:
|
||||
return !this->next_buffer_separator && !this->skip_components;
|
||||
}
|
||||
|
||||
const char *name() const
|
||||
{
|
||||
return this->orig_name;
|
||||
}
|
||||
|
||||
unsigned get_stream_id() const
|
||||
{
|
||||
return this->stream_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* The total number of varying components taken up by this variable. Only
|
||||
* valid if assign_location() has been called.
|
||||
@@ -210,6 +220,13 @@ private:
|
||||
* data structure that was found. Otherwise NULL.
|
||||
*/
|
||||
const tfeedback_candidate *matched_candidate;
|
||||
|
||||
/**
|
||||
* StreamId assigned to this varying (defaults to 0). Can only be set to
|
||||
* values other than 0 in geometry shaders that use the stream layout
|
||||
* modifier. Accepted values must be in the range [0, MAX_VERTEX_STREAMS-1].
|
||||
*/
|
||||
unsigned stream_id;
|
||||
};
|
||||
|
||||
|
||||
|
||||
618
3rdparty/glsl-optimizer/src/glsl/linker.cpp
vendored
618
3rdparty/glsl-optimizer/src/glsl/linker.cpp
vendored
@@ -65,6 +65,7 @@
|
||||
*/
|
||||
|
||||
#include "main/core.h"
|
||||
#include "main/errors.h"
|
||||
#include "glsl_symbol_table.h"
|
||||
#include "glsl_parser_extras.h"
|
||||
#include "ir.h"
|
||||
@@ -74,6 +75,7 @@
|
||||
#include "link_varyings.h"
|
||||
#include "ir_optimization.h"
|
||||
#include "ir_rvalue_visitor.h"
|
||||
#include "ir_uniform.h"
|
||||
|
||||
extern "C" {
|
||||
#include "standalone_scaffolding.h"
|
||||
@@ -248,31 +250,100 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Visitor that determines whether or not a shader uses ir_end_primitive.
|
||||
* Visitor that determines the highest stream id to which a (geometry) shader
|
||||
* emits vertices. It also checks whether End{Stream}Primitive is ever called.
|
||||
*/
|
||||
class find_end_primitive_visitor : public ir_hierarchical_visitor {
|
||||
class find_emit_vertex_visitor : public ir_hierarchical_visitor {
|
||||
public:
|
||||
find_end_primitive_visitor()
|
||||
: found(false)
|
||||
find_emit_vertex_visitor(int max_allowed)
|
||||
: max_stream_allowed(max_allowed),
|
||||
invalid_stream_id(0),
|
||||
invalid_stream_id_from_emit_vertex(false),
|
||||
end_primitive_found(false),
|
||||
uses_non_zero_stream(false)
|
||||
{
|
||||
/* empty */
|
||||
}
|
||||
|
||||
virtual ir_visitor_status visit(ir_end_primitive *)
|
||||
virtual ir_visitor_status visit_leave(ir_emit_vertex *ir)
|
||||
{
|
||||
found = true;
|
||||
return visit_stop;
|
||||
int stream_id = ir->stream_id();
|
||||
|
||||
if (stream_id < 0) {
|
||||
invalid_stream_id = stream_id;
|
||||
invalid_stream_id_from_emit_vertex = true;
|
||||
return visit_stop;
|
||||
}
|
||||
|
||||
if (stream_id > max_stream_allowed) {
|
||||
invalid_stream_id = stream_id;
|
||||
invalid_stream_id_from_emit_vertex = true;
|
||||
return visit_stop;
|
||||
}
|
||||
|
||||
if (stream_id != 0)
|
||||
uses_non_zero_stream = true;
|
||||
|
||||
return visit_continue;
|
||||
}
|
||||
|
||||
bool end_primitive_found()
|
||||
virtual ir_visitor_status visit_leave(ir_end_primitive *ir)
|
||||
{
|
||||
return found;
|
||||
end_primitive_found = true;
|
||||
|
||||
int stream_id = ir->stream_id();
|
||||
|
||||
if (stream_id < 0) {
|
||||
invalid_stream_id = stream_id;
|
||||
invalid_stream_id_from_emit_vertex = false;
|
||||
return visit_stop;
|
||||
}
|
||||
|
||||
if (stream_id > max_stream_allowed) {
|
||||
invalid_stream_id = stream_id;
|
||||
invalid_stream_id_from_emit_vertex = false;
|
||||
return visit_stop;
|
||||
}
|
||||
|
||||
if (stream_id != 0)
|
||||
uses_non_zero_stream = true;
|
||||
|
||||
return visit_continue;
|
||||
}
|
||||
|
||||
bool error()
|
||||
{
|
||||
return invalid_stream_id != 0;
|
||||
}
|
||||
|
||||
const char *error_func()
|
||||
{
|
||||
return invalid_stream_id_from_emit_vertex ?
|
||||
"EmitStreamVertex" : "EndStreamPrimitive";
|
||||
}
|
||||
|
||||
int error_stream()
|
||||
{
|
||||
return invalid_stream_id;
|
||||
}
|
||||
|
||||
bool uses_streams()
|
||||
{
|
||||
return uses_non_zero_stream;
|
||||
}
|
||||
|
||||
bool uses_end_primitive()
|
||||
{
|
||||
return end_primitive_found;
|
||||
}
|
||||
|
||||
private:
|
||||
bool found;
|
||||
int max_stream_allowed;
|
||||
int invalid_stream_id;
|
||||
bool invalid_stream_id_from_emit_vertex;
|
||||
bool end_primitive_found;
|
||||
bool uses_non_zero_stream;
|
||||
};
|
||||
|
||||
} /* anonymous namespace */
|
||||
@@ -296,7 +367,7 @@ linker_warning(gl_shader_program *prog, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
ralloc_strcat(&prog->InfoLog, "error: ");
|
||||
ralloc_strcat(&prog->InfoLog, "warning: ");
|
||||
va_start(ap, fmt);
|
||||
ralloc_vasprintf_append(&prog->InfoLog, fmt, ap);
|
||||
va_end(ap);
|
||||
@@ -366,8 +437,8 @@ parse_program_resource_name(const GLchar *name,
|
||||
void
|
||||
link_invalidate_variable_locations(exec_list *ir)
|
||||
{
|
||||
foreach_list(node, ir) {
|
||||
ir_variable *const var = ((ir_instruction *) node)->as_variable();
|
||||
foreach_in_list(ir_instruction, node, ir) {
|
||||
ir_variable *const var = node->as_variable();
|
||||
|
||||
if (var == NULL)
|
||||
continue;
|
||||
@@ -488,14 +559,21 @@ validate_vertex_shader_executable(struct gl_shader_program *prog,
|
||||
* vertex processing has occurred. Its value is undefined if
|
||||
* the vertex shader executable does not write gl_Position."
|
||||
*
|
||||
* GLSL ES 3.00 is similar to GLSL 1.40--failing to write to gl_Position is
|
||||
* not an error.
|
||||
* All GLSL ES Versions are similar to GLSL 1.40--failing to write to
|
||||
* gl_Position is not an error.
|
||||
*/
|
||||
if (prog->Version < (prog->IsES ? 300U : 140U)) {
|
||||
find_assignment_visitor find("gl_Position");
|
||||
find.run(shader->ir);
|
||||
if (!find.variable_found()) {
|
||||
linker_error(prog, "vertex shader does not write to `gl_Position'\n");
|
||||
if (prog->IsES) {
|
||||
linker_warning(prog,
|
||||
"vertex shader does not write to `gl_Position'."
|
||||
"It's value is undefined. \n");
|
||||
} else {
|
||||
linker_error(prog,
|
||||
"vertex shader does not write to `gl_Position'. \n");
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -549,10 +627,58 @@ validate_geometry_shader_executable(struct gl_shader_program *prog,
|
||||
|
||||
analyze_clip_usage(prog, shader, &prog->Geom.UsesClipDistance,
|
||||
&prog->Geom.ClipDistanceArraySize);
|
||||
}
|
||||
|
||||
find_end_primitive_visitor end_primitive;
|
||||
end_primitive.run(shader->ir);
|
||||
prog->Geom.UsesEndPrimitive = end_primitive.end_primitive_found();
|
||||
/**
|
||||
* Check if geometry shaders emit to non-zero streams and do corresponding
|
||||
* validations.
|
||||
*/
|
||||
static void
|
||||
validate_geometry_shader_emissions(struct gl_context *ctx,
|
||||
struct gl_shader_program *prog)
|
||||
{
|
||||
if (prog->_LinkedShaders[MESA_SHADER_GEOMETRY] != NULL) {
|
||||
find_emit_vertex_visitor emit_vertex(ctx->Const.MaxVertexStreams - 1);
|
||||
emit_vertex.run(prog->_LinkedShaders[MESA_SHADER_GEOMETRY]->ir);
|
||||
if (emit_vertex.error()) {
|
||||
linker_error(prog, "Invalid call %s(%d). Accepted values for the "
|
||||
"stream parameter are in the range [0, %d].",
|
||||
emit_vertex.error_func(),
|
||||
emit_vertex.error_stream(),
|
||||
ctx->Const.MaxVertexStreams - 1);
|
||||
}
|
||||
prog->Geom.UsesStreams = emit_vertex.uses_streams();
|
||||
prog->Geom.UsesEndPrimitive = emit_vertex.uses_end_primitive();
|
||||
|
||||
/* From the ARB_gpu_shader5 spec:
|
||||
*
|
||||
* "Multiple vertex streams are supported only if the output primitive
|
||||
* type is declared to be "points". A program will fail to link if it
|
||||
* contains a geometry shader calling EmitStreamVertex() or
|
||||
* EndStreamPrimitive() if its output primitive type is not "points".
|
||||
*
|
||||
* However, in the same spec:
|
||||
*
|
||||
* "The function EmitVertex() is equivalent to calling EmitStreamVertex()
|
||||
* with <stream> set to zero."
|
||||
*
|
||||
* And:
|
||||
*
|
||||
* "The function EndPrimitive() is equivalent to calling
|
||||
* EndStreamPrimitive() with <stream> set to zero."
|
||||
*
|
||||
* Since we can call EmitVertex() and EndPrimitive() when we output
|
||||
* primitives other than points, calling EmitStreamVertex(0) or
|
||||
* EmitEndPrimitive(0) should not produce errors. This it also what Nvidia
|
||||
* does. Currently we only set prog->Geom.UsesStreams to TRUE when
|
||||
* EmitStreamVertex() or EmitEndPrimitive() are called with a non-zero
|
||||
* stream.
|
||||
*/
|
||||
if (prog->Geom.UsesStreams && prog->Geom.OutputType != GL_POINTS) {
|
||||
linker_error(prog, "EmitStreamVertex(n) and EndStreamPrimitive(n) "
|
||||
"with n>0 requires point output");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -573,8 +699,8 @@ cross_validate_globals(struct gl_shader_program *prog,
|
||||
if (shader_list[i] == NULL)
|
||||
continue;
|
||||
|
||||
foreach_list(node, shader_list[i]->ir) {
|
||||
ir_variable *const var = ((ir_instruction *) node)->as_variable();
|
||||
foreach_in_list(ir_instruction, node, shader_list[i]->ir) {
|
||||
ir_variable *const var = node->as_variable();
|
||||
|
||||
if (var == NULL)
|
||||
continue;
|
||||
@@ -843,15 +969,15 @@ populate_symbol_table(gl_shader *sh)
|
||||
{
|
||||
sh->symbols = new(sh) glsl_symbol_table;
|
||||
|
||||
foreach_list(node, sh->ir) {
|
||||
ir_instruction *const inst = (ir_instruction *) node;
|
||||
foreach_in_list(ir_instruction, inst, sh->ir) {
|
||||
ir_variable *var;
|
||||
ir_function *func;
|
||||
|
||||
if ((func = inst->as_function()) != NULL) {
|
||||
sh->symbols->add_function(func);
|
||||
} else if ((var = inst->as_variable()) != NULL) {
|
||||
sh->symbols->add_variable(var);
|
||||
if (var->data.mode != ir_var_temporary)
|
||||
sh->symbols->add_variable(var);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -960,9 +1086,7 @@ move_non_declarations(exec_list *instructions, exec_node *last,
|
||||
temps = hash_table_ctor(0, hash_table_pointer_hash,
|
||||
hash_table_pointer_compare);
|
||||
|
||||
foreach_list_safe(node, instructions) {
|
||||
ir_instruction *inst = (ir_instruction *) node;
|
||||
|
||||
foreach_in_list_safe(ir_instruction, inst, instructions) {
|
||||
if (inst->as_function())
|
||||
continue;
|
||||
|
||||
@@ -1004,8 +1128,8 @@ move_non_declarations(exec_list *instructions, exec_node *last,
|
||||
/**
|
||||
* Get the function signature for main from a shader
|
||||
*/
|
||||
static ir_function_signature *
|
||||
get_main_function_signature(gl_shader *sh)
|
||||
ir_function_signature *
|
||||
link_get_main_function_signature(gl_shader *sh)
|
||||
{
|
||||
ir_function *const f = sh->symbols->get_function("main");
|
||||
if (f != NULL) {
|
||||
@@ -1018,7 +1142,8 @@ get_main_function_signature(gl_shader *sh)
|
||||
* We don't have to check for multiple definitions of main (in multiple
|
||||
* shaders) because that would have already been caught above.
|
||||
*/
|
||||
ir_function_signature *sig = f->matching_signature(NULL, &void_parameters);
|
||||
ir_function_signature *sig =
|
||||
f->matching_signature(NULL, &void_parameters, false);
|
||||
if ((sig != NULL) && sig->is_defined) {
|
||||
return sig;
|
||||
}
|
||||
@@ -1054,7 +1179,8 @@ public:
|
||||
if (var->type->is_interface()) {
|
||||
if (interface_contains_unsized_arrays(var->type)) {
|
||||
const glsl_type *new_type =
|
||||
resize_interface_members(var->type, var->max_ifc_array_access);
|
||||
resize_interface_members(var->type,
|
||||
var->get_max_ifc_array_access());
|
||||
var->type = new_type;
|
||||
var->change_interface_type(new_type);
|
||||
}
|
||||
@@ -1063,7 +1189,7 @@ public:
|
||||
if (interface_contains_unsized_arrays(var->type->fields.array)) {
|
||||
const glsl_type *new_type =
|
||||
resize_interface_members(var->type->fields.array,
|
||||
var->max_ifc_array_access);
|
||||
var->get_max_ifc_array_access());
|
||||
var->change_interface_type(new_type);
|
||||
var->type =
|
||||
glsl_type::get_array_instance(new_type, var->type->length);
|
||||
@@ -1198,6 +1324,83 @@ private:
|
||||
hash_table *unnamed_interfaces;
|
||||
};
|
||||
|
||||
/**
|
||||
* Performs the cross-validation of layout qualifiers specified in
|
||||
* redeclaration of gl_FragCoord for the attached fragment shaders,
|
||||
* and propagates them to the linked FS and linked shader program.
|
||||
*/
|
||||
static void
|
||||
link_fs_input_layout_qualifiers(struct gl_shader_program *prog,
|
||||
struct gl_shader *linked_shader,
|
||||
struct gl_shader **shader_list,
|
||||
unsigned num_shaders)
|
||||
{
|
||||
linked_shader->redeclares_gl_fragcoord = false;
|
||||
linked_shader->uses_gl_fragcoord = false;
|
||||
linked_shader->origin_upper_left = false;
|
||||
linked_shader->pixel_center_integer = false;
|
||||
|
||||
if (linked_shader->Stage != MESA_SHADER_FRAGMENT ||
|
||||
(prog->Version < 150 && !prog->ARB_fragment_coord_conventions_enable))
|
||||
return;
|
||||
|
||||
for (unsigned i = 0; i < num_shaders; i++) {
|
||||
struct gl_shader *shader = shader_list[i];
|
||||
/* From the GLSL 1.50 spec, page 39:
|
||||
*
|
||||
* "If gl_FragCoord is redeclared in any fragment shader in a program,
|
||||
* it must be redeclared in all the fragment shaders in that program
|
||||
* that have a static use gl_FragCoord."
|
||||
*
|
||||
* Exclude the case when one of the 'linked_shader' or 'shader' redeclares
|
||||
* gl_FragCoord with no layout qualifiers but the other one doesn't
|
||||
* redeclare it. If we strictly follow GLSL 1.50 spec's language, it
|
||||
* should be a link error. But, generating link error for this case will
|
||||
* be a wrong behaviour which spec didn't intend to do and it could also
|
||||
* break some applications.
|
||||
*/
|
||||
if ((linked_shader->redeclares_gl_fragcoord
|
||||
&& !shader->redeclares_gl_fragcoord
|
||||
&& shader->uses_gl_fragcoord
|
||||
&& (linked_shader->origin_upper_left
|
||||
|| linked_shader->pixel_center_integer))
|
||||
|| (shader->redeclares_gl_fragcoord
|
||||
&& !linked_shader->redeclares_gl_fragcoord
|
||||
&& linked_shader->uses_gl_fragcoord
|
||||
&& (shader->origin_upper_left
|
||||
|| shader->pixel_center_integer))) {
|
||||
linker_error(prog, "fragment shader defined with conflicting "
|
||||
"layout qualifiers for gl_FragCoord\n");
|
||||
}
|
||||
|
||||
/* From the GLSL 1.50 spec, page 39:
|
||||
*
|
||||
* "All redeclarations of gl_FragCoord in all fragment shaders in a
|
||||
* single program must have the same set of qualifiers."
|
||||
*/
|
||||
if (linked_shader->redeclares_gl_fragcoord && shader->redeclares_gl_fragcoord
|
||||
&& (shader->origin_upper_left != linked_shader->origin_upper_left
|
||||
|| shader->pixel_center_integer != linked_shader->pixel_center_integer)) {
|
||||
linker_error(prog, "fragment shader defined with conflicting "
|
||||
"layout qualifiers for gl_FragCoord\n");
|
||||
}
|
||||
|
||||
/* Update the linked shader state. Note that uses_gl_fragcoord should
|
||||
* accumulate the results. The other values should replace. If there
|
||||
* are multiple redeclarations, all the fields except uses_gl_fragcoord
|
||||
* are already known to be the same.
|
||||
*/
|
||||
if (shader->redeclares_gl_fragcoord || shader->uses_gl_fragcoord) {
|
||||
linked_shader->redeclares_gl_fragcoord =
|
||||
shader->redeclares_gl_fragcoord;
|
||||
linked_shader->uses_gl_fragcoord = linked_shader->uses_gl_fragcoord
|
||||
|| shader->uses_gl_fragcoord;
|
||||
linked_shader->origin_upper_left = shader->origin_upper_left;
|
||||
linked_shader->pixel_center_integer = shader->pixel_center_integer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the cross-validation of geometry shader max_vertices and
|
||||
* primitive type layout qualifiers for the attached geometry shaders,
|
||||
@@ -1210,6 +1413,7 @@ link_gs_inout_layout_qualifiers(struct gl_shader_program *prog,
|
||||
unsigned num_shaders)
|
||||
{
|
||||
linked_shader->Geom.VerticesOut = 0;
|
||||
linked_shader->Geom.Invocations = 0;
|
||||
linked_shader->Geom.InputType = PRIM_UNKNOWN;
|
||||
linked_shader->Geom.OutputType = PRIM_UNKNOWN;
|
||||
|
||||
@@ -1263,6 +1467,18 @@ link_gs_inout_layout_qualifiers(struct gl_shader_program *prog,
|
||||
}
|
||||
linked_shader->Geom.VerticesOut = shader->Geom.VerticesOut;
|
||||
}
|
||||
|
||||
if (shader->Geom.Invocations != 0) {
|
||||
if (linked_shader->Geom.Invocations != 0 &&
|
||||
linked_shader->Geom.Invocations != shader->Geom.Invocations) {
|
||||
linker_error(prog, "geometry shader defined with conflicting "
|
||||
"invocation count (%d and %d)\n",
|
||||
linked_shader->Geom.Invocations,
|
||||
shader->Geom.Invocations);
|
||||
return;
|
||||
}
|
||||
linked_shader->Geom.Invocations = shader->Geom.Invocations;
|
||||
}
|
||||
}
|
||||
|
||||
/* Just do the intrastage -> interstage propagation right now,
|
||||
@@ -1289,6 +1505,11 @@ link_gs_inout_layout_qualifiers(struct gl_shader_program *prog,
|
||||
return;
|
||||
}
|
||||
prog->Geom.VerticesOut = linked_shader->Geom.VerticesOut;
|
||||
|
||||
if (linked_shader->Geom.Invocations == 0)
|
||||
linked_shader->Geom.Invocations = 1;
|
||||
|
||||
prog->Geom.Invocations = linked_shader->Geom.Invocations;
|
||||
}
|
||||
|
||||
|
||||
@@ -1387,13 +1608,15 @@ link_intrastage_shaders(void *mem_ctx,
|
||||
const unsigned num_uniform_blocks =
|
||||
link_uniform_blocks(mem_ctx, prog, shader_list, num_shaders,
|
||||
&uniform_blocks);
|
||||
if (!prog->LinkStatus)
|
||||
return NULL;
|
||||
|
||||
/* Check that there is only a single definition of each function signature
|
||||
* across all shaders.
|
||||
*/
|
||||
for (unsigned i = 0; i < (num_shaders - 1); i++) {
|
||||
foreach_list(node, shader_list[i]->ir) {
|
||||
ir_function *const f = ((ir_instruction *) node)->as_function();
|
||||
foreach_in_list(ir_instruction, node, shader_list[i]->ir) {
|
||||
ir_function *const f = node->as_function();
|
||||
|
||||
if (f == NULL)
|
||||
continue;
|
||||
@@ -1408,9 +1631,7 @@ link_intrastage_shaders(void *mem_ctx,
|
||||
if (other == NULL)
|
||||
continue;
|
||||
|
||||
foreach_list(n, &f->signatures) {
|
||||
ir_function_signature *sig = (ir_function_signature *) n;
|
||||
|
||||
foreach_in_list(ir_function_signature, sig, &f->signatures) {
|
||||
if (!sig->is_defined || sig->is_builtin())
|
||||
continue;
|
||||
|
||||
@@ -1437,7 +1658,7 @@ link_intrastage_shaders(void *mem_ctx,
|
||||
*/
|
||||
gl_shader *main = NULL;
|
||||
for (unsigned i = 0; i < num_shaders; i++) {
|
||||
if (get_main_function_signature(shader_list[i]) != NULL) {
|
||||
if (link_get_main_function_signature(shader_list[i]) != NULL) {
|
||||
main = shader_list[i];
|
||||
break;
|
||||
}
|
||||
@@ -1457,6 +1678,7 @@ link_intrastage_shaders(void *mem_ctx,
|
||||
linked->NumUniformBlocks = num_uniform_blocks;
|
||||
ralloc_steal(linked, linked->UniformBlocks);
|
||||
|
||||
link_fs_input_layout_qualifiers(prog, linked, shader_list, num_shaders);
|
||||
link_gs_inout_layout_qualifiers(prog, linked, shader_list, num_shaders);
|
||||
link_cs_input_layout_qualifiers(prog, linked, shader_list, num_shaders);
|
||||
|
||||
@@ -1465,7 +1687,8 @@ link_intrastage_shaders(void *mem_ctx,
|
||||
/* The a pointer to the main function in the final linked shader (i.e., the
|
||||
* copy of the original shader that contained the main function).
|
||||
*/
|
||||
ir_function_signature *const main_sig = get_main_function_signature(linked);
|
||||
ir_function_signature *const main_sig =
|
||||
link_get_main_function_signature(linked);
|
||||
|
||||
/* Move any instructions other than variable declarations, function
|
||||
* declarations or precision statements into main.
|
||||
@@ -1498,12 +1721,19 @@ link_intrastage_shaders(void *mem_ctx,
|
||||
*/
|
||||
gl_shader **linking_shaders = (gl_shader **)
|
||||
calloc(num_shaders + 1, sizeof(gl_shader *));
|
||||
memcpy(linking_shaders, shader_list, num_shaders * sizeof(gl_shader *));
|
||||
linking_shaders[num_shaders] = _mesa_glsl_get_builtin_function_shader();
|
||||
|
||||
ok = link_function_calls(prog, linked, linking_shaders, num_shaders + 1);
|
||||
ok = linking_shaders != NULL;
|
||||
|
||||
free(linking_shaders);
|
||||
if (ok) {
|
||||
memcpy(linking_shaders, shader_list, num_shaders * sizeof(gl_shader *));
|
||||
linking_shaders[num_shaders] = _mesa_glsl_get_builtin_function_shader();
|
||||
|
||||
ok = link_function_calls(prog, linked, linking_shaders, num_shaders + 1);
|
||||
|
||||
free(linking_shaders);
|
||||
} else {
|
||||
_mesa_error_no_memory(__func__);
|
||||
}
|
||||
} else {
|
||||
ok = link_function_calls(prog, linked, shader_list, num_shaders);
|
||||
}
|
||||
@@ -1523,12 +1753,14 @@ link_intrastage_shaders(void *mem_ctx,
|
||||
if (linked->Stage == MESA_SHADER_GEOMETRY) {
|
||||
unsigned num_vertices = vertices_per_prim(prog->Geom.InputType);
|
||||
geom_array_resize_visitor input_resize_visitor(num_vertices, prog);
|
||||
foreach_list(n, linked->ir) {
|
||||
ir_instruction *ir = (ir_instruction *) n;
|
||||
foreach_in_list(ir_instruction, ir, linked->ir) {
|
||||
ir->accept(&input_resize_visitor);
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx->Const.VertexID_is_zero_based)
|
||||
lower_vertex_id(linked);
|
||||
|
||||
/* Make a pass over all variable declarations to ensure that arrays with
|
||||
* unspecified sizes have a size specified. The size is inferred from the
|
||||
* max_array_access field.
|
||||
@@ -1562,8 +1794,8 @@ update_array_sizes(struct gl_shader_program *prog)
|
||||
if (prog->_LinkedShaders[i] == NULL)
|
||||
continue;
|
||||
|
||||
foreach_list(node, prog->_LinkedShaders[i]->ir) {
|
||||
ir_variable *const var = ((ir_instruction *) node)->as_variable();
|
||||
foreach_in_list(ir_instruction, node, prog->_LinkedShaders[i]->ir) {
|
||||
ir_variable *const var = node->as_variable();
|
||||
|
||||
if ((var == NULL) || (var->data.mode != ir_var_uniform) ||
|
||||
!var->type->is_array())
|
||||
@@ -1585,8 +1817,8 @@ update_array_sizes(struct gl_shader_program *prog)
|
||||
if (prog->_LinkedShaders[j] == NULL)
|
||||
continue;
|
||||
|
||||
foreach_list(node2, prog->_LinkedShaders[j]->ir) {
|
||||
ir_variable *other_var = ((ir_instruction *) node2)->as_variable();
|
||||
foreach_in_list(ir_instruction, node2, prog->_LinkedShaders[j]->ir) {
|
||||
ir_variable *other_var = node2->as_variable();
|
||||
if (!other_var)
|
||||
continue;
|
||||
|
||||
@@ -1606,9 +1838,10 @@ update_array_sizes(struct gl_shader_program *prog)
|
||||
* Determine the number of slots per array element by dividing by
|
||||
* the old (total) size.
|
||||
*/
|
||||
if (var->num_state_slots > 0) {
|
||||
var->num_state_slots = (size + 1)
|
||||
* (var->num_state_slots / var->type->length);
|
||||
const unsigned num_slots = var->get_num_state_slots();
|
||||
if (num_slots > 0) {
|
||||
var->set_num_state_slots((size + 1)
|
||||
* (num_slots / var->type->length));
|
||||
}
|
||||
|
||||
var->type = glsl_type::get_array_instance(var->type->fields.array,
|
||||
@@ -1728,8 +1961,8 @@ assign_attribute_or_color_locations(gl_shader_program *prog,
|
||||
|
||||
unsigned num_attr = 0;
|
||||
|
||||
foreach_list(node, sh->ir) {
|
||||
ir_variable *const var = ((ir_instruction *) node)->as_variable();
|
||||
foreach_in_list(ir_instruction, node, sh->ir) {
|
||||
ir_variable *const var = node->as_variable();
|
||||
|
||||
if ((var == NULL) || (var->data.mode != (unsigned) direction))
|
||||
continue;
|
||||
@@ -1784,10 +2017,12 @@ assign_attribute_or_color_locations(gl_shader_program *prog,
|
||||
* active attribute array, both of which require multiple
|
||||
* contiguous generic attributes."
|
||||
*
|
||||
* Previous versions of the spec contain similar language but omit
|
||||
* the bit about attribute arrays.
|
||||
* I think above text prohibits the aliasing of explicit and
|
||||
* automatic assignments. But, aliasing is allowed in manual
|
||||
* assignments of attribute locations. See below comments for
|
||||
* the details.
|
||||
*
|
||||
* Page 61 of the OpenGL 4.0 spec also says:
|
||||
* From OpenGL 4.0 spec, page 61:
|
||||
*
|
||||
* "It is possible for an application to bind more than one
|
||||
* attribute name to the same location. This is referred to as
|
||||
@@ -1800,29 +2035,84 @@ assign_attribute_or_color_locations(gl_shader_program *prog,
|
||||
* but implementations are not required to generate an error
|
||||
* in this case."
|
||||
*
|
||||
* These two paragraphs are either somewhat contradictory, or I
|
||||
* don't fully understand one or both of them.
|
||||
*/
|
||||
/* FINISHME: The code as currently written does not support
|
||||
* FINISHME: attribute location aliasing (see comment above).
|
||||
* From GLSL 4.30 spec, page 54:
|
||||
*
|
||||
* "A program will fail to link if any two non-vertex shader
|
||||
* input variables are assigned to the same location. For
|
||||
* vertex shaders, multiple input variables may be assigned
|
||||
* to the same location using either layout qualifiers or via
|
||||
* the OpenGL API. However, such aliasing is intended only to
|
||||
* support vertex shaders where each execution path accesses
|
||||
* at most one input per each location. Implementations are
|
||||
* permitted, but not required, to generate link-time errors
|
||||
* if they detect that every path through the vertex shader
|
||||
* executable accesses multiple inputs assigned to any single
|
||||
* location. For all shader types, a program will fail to link
|
||||
* if explicit location assignments leave the linker unable
|
||||
* to find space for other variables without explicit
|
||||
* assignments."
|
||||
*
|
||||
* From OpenGL ES 3.0 spec, page 56:
|
||||
*
|
||||
* "Binding more than one attribute name to the same location
|
||||
* is referred to as aliasing, and is not permitted in OpenGL
|
||||
* ES Shading Language 3.00 vertex shaders. LinkProgram will
|
||||
* fail when this condition exists. However, aliasing is
|
||||
* possible in OpenGL ES Shading Language 1.00 vertex shaders.
|
||||
* This will only work if only one of the aliased attributes
|
||||
* is active in the executable program, or if no path through
|
||||
* the shader consumes more than one attribute of a set of
|
||||
* attributes aliased to the same location. A link error can
|
||||
* occur if the linker determines that every path through the
|
||||
* shader consumes multiple aliased attributes, but implemen-
|
||||
* tations are not required to generate an error in this case."
|
||||
*
|
||||
* After looking at above references from OpenGL, OpenGL ES and
|
||||
* GLSL specifications, we allow aliasing of vertex input variables
|
||||
* in: OpenGL 2.0 (and above) and OpenGL ES 2.0.
|
||||
*
|
||||
* NOTE: This is not required by the spec but its worth mentioning
|
||||
* here that we're not doing anything to make sure that no path
|
||||
* through the vertex shader executable accesses multiple inputs
|
||||
* assigned to any single location.
|
||||
*/
|
||||
|
||||
/* Mask representing the contiguous slots that will be used by
|
||||
* this attribute.
|
||||
*/
|
||||
const unsigned attr = var->data.location - generic_base;
|
||||
const unsigned use_mask = (1 << slots) - 1;
|
||||
const char *const string = (target_index == MESA_SHADER_VERTEX)
|
||||
? "vertex shader input" : "fragment shader output";
|
||||
|
||||
/* Generate a link error if the requested locations for this
|
||||
* attribute exceed the maximum allowed attribute location.
|
||||
*/
|
||||
if (attr + slots > max_index) {
|
||||
linker_error(prog,
|
||||
"insufficient contiguous locations "
|
||||
"available for %s `%s' %d %d %d", string,
|
||||
var->name, used_locations, use_mask, attr);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Generate a link error if the set of bits requested for this
|
||||
* attribute overlaps any previously allocated bits.
|
||||
*/
|
||||
if ((~(use_mask << attr) & used_locations) != used_locations) {
|
||||
const char *const string = (target_index == MESA_SHADER_VERTEX)
|
||||
? "vertex shader input" : "fragment shader output";
|
||||
linker_error(prog,
|
||||
"insufficient contiguous locations "
|
||||
"available for %s `%s' %d %d %d", string,
|
||||
var->name, used_locations, use_mask, attr);
|
||||
return false;
|
||||
if (target_index == MESA_SHADER_FRAGMENT ||
|
||||
(prog->IsES && prog->Version >= 300)) {
|
||||
linker_error(prog,
|
||||
"overlapping location is assigned "
|
||||
"to %s `%s' %d %d %d\n", string,
|
||||
var->name, used_locations, use_mask, attr);
|
||||
return false;
|
||||
} else {
|
||||
linker_warning(prog,
|
||||
"overlapping location is assigned "
|
||||
"to %s `%s' %d %d %d\n", string,
|
||||
var->name, used_locations, use_mask, attr);
|
||||
}
|
||||
}
|
||||
|
||||
used_locations |= (use_mask << attr);
|
||||
@@ -1890,8 +2180,8 @@ assign_attribute_or_color_locations(gl_shader_program *prog,
|
||||
void
|
||||
demote_shader_inputs_and_outputs(gl_shader *sh, enum ir_variable_mode mode)
|
||||
{
|
||||
foreach_list(node, sh->ir) {
|
||||
ir_variable *const var = ((ir_instruction *) node)->as_variable();
|
||||
foreach_in_list(ir_instruction, node, sh->ir) {
|
||||
ir_variable *const var = node->as_variable();
|
||||
|
||||
if ((var == NULL) || (var->data.mode != int(mode)))
|
||||
continue;
|
||||
@@ -1901,6 +2191,7 @@ demote_shader_inputs_and_outputs(gl_shader *sh, enum ir_variable_mode mode)
|
||||
* to have a location assigned.
|
||||
*/
|
||||
if (var->data.is_unmatched_generic_inout) {
|
||||
assert(var->data.mode != ir_var_temporary);
|
||||
var->data.mode = ir_var_auto;
|
||||
}
|
||||
}
|
||||
@@ -1926,8 +2217,8 @@ store_fragdepth_layout(struct gl_shader_program *prog)
|
||||
* We're only interested in the cases where the variable is NOT removed
|
||||
* from the IR.
|
||||
*/
|
||||
foreach_list(node, ir) {
|
||||
ir_variable *const var = ((ir_instruction *) node)->as_variable();
|
||||
foreach_in_list(ir_instruction, node, ir) {
|
||||
ir_variable *const var = node->as_variable();
|
||||
|
||||
if (var == NULL || var->data.mode != ir_var_shader_out) {
|
||||
continue;
|
||||
@@ -2058,8 +2349,8 @@ check_image_resources(struct gl_context *ctx, struct gl_shader_program *prog)
|
||||
total_image_units += sh->NumImages;
|
||||
|
||||
if (i == MESA_SHADER_FRAGMENT) {
|
||||
foreach_list(node, sh->ir) {
|
||||
ir_variable *var = ((ir_instruction *)node)->as_variable();
|
||||
foreach_in_list(ir_instruction, node, sh->ir) {
|
||||
ir_variable *var = node->as_variable();
|
||||
if (var && var->data.mode == ir_var_shader_out)
|
||||
fragment_outputs += var->type->count_attribute_slots();
|
||||
}
|
||||
@@ -2075,6 +2366,117 @@ check_image_resources(struct gl_context *ctx, struct gl_shader_program *prog)
|
||||
linker_error(prog, "Too many combined image uniforms and fragment outputs");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initializes explicit location slots to INACTIVE_UNIFORM_EXPLICIT_LOCATION
|
||||
* for a variable, checks for overlaps between other uniforms using explicit
|
||||
* locations.
|
||||
*/
|
||||
static bool
|
||||
reserve_explicit_locations(struct gl_shader_program *prog,
|
||||
string_to_uint_map *map, ir_variable *var)
|
||||
{
|
||||
unsigned slots = var->type->uniform_locations();
|
||||
unsigned max_loc = var->data.location + slots - 1;
|
||||
|
||||
/* Resize remap table if locations do not fit in the current one. */
|
||||
if (max_loc + 1 > prog->NumUniformRemapTable) {
|
||||
prog->UniformRemapTable =
|
||||
reralloc(prog, prog->UniformRemapTable,
|
||||
gl_uniform_storage *,
|
||||
max_loc + 1);
|
||||
|
||||
if (!prog->UniformRemapTable) {
|
||||
linker_error(prog, "Out of memory during linking.");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Initialize allocated space. */
|
||||
for (unsigned i = prog->NumUniformRemapTable; i < max_loc + 1; i++)
|
||||
prog->UniformRemapTable[i] = NULL;
|
||||
|
||||
prog->NumUniformRemapTable = max_loc + 1;
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < slots; i++) {
|
||||
unsigned loc = var->data.location + i;
|
||||
|
||||
/* Check if location is already used. */
|
||||
if (prog->UniformRemapTable[loc] == INACTIVE_UNIFORM_EXPLICIT_LOCATION) {
|
||||
|
||||
/* Possibly same uniform from a different stage, this is ok. */
|
||||
unsigned hash_loc;
|
||||
if (map->get(hash_loc, var->name) && hash_loc == loc - i)
|
||||
continue;
|
||||
|
||||
/* ARB_explicit_uniform_location specification states:
|
||||
*
|
||||
* "No two default-block uniform variables in the program can have
|
||||
* the same location, even if they are unused, otherwise a compiler
|
||||
* or linker error will be generated."
|
||||
*/
|
||||
linker_error(prog,
|
||||
"location qualifier for uniform %s overlaps"
|
||||
"previously used location",
|
||||
var->name);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Initialize location as inactive before optimization
|
||||
* rounds and location assignment.
|
||||
*/
|
||||
prog->UniformRemapTable[loc] = INACTIVE_UNIFORM_EXPLICIT_LOCATION;
|
||||
}
|
||||
|
||||
/* Note, base location used for arrays. */
|
||||
map->put(var->data.location, var->name);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check and reserve all explicit uniform locations, called before
|
||||
* any optimizations happen to handle also inactive uniforms and
|
||||
* inactive array elements that may get trimmed away.
|
||||
*/
|
||||
static void
|
||||
check_explicit_uniform_locations(struct gl_context *ctx,
|
||||
struct gl_shader_program *prog)
|
||||
{
|
||||
if (!ctx->Extensions.ARB_explicit_uniform_location)
|
||||
return;
|
||||
|
||||
/* This map is used to detect if overlapping explicit locations
|
||||
* occur with the same uniform (from different stage) or a different one.
|
||||
*/
|
||||
string_to_uint_map *uniform_map = new string_to_uint_map;
|
||||
|
||||
if (!uniform_map) {
|
||||
linker_error(prog, "Out of memory during linking.");
|
||||
return;
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
|
||||
struct gl_shader *sh = prog->_LinkedShaders[i];
|
||||
|
||||
if (!sh)
|
||||
continue;
|
||||
|
||||
foreach_in_list(ir_instruction, node, sh->ir) {
|
||||
ir_variable *var = node->as_variable();
|
||||
if ((var && var->data.mode == ir_var_uniform) &&
|
||||
var->data.explicit_location) {
|
||||
if (!reserve_explicit_locations(prog, uniform_map, var)) {
|
||||
delete uniform_map;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete uniform_map;
|
||||
}
|
||||
|
||||
void
|
||||
link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
|
||||
{
|
||||
@@ -2101,6 +2503,7 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
|
||||
ralloc_free(prog->AtomicBuffers);
|
||||
prog->AtomicBuffers = NULL;
|
||||
prog->NumAtomicBuffers = 0;
|
||||
prog->ARB_fragment_coord_conventions_enable = false;
|
||||
|
||||
/* Separate the shaders into groups based on their type.
|
||||
*/
|
||||
@@ -2127,6 +2530,9 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
|
||||
goto done;
|
||||
}
|
||||
|
||||
prog->ARB_fragment_coord_conventions_enable |=
|
||||
prog->Shaders[i]->ARB_fragment_coord_conventions_enable;
|
||||
|
||||
gl_shader_stage shader_type = prog->Shaders[i]->Stage;
|
||||
shader_list[shader_type][num_shaders[shader_type]] = prog->Shaders[i];
|
||||
num_shaders[shader_type]++;
|
||||
@@ -2147,7 +2553,8 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
|
||||
/* Geometry shaders have to be linked with vertex shaders.
|
||||
*/
|
||||
if (num_shaders[MESA_SHADER_GEOMETRY] > 0 &&
|
||||
num_shaders[MESA_SHADER_VERTEX] == 0) {
|
||||
num_shaders[MESA_SHADER_VERTEX] == 0 &&
|
||||
!prog->SeparateShader) {
|
||||
linker_error(prog, "Geometry shader must be linked with "
|
||||
"vertex shader\n");
|
||||
goto done;
|
||||
@@ -2218,6 +2625,10 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
|
||||
break;
|
||||
}
|
||||
|
||||
check_explicit_uniform_locations(ctx, prog);
|
||||
if (!prog->LinkStatus)
|
||||
goto done;
|
||||
|
||||
/* Validate the inputs of each stage with the output of the preceding
|
||||
* stage.
|
||||
*/
|
||||
@@ -2278,28 +2689,24 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
|
||||
if (!prog->LinkStatus)
|
||||
goto done;
|
||||
|
||||
if (ctx->ShaderCompilerOptions[i].LowerClipDistance) {
|
||||
if (ctx->Const.ShaderCompilerOptions[i].LowerClipDistance) {
|
||||
lower_clip_distance(prog->_LinkedShaders[i]);
|
||||
}
|
||||
|
||||
unsigned max_unroll = ctx->ShaderCompilerOptions[i].MaxUnrollIterations;
|
||||
|
||||
while (do_common_optimization(prog->_LinkedShaders[i]->ir, true, false, max_unroll, &ctx->ShaderCompilerOptions[i]))
|
||||
while (do_common_optimization(prog->_LinkedShaders[i]->ir, true, false,
|
||||
&ctx->Const.ShaderCompilerOptions[i],
|
||||
ctx->Const.NativeIntegers))
|
||||
;
|
||||
}
|
||||
|
||||
/* Check and validate stream emissions in geometry shaders */
|
||||
validate_geometry_shader_emissions(ctx, prog);
|
||||
|
||||
/* Mark all generic shader inputs and outputs as unpaired. */
|
||||
if (prog->_LinkedShaders[MESA_SHADER_VERTEX] != NULL) {
|
||||
link_invalidate_variable_locations(
|
||||
prog->_LinkedShaders[MESA_SHADER_VERTEX]->ir);
|
||||
}
|
||||
if (prog->_LinkedShaders[MESA_SHADER_GEOMETRY] != NULL) {
|
||||
link_invalidate_variable_locations(
|
||||
prog->_LinkedShaders[MESA_SHADER_GEOMETRY]->ir);
|
||||
}
|
||||
if (prog->_LinkedShaders[MESA_SHADER_FRAGMENT] != NULL) {
|
||||
link_invalidate_variable_locations(
|
||||
prog->_LinkedShaders[MESA_SHADER_FRAGMENT]->ir);
|
||||
for (unsigned i = MESA_SHADER_VERTEX; i <= MESA_SHADER_FRAGMENT; i++) {
|
||||
if (prog->_LinkedShaders[i] != NULL) {
|
||||
link_invalidate_variable_locations(prog->_LinkedShaders[i]->ir);
|
||||
}
|
||||
}
|
||||
|
||||
/* FINISHME: The value of the max_attribute_index parameter is
|
||||
@@ -2356,7 +2763,7 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
|
||||
if (last >= 0 && last < MESA_SHADER_FRAGMENT) {
|
||||
gl_shader *const sh = prog->_LinkedShaders[last];
|
||||
|
||||
if (num_tfeedback_decls != 0) {
|
||||
if (num_tfeedback_decls != 0 || prog->SeparateShader) {
|
||||
/* There was no fragment shader, but we still have to assign varying
|
||||
* locations for use by transform feedback.
|
||||
*/
|
||||
@@ -2370,7 +2777,8 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
|
||||
do_dead_builtin_varyings(ctx, sh, NULL,
|
||||
num_tfeedback_decls, tfeedback_decls);
|
||||
|
||||
demote_shader_inputs_and_outputs(sh, ir_var_shader_out);
|
||||
if (!prog->SeparateShader)
|
||||
demote_shader_inputs_and_outputs(sh, ir_var_shader_out);
|
||||
|
||||
/* Eliminate code that is now dead due to unused outputs being demoted.
|
||||
*/
|
||||
@@ -2385,7 +2793,16 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
|
||||
do_dead_builtin_varyings(ctx, NULL, sh,
|
||||
num_tfeedback_decls, tfeedback_decls);
|
||||
|
||||
demote_shader_inputs_and_outputs(sh, ir_var_shader_in);
|
||||
if (prog->SeparateShader) {
|
||||
if (!assign_varying_locations(ctx, mem_ctx, prog,
|
||||
NULL /* producer */,
|
||||
sh /* consumer */,
|
||||
0 /* num_tfeedback_decls */,
|
||||
NULL /* tfeedback_decls */,
|
||||
0 /* gs_input_vertices */))
|
||||
goto done;
|
||||
} else
|
||||
demote_shader_inputs_and_outputs(sh, ir_var_shader_in);
|
||||
|
||||
while (do_dead_code(sh->ir, false))
|
||||
;
|
||||
@@ -2433,7 +2850,7 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
|
||||
goto done;
|
||||
|
||||
update_array_sizes(prog);
|
||||
link_assign_uniform_locations(prog);
|
||||
link_assign_uniform_locations(prog, ctx->Const.UniformBooleanTrue);
|
||||
link_assign_atomic_counter_resources(ctx, prog);
|
||||
store_fragdepth_layout(prog);
|
||||
|
||||
@@ -2445,11 +2862,12 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
|
||||
goto done;
|
||||
|
||||
/* OpenGL ES requires that a vertex shader and a fragment shader both be
|
||||
* present in a linked program. By checking prog->IsES, we also
|
||||
* catch the GL_ARB_ES2_compatibility case.
|
||||
* present in a linked program. GL_ARB_ES2_compatibility doesn't say
|
||||
* anything about shader linking when one of the shaders (vertex or
|
||||
* fragment shader) is absent. So, the extension shouldn't change the
|
||||
* behavior specified in GLSL specification.
|
||||
*/
|
||||
if (!prog->InternalSeparateShader &&
|
||||
(ctx->API == API_OPENGLES2 || prog->IsES)) {
|
||||
if (!prog->SeparateShader && ctx->API == API_OPENGLES2) {
|
||||
if (prog->_LinkedShaders[MESA_SHADER_VERTEX] == NULL) {
|
||||
linker_error(prog, "program lacks a vertex shader\n");
|
||||
} else if (prog->_LinkedShaders[MESA_SHADER_FRAGMENT] == NULL) {
|
||||
|
||||
24
3rdparty/glsl-optimizer/src/glsl/linker.h
vendored
24
3rdparty/glsl-optimizer/src/glsl/linker.h
vendored
@@ -26,6 +26,9 @@
|
||||
#ifndef GLSL_LINKER_H
|
||||
#define GLSL_LINKER_H
|
||||
|
||||
ir_function_signature *
|
||||
link_get_main_function_signature(gl_shader *sh);
|
||||
|
||||
extern bool
|
||||
link_function_calls(gl_shader_program *prog, gl_shader *main,
|
||||
gl_shader **shader_list, unsigned num_shaders);
|
||||
@@ -34,10 +37,12 @@ extern void
|
||||
link_invalidate_variable_locations(exec_list *ir);
|
||||
|
||||
extern void
|
||||
link_assign_uniform_locations(struct gl_shader_program *prog);
|
||||
link_assign_uniform_locations(struct gl_shader_program *prog,
|
||||
unsigned int boolean_true);
|
||||
|
||||
extern void
|
||||
link_set_uniform_initializers(struct gl_shader_program *prog);
|
||||
link_set_uniform_initializers(struct gl_shader_program *prog,
|
||||
unsigned int boolean_true);
|
||||
|
||||
extern int
|
||||
link_cross_validate_uniform_block(void *mem_ctx,
|
||||
@@ -45,9 +50,6 @@ link_cross_validate_uniform_block(void *mem_ctx,
|
||||
unsigned int *num_linked_blocks,
|
||||
struct gl_uniform_block *new_block);
|
||||
|
||||
void
|
||||
link_assign_uniform_block_offsets(struct gl_shader *shader);
|
||||
|
||||
extern bool
|
||||
link_uniform_blocks_are_compatible(const gl_uniform_block *a,
|
||||
const gl_uniform_block *b);
|
||||
@@ -138,11 +140,15 @@ protected:
|
||||
* \param name Fully qualified name of the field.
|
||||
* \param row_major For a matrix type, is it stored row-major.
|
||||
* \param record_type Type of the record containing the field.
|
||||
* \param last_field Set if \c name is the last field of the structure
|
||||
* containing it. This will always be false for items
|
||||
* not contained in a structure or interface block.
|
||||
*
|
||||
* The default implementation just calls the other \c visit_field method.
|
||||
*/
|
||||
virtual void visit_field(const glsl_type *type, const char *name,
|
||||
bool row_major, const glsl_type *record_type);
|
||||
bool row_major, const glsl_type *record_type,
|
||||
bool last_field);
|
||||
|
||||
/**
|
||||
* Method invoked for each leaf of the variable
|
||||
@@ -168,9 +174,13 @@ private:
|
||||
/**
|
||||
* \param name_length Length of the current name \b not including the
|
||||
* terminating \c NUL character.
|
||||
* \param last_field Set if \c name is the last field of the structure
|
||||
* containing it. This will always be false for items
|
||||
* not contained in a structure or interface block.
|
||||
*/
|
||||
void recursion(const glsl_type *t, char **name, size_t name_length,
|
||||
bool row_major, const glsl_type *record_type);
|
||||
bool row_major, const glsl_type *record_type,
|
||||
bool last_field);
|
||||
};
|
||||
|
||||
extern struct gl_shader *
|
||||
|
||||
641
3rdparty/glsl-optimizer/src/glsl/list.h
vendored
641
3rdparty/glsl-optimizer/src/glsl/list.h
vendored
@@ -69,7 +69,7 @@
|
||||
#endif
|
||||
#include <assert.h>
|
||||
|
||||
#include "ralloc.h"
|
||||
#include "util/ralloc.h"
|
||||
|
||||
struct exec_node {
|
||||
struct exec_node *next;
|
||||
@@ -83,67 +83,29 @@ struct exec_node {
|
||||
/* empty */
|
||||
}
|
||||
|
||||
const exec_node *get_next() const
|
||||
{
|
||||
return next;
|
||||
}
|
||||
const exec_node *get_next() const;
|
||||
exec_node *get_next();
|
||||
|
||||
exec_node *get_next()
|
||||
{
|
||||
return next;
|
||||
}
|
||||
const exec_node *get_prev() const;
|
||||
exec_node *get_prev();
|
||||
|
||||
const exec_node *get_prev() const
|
||||
{
|
||||
return prev;
|
||||
}
|
||||
|
||||
exec_node *get_prev()
|
||||
{
|
||||
return prev;
|
||||
}
|
||||
|
||||
void remove()
|
||||
{
|
||||
next->prev = prev;
|
||||
prev->next = next;
|
||||
next = NULL;
|
||||
prev = NULL;
|
||||
}
|
||||
void remove();
|
||||
|
||||
/**
|
||||
* Link a node with itself
|
||||
*
|
||||
* This creates a sort of degenerate list that is occasionally useful.
|
||||
*/
|
||||
void self_link()
|
||||
{
|
||||
next = this;
|
||||
prev = this;
|
||||
}
|
||||
void self_link();
|
||||
|
||||
/**
|
||||
* Insert a node in the list after the current node
|
||||
*/
|
||||
void insert_after(exec_node *after)
|
||||
{
|
||||
after->next = this->next;
|
||||
after->prev = this;
|
||||
|
||||
this->next->prev = after;
|
||||
this->next = after;
|
||||
}
|
||||
void insert_after(exec_node *after);
|
||||
/**
|
||||
* Insert a node in the list before the current node
|
||||
*/
|
||||
void insert_before(exec_node *before)
|
||||
{
|
||||
before->next = this;
|
||||
before->prev = this->prev;
|
||||
|
||||
this->prev->next = before;
|
||||
this->prev = before;
|
||||
}
|
||||
void insert_before(exec_node *before);
|
||||
|
||||
/**
|
||||
* Insert another list in the list before the current node
|
||||
@@ -153,33 +115,165 @@ struct exec_node {
|
||||
/**
|
||||
* Replace the current node with the given node.
|
||||
*/
|
||||
void replace_with(exec_node *replacement)
|
||||
{
|
||||
replacement->prev = this->prev;
|
||||
replacement->next = this->next;
|
||||
|
||||
this->prev->next = replacement;
|
||||
this->next->prev = replacement;
|
||||
}
|
||||
void replace_with(exec_node *replacement);
|
||||
|
||||
/**
|
||||
* Is this the sentinel at the tail of the list?
|
||||
*/
|
||||
bool is_tail_sentinel() const
|
||||
{
|
||||
return this->next == NULL;
|
||||
}
|
||||
bool is_tail_sentinel() const;
|
||||
|
||||
/**
|
||||
* Is this the sentinel at the head of the list?
|
||||
*/
|
||||
bool is_head_sentinel() const
|
||||
{
|
||||
return this->prev == NULL;
|
||||
}
|
||||
bool is_head_sentinel() const;
|
||||
#endif
|
||||
};
|
||||
|
||||
static inline void
|
||||
exec_node_init(struct exec_node *n)
|
||||
{
|
||||
n->next = NULL;
|
||||
n->prev = NULL;
|
||||
}
|
||||
|
||||
static inline const struct exec_node *
|
||||
exec_node_get_next_const(const struct exec_node *n)
|
||||
{
|
||||
return n->next;
|
||||
}
|
||||
|
||||
static inline struct exec_node *
|
||||
exec_node_get_next(struct exec_node *n)
|
||||
{
|
||||
return n->next;
|
||||
}
|
||||
|
||||
static inline const struct exec_node *
|
||||
exec_node_get_prev_const(const struct exec_node *n)
|
||||
{
|
||||
return n->prev;
|
||||
}
|
||||
|
||||
static inline struct exec_node *
|
||||
exec_node_get_prev(struct exec_node *n)
|
||||
{
|
||||
return n->prev;
|
||||
}
|
||||
|
||||
static inline void
|
||||
exec_node_remove(struct exec_node *n)
|
||||
{
|
||||
n->next->prev = n->prev;
|
||||
n->prev->next = n->next;
|
||||
n->next = NULL;
|
||||
n->prev = NULL;
|
||||
}
|
||||
|
||||
static inline void
|
||||
exec_node_self_link(struct exec_node *n)
|
||||
{
|
||||
n->next = n;
|
||||
n->prev = n;
|
||||
}
|
||||
|
||||
static inline void
|
||||
exec_node_insert_after(struct exec_node *n, struct exec_node *after)
|
||||
{
|
||||
after->next = n->next;
|
||||
after->prev = n;
|
||||
|
||||
n->next->prev = after;
|
||||
n->next = after;
|
||||
}
|
||||
|
||||
static inline void
|
||||
exec_node_insert_node_before(struct exec_node *n, struct exec_node *before)
|
||||
{
|
||||
before->next = n;
|
||||
before->prev = n->prev;
|
||||
|
||||
n->prev->next = before;
|
||||
n->prev = before;
|
||||
}
|
||||
|
||||
static inline void
|
||||
exec_node_replace_with(struct exec_node *n, struct exec_node *replacement)
|
||||
{
|
||||
replacement->prev = n->prev;
|
||||
replacement->next = n->next;
|
||||
|
||||
n->prev->next = replacement;
|
||||
n->next->prev = replacement;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
exec_node_is_tail_sentinel(const struct exec_node *n)
|
||||
{
|
||||
return n->next == NULL;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
exec_node_is_head_sentinel(const struct exec_node *n)
|
||||
{
|
||||
return n->prev == NULL;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
inline const exec_node *exec_node::get_next() const
|
||||
{
|
||||
return exec_node_get_next_const(this);
|
||||
}
|
||||
|
||||
inline exec_node *exec_node::get_next()
|
||||
{
|
||||
return exec_node_get_next(this);
|
||||
}
|
||||
|
||||
inline const exec_node *exec_node::get_prev() const
|
||||
{
|
||||
return exec_node_get_prev_const(this);
|
||||
}
|
||||
|
||||
inline exec_node *exec_node::get_prev()
|
||||
{
|
||||
return exec_node_get_prev(this);
|
||||
}
|
||||
|
||||
inline void exec_node::remove()
|
||||
{
|
||||
exec_node_remove(this);
|
||||
}
|
||||
|
||||
inline void exec_node::self_link()
|
||||
{
|
||||
exec_node_self_link(this);
|
||||
}
|
||||
|
||||
inline void exec_node::insert_after(exec_node *after)
|
||||
{
|
||||
exec_node_insert_after(this, after);
|
||||
}
|
||||
|
||||
inline void exec_node::insert_before(exec_node *before)
|
||||
{
|
||||
exec_node_insert_node_before(this, before);
|
||||
}
|
||||
|
||||
inline void exec_node::replace_with(exec_node *replacement)
|
||||
{
|
||||
exec_node_replace_with(this, replacement);
|
||||
}
|
||||
|
||||
inline bool exec_node::is_tail_sentinel() const
|
||||
{
|
||||
return exec_node_is_tail_sentinel(this);
|
||||
}
|
||||
|
||||
inline bool exec_node::is_head_sentinel() const
|
||||
{
|
||||
return exec_node_is_head_sentinel(this);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
/* This macro will not work correctly if `t' uses virtual inheritance. If you
|
||||
@@ -221,75 +315,21 @@ struct exec_list {
|
||||
make_empty();
|
||||
}
|
||||
|
||||
void make_empty()
|
||||
{
|
||||
head = (exec_node *) & tail;
|
||||
tail = NULL;
|
||||
tail_pred = (exec_node *) & head;
|
||||
}
|
||||
void make_empty();
|
||||
|
||||
bool is_empty() const
|
||||
{
|
||||
/* There are three ways to test whether a list is empty or not.
|
||||
*
|
||||
* - Check to see if the \c head points to the \c tail.
|
||||
* - Check to see if the \c tail_pred points to the \c head.
|
||||
* - Check to see if the \c head is the sentinel node by test whether its
|
||||
* \c next pointer is \c NULL.
|
||||
*
|
||||
* The first two methods tend to generate better code on modern systems
|
||||
* because they save a pointer dereference.
|
||||
*/
|
||||
return head == (exec_node *) &tail;
|
||||
}
|
||||
bool is_empty() const;
|
||||
|
||||
const exec_node *get_head() const
|
||||
{
|
||||
return !is_empty() ? head : NULL;
|
||||
}
|
||||
const exec_node *get_head() const;
|
||||
exec_node *get_head();
|
||||
|
||||
exec_node *get_head()
|
||||
{
|
||||
return !is_empty() ? head : NULL;
|
||||
}
|
||||
const exec_node *get_tail() const;
|
||||
exec_node *get_tail();
|
||||
|
||||
const exec_node *get_tail() const
|
||||
{
|
||||
return !is_empty() ? tail_pred : NULL;
|
||||
}
|
||||
unsigned length() const;
|
||||
|
||||
exec_node *get_tail()
|
||||
{
|
||||
return !is_empty() ? tail_pred : NULL;
|
||||
}
|
||||
|
||||
void push_head(exec_node *n)
|
||||
{
|
||||
n->next = head;
|
||||
n->prev = (exec_node *) &head;
|
||||
|
||||
n->next->prev = n;
|
||||
head = n;
|
||||
}
|
||||
|
||||
void push_tail(exec_node *n)
|
||||
{
|
||||
n->next = (exec_node *) &tail;
|
||||
n->prev = tail_pred;
|
||||
|
||||
n->prev->next = n;
|
||||
tail_pred = n;
|
||||
}
|
||||
|
||||
void push_degenerate_list_at_head(exec_node *n)
|
||||
{
|
||||
assert(n->prev->next == n);
|
||||
|
||||
n->prev->next = head;
|
||||
head->prev = n->prev;
|
||||
n->prev = (exec_node *) &head;
|
||||
head = n;
|
||||
}
|
||||
void push_head(exec_node *n);
|
||||
void push_tail(exec_node *n);
|
||||
void push_degenerate_list_at_head(exec_node *n);
|
||||
|
||||
/**
|
||||
* Remove the first node from a list and return it
|
||||
@@ -299,121 +339,318 @@ struct exec_list {
|
||||
*
|
||||
* \sa exec_list::get_head
|
||||
*/
|
||||
exec_node *pop_head()
|
||||
{
|
||||
exec_node *const n = this->get_head();
|
||||
if (n != NULL)
|
||||
n->remove();
|
||||
|
||||
return n;
|
||||
}
|
||||
exec_node *pop_head();
|
||||
|
||||
/**
|
||||
* Move all of the nodes from this list to the target list
|
||||
*/
|
||||
void move_nodes_to(exec_list *target)
|
||||
{
|
||||
if (is_empty()) {
|
||||
target->make_empty();
|
||||
} else {
|
||||
target->head = head;
|
||||
target->tail = NULL;
|
||||
target->tail_pred = tail_pred;
|
||||
|
||||
target->head->prev = (exec_node *) &target->head;
|
||||
target->tail_pred->next = (exec_node *) &target->tail;
|
||||
|
||||
make_empty();
|
||||
}
|
||||
}
|
||||
void move_nodes_to(exec_list *target);
|
||||
|
||||
/**
|
||||
* Append all nodes from the source list to the target list
|
||||
* Append all nodes from the source list to the end of the target list
|
||||
*/
|
||||
void
|
||||
append_list(exec_list *source)
|
||||
{
|
||||
if (source->is_empty())
|
||||
return;
|
||||
void append_list(exec_list *source);
|
||||
|
||||
/* Link the first node of the source with the last node of the target list.
|
||||
*/
|
||||
this->tail_pred->next = source->head;
|
||||
source->head->prev = this->tail_pred;
|
||||
|
||||
/* Make the tail of the source list be the tail of the target list.
|
||||
*/
|
||||
this->tail_pred = source->tail_pred;
|
||||
this->tail_pred->next = (exec_node *) &this->tail;
|
||||
|
||||
/* Make the source list empty for good measure.
|
||||
*/
|
||||
source->make_empty();
|
||||
}
|
||||
/**
|
||||
* Prepend all nodes from the source list to the beginning of the target
|
||||
* list
|
||||
*/
|
||||
void prepend_list(exec_list *source);
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
inline void exec_node::insert_before(exec_list *before)
|
||||
static inline void
|
||||
exec_list_make_empty(struct exec_list *list)
|
||||
{
|
||||
if (before->is_empty())
|
||||
list->head = (struct exec_node *) & list->tail;
|
||||
list->tail = NULL;
|
||||
list->tail_pred = (struct exec_node *) & list->head;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
exec_list_is_empty(const struct exec_list *list)
|
||||
{
|
||||
/* There are three ways to test whether a list is empty or not.
|
||||
*
|
||||
* - Check to see if the \c head points to the \c tail.
|
||||
* - Check to see if the \c tail_pred points to the \c head.
|
||||
* - Check to see if the \c head is the sentinel node by test whether its
|
||||
* \c next pointer is \c NULL.
|
||||
*
|
||||
* The first two methods tend to generate better code on modern systems
|
||||
* because they save a pointer dereference.
|
||||
*/
|
||||
return list->head == (struct exec_node *) &list->tail;
|
||||
}
|
||||
|
||||
static inline const struct exec_node *
|
||||
exec_list_get_head_const(const struct exec_list *list)
|
||||
{
|
||||
return !exec_list_is_empty(list) ? list->head : NULL;
|
||||
}
|
||||
|
||||
static inline struct exec_node *
|
||||
exec_list_get_head(struct exec_list *list)
|
||||
{
|
||||
return !exec_list_is_empty(list) ? list->head : NULL;
|
||||
}
|
||||
|
||||
static inline const struct exec_node *
|
||||
exec_list_get_tail_const(const struct exec_list *list)
|
||||
{
|
||||
return !exec_list_is_empty(list) ? list->tail_pred : NULL;
|
||||
}
|
||||
|
||||
static inline struct exec_node *
|
||||
exec_list_get_tail(struct exec_list *list)
|
||||
{
|
||||
return !exec_list_is_empty(list) ? list->tail_pred : NULL;
|
||||
}
|
||||
|
||||
static inline unsigned
|
||||
exec_list_length(const struct exec_list *list)
|
||||
{
|
||||
unsigned size = 0;
|
||||
struct exec_node *node;
|
||||
|
||||
for (node = list->head; node->next != NULL; node = node->next) {
|
||||
size++;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static inline void
|
||||
exec_list_push_head(struct exec_list *list, struct exec_node *n)
|
||||
{
|
||||
n->next = list->head;
|
||||
n->prev = (struct exec_node *) &list->head;
|
||||
|
||||
n->next->prev = n;
|
||||
list->head = n;
|
||||
}
|
||||
|
||||
static inline void
|
||||
exec_list_push_tail(struct exec_list *list, struct exec_node *n)
|
||||
{
|
||||
n->next = (struct exec_node *) &list->tail;
|
||||
n->prev = list->tail_pred;
|
||||
|
||||
n->prev->next = n;
|
||||
list->tail_pred = n;
|
||||
}
|
||||
|
||||
static inline void
|
||||
exec_list_push_degenerate_list_at_head(struct exec_list *list, struct exec_node *n)
|
||||
{
|
||||
assert(n->prev->next == n);
|
||||
|
||||
n->prev->next = list->head;
|
||||
list->head->prev = n->prev;
|
||||
n->prev = (struct exec_node *) &list->head;
|
||||
list->head = n;
|
||||
}
|
||||
|
||||
static inline struct exec_node *
|
||||
exec_list_pop_head(struct exec_list *list)
|
||||
{
|
||||
struct exec_node *const n = exec_list_get_head(list);
|
||||
if (n != NULL)
|
||||
exec_node_remove(n);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
static inline void
|
||||
exec_list_move_nodes_to(struct exec_list *list, struct exec_list *target)
|
||||
{
|
||||
if (exec_list_is_empty(list)) {
|
||||
exec_list_make_empty(target);
|
||||
} else {
|
||||
target->head = list->head;
|
||||
target->tail = NULL;
|
||||
target->tail_pred = list->tail_pred;
|
||||
|
||||
target->head->prev = (struct exec_node *) &target->head;
|
||||
target->tail_pred->next = (struct exec_node *) &target->tail;
|
||||
|
||||
exec_list_make_empty(list);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
exec_list_append(struct exec_list *list, struct exec_list *source)
|
||||
{
|
||||
if (exec_list_is_empty(source))
|
||||
return;
|
||||
|
||||
before->tail_pred->next = this;
|
||||
before->head->prev = this->prev;
|
||||
/* Link the first node of the source with the last node of the target list.
|
||||
*/
|
||||
list->tail_pred->next = source->head;
|
||||
source->head->prev = list->tail_pred;
|
||||
|
||||
this->prev->next = before->head;
|
||||
this->prev = before->tail_pred;
|
||||
/* Make the tail of the source list be the tail of the target list.
|
||||
*/
|
||||
list->tail_pred = source->tail_pred;
|
||||
list->tail_pred->next = (struct exec_node *) &list->tail;
|
||||
|
||||
before->make_empty();
|
||||
/* Make the source list empty for good measure.
|
||||
*/
|
||||
exec_list_make_empty(source);
|
||||
}
|
||||
|
||||
static inline void
|
||||
exec_list_prepend(struct exec_list *list, struct exec_list *source)
|
||||
{
|
||||
exec_list_append(source, list);
|
||||
exec_list_move_nodes_to(source, list);
|
||||
}
|
||||
|
||||
static inline void
|
||||
exec_node_insert_list_before(struct exec_node *n, struct exec_list *before)
|
||||
{
|
||||
if (exec_list_is_empty(before))
|
||||
return;
|
||||
|
||||
before->tail_pred->next = n;
|
||||
before->head->prev = n->prev;
|
||||
|
||||
n->prev->next = before->head;
|
||||
n->prev = before->tail_pred;
|
||||
|
||||
exec_list_make_empty(before);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
inline void exec_list::make_empty()
|
||||
{
|
||||
exec_list_make_empty(this);
|
||||
}
|
||||
|
||||
inline bool exec_list::is_empty() const
|
||||
{
|
||||
return exec_list_is_empty(this);
|
||||
}
|
||||
|
||||
inline const exec_node *exec_list::get_head() const
|
||||
{
|
||||
return exec_list_get_head_const(this);
|
||||
}
|
||||
|
||||
inline exec_node *exec_list::get_head()
|
||||
{
|
||||
return exec_list_get_head(this);
|
||||
}
|
||||
|
||||
inline const exec_node *exec_list::get_tail() const
|
||||
{
|
||||
return exec_list_get_tail_const(this);
|
||||
}
|
||||
|
||||
inline exec_node *exec_list::get_tail()
|
||||
{
|
||||
return exec_list_get_tail(this);
|
||||
}
|
||||
|
||||
inline unsigned exec_list::length() const
|
||||
{
|
||||
return exec_list_length(this);
|
||||
}
|
||||
|
||||
inline void exec_list::push_head(exec_node *n)
|
||||
{
|
||||
exec_list_push_head(this, n);
|
||||
}
|
||||
|
||||
inline void exec_list::push_tail(exec_node *n)
|
||||
{
|
||||
exec_list_push_tail(this, n);
|
||||
}
|
||||
|
||||
inline void exec_list::push_degenerate_list_at_head(exec_node *n)
|
||||
{
|
||||
exec_list_push_degenerate_list_at_head(this, n);
|
||||
}
|
||||
|
||||
inline exec_node *exec_list::pop_head()
|
||||
{
|
||||
return exec_list_pop_head(this);
|
||||
}
|
||||
|
||||
inline void exec_list::move_nodes_to(exec_list *target)
|
||||
{
|
||||
exec_list_move_nodes_to(this, target);
|
||||
}
|
||||
|
||||
inline void exec_list::append_list(exec_list *source)
|
||||
{
|
||||
exec_list_append(this, source);
|
||||
}
|
||||
|
||||
inline void exec_list::prepend_list(exec_list *source)
|
||||
{
|
||||
exec_list_prepend(this, source);
|
||||
}
|
||||
|
||||
inline void exec_node::insert_before(exec_list *before)
|
||||
{
|
||||
exec_node_insert_list_before(this, before);
|
||||
}
|
||||
#endif
|
||||
|
||||
#define foreach_in_list(__type, __inst, __list) \
|
||||
for (__type *(__inst) = (__type *)(__list)->head; \
|
||||
!(__inst)->is_tail_sentinel(); \
|
||||
(__inst) = (__type *)(__inst)->next)
|
||||
|
||||
#define foreach_in_list_reverse(__type, __inst, __list) \
|
||||
for (__type *(__inst) = (__type *)(__list)->tail_pred; \
|
||||
!(__inst)->is_head_sentinel(); \
|
||||
(__inst) = (__type *)(__inst)->prev)
|
||||
|
||||
/**
|
||||
* This version is safe even if the current node is removed.
|
||||
*/
|
||||
#define foreach_list_safe(__node, __list) \
|
||||
for (exec_node * __node = (__list)->head, * __next = __node->next \
|
||||
; __next != NULL \
|
||||
; __node = __next, __next = __next->next)
|
||||
|
||||
#define foreach_list(__node, __list) \
|
||||
for (exec_node * __node = (__list)->head \
|
||||
; (__node)->next != NULL \
|
||||
; (__node) = (__node)->next)
|
||||
#define foreach_in_list_safe(__type, __node, __list) \
|
||||
for (__type *__node = (__type *)(__list)->head, \
|
||||
*__next = (__type *)__node->next; \
|
||||
__next != NULL; \
|
||||
__node = __next, __next = (__type *)__next->next)
|
||||
|
||||
#define foreach_in_list_use_after(__type, __inst, __list) \
|
||||
__type *(__inst); \
|
||||
for ((__inst) = (__type *)(__list)->head; \
|
||||
!(__inst)->is_tail_sentinel(); \
|
||||
(__inst) = (__type *)(__inst)->next)
|
||||
/**
|
||||
* Iterate through two lists at once. Stops at the end of the shorter list.
|
||||
*
|
||||
* This is safe against either current node being removed or replaced.
|
||||
*/
|
||||
#define foreach_two_lists(__node1, __list1, __node2, __list2) \
|
||||
for (exec_node * __node1 = (__list1)->head, \
|
||||
* __node2 = (__list2)->head, \
|
||||
* __next1 = __node1->next, \
|
||||
* __next2 = __node2->next \
|
||||
for (struct exec_node * __node1 = (__list1)->head, \
|
||||
* __node2 = (__list2)->head, \
|
||||
* __next1 = __node1->next, \
|
||||
* __next2 = __node2->next \
|
||||
; __next1 != NULL && __next2 != NULL \
|
||||
; __node1 = __next1, \
|
||||
__node2 = __next2, \
|
||||
__next1 = __next1->next, \
|
||||
__next2 = __next2->next)
|
||||
|
||||
#define foreach_list_const(__node, __list) \
|
||||
for (const exec_node * __node = (__list)->head \
|
||||
; (__node)->next != NULL \
|
||||
; (__node) = (__node)->next)
|
||||
|
||||
#define foreach_list_typed(__type, __node, __field, __list) \
|
||||
for (__type * __node = \
|
||||
exec_node_data(__type, (__list)->head, __field); \
|
||||
(__node)->__field.next != NULL; \
|
||||
(__node) = exec_node_data(__type, (__node)->__field.next, __field))
|
||||
|
||||
#define foreach_list_typed_const(__type, __node, __field, __list) \
|
||||
for (const __type * __node = \
|
||||
exec_node_data(__type, (__list)->head, __field); \
|
||||
(__node)->__field.next != NULL; \
|
||||
(__node) = exec_node_data(__type, (__node)->__field.next, __field))
|
||||
#define foreach_list_typed_safe(__type, __node, __field, __list) \
|
||||
for (__type * __node = \
|
||||
exec_node_data(__type, (__list)->head, __field), \
|
||||
* __next = \
|
||||
exec_node_data(__type, (__node)->__field.next, __field); \
|
||||
__next != NULL; \
|
||||
__node = __next, __next = \
|
||||
exec_node_data(__type, (__next)->__field.next, __field))
|
||||
|
||||
#endif /* LIST_CONTAINER_H */
|
||||
|
||||
@@ -264,13 +264,12 @@ loop_analysis::visit(ir_loop_jump *ir)
|
||||
|
||||
|
||||
ir_visitor_status
|
||||
loop_analysis::visit_enter(ir_call *ir)
|
||||
loop_analysis::visit_enter(ir_call *)
|
||||
{
|
||||
/* Mark every loop that we're currently analyzing as containing an ir_call
|
||||
* (even those at outer nesting levels).
|
||||
*/
|
||||
foreach_list(node, &this->state) {
|
||||
loop_variable_state *const ls = (loop_variable_state *) node;
|
||||
foreach_in_list(loop_variable_state, ls, &this->state) {
|
||||
ls->contains_calls = true;
|
||||
}
|
||||
|
||||
@@ -288,9 +287,7 @@ loop_analysis::visit(ir_dereference_variable *ir)
|
||||
|
||||
bool nested = false;
|
||||
|
||||
foreach_list(node, &this->state) {
|
||||
loop_variable_state *const ls = (loop_variable_state *) node;
|
||||
|
||||
foreach_in_list(loop_variable_state, ls, &this->state) {
|
||||
ir_variable *var = ir->variable_referenced();
|
||||
loop_variable *lv = ls->get_or_insert(var, this->in_assignee);
|
||||
|
||||
@@ -330,10 +327,10 @@ loop_analysis::visit_leave(ir_loop *ir)
|
||||
if (ls->contains_calls)
|
||||
return visit_continue;
|
||||
|
||||
foreach_list(node, &ir->body_instructions) {
|
||||
foreach_in_list(ir_instruction, node, &ir->body_instructions) {
|
||||
/* Skip over declarations at the start of a loop.
|
||||
*/
|
||||
if (((ir_instruction *) node)->as_variable())
|
||||
if (node->as_variable())
|
||||
continue;
|
||||
|
||||
ir_if *if_stmt = ((ir_instruction *) node)->as_if();
|
||||
@@ -345,9 +342,11 @@ loop_analysis::visit_leave(ir_loop *ir)
|
||||
}
|
||||
|
||||
|
||||
foreach_list_safe(node, &ls->variables) {
|
||||
loop_variable *lv = (loop_variable *) node;
|
||||
|
||||
foreach_in_list_safe(loop_variable, lv, &ls->variables) {
|
||||
ir_variable *var = lv->var;
|
||||
if (var != NULL) {
|
||||
lv->initial_value = find_initial_value(ir, var);
|
||||
}
|
||||
/* Move variables that are already marked as being loop constant to
|
||||
* a separate list. These trivially don't need to be tested.
|
||||
*/
|
||||
@@ -375,9 +374,7 @@ loop_analysis::visit_leave(ir_loop *ir)
|
||||
do {
|
||||
progress = false;
|
||||
|
||||
foreach_list_safe(node, &ls->variables) {
|
||||
loop_variable *lv = (loop_variable *) node;
|
||||
|
||||
foreach_in_list_safe(loop_variable, lv, &ls->variables) {
|
||||
if (lv->conditional_or_nested_assignment || (lv->num_assignments > 1))
|
||||
continue;
|
||||
|
||||
@@ -401,9 +398,7 @@ loop_analysis::visit_leave(ir_loop *ir)
|
||||
/* The remaining variables that are not loop invariant might be loop
|
||||
* induction variables.
|
||||
*/
|
||||
foreach_list_safe(node, &ls->variables) {
|
||||
loop_variable *lv = (loop_variable *) node;
|
||||
|
||||
foreach_in_list_safe(loop_variable, lv, &ls->variables) {
|
||||
/* If there is more than one assignment to a variable, it cannot be a
|
||||
* loop induction variable. This isn't strictly true, but this is a
|
||||
* very simple induction variable detector, and it can't handle more
|
||||
@@ -445,8 +440,7 @@ loop_analysis::visit_leave(ir_loop *ir)
|
||||
* Also figure out which terminator (if any) produces the smallest
|
||||
* iteration count--this is the limiting terminator.
|
||||
*/
|
||||
foreach_list(node, &ls->terminators) {
|
||||
loop_terminator *t = (loop_terminator *) node;
|
||||
foreach_in_list(loop_terminator, t, &ls->terminators) {
|
||||
ir_if *if_stmt = t->ir;
|
||||
|
||||
/* If-statements can be either 'if (expr)' or 'if (deref)'. We only care
|
||||
@@ -487,12 +481,9 @@ loop_analysis::visit_leave(ir_loop *ir)
|
||||
|
||||
ir_variable *var = counter->variable_referenced();
|
||||
|
||||
ir_rvalue *init = find_initial_value(ir, var);
|
||||
|
||||
loop_variable *lv = ls->get(var);
|
||||
if (lv != NULL && lv->is_induction_var()) {
|
||||
lv->initial_value = init;
|
||||
t->iterations = calculate_iterations(init, limit, lv->increment,
|
||||
t->iterations = calculate_iterations(lv->initial_value, limit, lv->increment,
|
||||
cmp);
|
||||
|
||||
if (t->iterations >= 0 &&
|
||||
@@ -633,8 +624,10 @@ get_basic_induction_increment(ir_assignment *ir, hash_table *var_hash)
|
||||
loop_variable *lv =
|
||||
(loop_variable *) hash_table_find(var_hash, inc_var);
|
||||
|
||||
if (!lv->is_loop_constant())
|
||||
inc = NULL;
|
||||
if (lv == NULL || !lv->is_loop_constant()) {
|
||||
assert(lv != NULL);
|
||||
inc = NULL;
|
||||
}
|
||||
} else
|
||||
inc = NULL;
|
||||
}
|
||||
|
||||
30
3rdparty/glsl-optimizer/src/glsl/loop_analysis.h
vendored
30
3rdparty/glsl-optimizer/src/glsl/loop_analysis.h
vendored
@@ -27,6 +27,7 @@
|
||||
#define LOOP_ANALYSIS_H
|
||||
|
||||
#include "ir.h"
|
||||
#include "glsl_types.h"
|
||||
#include "program/hash_table.h"
|
||||
|
||||
/**
|
||||
@@ -53,7 +54,8 @@ set_loop_controls(exec_list *instructions, loop_state *ls);
|
||||
|
||||
|
||||
extern bool
|
||||
unroll_loops(exec_list *instructions, loop_state *ls, unsigned max_iterations);
|
||||
unroll_loops(exec_list *instructions, loop_state *ls,
|
||||
const struct gl_shader_compiler_options *options);
|
||||
|
||||
ir_rvalue *
|
||||
find_initial_value(ir_loop *loop, ir_variable *var);
|
||||
@@ -140,22 +142,7 @@ public:
|
||||
hash_table_dtor(this->var_hash);
|
||||
}
|
||||
|
||||
static void* operator new(size_t size, void *ctx)
|
||||
{
|
||||
void *lvs = ralloc_size(ctx, size);
|
||||
assert(lvs != NULL);
|
||||
|
||||
ralloc_set_destructor(lvs, (void (*)(void*)) destructor);
|
||||
|
||||
return lvs;
|
||||
}
|
||||
|
||||
private:
|
||||
static void
|
||||
destructor(loop_variable_state *lvs)
|
||||
{
|
||||
lvs->~loop_variable_state();
|
||||
}
|
||||
DECLARE_RALLOC_CXX_OPERATORS(loop_variable_state)
|
||||
};
|
||||
|
||||
|
||||
@@ -208,10 +195,10 @@ public:
|
||||
inline bool is_loop_constant() const
|
||||
{
|
||||
const bool is_const = (this->num_assignments == 0)
|
||||
|| ((this->num_assignments == 1)
|
||||
|| (((this->num_assignments == 1)
|
||||
&& !this->conditional_or_nested_assignment
|
||||
&& !this->read_before_write
|
||||
&& this->rhs_clean);
|
||||
&& this->rhs_clean) || this->var->data.read_only);
|
||||
|
||||
/* If the RHS of *the* assignment is clean, then there must be exactly
|
||||
* one assignment of the variable.
|
||||
@@ -219,11 +206,6 @@ public:
|
||||
assert((this->rhs_clean && (this->num_assignments == 1))
|
||||
|| !this->rhs_clean);
|
||||
|
||||
/* Variables that are marked read-only *MUST* be loop constant.
|
||||
*/
|
||||
assert(!this->var->data.read_only
|
||||
|| (this->var->data.read_only && is_const));
|
||||
|
||||
return is_const;
|
||||
}
|
||||
|
||||
|
||||
@@ -130,9 +130,20 @@ calculate_iterations(ir_rvalue *from, ir_rvalue *to, ir_rvalue *increment,
|
||||
bool valid_loop = false;
|
||||
|
||||
for (unsigned i = 0; i < Elements(bias); i++) {
|
||||
iter = (increment->type->is_integer())
|
||||
? new(mem_ctx) ir_constant(iter_value + bias[i])
|
||||
: new(mem_ctx) ir_constant(float(iter_value + bias[i]));
|
||||
/* Increment may be of type int, uint or float. */
|
||||
switch (increment->type->base_type) {
|
||||
case GLSL_TYPE_INT:
|
||||
iter = new(mem_ctx) ir_constant(iter_value + bias[i]);
|
||||
break;
|
||||
case GLSL_TYPE_UINT:
|
||||
iter = new(mem_ctx) ir_constant(unsigned(iter_value + bias[i]));
|
||||
break;
|
||||
case GLSL_TYPE_FLOAT:
|
||||
iter = new(mem_ctx) ir_constant(float(iter_value + bias[i]));
|
||||
break;
|
||||
default:
|
||||
unreachable(!"Unsupported type for loop iterator.");
|
||||
}
|
||||
|
||||
ir_expression *const mul =
|
||||
new(mem_ctx) ir_expression(ir_binop_mul, increment->type, iter,
|
||||
@@ -209,9 +220,7 @@ loop_control_visitor::visit_leave(ir_loop *ir)
|
||||
* bound, then that terminates the loop, so we don't even need the limiting
|
||||
* terminator.
|
||||
*/
|
||||
foreach_list(node, &ls->terminators) {
|
||||
loop_terminator *t = (loop_terminator *) node;
|
||||
|
||||
foreach_in_list(loop_terminator, t, &ls->terminators) {
|
||||
if (t->iterations < 0)
|
||||
continue;
|
||||
|
||||
|
||||
98
3rdparty/glsl-optimizer/src/glsl/loop_unroll.cpp
vendored
98
3rdparty/glsl-optimizer/src/glsl/loop_unroll.cpp
vendored
@@ -25,15 +25,18 @@
|
||||
#include "loop_analysis.h"
|
||||
#include "ir_hierarchical_visitor.h"
|
||||
|
||||
#include "main/mtypes.h"
|
||||
|
||||
namespace {
|
||||
|
||||
class loop_unroll_visitor : public ir_hierarchical_visitor {
|
||||
public:
|
||||
loop_unroll_visitor(loop_state *state, unsigned max_iterations)
|
||||
loop_unroll_visitor(loop_state *state,
|
||||
const struct gl_shader_compiler_options *options)
|
||||
{
|
||||
this->state = state;
|
||||
this->progress = false;
|
||||
this->max_iterations = max_iterations;
|
||||
this->options = options;
|
||||
}
|
||||
|
||||
virtual ir_visitor_status visit_leave(ir_loop *ir);
|
||||
@@ -45,7 +48,7 @@ public:
|
||||
loop_state *state;
|
||||
|
||||
bool progress;
|
||||
unsigned max_iterations;
|
||||
const struct gl_shader_compiler_options *options;
|
||||
};
|
||||
|
||||
} /* anonymous namespace */
|
||||
@@ -60,33 +63,86 @@ is_break(ir_instruction *ir)
|
||||
class loop_unroll_count : public ir_hierarchical_visitor {
|
||||
public:
|
||||
int nodes;
|
||||
bool fail;
|
||||
bool unsupported_variable_indexing;
|
||||
/* If there are nested loops, the node count will be inaccurate. */
|
||||
bool nested_loop;
|
||||
|
||||
loop_unroll_count(exec_list *list)
|
||||
loop_unroll_count(exec_list *list, loop_variable_state *ls,
|
||||
const struct gl_shader_compiler_options *options)
|
||||
: ls(ls), options(options)
|
||||
{
|
||||
nodes = 0;
|
||||
fail = false;
|
||||
nested_loop = false;
|
||||
unsupported_variable_indexing = false;
|
||||
|
||||
run(list);
|
||||
}
|
||||
|
||||
virtual ir_visitor_status visit_enter(ir_assignment *ir)
|
||||
virtual ir_visitor_status visit_enter(ir_assignment *)
|
||||
{
|
||||
nodes++;
|
||||
return visit_continue;
|
||||
}
|
||||
|
||||
virtual ir_visitor_status visit_enter(ir_expression *ir)
|
||||
virtual ir_visitor_status visit_enter(ir_expression *)
|
||||
{
|
||||
nodes++;
|
||||
return visit_continue;
|
||||
}
|
||||
|
||||
virtual ir_visitor_status visit_enter(ir_loop *ir)
|
||||
virtual ir_visitor_status visit_enter(ir_loop *)
|
||||
{
|
||||
fail = true;
|
||||
nested_loop = true;
|
||||
return visit_continue;
|
||||
}
|
||||
|
||||
virtual ir_visitor_status visit_enter(ir_dereference_array *ir)
|
||||
{
|
||||
/* Check for arrays variably-indexed by a loop induction variable.
|
||||
* Unrolling the loop may convert that access into constant-indexing.
|
||||
*
|
||||
* Many drivers don't support particular kinds of variable indexing,
|
||||
* and have to resort to using lower_variable_index_to_cond_assign to
|
||||
* handle it. This results in huge amounts of horrible code, so we'd
|
||||
* like to avoid that if possible. Here, we just note that it will
|
||||
* happen.
|
||||
*/
|
||||
if ((ir->array->type->is_array() || ir->array->type->is_matrix()) &&
|
||||
!ir->array_index->as_constant()) {
|
||||
ir_variable *array = ir->array->variable_referenced();
|
||||
loop_variable *lv = ls->get(ir->array_index->variable_referenced());
|
||||
if (array && lv && lv->is_induction_var()) {
|
||||
switch (array->data.mode) {
|
||||
case ir_var_auto:
|
||||
case ir_var_temporary:
|
||||
case ir_var_const_in:
|
||||
case ir_var_function_in:
|
||||
case ir_var_function_out:
|
||||
case ir_var_function_inout:
|
||||
if (options->EmitNoIndirectTemp)
|
||||
unsupported_variable_indexing = true;
|
||||
break;
|
||||
case ir_var_uniform:
|
||||
if (options->EmitNoIndirectUniform)
|
||||
unsupported_variable_indexing = true;
|
||||
break;
|
||||
case ir_var_shader_in:
|
||||
if (options->EmitNoIndirectInput)
|
||||
unsupported_variable_indexing = true;
|
||||
break;
|
||||
case ir_var_shader_out:
|
||||
if (options->EmitNoIndirectOutput)
|
||||
unsupported_variable_indexing = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return visit_continue;
|
||||
}
|
||||
|
||||
private:
|
||||
loop_variable_state *ls;
|
||||
const struct gl_shader_compiler_options *options;
|
||||
};
|
||||
|
||||
|
||||
@@ -244,16 +300,21 @@ loop_unroll_visitor::visit_leave(ir_loop *ir)
|
||||
|
||||
iterations = ls->limiting_terminator->iterations;
|
||||
|
||||
const int max_iterations = options->MaxUnrollIterations;
|
||||
|
||||
/* Don't try to unroll loops that have zillions of iterations either.
|
||||
*/
|
||||
if (iterations > (int) max_iterations)
|
||||
if (iterations > max_iterations)
|
||||
return visit_continue;
|
||||
|
||||
/* Don't try to unroll nested loops and loops with a huge body.
|
||||
*/
|
||||
loop_unroll_count count(&ir->body_instructions);
|
||||
loop_unroll_count count(&ir->body_instructions, ls, options);
|
||||
|
||||
if (count.fail || count.nodes * iterations > (int)max_iterations * 25)
|
||||
bool loop_too_large =
|
||||
count.nested_loop || count.nodes * iterations > (int)max_iterations * 25;
|
||||
|
||||
if (loop_too_large && !count.unsupported_variable_indexing)
|
||||
return visit_continue;
|
||||
|
||||
/* Note: the limiting terminator contributes 1 to ls->num_loop_jumps.
|
||||
@@ -286,10 +347,8 @@ loop_unroll_visitor::visit_leave(ir_loop *ir)
|
||||
return visit_continue;
|
||||
}
|
||||
|
||||
foreach_list(node, &ir->body_instructions) {
|
||||
/* recognize loops in the form produced by ir_lower_jumps */
|
||||
ir_instruction *cur_ir = (ir_instruction *) node;
|
||||
|
||||
/* recognize loops in the form produced by ir_lower_jumps */
|
||||
foreach_in_list(ir_instruction, cur_ir, &ir->body_instructions) {
|
||||
/* Skip the limiting terminator, since it will go away when we
|
||||
* unroll.
|
||||
*/
|
||||
@@ -338,9 +397,10 @@ loop_unroll_visitor::visit_leave(ir_loop *ir)
|
||||
|
||||
|
||||
bool
|
||||
unroll_loops(exec_list *instructions, loop_state *ls, unsigned max_iterations)
|
||||
unroll_loops(exec_list *instructions, loop_state *ls,
|
||||
const struct gl_shader_compiler_options *options)
|
||||
{
|
||||
loop_unroll_visitor v(ls, max_iterations);
|
||||
loop_unroll_visitor v(ls, options);
|
||||
|
||||
v.run(instructions);
|
||||
|
||||
|
||||
@@ -138,8 +138,8 @@ lower_discard(exec_list *instructions)
|
||||
static ir_discard *
|
||||
find_discard(exec_list &instructions)
|
||||
{
|
||||
foreach_list(n, &instructions) {
|
||||
ir_discard *ir = ((ir_instruction *) n)->as_discard();
|
||||
foreach_in_list(ir_instruction, node, &instructions) {
|
||||
ir_discard *ir = node->as_discard();
|
||||
if (ir != NULL)
|
||||
return ir;
|
||||
}
|
||||
|
||||
@@ -116,9 +116,7 @@ move_block_to_cond_assign(void *mem_ctx,
|
||||
exec_list *instructions,
|
||||
struct hash_table *ht)
|
||||
{
|
||||
foreach_list_safe(node, instructions) {
|
||||
ir_instruction *ir = (ir_instruction *) node;
|
||||
|
||||
foreach_in_list_safe(ir_instruction, ir, instructions) {
|
||||
if (ir->ir_type == ir_type_assignment) {
|
||||
ir_assignment *assign = (ir_assignment *)ir;
|
||||
|
||||
@@ -178,12 +176,10 @@ ir_if_to_cond_assign_visitor::visit_leave(ir_if *ir)
|
||||
ir_assignment *assign;
|
||||
|
||||
/* Check that both blocks don't contain anything we can't support. */
|
||||
foreach_list(n, &ir->then_instructions) {
|
||||
ir_instruction *then_ir = (ir_instruction *) n;
|
||||
foreach_in_list(ir_instruction, then_ir, &ir->then_instructions) {
|
||||
visit_tree(then_ir, check_control_flow, &found_control_flow);
|
||||
}
|
||||
foreach_list(n, &ir->else_instructions) {
|
||||
ir_instruction *else_ir = (ir_instruction *) n;
|
||||
foreach_in_list(ir_instruction, else_ir, &ir->else_instructions) {
|
||||
visit_tree(else_ir, check_control_flow, &found_control_flow);
|
||||
}
|
||||
if (found_control_flow)
|
||||
|
||||
@@ -38,8 +38,10 @@
|
||||
* - LOG_TO_LOG2
|
||||
* - MOD_TO_FRACT
|
||||
* - LDEXP_TO_ARITH
|
||||
* - LRP_TO_ARITH
|
||||
* - BITFIELD_INSERT_TO_BFM_BFI
|
||||
* - CARRY_TO_ARITH
|
||||
* - BORROW_TO_ARITH
|
||||
* - SAT_TO_CLAMP
|
||||
*
|
||||
* SUB_TO_ADD_NEG:
|
||||
* ---------------
|
||||
@@ -87,10 +89,6 @@
|
||||
* -------------
|
||||
* Converts ir_binop_ldexp to arithmetic and bit operations.
|
||||
*
|
||||
* LRP_TO_ARITH:
|
||||
* -------------
|
||||
* Converts ir_triop_lrp to (op0 * (1.0f - op2)) + (op1 * op2).
|
||||
*
|
||||
* BITFIELD_INSERT_TO_BFM_BFI:
|
||||
* ---------------------------
|
||||
* Breaks ir_quadop_bitfield_insert into ir_binop_bfm (bitfield mask) and
|
||||
@@ -99,6 +97,18 @@
|
||||
* Many GPUs implement the bitfieldInsert() built-in from ARB_gpu_shader_5
|
||||
* with a pair of instructions.
|
||||
*
|
||||
* CARRY_TO_ARITH:
|
||||
* ---------------
|
||||
* Converts ir_carry into (x + y) < x.
|
||||
*
|
||||
* BORROW_TO_ARITH:
|
||||
* ----------------
|
||||
* Converts ir_borrow into (x < y).
|
||||
*
|
||||
* SAT_TO_CLAMP:
|
||||
* -------------
|
||||
* Converts ir_unop_saturate into min(max(x, 0.0), 1.0)
|
||||
*
|
||||
*/
|
||||
|
||||
#include "main/core.h" /* for M_LOG2E */
|
||||
@@ -130,9 +140,11 @@ private:
|
||||
void exp_to_exp2(ir_expression *);
|
||||
void pow_to_exp2(ir_expression *);
|
||||
void log_to_log2(ir_expression *);
|
||||
void lrp_to_arith(ir_expression *);
|
||||
void bitfield_insert_to_bfm_bfi(ir_expression *);
|
||||
void ldexp_to_arith(ir_expression *);
|
||||
void carry_to_arith(ir_expression *);
|
||||
void borrow_to_arith(ir_expression *);
|
||||
void sat_to_clamp(ir_expression *);
|
||||
};
|
||||
|
||||
} /* anonymous namespace */
|
||||
@@ -298,27 +310,6 @@ lower_instructions_visitor::mod_to_fract(ir_expression *ir)
|
||||
this->progress = true;
|
||||
}
|
||||
|
||||
void
|
||||
lower_instructions_visitor::lrp_to_arith(ir_expression *ir)
|
||||
{
|
||||
/* (lrp x y a) -> x*(1-a) + y*a */
|
||||
|
||||
/* Save op2 */
|
||||
ir_variable *temp = new(ir) ir_variable(ir->operands[2]->type, "lrp_factor",
|
||||
ir_var_temporary, precision_from_ir(ir->operands[2]));
|
||||
this->base_ir->insert_before(temp);
|
||||
this->base_ir->insert_before(assign(temp, ir->operands[2]));
|
||||
|
||||
ir_constant *one = new(ir) ir_constant(1.0f);
|
||||
|
||||
ir->operation = ir_binop_add;
|
||||
ir->operands[0] = mul(ir->operands[0], sub(one, temp));
|
||||
ir->operands[1] = mul(ir->operands[1], temp);
|
||||
ir->operands[2] = NULL;
|
||||
|
||||
this->progress = true;
|
||||
}
|
||||
|
||||
void
|
||||
lower_instructions_visitor::bitfield_insert_to_bfm_bfi(ir_expression *ir)
|
||||
{
|
||||
@@ -386,8 +377,8 @@ lower_instructions_visitor::ldexp_to_arith(ir_expression *ir)
|
||||
|
||||
ir_constant *sign_mask = new(ir) ir_constant(0x80000000u, vec_elem);
|
||||
|
||||
ir_constant *exp_shift = new(ir) ir_constant(23u, vec_elem);
|
||||
ir_constant *exp_width = new(ir) ir_constant(8u, vec_elem);
|
||||
ir_constant *exp_shift = new(ir) ir_constant(23);
|
||||
ir_constant *exp_width = new(ir) ir_constant(8);
|
||||
|
||||
/* Temporary variables */
|
||||
glsl_precision prec = ir->get_precision();
|
||||
@@ -464,6 +455,60 @@ lower_instructions_visitor::ldexp_to_arith(ir_expression *ir)
|
||||
this->progress = true;
|
||||
}
|
||||
|
||||
void
|
||||
lower_instructions_visitor::carry_to_arith(ir_expression *ir)
|
||||
{
|
||||
/* Translates
|
||||
* ir_binop_carry x y
|
||||
* into
|
||||
* sum = ir_binop_add x y
|
||||
* bcarry = ir_binop_less sum x
|
||||
* carry = ir_unop_b2i bcarry
|
||||
*/
|
||||
|
||||
ir_rvalue *x_clone = ir->operands[0]->clone(ir, NULL);
|
||||
ir->operation = ir_unop_i2u;
|
||||
ir->operands[0] = b2i(less(add(ir->operands[0], ir->operands[1]), x_clone));
|
||||
ir->operands[1] = NULL;
|
||||
|
||||
this->progress = true;
|
||||
}
|
||||
|
||||
void
|
||||
lower_instructions_visitor::borrow_to_arith(ir_expression *ir)
|
||||
{
|
||||
/* Translates
|
||||
* ir_binop_borrow x y
|
||||
* into
|
||||
* bcarry = ir_binop_less x y
|
||||
* carry = ir_unop_b2i bcarry
|
||||
*/
|
||||
|
||||
ir->operation = ir_unop_i2u;
|
||||
ir->operands[0] = b2i(less(ir->operands[0], ir->operands[1]));
|
||||
ir->operands[1] = NULL;
|
||||
|
||||
this->progress = true;
|
||||
}
|
||||
|
||||
void
|
||||
lower_instructions_visitor::sat_to_clamp(ir_expression *ir)
|
||||
{
|
||||
/* Translates
|
||||
* ir_unop_saturate x
|
||||
* into
|
||||
* ir_binop_min (ir_binop_max(x, 0.0), 1.0)
|
||||
*/
|
||||
|
||||
ir->operation = ir_binop_min;
|
||||
ir->operands[0] = new(ir) ir_expression(ir_binop_max, ir->operands[0]->type,
|
||||
ir->operands[0],
|
||||
new(ir) ir_constant(0.0f));
|
||||
ir->operands[1] = new(ir) ir_constant(1.0f);
|
||||
|
||||
this->progress = true;
|
||||
}
|
||||
|
||||
ir_visitor_status
|
||||
lower_instructions_visitor::visit_leave(ir_expression *ir)
|
||||
{
|
||||
@@ -500,11 +545,6 @@ lower_instructions_visitor::visit_leave(ir_expression *ir)
|
||||
pow_to_exp2(ir);
|
||||
break;
|
||||
|
||||
case ir_triop_lrp:
|
||||
if (lowering(LRP_TO_ARITH))
|
||||
lrp_to_arith(ir);
|
||||
break;
|
||||
|
||||
case ir_quadop_bitfield_insert:
|
||||
if (lowering(BITFIELD_INSERT_TO_BFM_BFI))
|
||||
bitfield_insert_to_bfm_bfi(ir);
|
||||
@@ -515,6 +555,21 @@ lower_instructions_visitor::visit_leave(ir_expression *ir)
|
||||
ldexp_to_arith(ir);
|
||||
break;
|
||||
|
||||
case ir_binop_carry:
|
||||
if (lowering(CARRY_TO_ARITH))
|
||||
carry_to_arith(ir);
|
||||
break;
|
||||
|
||||
case ir_binop_borrow:
|
||||
if (lowering(BORROW_TO_ARITH))
|
||||
borrow_to_arith(ir);
|
||||
break;
|
||||
|
||||
case ir_unop_saturate:
|
||||
if (lowering(SAT_TO_CLAMP))
|
||||
sat_to_clamp(ir);
|
||||
break;
|
||||
|
||||
default:
|
||||
return visit_continue;
|
||||
}
|
||||
|
||||
@@ -510,16 +510,16 @@ struct ir_lower_jumps_visitor : public ir_control_flow_visitor {
|
||||
/* Note: since visiting a node may change that node's next
|
||||
* pointer, we can't use visit_exec_list(), because
|
||||
* visit_exec_list() caches the node's next pointer before
|
||||
* visiting it. So we use foreach_list() instead.
|
||||
* visiting it. So we use foreach_in_list() instead.
|
||||
*
|
||||
* foreach_list() isn't safe if the node being visited gets
|
||||
* foreach_in_list() isn't safe if the node being visited gets
|
||||
* removed, but fortunately this visitor doesn't do that.
|
||||
*/
|
||||
|
||||
block_record saved_block = this->block;
|
||||
this->block = block_record();
|
||||
foreach_list(node, list) {
|
||||
((ir_instruction *) node)->accept(this);
|
||||
foreach_in_list(ir_instruction, node, list) {
|
||||
node->accept(this);
|
||||
}
|
||||
block_record ret = this->block;
|
||||
this->block = saved_block;
|
||||
|
||||
@@ -99,8 +99,8 @@ flatten_named_interface_blocks_declarations::run(exec_list *instructions)
|
||||
* The interface block variables are stored in the interface_namespace
|
||||
* hash table so they can be used in the second pass.
|
||||
*/
|
||||
foreach_list_safe(node, instructions) {
|
||||
ir_variable *var = ((ir_instruction *) node)->as_variable();
|
||||
foreach_in_list_safe(ir_instruction, node, instructions) {
|
||||
ir_variable *var = node->as_variable();
|
||||
if (!var || !var->is_interface_instance())
|
||||
continue;
|
||||
|
||||
@@ -125,8 +125,8 @@ flatten_named_interface_blocks_declarations::run(exec_list *instructions)
|
||||
for (unsigned i = 0; i < iface_t->length; i++) {
|
||||
const char * field_name = iface_t->fields.structure[i].name;
|
||||
char *iface_field_name =
|
||||
ralloc_asprintf(mem_ctx, "%s.%s",
|
||||
iface_t->name, field_name);
|
||||
ralloc_asprintf(mem_ctx, "%s.%s.%s",
|
||||
iface_t->name, var->name, field_name);
|
||||
|
||||
ir_variable *found_var =
|
||||
(ir_variable *) hash_table_find(interface_namespace,
|
||||
@@ -219,8 +219,8 @@ flatten_named_interface_blocks_declarations::handle_rvalue(ir_rvalue **rvalue)
|
||||
|
||||
if (var->get_interface_type() != NULL) {
|
||||
char *iface_field_name =
|
||||
ralloc_asprintf(mem_ctx, "%s.%s", var->get_interface_type()->name,
|
||||
ir->field);
|
||||
ralloc_asprintf(mem_ctx, "%s.%s.%s", var->get_interface_type()->name,
|
||||
var->name, ir->field);
|
||||
/* Find the variable in the set of flattened interface blocks */
|
||||
ir_variable *found_var =
|
||||
(ir_variable *) hash_table_find(interface_namespace,
|
||||
|
||||
91
3rdparty/glsl-optimizer/src/glsl/lower_offset_array.cpp
vendored
Normal file
91
3rdparty/glsl-optimizer/src/glsl/lower_offset_array.cpp
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright © 2013 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file brw_lower_offset_array.cpp
|
||||
*
|
||||
* IR lower pass to decompose ir_texture ir_tg4 with an array of offsets
|
||||
* into four ir_tg4s with a single ivec2 offset, select the .w component of each,
|
||||
* and return those four values packed into a gvec4.
|
||||
*
|
||||
* \author Chris Forbes <chrisf@ijw.co.nz>
|
||||
*/
|
||||
|
||||
#include "glsl_types.h"
|
||||
#include "ir.h"
|
||||
#include "ir_builder.h"
|
||||
#include "ir_optimization.h"
|
||||
#include "ir_rvalue_visitor.h"
|
||||
|
||||
using namespace ir_builder;
|
||||
|
||||
class brw_lower_offset_array_visitor : public ir_rvalue_visitor {
|
||||
public:
|
||||
brw_lower_offset_array_visitor()
|
||||
{
|
||||
progress = false;
|
||||
}
|
||||
|
||||
void handle_rvalue(ir_rvalue **rv);
|
||||
|
||||
bool progress;
|
||||
};
|
||||
|
||||
void
|
||||
brw_lower_offset_array_visitor::handle_rvalue(ir_rvalue **rv)
|
||||
{
|
||||
if (*rv == NULL || (*rv)->ir_type != ir_type_texture)
|
||||
return;
|
||||
|
||||
ir_texture *ir = (ir_texture *) *rv;
|
||||
if (ir->op != ir_tg4 || !ir->offset || !ir->offset->type->is_array())
|
||||
return;
|
||||
|
||||
void *mem_ctx = ralloc_parent(ir);
|
||||
|
||||
ir_variable *var =
|
||||
new (mem_ctx) ir_variable(ir->type, "result", ir_var_temporary, ir->get_precision());
|
||||
base_ir->insert_before(var);
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
ir_texture *tex = ir->clone(mem_ctx, NULL);
|
||||
tex->offset = new (mem_ctx) ir_dereference_array(tex->offset,
|
||||
new (mem_ctx) ir_constant(i));
|
||||
|
||||
base_ir->insert_before(assign(var, swizzle_w(tex), 1 << i));
|
||||
}
|
||||
|
||||
*rv = new (mem_ctx) ir_dereference_variable(var);
|
||||
|
||||
progress = true;
|
||||
}
|
||||
|
||||
bool
|
||||
lower_offset_arrays(exec_list *instructions)
|
||||
{
|
||||
brw_lower_offset_array_visitor v;
|
||||
|
||||
visit_list_elements(&v, instructions);
|
||||
|
||||
return v.progress;
|
||||
}
|
||||
@@ -52,7 +52,7 @@ public:
|
||||
output_read_remover();
|
||||
~output_read_remover();
|
||||
virtual ir_visitor_status visit(class ir_dereference_variable *);
|
||||
virtual ir_visitor_status visit(class ir_emit_vertex *);
|
||||
virtual ir_visitor_status visit_leave(class ir_emit_vertex *);
|
||||
virtual ir_visitor_status visit_leave(class ir_return *);
|
||||
virtual ir_visitor_status visit_leave(class ir_function_signature *);
|
||||
};
|
||||
@@ -148,7 +148,7 @@ output_read_remover::visit_leave(ir_return *ir)
|
||||
}
|
||||
|
||||
ir_visitor_status
|
||||
output_read_remover::visit(ir_emit_vertex *ir)
|
||||
output_read_remover::visit_leave(ir_emit_vertex *ir)
|
||||
{
|
||||
hash_table_call_foreach(replacements, emit_return_copy, ir);
|
||||
hash_table_clear(replacements);
|
||||
|
||||
@@ -160,8 +160,7 @@ namespace {
|
||||
class lower_packed_varyings_visitor
|
||||
{
|
||||
public:
|
||||
lower_packed_varyings_visitor(void *mem_ctx, unsigned location_base,
|
||||
unsigned locations_used,
|
||||
lower_packed_varyings_visitor(void *mem_ctx, unsigned locations_used,
|
||||
ir_variable_mode mode,
|
||||
unsigned gs_input_vertices,
|
||||
exec_list *out_instructions);
|
||||
@@ -189,19 +188,11 @@ private:
|
||||
*/
|
||||
void * const mem_ctx;
|
||||
|
||||
/**
|
||||
* Location representing the first generic varying slot for this shader
|
||||
* stage (e.g. VARYING_SLOT_VAR0 if we are packing vertex shader outputs).
|
||||
* Varyings whose location is less than this value are assumed to
|
||||
* correspond to special fixed function hardware, so they are not lowered.
|
||||
*/
|
||||
const unsigned location_base;
|
||||
|
||||
/**
|
||||
* Number of generic varying slots which are used by this shader. This is
|
||||
* used to allocate temporary intermediate data structures. If any any
|
||||
* varying used by this shader has a location greater than or equal to
|
||||
* location_base + locations_used, an assertion will fire.
|
||||
* used to allocate temporary intermediate data structures. If any varying
|
||||
* used by this shader has a location greater than or equal to
|
||||
* VARYING_SLOT_VAR0 + locations_used, an assertion will fire.
|
||||
*/
|
||||
const unsigned locations_used;
|
||||
|
||||
@@ -235,11 +226,9 @@ private:
|
||||
} /* anonymous namespace */
|
||||
|
||||
lower_packed_varyings_visitor::lower_packed_varyings_visitor(
|
||||
void *mem_ctx, unsigned location_base, unsigned locations_used,
|
||||
ir_variable_mode mode, unsigned gs_input_vertices,
|
||||
exec_list *out_instructions)
|
||||
void *mem_ctx, unsigned locations_used, ir_variable_mode mode,
|
||||
unsigned gs_input_vertices, exec_list *out_instructions)
|
||||
: mem_ctx(mem_ctx),
|
||||
location_base(location_base),
|
||||
locations_used(locations_used),
|
||||
packed_varyings((ir_variable **)
|
||||
rzalloc_array_size(mem_ctx, sizeof(*packed_varyings),
|
||||
@@ -253,13 +242,13 @@ lower_packed_varyings_visitor::lower_packed_varyings_visitor(
|
||||
void
|
||||
lower_packed_varyings_visitor::run(exec_list *instructions)
|
||||
{
|
||||
foreach_list (node, instructions) {
|
||||
ir_variable *var = ((ir_instruction *) node)->as_variable();
|
||||
foreach_in_list(ir_instruction, node, instructions) {
|
||||
ir_variable *var = node->as_variable();
|
||||
if (var == NULL)
|
||||
continue;
|
||||
|
||||
if (var->data.mode != this->mode ||
|
||||
var->data.location < (int) this->location_base ||
|
||||
var->data.location < VARYING_SLOT_VAR0 ||
|
||||
!this->needs_lowering(var))
|
||||
continue;
|
||||
|
||||
@@ -272,6 +261,7 @@ lower_packed_varyings_visitor::run(exec_list *instructions)
|
||||
!var->type->contains_integer());
|
||||
|
||||
/* Change the old varying into an ordinary global. */
|
||||
assert(var->data.mode != ir_var_temporary);
|
||||
var->data.mode = ir_var_auto;
|
||||
|
||||
/* Create a reference to the old varying. */
|
||||
@@ -542,7 +532,7 @@ lower_packed_varyings_visitor::get_packed_varying_deref(
|
||||
unsigned location, ir_variable *unpacked_var, const char *name,
|
||||
unsigned vertex_index)
|
||||
{
|
||||
unsigned slot = location - this->location_base;
|
||||
unsigned slot = location - VARYING_SLOT_VAR0;
|
||||
assert(slot < locations_used);
|
||||
if (this->packed_varyings[slot] == NULL) {
|
||||
char *packed_name = ralloc_asprintf(this->mem_ctx, "packed:%s", name);
|
||||
@@ -595,7 +585,12 @@ lower_packed_varyings_visitor::get_packed_varying_deref(
|
||||
bool
|
||||
lower_packed_varyings_visitor::needs_lowering(ir_variable *var)
|
||||
{
|
||||
/* Things composed of vec4's don't need lowering. Everything else does. */
|
||||
/* Things composed of vec4's and varyings with explicitly assigned
|
||||
* locations don't need lowering. Everything else does.
|
||||
*/
|
||||
if (var->data.explicit_location)
|
||||
return false;
|
||||
|
||||
const glsl_type *type = var->type;
|
||||
if (this->gs_input_vertices != 0) {
|
||||
assert(type->is_array());
|
||||
@@ -619,7 +614,7 @@ public:
|
||||
explicit lower_packed_varyings_gs_splicer(void *mem_ctx,
|
||||
const exec_list *instructions);
|
||||
|
||||
virtual ir_visitor_status visit(ir_emit_vertex *ev);
|
||||
virtual ir_visitor_status visit_leave(ir_emit_vertex *ev);
|
||||
|
||||
private:
|
||||
/**
|
||||
@@ -643,10 +638,9 @@ lower_packed_varyings_gs_splicer::lower_packed_varyings_gs_splicer(
|
||||
|
||||
|
||||
ir_visitor_status
|
||||
lower_packed_varyings_gs_splicer::visit(ir_emit_vertex *ev)
|
||||
lower_packed_varyings_gs_splicer::visit_leave(ir_emit_vertex *ev)
|
||||
{
|
||||
foreach_list(node, this->instructions) {
|
||||
ir_instruction *ir = (ir_instruction *) node;
|
||||
foreach_in_list(ir_instruction, ir, this->instructions) {
|
||||
ev->insert_before(ir->clone(this->mem_ctx, NULL));
|
||||
}
|
||||
return visit_continue;
|
||||
@@ -654,18 +648,17 @@ lower_packed_varyings_gs_splicer::visit(ir_emit_vertex *ev)
|
||||
|
||||
|
||||
void
|
||||
lower_packed_varyings(void *mem_ctx, unsigned location_base,
|
||||
unsigned locations_used, ir_variable_mode mode,
|
||||
unsigned gs_input_vertices, gl_shader *shader)
|
||||
lower_packed_varyings(void *mem_ctx, unsigned locations_used,
|
||||
ir_variable_mode mode, unsigned gs_input_vertices,
|
||||
gl_shader *shader)
|
||||
{
|
||||
exec_list *instructions = shader->ir;
|
||||
ir_function *main_func = shader->symbols->get_function("main");
|
||||
exec_list void_parameters;
|
||||
ir_function_signature *main_func_sig
|
||||
= main_func->matching_signature(NULL, &void_parameters);
|
||||
= main_func->matching_signature(NULL, &void_parameters, false);
|
||||
exec_list new_instructions;
|
||||
lower_packed_varyings_visitor visitor(mem_ctx, location_base,
|
||||
locations_used, mode,
|
||||
lower_packed_varyings_visitor visitor(mem_ctx, locations_used, mode,
|
||||
gs_input_vertices, &new_instructions);
|
||||
visitor.run(instructions);
|
||||
if (mode == ir_var_shader_out) {
|
||||
|
||||
@@ -40,6 +40,96 @@
|
||||
|
||||
using namespace ir_builder;
|
||||
|
||||
/**
|
||||
* Determine if a thing being dereferenced is row-major
|
||||
*
|
||||
* There is some trickery here.
|
||||
*
|
||||
* If the thing being dereferenced is a member of uniform block \b without an
|
||||
* instance name, then the name of the \c ir_variable is the field name of an
|
||||
* interface type. If this field is row-major, then the thing referenced is
|
||||
* row-major.
|
||||
*
|
||||
* If the thing being dereferenced is a member of uniform block \b with an
|
||||
* instance name, then the last dereference in the tree will be an
|
||||
* \c ir_dereference_record. If that record field is row-major, then the
|
||||
* thing referenced is row-major.
|
||||
*/
|
||||
static bool
|
||||
is_dereferenced_thing_row_major(const ir_dereference *deref)
|
||||
{
|
||||
bool matrix = false;
|
||||
const ir_rvalue *ir = deref;
|
||||
|
||||
while (true) {
|
||||
matrix = matrix || ir->type->without_array()->is_matrix();
|
||||
|
||||
switch (ir->ir_type) {
|
||||
case ir_type_dereference_array: {
|
||||
const ir_dereference_array *const array_deref =
|
||||
(const ir_dereference_array *) ir;
|
||||
|
||||
ir = array_deref->array;
|
||||
break;
|
||||
}
|
||||
|
||||
case ir_type_dereference_record: {
|
||||
const ir_dereference_record *const record_deref =
|
||||
(const ir_dereference_record *) ir;
|
||||
|
||||
ir = record_deref->record;
|
||||
|
||||
const int idx = ir->type->field_index(record_deref->field);
|
||||
assert(idx >= 0);
|
||||
|
||||
const enum glsl_matrix_layout matrix_layout =
|
||||
glsl_matrix_layout(ir->type->fields.structure[idx].matrix_layout);
|
||||
|
||||
switch (matrix_layout) {
|
||||
case GLSL_MATRIX_LAYOUT_INHERITED:
|
||||
break;
|
||||
case GLSL_MATRIX_LAYOUT_COLUMN_MAJOR:
|
||||
return false;
|
||||
case GLSL_MATRIX_LAYOUT_ROW_MAJOR:
|
||||
return matrix || deref->type->without_array()->is_record();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case ir_type_dereference_variable: {
|
||||
const ir_dereference_variable *const var_deref =
|
||||
(const ir_dereference_variable *) ir;
|
||||
|
||||
const enum glsl_matrix_layout matrix_layout =
|
||||
glsl_matrix_layout(var_deref->var->data.matrix_layout);
|
||||
|
||||
switch (matrix_layout) {
|
||||
case GLSL_MATRIX_LAYOUT_INHERITED:
|
||||
assert(!matrix);
|
||||
return false;
|
||||
case GLSL_MATRIX_LAYOUT_COLUMN_MAJOR:
|
||||
return false;
|
||||
case GLSL_MATRIX_LAYOUT_ROW_MAJOR:
|
||||
return matrix || deref->type->without_array()->is_record();
|
||||
}
|
||||
|
||||
unreachable("invalid matrix layout");
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* The tree must have ended with a dereference that wasn't an
|
||||
* ir_dereference_variable. That is invalid, and it should be impossible.
|
||||
*/
|
||||
unreachable("invalid dereference tree");
|
||||
return false;
|
||||
}
|
||||
|
||||
namespace {
|
||||
class lower_ubo_reference_visitor : public ir_rvalue_enter_visitor {
|
||||
public:
|
||||
@@ -50,14 +140,14 @@ public:
|
||||
|
||||
void handle_rvalue(ir_rvalue **rvalue);
|
||||
void emit_ubo_loads(ir_dereference *deref, ir_variable *base_offset,
|
||||
unsigned int deref_offset);
|
||||
unsigned int deref_offset, bool row_major);
|
||||
ir_expression *ubo_load(const struct glsl_type *type,
|
||||
ir_rvalue *offset);
|
||||
|
||||
void *mem_ctx;
|
||||
struct gl_shader *shader;
|
||||
struct gl_uniform_buffer_variable *ubo_var;
|
||||
unsigned uniform_block;
|
||||
ir_rvalue *uniform_block;
|
||||
bool progress;
|
||||
};
|
||||
|
||||
@@ -69,9 +159,11 @@ public:
|
||||
* \c UniformBlocks array.
|
||||
*/
|
||||
static const char *
|
||||
interface_field_name(void *mem_ctx, char *base_name, ir_dereference *d)
|
||||
interface_field_name(void *mem_ctx, char *base_name, ir_dereference *d,
|
||||
ir_rvalue **nonconst_block_index)
|
||||
{
|
||||
ir_constant *previous_index = NULL;
|
||||
ir_rvalue *previous_index = NULL;
|
||||
*nonconst_block_index = NULL;
|
||||
|
||||
while (d != NULL) {
|
||||
switch (d->ir_type) {
|
||||
@@ -79,13 +171,21 @@ interface_field_name(void *mem_ctx, char *base_name, ir_dereference *d)
|
||||
ir_dereference_variable *v = (ir_dereference_variable *) d;
|
||||
if (previous_index
|
||||
&& v->var->is_interface_instance()
|
||||
&& v->var->type->is_array())
|
||||
return ralloc_asprintf(mem_ctx,
|
||||
"%s[%d]",
|
||||
base_name,
|
||||
previous_index->get_uint_component(0));
|
||||
else
|
||||
&& v->var->type->is_array()) {
|
||||
|
||||
ir_constant *const_index = previous_index->as_constant();
|
||||
if (!const_index) {
|
||||
*nonconst_block_index = previous_index;
|
||||
return ralloc_asprintf(mem_ctx, "%s[0]", base_name);
|
||||
} else {
|
||||
return ralloc_asprintf(mem_ctx,
|
||||
"%s[%d]",
|
||||
base_name,
|
||||
const_index->get_uint_component(0));
|
||||
}
|
||||
} else {
|
||||
return base_name;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -101,7 +201,8 @@ interface_field_name(void *mem_ctx, char *base_name, ir_dereference *d)
|
||||
ir_dereference_array *a = (ir_dereference_array *) d;
|
||||
|
||||
d = a->array->as_dereference();
|
||||
previous_index = a->array_index->as_constant();
|
||||
previous_index = a->array_index;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -131,14 +232,24 @@ lower_ubo_reference_visitor::handle_rvalue(ir_rvalue **rvalue)
|
||||
|
||||
mem_ctx = ralloc_parent(*rvalue);
|
||||
|
||||
ir_rvalue *nonconst_block_index;
|
||||
const char *const field_name =
|
||||
interface_field_name(mem_ctx, (char *) var->get_interface_type()->name,
|
||||
deref);
|
||||
deref, &nonconst_block_index);
|
||||
|
||||
this->uniform_block = -1;
|
||||
this->uniform_block = NULL;
|
||||
for (unsigned i = 0; i < shader->NumUniformBlocks; i++) {
|
||||
if (strcmp(field_name, shader->UniformBlocks[i].Name) == 0) {
|
||||
this->uniform_block = i;
|
||||
|
||||
ir_constant *index = new(mem_ctx) ir_constant(i);
|
||||
|
||||
if (nonconst_block_index) {
|
||||
if (nonconst_block_index->type != glsl_type::uint_type)
|
||||
nonconst_block_index = i2u(nonconst_block_index);
|
||||
this->uniform_block = add(nonconst_block_index, index);
|
||||
} else {
|
||||
this->uniform_block = index;
|
||||
}
|
||||
|
||||
struct gl_uniform_block *block = &shader->UniformBlocks[i];
|
||||
|
||||
@@ -149,11 +260,11 @@ lower_ubo_reference_visitor::handle_rvalue(ir_rvalue **rvalue)
|
||||
}
|
||||
}
|
||||
|
||||
assert(this->uniform_block != (unsigned) -1);
|
||||
assert(this->uniform_block);
|
||||
|
||||
ir_rvalue *offset = new(mem_ctx) ir_constant(0u);
|
||||
unsigned const_offset = 0;
|
||||
bool row_major = !!ubo_var->RowMajor;
|
||||
bool row_major = is_dereferenced_thing_row_major(deref);
|
||||
|
||||
/* Calculate the offset to the start of the region of the UBO
|
||||
* dereferenced by *rvalue. This may be a variable offset if an
|
||||
@@ -190,16 +301,28 @@ lower_ubo_reference_visitor::handle_rvalue(ir_rvalue **rvalue)
|
||||
deref = deref_array->array->as_dereference();
|
||||
break;
|
||||
} else {
|
||||
array_stride = deref_array->type->std140_size(row_major);
|
||||
/* Whether or not the field is row-major (because it might be a
|
||||
* bvec2 or something) does not affect the array itself. We need
|
||||
* to know whether an array element in its entirety is row-major.
|
||||
*/
|
||||
const bool array_row_major =
|
||||
is_dereferenced_thing_row_major(deref_array);
|
||||
|
||||
array_stride = deref_array->type->std140_size(array_row_major);
|
||||
array_stride = glsl_align(array_stride, 16);
|
||||
}
|
||||
|
||||
ir_constant *const_index = deref_array->array_index->as_constant();
|
||||
ir_rvalue *array_index = deref_array->array_index;
|
||||
if (array_index->type->base_type == GLSL_TYPE_INT)
|
||||
array_index = i2u(array_index);
|
||||
|
||||
ir_constant *const_index =
|
||||
array_index->constant_expression_value(NULL);
|
||||
if (const_index) {
|
||||
const_offset += array_stride * const_index->value.i[0];
|
||||
const_offset += array_stride * const_index->value.u[0];
|
||||
} else {
|
||||
offset = add(offset,
|
||||
mul(deref_array->array_index,
|
||||
mul(array_index,
|
||||
new(mem_ctx) ir_constant(array_stride)));
|
||||
}
|
||||
deref = deref_array->array->as_dereference();
|
||||
@@ -211,20 +334,49 @@ lower_ubo_reference_visitor::handle_rvalue(ir_rvalue **rvalue)
|
||||
const glsl_type *struct_type = deref_record->record->type;
|
||||
unsigned intra_struct_offset = 0;
|
||||
|
||||
unsigned max_field_align = 16;
|
||||
/* glsl_type::std140_base_alignment doesn't grok interfaces. Use
|
||||
* 16-bytes for the alignment because that is the general minimum of
|
||||
* std140.
|
||||
*/
|
||||
const unsigned struct_alignment = struct_type->is_interface()
|
||||
? 16
|
||||
: struct_type->std140_base_alignment(row_major);
|
||||
|
||||
|
||||
for (unsigned int i = 0; i < struct_type->length; i++) {
|
||||
const glsl_type *type = struct_type->fields.structure[i].type;
|
||||
unsigned field_align = type->std140_base_alignment(row_major);
|
||||
max_field_align = MAX2(field_align, max_field_align);
|
||||
|
||||
ir_dereference_record *field_deref =
|
||||
new(mem_ctx) ir_dereference_record(deref_record->record,
|
||||
struct_type->fields.structure[i].name);
|
||||
const bool field_row_major =
|
||||
is_dereferenced_thing_row_major(field_deref);
|
||||
|
||||
ralloc_free(field_deref);
|
||||
|
||||
unsigned field_align = type->std140_base_alignment(field_row_major);
|
||||
|
||||
intra_struct_offset = glsl_align(intra_struct_offset, field_align);
|
||||
|
||||
if (strcmp(struct_type->fields.structure[i].name,
|
||||
deref_record->field) == 0)
|
||||
break;
|
||||
intra_struct_offset += type->std140_size(row_major);
|
||||
intra_struct_offset += type->std140_size(field_row_major);
|
||||
|
||||
/* If the field just examined was itself a structure, apply rule
|
||||
* #9:
|
||||
*
|
||||
* "The structure may have padding at the end; the base offset
|
||||
* of the member following the sub-structure is rounded up to
|
||||
* the next multiple of the base alignment of the structure."
|
||||
*/
|
||||
if (type->without_array()->is_record()) {
|
||||
intra_struct_offset = glsl_align(intra_struct_offset,
|
||||
struct_alignment);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
const_offset = glsl_align(const_offset, max_field_align);
|
||||
const_offset += intra_struct_offset;
|
||||
|
||||
deref = deref_record->record->as_dereference();
|
||||
@@ -253,7 +405,7 @@ lower_ubo_reference_visitor::handle_rvalue(ir_rvalue **rvalue)
|
||||
base_ir->insert_before(assign(load_offset, offset));
|
||||
|
||||
deref = new(mem_ctx) ir_dereference_variable(load_var);
|
||||
emit_ubo_loads(deref, load_offset, const_offset);
|
||||
emit_ubo_loads(deref, load_offset, const_offset, row_major);
|
||||
*rvalue = deref;
|
||||
|
||||
progress = true;
|
||||
@@ -263,11 +415,12 @@ ir_expression *
|
||||
lower_ubo_reference_visitor::ubo_load(const glsl_type *type,
|
||||
ir_rvalue *offset)
|
||||
{
|
||||
ir_rvalue *block_ref = this->uniform_block->clone(mem_ctx, NULL);
|
||||
return new(mem_ctx)
|
||||
ir_expression(ir_binop_ubo_load,
|
||||
type,
|
||||
new(mem_ctx) ir_constant(this->uniform_block),
|
||||
offset);
|
||||
type,
|
||||
block_ref,
|
||||
offset);
|
||||
|
||||
}
|
||||
|
||||
@@ -282,7 +435,8 @@ lower_ubo_reference_visitor::ubo_load(const glsl_type *type,
|
||||
void
|
||||
lower_ubo_reference_visitor::emit_ubo_loads(ir_dereference *deref,
|
||||
ir_variable *base_offset,
|
||||
unsigned int deref_offset)
|
||||
unsigned int deref_offset,
|
||||
bool row_major)
|
||||
{
|
||||
if (deref->type->is_record()) {
|
||||
unsigned int field_offset = 0;
|
||||
@@ -296,18 +450,19 @@ lower_ubo_reference_visitor::emit_ubo_loads(ir_dereference *deref,
|
||||
|
||||
field_offset =
|
||||
glsl_align(field_offset,
|
||||
field->type->std140_base_alignment(!!ubo_var->RowMajor));
|
||||
field->type->std140_base_alignment(row_major));
|
||||
|
||||
emit_ubo_loads(field_deref, base_offset, deref_offset + field_offset);
|
||||
emit_ubo_loads(field_deref, base_offset, deref_offset + field_offset,
|
||||
row_major);
|
||||
|
||||
field_offset += field->type->std140_size(!!ubo_var->RowMajor);
|
||||
field_offset += field->type->std140_size(row_major);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (deref->type->is_array()) {
|
||||
unsigned array_stride =
|
||||
glsl_align(deref->type->fields.array->std140_size(!!ubo_var->RowMajor),
|
||||
glsl_align(deref->type->fields.array->std140_size(row_major),
|
||||
16);
|
||||
|
||||
for (unsigned i = 0; i < deref->type->length; i++) {
|
||||
@@ -316,7 +471,8 @@ lower_ubo_reference_visitor::emit_ubo_loads(ir_dereference *deref,
|
||||
new(mem_ctx) ir_dereference_array(deref->clone(mem_ctx, NULL),
|
||||
element);
|
||||
emit_ubo_loads(element_deref, base_offset,
|
||||
deref_offset + i * array_stride);
|
||||
deref_offset + i * array_stride,
|
||||
row_major);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -328,10 +484,19 @@ lower_ubo_reference_visitor::emit_ubo_loads(ir_dereference *deref,
|
||||
new(mem_ctx) ir_dereference_array(deref->clone(mem_ctx, NULL),
|
||||
col);
|
||||
|
||||
/* std140 always rounds the stride of arrays (and matrices)
|
||||
* to a vec4, so matrices are always 16 between columns/rows.
|
||||
*/
|
||||
emit_ubo_loads(col_deref, base_offset, deref_offset + i * 16);
|
||||
if (row_major) {
|
||||
/* For a row-major matrix, the next column starts at the next
|
||||
* element.
|
||||
*/
|
||||
emit_ubo_loads(col_deref, base_offset, deref_offset + i * 4,
|
||||
row_major);
|
||||
} else {
|
||||
/* std140 always rounds the stride of arrays (and matrices) to a
|
||||
* vec4, so matrices are always 16 between columns/rows.
|
||||
*/
|
||||
emit_ubo_loads(col_deref, base_offset, deref_offset + i * 16,
|
||||
row_major);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -339,7 +504,7 @@ lower_ubo_reference_visitor::emit_ubo_loads(ir_dereference *deref,
|
||||
assert(deref->type->is_scalar() ||
|
||||
deref->type->is_vector());
|
||||
|
||||
if (!ubo_var->RowMajor) {
|
||||
if (!row_major) {
|
||||
ir_rvalue *offset = add(base_offset,
|
||||
new(mem_ctx) ir_constant(deref_offset));
|
||||
base_ir->insert_before(assign(deref->clone(mem_ctx, NULL),
|
||||
|
||||
@@ -76,7 +76,7 @@ compare_index_block(exec_list *instructions, ir_variable *index,
|
||||
ir_rvalue *broadcast_index = new(mem_ctx) ir_dereference_variable(index);
|
||||
|
||||
assert(index->type->is_scalar());
|
||||
assert(index->type->base_type == GLSL_TYPE_INT);
|
||||
assert(index->type->base_type == GLSL_TYPE_INT || index->type->base_type == GLSL_TYPE_UINT);
|
||||
assert(components >= 1 && components <= 4);
|
||||
|
||||
if (components > 1) {
|
||||
@@ -379,6 +379,7 @@ public:
|
||||
case ir_var_function_out:
|
||||
return this->lower_temps;
|
||||
case ir_var_shader_out:
|
||||
case ir_var_shader_inout:
|
||||
return this->lower_outputs;
|
||||
case ir_var_function_inout:
|
||||
return this->lower_temps;
|
||||
|
||||
@@ -198,8 +198,7 @@ ir_vec_index_to_cond_assign_visitor::visit_leave(ir_assignment *ir)
|
||||
ir_visitor_status
|
||||
ir_vec_index_to_cond_assign_visitor::visit_enter(ir_call *ir)
|
||||
{
|
||||
foreach_list_safe(n, &ir->actual_parameters) {
|
||||
ir_rvalue *param = (ir_rvalue *) n;
|
||||
foreach_in_list_safe(ir_rvalue, param, &ir->actual_parameters) {
|
||||
ir_rvalue *new_param = convert_vector_extract_to_cond_assign(param);
|
||||
|
||||
if (new_param != param) {
|
||||
|
||||
@@ -131,8 +131,7 @@ ir_vec_index_to_swizzle_visitor::visit_enter(ir_assignment *ir)
|
||||
ir_visitor_status
|
||||
ir_vec_index_to_swizzle_visitor::visit_enter(ir_call *ir)
|
||||
{
|
||||
foreach_list_safe(n, &ir->actual_parameters) {
|
||||
ir_rvalue *param = (ir_rvalue *) n;
|
||||
foreach_in_list_safe(ir_rvalue, param, &ir->actual_parameters) {
|
||||
ir_rvalue *new_param = convert_vector_extract_to_swizzle(param);
|
||||
|
||||
if (new_param != param) {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user