diff options
Diffstat (limited to 'src/mesa/shader/slang')
-rw-r--r-- | src/mesa/shader/slang/library/slang_common_builtin.gc | 17 | ||||
-rw-r--r-- | src/mesa/shader/slang/library/slang_common_builtin_gc.h | 102 | ||||
-rw-r--r-- | src/mesa/shader/slang/slang_builtin.c | 299 | ||||
-rw-r--r-- | src/mesa/shader/slang/slang_builtin.h | 3 | ||||
-rw-r--r-- | src/mesa/shader/slang/slang_codegen.c | 24 | ||||
-rw-r--r-- | src/mesa/shader/slang/slang_compile.c | 2 | ||||
-rw-r--r-- | src/mesa/shader/slang/slang_emit.c | 73 | ||||
-rw-r--r-- | src/mesa/shader/slang/slang_link.c | 75 |
8 files changed, 464 insertions, 131 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..230c57cea8d 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"), @@ -26,8 +27,9 @@ // From Shader Spec, ver. 1.10, rev. 59 // -//bp: XXX these will probably go away since the value needs to be -//determined at runtime and may vary from one GLcontext to another... +// Note: the values assigned to these constants here aren't actually used. +// They're set by the compiler according to the GL context limits. +// See slang_simplify.c const int gl_MaxLights = 8; const int gl_MaxClipPlanes = 6; const int gl_MaxTextureUnits = 8; @@ -98,6 +100,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 +110,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_codegen.c b/src/mesa/shader/slang/slang_codegen.c index 7d764cb5c1d..66615d3afd6 100644 --- a/src/mesa/shader/slang/slang_codegen.c +++ b/src/mesa/shader/slang/slang_codegen.c @@ -391,7 +391,7 @@ _slang_input_index(const char *name, GLenum target, GLuint *swizzleOut) const struct input_info *inputs = (target == GL_VERTEX_PROGRAM_ARB) ? vertInputs : fragInputs; - ASSERT(MAX_TEXTURE_UNITS == 8); /* if this fails, fix vertInputs above */ + ASSERT(MAX_TEXTURE_COORD_UNITS == 8); /* if this fails, fix vertInputs above */ for (i = 0; inputs[i].Name; i++) { if (strcmp(inputs[i].Name, name) == 0) { @@ -1976,7 +1976,7 @@ _slang_make_array_constructor(slang_assemble_ctx *A, slang_operation *oper) */ slang_variable *p = slang_variable_scope_grow(fun->parameters); char name[10]; - snprintf(name, sizeof(name), "p%d", i); + _mesa_snprintf(name, sizeof(name), "p%d", i); p->a_name = slang_atom_pool_atom(A->atoms, name); p->type.qualifier = SLANG_QUAL_CONST; p->type.specifier.type = baseType; @@ -3323,6 +3323,22 @@ is_store_writable(const slang_assemble_ctx *A, const slang_ir_storage *store) /** + * Walk up an IR storage path to compute the final swizzle. + * This is used when we find an expression such as "foo.xz.yx". + */ +static GLuint +root_swizzle(const slang_ir_storage *st) +{ + GLuint swizzle = st->Swizzle; + while (st->Parent) { + st = st->Parent; + swizzle = _slang_swizzle_swizzle(st->Swizzle, swizzle); + } + return swizzle; +} + + +/** * Generate IR tree for an assignment (=). */ static slang_ir_node * @@ -3397,9 +3413,9 @@ _slang_gen_assignment(slang_assemble_ctx * A, slang_operation *oper) rhs = _slang_gen_operation(A, &oper->children[1]); if (lhs && rhs) { /* convert lhs swizzle into writemask */ + const GLuint swizzle = root_swizzle(lhs->Store); GLuint writemask, newSwizzle; - if (!swizzle_to_writemask(A, lhs->Store->Swizzle, - &writemask, &newSwizzle)) { + if (!swizzle_to_writemask(A, swizzle, &writemask, &newSwizzle)) { /* Non-simple writemask, need to swizzle right hand side in * order to put components into the right place. */ diff --git a/src/mesa/shader/slang/slang_compile.c b/src/mesa/shader/slang/slang_compile.c index d8aefd64950..b8044b10600 100644 --- a/src/mesa/shader/slang/slang_compile.c +++ b/src/mesa/shader/slang/slang_compile.c @@ -1470,9 +1470,9 @@ parse_expression(slang_parse_ctx * C, slang_output_ctx * O, RETURN0; } else { + slang_operation array_size; array_constructor = GL_TRUE; /* parse the array constructor size */ - slang_operation array_size; slang_operation_construct(&array_size); if (!parse_expression(C, O, &array_size)) { slang_operation_destruct(&array_size); diff --git a/src/mesa/shader/slang/slang_emit.c b/src/mesa/shader/slang/slang_emit.c index 6587f9cf276..d3b4e64b78d 100644 --- a/src/mesa/shader/slang/slang_emit.c +++ b/src/mesa/shader/slang/slang_emit.c @@ -310,24 +310,22 @@ storage_to_dst_reg(struct prog_dst_register *dst, const slang_ir_storage *st) dst->WriteMask = swizzle_to_writemask(swizzle); } else { - GLuint writemask; switch (size) { case 1: - writemask = WRITEMASK_X << GET_SWZ(st->Swizzle, 0); + dst->WriteMask = WRITEMASK_X << GET_SWZ(st->Swizzle, 0); break; case 2: - writemask = WRITEMASK_XY; + dst->WriteMask = WRITEMASK_XY; break; case 3: - writemask = WRITEMASK_XYZ; + dst->WriteMask = WRITEMASK_XYZ; break; case 4: - writemask = WRITEMASK_XYZW; + dst->WriteMask = WRITEMASK_XYZW; break; default: ; /* error would have been caught above */ } - dst->WriteMask = writemask; } dst->RelAddr = relAddr; @@ -348,6 +346,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); @@ -1286,6 +1288,7 @@ emit_tex(slang_emit_info *emitInfo, slang_ir_node *n) /* Child[0] is the sampler (a uniform which'll indicate the texture unit) */ assert(n->Children[0]->Store); + assert(n->Children[0]->Store->File == PROGRAM_SAMPLER); /* Store->Index is the sampler index */ assert(n->Children[0]->Store->Index >= 0); /* Store->Size is the texture target */ @@ -1295,6 +1298,10 @@ emit_tex(slang_emit_info *emitInfo, slang_ir_node *n) inst->TexSrcTarget = n->Children[0]->Store->Size; inst->TexSrcUnit = n->Children[0]->Store->Index; /* i.e. uniform's index */ + /* mark the sampler as being used */ + _mesa_use_uniform(emitInfo->prog->Parameters, + (char *) n->Children[0]->Var->a_name); + return inst; } @@ -1841,9 +1848,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,28 +1982,30 @@ 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; _slang_copy_ir_storage(n->Store, n->Children[0]->Store); n->Store->Index = n->Children[0]->Store->Index + fieldOffset / 4; - /* XXX test this: - n->Store->Index += fieldOffset / 4; - */ + n->Store->Size = fieldSize; switch (fieldSize) { case 1: @@ -2077,9 +2094,21 @@ 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]; + _mesa_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) { + else if (n->Store->File == PROGRAM_UNIFORM || + n->Store->File == PROGRAM_SAMPLER) { /* mark var as used */ _mesa_use_uniform(emitInfo->prog->Parameters, (char *) n->Var->a_name); } diff --git a/src/mesa/shader/slang/slang_link.c b/src/mesa/shader/slang/slang_link.c index 3e97c8672b6..3f953d86e74 100644 --- a/src/mesa/shader/slang/slang_link.c +++ b/src/mesa/shader/slang/slang_link.c @@ -1,8 +1,9 @@ /* * Mesa 3-D graphics library - * Version: 7.2 + * Version: 7.3 * * Copyright (C) 2008 Brian Paul All Rights Reserved. + * Copyright (C) 2009 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"), @@ -136,15 +137,15 @@ link_varying_vars(struct gl_shader_program *shProg, struct gl_program *prog) } if (!bits_agree(var->Flags, v->Flags, PROG_PARAM_BIT_CENTROID)) { char msg[100]; - snprintf(msg, sizeof(msg), - "centroid modifier mismatch for '%s'", var->Name); + _mesa_snprintf(msg, sizeof(msg), + "centroid modifier mismatch for '%s'", var->Name); link_error(shProg, msg); return GL_FALSE; } if (!bits_agree(var->Flags, v->Flags, PROG_PARAM_BIT_INVARIANT)) { char msg[100]; - snprintf(msg, sizeof(msg), - "invariant modifier mismatch for '%s'", var->Name); + _mesa_snprintf(msg, sizeof(msg), + "invariant modifier mismatch for '%s'", var->Name); link_error(shProg, msg); return GL_FALSE; } @@ -206,13 +207,27 @@ link_varying_vars(struct gl_shader_program *shProg, struct gl_program *prog) * Build the shProg->Uniforms list. * This is basically a list/index of all uniforms found in either/both of * the vertex and fragment shaders. + * + * About uniforms: + * Each uniform has two indexes, one that points into the vertex + * program's parameter array and another that points into the fragment + * program's parameter array. When the user changes a uniform's value + * we have to change the value in the vertex and/or fragment program's + * parameter array. + * + * This function will be called twice to set up the two uniform->parameter + * mappings. + * + * If a uniform is only present in the vertex program OR fragment program + * then the fragment/vertex parameter index, respectively, will be -1. */ static GLboolean -link_uniform_vars(struct gl_shader_program *shProg, +link_uniform_vars(GLcontext *ctx, + struct gl_shader_program *shProg, struct gl_program *prog, GLuint *numSamplers) { - GLuint samplerMap[MAX_SAMPLERS]; + GLuint samplerMap[200]; /* max number of samplers declared, not used */ GLuint i; for (i = 0; i < prog->Parameters->NumParameters; i++) { @@ -227,30 +242,41 @@ link_uniform_vars(struct gl_shader_program *shProg, * Furthermore, we'll need to fix the state-var's size/datatype info. */ - if ((p->Type == PROGRAM_UNIFORM && p->Used) || - p->Type == PROGRAM_SAMPLER) { + if ((p->Type == PROGRAM_UNIFORM || p->Type == PROGRAM_SAMPLER) + && p->Used) { + /* add this uniform, indexing into the target's Parameters list */ struct gl_uniform *uniform = _mesa_append_uniform(shProg->Uniforms, p->Name, prog->Target, i); if (uniform) uniform->Initialized = p->Initialized; } - if (p->Type == PROGRAM_SAMPLER) { + /* The samplerMap[] table we build here is used to remap/re-index + * sampler references by TEX instructions. + */ + if (p->Type == PROGRAM_SAMPLER && p->Used) { /* Allocate a new sampler index */ - GLuint sampNum = *numSamplers; GLuint oldSampNum = (GLuint) prog->Parameters->ParameterValues[i][0]; - if (oldSampNum >= MAX_SAMPLERS) { - link_error(shProg, "Too many texture samplers"); + GLuint newSampNum = *numSamplers; + if (newSampNum >= ctx->Const.MaxTextureImageUnits) { + char s[100]; + sprintf(s, "Too many texture samplers (%u, max is %u)", + newSampNum, ctx->Const.MaxTextureImageUnits); + link_error(shProg, s); return GL_FALSE; } - samplerMap[oldSampNum] = sampNum; + /* save old->new mapping in the table */ + if (oldSampNum < Elements(samplerMap)) + samplerMap[oldSampNum] = newSampNum; + /* update parameter's sampler index */ + prog->Parameters->ParameterValues[i][0] = (GLfloat) newSampNum; (*numSamplers)++; } } - - /* OK, now scan the program/shader instructions looking for sampler vars, - * replacing the old index with the new index. + /* OK, now scan the program/shader instructions looking for texture + * instructions using sampler vars. Replace old sampler indexes with + * new ones. */ prog->SamplersUsed = 0x0; for (i = 0; i < prog->NumInstructions; i++) { @@ -261,10 +287,13 @@ link_uniform_vars(struct gl_shader_program *shProg, inst->Sampler, map[ inst->Sampler ]); */ /* here, texUnit is really samplerUnit */ - assert(inst->TexSrcUnit < MAX_SAMPLERS); - inst->TexSrcUnit = samplerMap[inst->TexSrcUnit]; - prog->SamplerTargets[inst->TexSrcUnit] = inst->TexSrcTarget; - prog->SamplersUsed |= (1 << inst->TexSrcUnit); + const GLint oldSampNum = inst->TexSrcUnit; + if (oldSampNum < Elements(samplerMap)) { + const GLuint newSampNum = samplerMap[oldSampNum]; + inst->TexSrcUnit = newSampNum; + prog->SamplerTargets[newSampNum] = inst->TexSrcTarget; + prog->SamplersUsed |= (1 << newSampNum); + } } } @@ -564,13 +593,13 @@ _slang_link(GLcontext *ctx, /* link uniform vars */ if (shProg->VertexProgram) { - if (!link_uniform_vars(shProg, &shProg->VertexProgram->Base, + if (!link_uniform_vars(ctx, shProg, &shProg->VertexProgram->Base, &numSamplers)) { return; } } if (shProg->FragmentProgram) { - if (!link_uniform_vars(shProg, &shProg->FragmentProgram->Base, + if (!link_uniform_vars(ctx, shProg, &shProg->FragmentProgram->Base, &numSamplers)) { return; } |