From c6537ac8b8130cf2271c8d1e51137a575073c762 Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Tue, 30 Dec 2008 17:11:32 -0700 Subject: [PATCH] mesa: allow variable indexing into the predefined uniform variable arrays This allows code such as "vec4 a = gl_LightSource[i].ambient;" to work. When a built-in uniform array is indexed with a variable index we need to "unroll" the whole array into the parameter list (aka constant buffer) because we don't know which elements may be accessed at compile-time. In the case of the gl_LightSource array of size [8], we emit 64 state references into the parameter array (8 elements times 8 vec4s per gl_LightSourceParameters struct). Previously, we only allowed constant-indexed references to uniform arrays (such as gl_LightSource[2].position) which resulted in a single state reference being added to the parameter array, not 64. We still optimize this case. Users should be aware that using "gl_LightSource[i].ambient" in their shaders is a bit expensive since state validation will involve updating all 64 light source entries in the parameter list. --- .../slang/library/slang_common_builtin.gc | 12 +- .../slang/library/slang_common_builtin_gc.h | 102 +++--- src/mesa/shader/slang/slang_builtin.c | 299 ++++++++++++++++-- src/mesa/shader/slang/slang_builtin.h | 3 +- src/mesa/shader/slang/slang_emit.c | 51 ++- 5 files changed, 376 insertions(+), 91 deletions(-) diff --git a/src/mesa/shader/slang/library/slang_common_builtin.gc b/src/mesa/shader/slang/library/slang_common_builtin.gc index a051c53eea3..3e03b101b87 100644 --- a/src/mesa/shader/slang/library/slang_common_builtin.gc +++ b/src/mesa/shader/slang/library/slang_common_builtin.gc @@ -1,8 +1,9 @@ /* * Mesa 3-D graphics library - * Version: 6.5 + * Version: 7.3 * * Copyright (C) 2006 Brian Paul All Rights Reserved. + * Copyright (C) 2008 VMware, Inc. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -98,6 +99,9 @@ struct gl_MaterialParameters { uniform gl_MaterialParameters gl_FrontMaterial; uniform gl_MaterialParameters gl_BackMaterial; +/* NOTE: the order of these fields is significant! + * See the definition of the lighting state vars such as STATE_SPOT_DIRECTION. + */ struct gl_LightSourceParameters { vec4 ambient; vec4 diffuse; @@ -105,12 +109,14 @@ struct gl_LightSourceParameters { vec4 position; vec4 halfVector; vec3 spotDirection; - float spotExponent; - float spotCutoff; float spotCosCutoff; + float constantAttenuation; float linearAttenuation; float quadraticAttenuation; + float spotExponent; + + float spotCutoff; }; uniform gl_LightSourceParameters gl_LightSource[gl_MaxLights]; diff --git a/src/mesa/shader/slang/library/slang_common_builtin_gc.h b/src/mesa/shader/slang/library/slang_common_builtin_gc.h index 46632010815..759bf247d80 100644 --- a/src/mesa/shader/slang/library/slang_common_builtin_gc.h +++ b/src/mesa/shader/slang/library/slang_common_builtin_gc.h @@ -66,58 +66,58 @@ 116,83,111,117,114,99,101,80,97,114,97,109,101,116,101,114,115,0,12,0,97,109,98,105,101,110,116,0, 0,0,1,12,0,100,105,102,102,117,115,101,0,0,0,1,12,0,115,112,101,99,117,108,97,114,0,0,0,1,12,0,112, 111,115,105,116,105,111,110,0,0,0,1,12,0,104,97,108,102,86,101,99,116,111,114,0,0,0,1,11,0,115,112, -111,116,68,105,114,101,99,116,105,111,110,0,0,0,1,9,0,115,112,111,116,69,120,112,111,110,101,110, -116,0,0,0,1,9,0,115,112,111,116,67,117,116,111,102,102,0,0,0,1,9,0,115,112,111,116,67,111,115,67, -117,116,111,102,102,0,0,0,1,9,0,99,111,110,115,116,97,110,116,65,116,116,101,110,117,97,116,105, -111,110,0,0,0,1,9,0,108,105,110,101,97,114,65,116,116,101,110,117,97,116,105,111,110,0,0,0,1,9,0, -113,117,97,100,114,97,116,105,99,65,116,116,101,110,117,97,116,105,111,110,0,0,0,0,0,0,0,2,2,90,95, -4,0,25,103,108,95,76,105,103,104,116,83,111,117,114,99,101,80,97,114,97,109,101,116,101,114,115,0, -0,1,103,108,95,76,105,103,104,116,83,111,117,114,99,101,0,3,18,103,108,95,77,97,120,76,105,103,104, -116,115,0,0,0,2,2,90,95,0,0,24,103,108,95,76,105,103,104,116,77,111,100,101,108,80,97,114,97,109, -101,116,101,114,115,0,12,0,97,109,98,105,101,110,116,0,0,0,0,0,0,0,2,2,90,95,4,0,25,103,108,95,76, -105,103,104,116,77,111,100,101,108,80,97,114,97,109,101,116,101,114,115,0,0,1,103,108,95,76,105, -103,104,116,77,111,100,101,108,0,0,0,2,2,90,95,0,0,24,103,108,95,76,105,103,104,116,77,111,100,101, -108,80,114,111,100,117,99,116,115,0,12,0,115,99,101,110,101,67,111,108,111,114,0,0,0,0,0,0,0,2,2, -90,95,4,0,25,103,108,95,76,105,103,104,116,77,111,100,101,108,80,114,111,100,117,99,116,115,0,0,1, -103,108,95,70,114,111,110,116,76,105,103,104,116,77,111,100,101,108,80,114,111,100,117,99,116,0,0, -0,2,2,90,95,4,0,25,103,108,95,76,105,103,104,116,77,111,100,101,108,80,114,111,100,117,99,116,115, -0,0,1,103,108,95,66,97,99,107,76,105,103,104,116,77,111,100,101,108,80,114,111,100,117,99,116,0,0, -0,2,2,90,95,0,0,24,103,108,95,76,105,103,104,116,80,114,111,100,117,99,116,115,0,12,0,97,109,98, -105,101,110,116,0,0,0,1,12,0,100,105,102,102,117,115,101,0,0,0,1,12,0,115,112,101,99,117,108,97, -114,0,0,0,0,0,0,0,2,2,90,95,4,0,25,103,108,95,76,105,103,104,116,80,114,111,100,117,99,116,115,0,0, -1,103,108,95,70,114,111,110,116,76,105,103,104,116,80,114,111,100,117,99,116,0,3,18,103,108,95,77, -97,120,76,105,103,104,116,115,0,0,0,2,2,90,95,4,0,25,103,108,95,76,105,103,104,116,80,114,111,100, -117,99,116,115,0,0,1,103,108,95,66,97,99,107,76,105,103,104,116,80,114,111,100,117,99,116,0,3,18, -103,108,95,77,97,120,76,105,103,104,116,115,0,0,0,2,2,90,95,4,0,12,0,1,103,108,95,84,101,120,116, -117,114,101,69,110,118,67,111,108,111,114,0,3,18,103,108,95,77,97,120,84,101,120,116,117,114,101, -73,109,97,103,101,85,110,105,116,115,0,0,0,2,2,90,95,4,0,12,0,1,103,108,95,69,121,101,80,108,97, +111,116,68,105,114,101,99,116,105,111,110,0,0,0,1,9,0,115,112,111,116,67,111,115,67,117,116,111, +102,102,0,0,0,1,9,0,99,111,110,115,116,97,110,116,65,116,116,101,110,117,97,116,105,111,110,0,0,0, +1,9,0,108,105,110,101,97,114,65,116,116,101,110,117,97,116,105,111,110,0,0,0,1,9,0,113,117,97,100, +114,97,116,105,99,65,116,116,101,110,117,97,116,105,111,110,0,0,0,1,9,0,115,112,111,116,69,120,112, +111,110,101,110,116,0,0,0,1,9,0,115,112,111,116,67,117,116,111,102,102,0,0,0,0,0,0,0,2,2,90,95,4,0, +25,103,108,95,76,105,103,104,116,83,111,117,114,99,101,80,97,114,97,109,101,116,101,114,115,0,0,1, +103,108,95,76,105,103,104,116,83,111,117,114,99,101,0,3,18,103,108,95,77,97,120,76,105,103,104,116, +115,0,0,0,2,2,90,95,0,0,24,103,108,95,76,105,103,104,116,77,111,100,101,108,80,97,114,97,109,101, +116,101,114,115,0,12,0,97,109,98,105,101,110,116,0,0,0,0,0,0,0,2,2,90,95,4,0,25,103,108,95,76,105, +103,104,116,77,111,100,101,108,80,97,114,97,109,101,116,101,114,115,0,0,1,103,108,95,76,105,103, +104,116,77,111,100,101,108,0,0,0,2,2,90,95,0,0,24,103,108,95,76,105,103,104,116,77,111,100,101,108, +80,114,111,100,117,99,116,115,0,12,0,115,99,101,110,101,67,111,108,111,114,0,0,0,0,0,0,0,2,2,90,95, +4,0,25,103,108,95,76,105,103,104,116,77,111,100,101,108,80,114,111,100,117,99,116,115,0,0,1,103, +108,95,70,114,111,110,116,76,105,103,104,116,77,111,100,101,108,80,114,111,100,117,99,116,0,0,0,2, +2,90,95,4,0,25,103,108,95,76,105,103,104,116,77,111,100,101,108,80,114,111,100,117,99,116,115,0,0, +1,103,108,95,66,97,99,107,76,105,103,104,116,77,111,100,101,108,80,114,111,100,117,99,116,0,0,0,2, +2,90,95,0,0,24,103,108,95,76,105,103,104,116,80,114,111,100,117,99,116,115,0,12,0,97,109,98,105, +101,110,116,0,0,0,1,12,0,100,105,102,102,117,115,101,0,0,0,1,12,0,115,112,101,99,117,108,97,114,0, +0,0,0,0,0,0,2,2,90,95,4,0,25,103,108,95,76,105,103,104,116,80,114,111,100,117,99,116,115,0,0,1,103, +108,95,70,114,111,110,116,76,105,103,104,116,80,114,111,100,117,99,116,0,3,18,103,108,95,77,97,120, +76,105,103,104,116,115,0,0,0,2,2,90,95,4,0,25,103,108,95,76,105,103,104,116,80,114,111,100,117,99, +116,115,0,0,1,103,108,95,66,97,99,107,76,105,103,104,116,80,114,111,100,117,99,116,0,3,18,103,108, +95,77,97,120,76,105,103,104,116,115,0,0,0,2,2,90,95,4,0,12,0,1,103,108,95,84,101,120,116,117,114, +101,69,110,118,67,111,108,111,114,0,3,18,103,108,95,77,97,120,84,101,120,116,117,114,101,73,109,97, +103,101,85,110,105,116,115,0,0,0,2,2,90,95,4,0,12,0,1,103,108,95,69,121,101,80,108,97,110,101,83,0, +3,18,103,108,95,77,97,120,84,101,120,116,117,114,101,67,111,111,114,100,115,0,0,0,2,2,90,95,4,0,12, +0,1,103,108,95,69,121,101,80,108,97,110,101,84,0,3,18,103,108,95,77,97,120,84,101,120,116,117,114, +101,67,111,111,114,100,115,0,0,0,2,2,90,95,4,0,12,0,1,103,108,95,69,121,101,80,108,97,110,101,82,0, +3,18,103,108,95,77,97,120,84,101,120,116,117,114,101,67,111,111,114,100,115,0,0,0,2,2,90,95,4,0,12, +0,1,103,108,95,69,121,101,80,108,97,110,101,81,0,3,18,103,108,95,77,97,120,84,101,120,116,117,114, +101,67,111,111,114,100,115,0,0,0,2,2,90,95,4,0,12,0,1,103,108,95,79,98,106,101,99,116,80,108,97, 110,101,83,0,3,18,103,108,95,77,97,120,84,101,120,116,117,114,101,67,111,111,114,100,115,0,0,0,2,2, -90,95,4,0,12,0,1,103,108,95,69,121,101,80,108,97,110,101,84,0,3,18,103,108,95,77,97,120,84,101,120, -116,117,114,101,67,111,111,114,100,115,0,0,0,2,2,90,95,4,0,12,0,1,103,108,95,69,121,101,80,108,97, -110,101,82,0,3,18,103,108,95,77,97,120,84,101,120,116,117,114,101,67,111,111,114,100,115,0,0,0,2,2, -90,95,4,0,12,0,1,103,108,95,69,121,101,80,108,97,110,101,81,0,3,18,103,108,95,77,97,120,84,101,120, -116,117,114,101,67,111,111,114,100,115,0,0,0,2,2,90,95,4,0,12,0,1,103,108,95,79,98,106,101,99,116, -80,108,97,110,101,83,0,3,18,103,108,95,77,97,120,84,101,120,116,117,114,101,67,111,111,114,100,115, -0,0,0,2,2,90,95,4,0,12,0,1,103,108,95,79,98,106,101,99,116,80,108,97,110,101,84,0,3,18,103,108,95, -77,97,120,84,101,120,116,117,114,101,67,111,111,114,100,115,0,0,0,2,2,90,95,4,0,12,0,1,103,108,95, -79,98,106,101,99,116,80,108,97,110,101,82,0,3,18,103,108,95,77,97,120,84,101,120,116,117,114,101, -67,111,111,114,100,115,0,0,0,2,2,90,95,4,0,12,0,1,103,108,95,79,98,106,101,99,116,80,108,97,110, -101,81,0,3,18,103,108,95,77,97,120,84,101,120,116,117,114,101,67,111,111,114,100,115,0,0,0,2,2,90, -95,0,0,24,103,108,95,70,111,103,80,97,114,97,109,101,116,101,114,115,0,12,0,99,111,108,111,114,0,0, -0,1,9,0,100,101,110,115,105,116,121,0,0,0,1,9,0,115,116,97,114,116,0,0,0,1,9,0,101,110,100,0,0,0,1, -9,0,115,99,97,108,101,0,0,0,0,0,0,0,2,2,90,95,4,0,25,103,108,95,70,111,103,80,97,114,97,109,101, -116,101,114,115,0,0,1,103,108,95,70,111,103,0,0,0,1,90,95,0,0,9,0,0,114,97,100,105,97,110,115,0,1, -1,0,0,9,0,100,101,103,0,0,0,1,3,2,90,95,1,0,9,0,1,99,0,2,17,51,0,49,52,49,53,57,50,54,0,0,17,49,56, -48,0,48,0,0,49,0,0,4,118,101,99,52,95,109,117,108,116,105,112,108,121,0,18,95,95,114,101,116,86,97, -108,0,0,18,100,101,103,0,0,18,99,0,0,0,0,1,90,95,0,0,10,0,0,114,97,100,105,97,110,115,0,1,1,0,0,10, -0,100,101,103,0,0,0,1,3,2,90,95,1,0,9,0,1,99,0,2,17,51,0,49,52,49,53,57,50,54,0,0,17,49,56,48,0,48, -0,0,49,0,0,4,118,101,99,52,95,109,117,108,116,105,112,108,121,0,18,95,95,114,101,116,86,97,108,0, -59,120,121,0,0,18,100,101,103,0,59,120,121,0,0,18,99,0,59,120,120,0,0,0,0,1,90,95,0,0,11,0,0,114, -97,100,105,97,110,115,0,1,1,0,0,11,0,100,101,103,0,0,0,1,3,2,90,95,1,0,9,0,1,99,0,2,17,51,0,49,52, -49,53,57,50,54,0,0,17,49,56,48,0,48,0,0,49,0,0,4,118,101,99,52,95,109,117,108,116,105,112,108,121, -0,18,95,95,114,101,116,86,97,108,0,59,120,121,122,0,0,18,100,101,103,0,59,120,121,122,0,0,18,99,0, -59,120,120,120,0,0,0,0,1,90,95,0,0,12,0,0,114,97,100,105,97,110,115,0,1,1,0,0,12,0,100,101,103,0,0, -0,1,3,2,90,95,1,0,9,0,1,99,0,2,17,51,0,49,52,49,53,57,50,54,0,0,17,49,56,48,0,48,0,0,49,0,0,4,118, +90,95,4,0,12,0,1,103,108,95,79,98,106,101,99,116,80,108,97,110,101,84,0,3,18,103,108,95,77,97,120, +84,101,120,116,117,114,101,67,111,111,114,100,115,0,0,0,2,2,90,95,4,0,12,0,1,103,108,95,79,98,106, +101,99,116,80,108,97,110,101,82,0,3,18,103,108,95,77,97,120,84,101,120,116,117,114,101,67,111,111, +114,100,115,0,0,0,2,2,90,95,4,0,12,0,1,103,108,95,79,98,106,101,99,116,80,108,97,110,101,81,0,3,18, +103,108,95,77,97,120,84,101,120,116,117,114,101,67,111,111,114,100,115,0,0,0,2,2,90,95,0,0,24,103, +108,95,70,111,103,80,97,114,97,109,101,116,101,114,115,0,12,0,99,111,108,111,114,0,0,0,1,9,0,100, +101,110,115,105,116,121,0,0,0,1,9,0,115,116,97,114,116,0,0,0,1,9,0,101,110,100,0,0,0,1,9,0,115,99, +97,108,101,0,0,0,0,0,0,0,2,2,90,95,4,0,25,103,108,95,70,111,103,80,97,114,97,109,101,116,101,114, +115,0,0,1,103,108,95,70,111,103,0,0,0,1,90,95,0,0,9,0,0,114,97,100,105,97,110,115,0,1,1,0,0,9,0, +100,101,103,0,0,0,1,3,2,90,95,1,0,9,0,1,99,0,2,17,51,0,49,52,49,53,57,50,54,0,0,17,49,56,48,0,48,0, +0,49,0,0,4,118,101,99,52,95,109,117,108,116,105,112,108,121,0,18,95,95,114,101,116,86,97,108,0,0, +18,100,101,103,0,0,18,99,0,0,0,0,1,90,95,0,0,10,0,0,114,97,100,105,97,110,115,0,1,1,0,0,10,0,100, +101,103,0,0,0,1,3,2,90,95,1,0,9,0,1,99,0,2,17,51,0,49,52,49,53,57,50,54,0,0,17,49,56,48,0,48,0,0, +49,0,0,4,118,101,99,52,95,109,117,108,116,105,112,108,121,0,18,95,95,114,101,116,86,97,108,0,59, +120,121,0,0,18,100,101,103,0,59,120,121,0,0,18,99,0,59,120,120,0,0,0,0,1,90,95,0,0,11,0,0,114,97, +100,105,97,110,115,0,1,1,0,0,11,0,100,101,103,0,0,0,1,3,2,90,95,1,0,9,0,1,99,0,2,17,51,0,49,52,49, +53,57,50,54,0,0,17,49,56,48,0,48,0,0,49,0,0,4,118,101,99,52,95,109,117,108,116,105,112,108,121,0, +18,95,95,114,101,116,86,97,108,0,59,120,121,122,0,0,18,100,101,103,0,59,120,121,122,0,0,18,99,0,59, +120,120,120,0,0,0,0,1,90,95,0,0,12,0,0,114,97,100,105,97,110,115,0,1,1,0,0,12,0,100,101,103,0,0,0, +1,3,2,90,95,1,0,9,0,1,99,0,2,17,51,0,49,52,49,53,57,50,54,0,0,17,49,56,48,0,48,0,0,49,0,0,4,118, 101,99,52,95,109,117,108,116,105,112,108,121,0,18,95,95,114,101,116,86,97,108,0,0,18,100,101,103,0, 0,18,99,0,59,120,120,120,120,0,0,0,0,1,90,95,0,0,9,0,0,100,101,103,114,101,101,115,0,1,1,0,0,9,0, 114,97,100,0,0,0,1,3,2,90,95,1,0,9,0,1,99,0,2,17,49,56,48,0,48,0,0,17,51,0,49,52,49,53,57,50,54,0, diff --git a/src/mesa/shader/slang/slang_builtin.c b/src/mesa/shader/slang/slang_builtin.c index db00c54b8a2..c0f4c79e136 100644 --- a/src/mesa/shader/slang/slang_builtin.c +++ b/src/mesa/shader/slang/slang_builtin.c @@ -1,8 +1,9 @@ /* * Mesa 3-D graphics library - * Version: 6.5.3 + * Version: 7.3 * * Copyright (C) 2005-2007 Brian Paul All Rights Reserved. + * Copyright (C) 2008 VMware, Inc. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -39,6 +40,10 @@ #include "shader/slang/slang_builtin.h" +/** special state token (see below) */ +#define STATE_ARRAY ((gl_state_index) 0xfffff) + + /** * Lookup GL state given a variable name, 0, 1 or 2 indexes and a field. * Allocate room for the state in the given param list and return position @@ -132,6 +137,8 @@ lookup_statevar(const char *var, GLint index1, GLint index2, const char *field, } } else if (strcmp(var, "gl_ClipPlane") == 0) { + if (index1 < 0) + return -1; tokens[0] = STATE_CLIPPLANE; tokens[1] = index1; } @@ -196,8 +203,12 @@ lookup_statevar(const char *var, GLint index1, GLint index2, const char *field, } } else if (strcmp(var, "gl_LightSource") == 0) { + if (!field || index1 < 0) + return -1; + tokens[0] = STATE_LIGHT; tokens[1] = index1; + if (strcmp(field, "ambient") == 0) { tokens[2] = STATE_AMBIENT; } @@ -272,6 +283,9 @@ lookup_statevar(const char *var, GLint index1, GLint index2, const char *field, } else if (strcmp(var, "gl_FrontLightProduct") == 0 || strcmp(var, "gl_BackLightProduct") == 0) { + if (index1 < 0 || !field) + return -1; + tokens[0] = STATE_LIGHTPROD; tokens[1] = index1; /* light number */ if (strcmp(var, "gl_FrontLightProduct") == 0) { @@ -294,45 +308,63 @@ lookup_statevar(const char *var, GLint index1, GLint index2, const char *field, } } else if (strcmp(var, "gl_TextureEnvColor") == 0) { + if (index1 < 0) + return -1; tokens[0] = STATE_TEXENV_COLOR; tokens[1] = index1; } else if (strcmp(var, "gl_EyePlaneS") == 0) { + if (index1 < 0) + return -1; tokens[0] = STATE_TEXGEN; tokens[1] = index1; /* tex unit */ tokens[2] = STATE_TEXGEN_EYE_S; } else if (strcmp(var, "gl_EyePlaneT") == 0) { + if (index1 < 0) + return -1; tokens[0] = STATE_TEXGEN; tokens[1] = index1; /* tex unit */ tokens[2] = STATE_TEXGEN_EYE_T; } else if (strcmp(var, "gl_EyePlaneR") == 0) { + if (index1 < 0) + return -1; tokens[0] = STATE_TEXGEN; tokens[1] = index1; /* tex unit */ tokens[2] = STATE_TEXGEN_EYE_R; } else if (strcmp(var, "gl_EyePlaneQ") == 0) { + if (index1 < 0) + return -1; tokens[0] = STATE_TEXGEN; tokens[1] = index1; /* tex unit */ tokens[2] = STATE_TEXGEN_EYE_Q; } else if (strcmp(var, "gl_ObjectPlaneS") == 0) { + if (index1 < 0) + return -1; tokens[0] = STATE_TEXGEN; tokens[1] = index1; /* tex unit */ tokens[2] = STATE_TEXGEN_OBJECT_S; } else if (strcmp(var, "gl_ObjectPlaneT") == 0) { + if (index1 < 0) + return -1; tokens[0] = STATE_TEXGEN; tokens[1] = index1; /* tex unit */ tokens[2] = STATE_TEXGEN_OBJECT_T; } else if (strcmp(var, "gl_ObjectPlaneR") == 0) { + if (index1 < 0) + return -1; tokens[0] = STATE_TEXGEN; tokens[1] = index1; /* tex unit */ tokens[2] = STATE_TEXGEN_OBJECT_R; } else if (strcmp(var, "gl_ObjectPlaneQ") == 0) { + if (index1 < 0) + return -1; tokens[0] = STATE_TEXGEN; tokens[1] = index1; /* tex unit */ tokens[2] = STATE_TEXGEN_OBJECT_Q; @@ -386,13 +418,222 @@ lookup_statevar(const char *var, GLint index1, GLint index2, const char *field, } + +/** + * Given a variable name and datatype, emit uniform/constant buffer + * entries which will store that state variable. + * For example, if name="gl_LightSource" we'll emit 64 state variable + * vectors/references and return position where that data starts. This will + * allow run-time array indexing into the light source array. + * + * Note that this is a recursive function. + * + * \return -1 if error, else index of start of data in the program parameter list + */ +static GLint +emit_statevars(const char *name, int array_len, + const slang_type_specifier *type, + gl_state_index tokens[STATE_LENGTH], + struct gl_program_parameter_list *paramList) +{ + if (type->type == SLANG_SPEC_ARRAY) { + GLint i, pos; + assert(array_len > 0); + if (strcmp(name, "gl_ClipPlane") == 0) { + tokens[0] = STATE_CLIPPLANE; + } + else if (strcmp(name, "gl_LightSource") == 0) { + tokens[0] = STATE_LIGHT; + } + else if (strcmp(name, "gl_FrontLightProduct") == 0) { + tokens[0] = STATE_LIGHTPROD; + tokens[2] = 0; /* front */ + } + else if (strcmp(name, "gl_BackLightProduct") == 0) { + tokens[0] = STATE_LIGHTPROD; + tokens[2] = 1; /* back */ + } + else if (strcmp(name, "gl_TextureEnvColor") == 0) { + tokens[0] = STATE_TEXENV_COLOR; + } + else if (strcmp(name, "gl_EyePlaneS") == 0) { + tokens[0] = STATE_TEXGEN_EYE_S; + } + else if (strcmp(name, "gl_EyePlaneT") == 0) { + tokens[0] = STATE_TEXGEN_EYE_T; + } + else if (strcmp(name, "gl_EyePlaneR") == 0) { + tokens[0] = STATE_TEXGEN_EYE_R; + } + else if (strcmp(name, "gl_EyePlaneQ") == 0) { + tokens[0] = STATE_TEXGEN_EYE_Q; + } + else if (strcmp(name, "gl_ObjectPlaneS") == 0) { + tokens[0] = STATE_TEXGEN_OBJECT_S; + } + else if (strcmp(name, "gl_ObjectPlaneT") == 0) { + tokens[0] = STATE_TEXGEN_OBJECT_T; + } + else if (strcmp(name, "gl_ObjectPlaneR") == 0) { + tokens[0] = STATE_TEXGEN_OBJECT_R; + } + else if (strcmp(name, "gl_ObjectPlaneQ") == 0) { + tokens[0] = STATE_TEXGEN_OBJECT_Q; + } + else { + return -1; /* invalid array name */ + } + for (i = 0; i < array_len; i++) { + GLint p; + tokens[1] = i; + p = emit_statevars(NULL, 0, type->_array, tokens, paramList); + if (i == 0) + pos = p; + } + return pos; + } + else if (type->type == SLANG_SPEC_STRUCT) { + const slang_variable_scope *fields = type->_struct->fields; + GLuint i, pos; + for (i = 0; i < fields->num_variables; i++) { + const slang_variable *var = fields->variables[i]; + GLint p = emit_statevars(var->a_name, 0, &var->type.specifier, + tokens, paramList); + if (i == 0) + pos = p; + } + return pos; + } + else { + GLint pos; + assert(type->type == SLANG_SPEC_VEC4 || + type->type == SLANG_SPEC_VEC3 || + type->type == SLANG_SPEC_VEC2 || + type->type == SLANG_SPEC_FLOAT || + type->type == SLANG_SPEC_IVEC4 || + type->type == SLANG_SPEC_IVEC3 || + type->type == SLANG_SPEC_IVEC2 || + type->type == SLANG_SPEC_INT); + if (name) { + GLint t; + + if (tokens[0] == STATE_LIGHT) + t = 2; + else if (tokens[0] == STATE_LIGHTPROD) + t = 3; + else + return -1; /* invalid array name */ + + if (strcmp(name, "ambient") == 0) { + tokens[t] = STATE_AMBIENT; + } + else if (strcmp(name, "diffuse") == 0) { + tokens[t] = STATE_DIFFUSE; + } + else if (strcmp(name, "specular") == 0) { + tokens[t] = STATE_SPECULAR; + } + else if (strcmp(name, "position") == 0) { + tokens[t] = STATE_POSITION; + } + else if (strcmp(name, "halfVector") == 0) { + tokens[t] = STATE_HALF_VECTOR; + } + else if (strcmp(name, "spotDirection") == 0) { + tokens[t] = STATE_SPOT_DIRECTION; /* xyz components */ + } + else if (strcmp(name, "spotCosCutoff") == 0) { + tokens[t] = STATE_SPOT_DIRECTION; /* w component */ + } + + else if (strcmp(name, "constantAttenuation") == 0) { + tokens[t] = STATE_ATTENUATION; /* x component */ + } + else if (strcmp(name, "linearAttenuation") == 0) { + tokens[t] = STATE_ATTENUATION; /* y component */ + } + else if (strcmp(name, "quadraticAttenuation") == 0) { + tokens[t] = STATE_ATTENUATION; /* z component */ + } + else if (strcmp(name, "spotExponent") == 0) { + tokens[t] = STATE_ATTENUATION; /* w = spot exponent */ + } + + else if (strcmp(name, "spotCutoff") == 0) { + tokens[t] = STATE_SPOT_CUTOFF; /* x component */ + } + + else { + return -1; /* invalid field name */ + } + } + + pos = _mesa_add_state_reference(paramList, tokens); + return pos; + } + + return 1; +} + + +/** + * Unroll the named built-in uniform variable into a sequence of state + * vars in the given parameter list. + */ +static GLint +alloc_state_var_array(const slang_variable *var, + struct gl_program_parameter_list *paramList) +{ + gl_state_index tokens[STATE_LENGTH]; + GLuint i; + GLint pos; + + /* Initialize the state tokens array. This is very important. + * When we call _mesa_add_state_reference() it'll searches the parameter + * list to see if the given statevar token sequence is already present. + * This is normally a good thing since it prevents redundant values in the + * constant buffer. + * + * But when we're building arrays of state this can be bad. For example, + * consider this fragment of GLSL code: + * foo = gl_LightSource[3].diffuse; + * ... + * bar = gl_LightSource[i].diffuse; + * + * When we unroll the gl_LightSource array (for "bar") we want to re-emit + * gl_LightSource[3].diffuse and not re-use the first instance (from "foo") + * since that would upset the array layout. We handle this situation by + * setting the last token in the state var token array to the special + * value STATE_ARRAY. + * This token will only be set for array state. We can hijack the last + * element in the array for this since it's never used for light, clipplane + * or texture env array state. + */ + for (i = 0; i < STATE_LENGTH; i++) + tokens[i] = 0; + tokens[STATE_LENGTH - 1] = STATE_ARRAY; + + pos = emit_statevars(var->a_name, var->array_len, &var->type.specifier, + tokens, paramList); + + return pos; +} + + + /** * Allocate storage for a pre-defined uniform (a GL state variable). * As a memory-saving optimization, we try to only allocate storage for * state vars that are actually used. - * For example, the "gl_LightSource" uniform is huge. If we only use - * a handful of gl_LightSource fields, we don't want to allocate storage - * for all of gl_LightSource. + * + * Arrays such as gl_LightSource are handled specially. For an expression + * like "gl_LightSource[2].diffuse", we can allocate a single uniform/constant + * slot and return the index. In this case, we return direct=TRUE. + * + * Buf for something like "gl_LightSource[i].diffuse" we don't know the value + * of 'i' at compile time so we need to "unroll" the gl_LightSource array + * into a consecutive sequence of uniform/constant slots so it can be indexed + * at runtime. In this case, we return direct=FALSE. * * Currently, all pre-defined uniforms are in one of these forms: * var @@ -401,52 +642,62 @@ lookup_statevar(const char *var, GLint index1, GLint index2, const char *field, * var[i].field * var[i][j] * - * \return -1 upon error, else position in paramList of the state var/data + * \return -1 upon error, else position in paramList of the state variable/data */ GLint _slang_alloc_statevar(slang_ir_node *n, - struct gl_program_parameter_list *paramList) + struct gl_program_parameter_list *paramList, + GLboolean *direct) { slang_ir_node *n0 = n; - const char *field = NULL, *var; - GLint index1 = -1, index2 = -1, pos; + const char *field = NULL; + GLint index1 = -1, index2 = -1; GLuint swizzle; + *direct = GL_TRUE; + if (n->Opcode == IR_FIELD) { field = n->Field; n = n->Children[0]; } if (n->Opcode == IR_ELEMENT) { - /* XXX can only handle constant indexes for now */ if (n->Children[1]->Opcode == IR_FLOAT) { index1 = (GLint) n->Children[1]->Value[0]; - n = n->Children[0]; } else { - return -1; + *direct = GL_FALSE; } + n = n->Children[0]; } if (n->Opcode == IR_ELEMENT) { /* XXX can only handle constant indexes for now */ - assert(n->Children[1]->Opcode == IR_FLOAT); - index2 = (GLint) n->Children[1]->Value[0]; + if (n->Children[1]->Opcode == IR_FLOAT) { + index2 = (GLint) n->Children[1]->Value[0]; + } + else { + *direct = GL_FALSE; + } n = n->Children[0]; } assert(n->Opcode == IR_VAR); - var = (char *) n->Var->a_name; - pos = lookup_statevar(var, index1, index2, field, &swizzle, paramList); - assert(pos >= 0); - if (pos >= 0) { - /* newly resolved storage for the statevar/constant/uniform */ - n0->Store->File = PROGRAM_STATE_VAR; - n0->Store->Index = pos; - n0->Store->Swizzle = swizzle; - n0->Store->Parent = NULL; + if (*direct) { + const char *var = (const char *) n->Var->a_name; + GLint pos = + lookup_statevar(var, index1, index2, field, &swizzle, paramList); + if (pos >= 0) { + /* newly resolved storage for the statevar/constant/uniform */ + n0->Store->File = PROGRAM_STATE_VAR; + n0->Store->Index = pos; + n0->Store->Swizzle = swizzle; + n0->Store->Parent = NULL; + return pos; + } } - return pos; -} + *direct = GL_FALSE; + return alloc_state_var_array(n->Var, paramList); +} diff --git a/src/mesa/shader/slang/slang_builtin.h b/src/mesa/shader/slang/slang_builtin.h index 58629f4f7fe..7f6fe80fcca 100644 --- a/src/mesa/shader/slang/slang_builtin.h +++ b/src/mesa/shader/slang/slang_builtin.h @@ -33,7 +33,8 @@ extern GLint _slang_alloc_statevar(slang_ir_node *n, - struct gl_program_parameter_list *paramList); + struct gl_program_parameter_list *paramList, + GLboolean *direct); #endif /* SLANG_BUILTIN_H */ diff --git a/src/mesa/shader/slang/slang_emit.c b/src/mesa/shader/slang/slang_emit.c index 6587f9cf276..4f8e694a739 100644 --- a/src/mesa/shader/slang/slang_emit.c +++ b/src/mesa/shader/slang/slang_emit.c @@ -348,6 +348,10 @@ storage_to_src_reg(struct prog_src_register *src, const slang_ir_storage *st) assert(index >= 0); while (st->Parent) { st = st->Parent; + if (st->Index < 0) { + /* an error should have been reported already */ + return; + } assert(st->Index >= 0); index += st->Index; swizzle = _slang_swizzle_swizzle(fix_swizzle(st->Swizzle), swizzle); @@ -1841,9 +1845,17 @@ emit_array_element(slang_emit_info *emitInfo, slang_ir_node *n) root = root->Parent; if (root->File == PROGRAM_STATE_VAR) { - GLint index = _slang_alloc_statevar(n, emitInfo->prog->Parameters); - assert(n->Store->Index == index); - return NULL; + GLboolean direct; + GLint index = + _slang_alloc_statevar(n, emitInfo->prog->Parameters, &direct); + if (index < 0) { + /* error */ + return NULL; + } + if (direct) { + n->Store->Index = index; + return NULL; /* all done */ + } } } @@ -1967,19 +1979,23 @@ emit_struct_field(slang_emit_info *emitInfo, slang_ir_node *n) * space for the ones that we actually use! */ if (root->File == PROGRAM_STATE_VAR) { - root->Index = _slang_alloc_statevar(n, emitInfo->prog->Parameters); - if (root->Index < 0) { + GLboolean direct; + GLint index = _slang_alloc_statevar(n, emitInfo->prog->Parameters, &direct); + if (index < 0) { slang_info_log_error(emitInfo->log, "Error parsing state variable"); return NULL; } - return NULL; - } - else { - /* do codegen for struct */ - emit(emitInfo, n->Children[0]); - assert(n->Children[0]->Store->Index >= 0); + if (direct) { + root->Index = index; + return NULL; /* all done */ + } } + /* do codegen for struct */ + emit(emitInfo, n->Children[0]); + assert(n->Children[0]->Store->Index >= 0); + + fieldOffset = n->Store->Index; fieldSize = n->Store->Size; @@ -2077,7 +2093,18 @@ emit_var_ref(slang_emit_info *emitInfo, slang_ir_node *n) assert(n->Store->File != PROGRAM_UNDEFINED); if (n->Store->File == PROGRAM_STATE_VAR && n->Store->Index < 0) { - n->Store->Index = _slang_alloc_statevar(n, emitInfo->prog->Parameters); + GLboolean direct; + GLint index = _slang_alloc_statevar(n, emitInfo->prog->Parameters, &direct); + if (index < 0) { + /* error */ + char s[100]; + snprintf(s, sizeof(s), "Undefined variable '%s'", + (char *) n->Var->a_name); + slang_info_log_error(emitInfo->log, s); + return NULL; + } + + n->Store->Index = index; } else if (n->Store->File == PROGRAM_UNIFORM) { /* mark var as used */ -- 2.30.2