Updated glsl-optimizer.

This commit is contained in:
Branimir Karadžić
2014-10-11 12:32:43 -07:00
parent 9126ca8fd7
commit 4a1a31b538
1394 changed files with 40096 additions and 89698 deletions

View File

@@ -1,3 +1,4 @@
node_modules
*.a
*.dll
*.exe
@@ -73,4 +74,5 @@ glsl_compiler
.settings/
.pydevproject
build
build
metalTemp.metal

View File

@@ -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})

View File

@@ -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
-------

View File

@@ -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.

View File

@@ -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"', {

View File

@@ -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;

View File

@@ -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"
}
}

View File

@@ -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">

View File

@@ -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" />

View File

@@ -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;
};

View File

@@ -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

View File

@@ -2,3 +2,7 @@ glsl_compiler
glsl_parser.output
builtincompiler
glsl_test
subtest-cr/
subtest-lf/
subtest-cr-lf/
subtest-lf-cr/

View File

@@ -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

View File

@@ -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)

View File

@@ -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 */
};

View File

@@ -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 "

View File

@@ -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);

File diff suppressed because it is too large Load Diff

View File

@@ -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;
}

View File

@@ -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, &params) {
ir_variable *var = (ir_variable *) node;
foreach_in_list(ir_variable, var, &params) {
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;
}

View File

@@ -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]);
}
}

View File

@@ -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);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -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);
}
}
%%

File diff suppressed because it is too large Load Diff

View File

@@ -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

File diff suppressed because it is too large Load Diff

View File

@@ -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;

View File

@@ -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;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -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);
}
}

View File

@@ -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)

View File

@@ -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.

File diff suppressed because it is too large Load Diff

View File

@@ -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;

File diff suppressed because it is too large Load Diff

View File

@@ -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;

View File

@@ -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) \

View File

@@ -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)
{

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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

View File

@@ -22,7 +22,6 @@
*/
#include "ir.h"
#include "program/symbol_table.h"
#include "glsl_parser_extras.h"
#include "ast.h"
#include "glsl_types.h"

View File

@@ -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";

File diff suppressed because it is too large Load Diff

View File

@@ -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);
}
}

View File

@@ -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)
{

View File

@@ -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);

View File

@@ -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);

View File

@@ -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;

View File

@@ -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)

View File

@@ -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);
}
}

View File

@@ -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;

View File

@@ -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();
}
}

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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,

View File

@@ -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();

View File

@@ -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 */

File diff suppressed because it is too large Load Diff

View 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 */

View File

@@ -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");
}

View File

@@ -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;
};

View File

@@ -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);
}

View File

@@ -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 *);
};

View File

@@ -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

View File

@@ -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)

View File

@@ -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

View File

@@ -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) {

View File

@@ -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;
};

View File

@@ -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() ?

View File

@@ -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))

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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);

View File

@@ -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);
}
}
}

View File

@@ -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;
}

View File

@@ -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();
}
}

View File

@@ -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;
};

View File

@@ -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) {

View File

@@ -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 *

View File

@@ -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 */

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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)

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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,

View 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;
}

View File

@@ -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);

View File

@@ -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) {

View File

@@ -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),

View File

@@ -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;

View File

@@ -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) {

View File

@@ -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