xref: /third_party/mesa3d/src/mesa/program/program.c (revision bf215546)
1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Mesa 3-D graphics library
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
5bf215546Sopenharmony_ci *
6bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
7bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
8bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
9bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
11bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
12bf215546Sopenharmony_ci *
13bf215546Sopenharmony_ci * The above copyright notice and this permission notice shall be included
14bf215546Sopenharmony_ci * in all copies or substantial portions of the Software.
15bf215546Sopenharmony_ci *
16bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20bf215546Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21bf215546Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22bf215546Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE.
23bf215546Sopenharmony_ci */
24bf215546Sopenharmony_ci
25bf215546Sopenharmony_ci/**
26bf215546Sopenharmony_ci * \file program.c
27bf215546Sopenharmony_ci * Vertex and fragment program support functions.
28bf215546Sopenharmony_ci * \author Brian Paul
29bf215546Sopenharmony_ci */
30bf215546Sopenharmony_ci
31bf215546Sopenharmony_ci
32bf215546Sopenharmony_ci#include "main/glheader.h"
33bf215546Sopenharmony_ci#include "main/context.h"
34bf215546Sopenharmony_ci#include "main/framebuffer.h"
35bf215546Sopenharmony_ci#include "main/hash.h"
36bf215546Sopenharmony_ci#include "main/macros.h"
37bf215546Sopenharmony_ci#include "main/shaderobj.h"
38bf215546Sopenharmony_ci#include "main/state.h"
39bf215546Sopenharmony_ci#include "program.h"
40bf215546Sopenharmony_ci#include "prog_cache.h"
41bf215546Sopenharmony_ci#include "prog_parameter.h"
42bf215546Sopenharmony_ci#include "prog_instruction.h"
43bf215546Sopenharmony_ci#include "util/bitscan.h"
44bf215546Sopenharmony_ci#include "util/ralloc.h"
45bf215546Sopenharmony_ci#include "util/u_atomic.h"
46bf215546Sopenharmony_ci
47bf215546Sopenharmony_ci#include "state_tracker/st_program.h"
48bf215546Sopenharmony_ci#include "state_tracker/st_context.h"
49bf215546Sopenharmony_ci
50bf215546Sopenharmony_ci/**
51bf215546Sopenharmony_ci * A pointer to this dummy program is put into the hash table when
52bf215546Sopenharmony_ci * glGenPrograms is called.
53bf215546Sopenharmony_ci */
54bf215546Sopenharmony_cistruct gl_program _mesa_DummyProgram;
55bf215546Sopenharmony_ci
56bf215546Sopenharmony_ci
57bf215546Sopenharmony_ci/**
58bf215546Sopenharmony_ci * Init context's vertex/fragment program state
59bf215546Sopenharmony_ci */
60bf215546Sopenharmony_civoid
61bf215546Sopenharmony_ci_mesa_init_program(struct gl_context *ctx)
62bf215546Sopenharmony_ci{
63bf215546Sopenharmony_ci   /*
64bf215546Sopenharmony_ci    * If this assertion fails, we need to increase the field
65bf215546Sopenharmony_ci    * size for register indexes (see INST_INDEX_BITS).
66bf215546Sopenharmony_ci    */
67bf215546Sopenharmony_ci   assert(ctx->Const.Program[MESA_SHADER_VERTEX].MaxUniformComponents / 4
68bf215546Sopenharmony_ci          <= (1 << INST_INDEX_BITS));
69bf215546Sopenharmony_ci   assert(ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxUniformComponents / 4
70bf215546Sopenharmony_ci          <= (1 << INST_INDEX_BITS));
71bf215546Sopenharmony_ci
72bf215546Sopenharmony_ci   assert(ctx->Const.Program[MESA_SHADER_VERTEX].MaxTemps <= (1 << INST_INDEX_BITS));
73bf215546Sopenharmony_ci   assert(ctx->Const.Program[MESA_SHADER_VERTEX].MaxLocalParams <= (1 << INST_INDEX_BITS));
74bf215546Sopenharmony_ci   assert(ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxTemps <= (1 << INST_INDEX_BITS));
75bf215546Sopenharmony_ci   assert(ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxLocalParams <= (1 << INST_INDEX_BITS));
76bf215546Sopenharmony_ci
77bf215546Sopenharmony_ci   assert(ctx->Const.Program[MESA_SHADER_VERTEX].MaxUniformComponents <= 4 * MAX_UNIFORMS);
78bf215546Sopenharmony_ci   assert(ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxUniformComponents <= 4 * MAX_UNIFORMS);
79bf215546Sopenharmony_ci
80bf215546Sopenharmony_ci   assert(ctx->Const.Program[MESA_SHADER_VERTEX].MaxAddressOffset <= (1 << INST_INDEX_BITS));
81bf215546Sopenharmony_ci   assert(ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxAddressOffset <= (1 << INST_INDEX_BITS));
82bf215546Sopenharmony_ci
83bf215546Sopenharmony_ci   /* If this fails, increase prog_instruction::TexSrcUnit size */
84bf215546Sopenharmony_ci   STATIC_ASSERT(MAX_TEXTURE_UNITS <= (1 << 5));
85bf215546Sopenharmony_ci
86bf215546Sopenharmony_ci   /* If this fails, increase prog_instruction::TexSrcTarget size */
87bf215546Sopenharmony_ci   STATIC_ASSERT(NUM_TEXTURE_TARGETS <= (1 << 4));
88bf215546Sopenharmony_ci
89bf215546Sopenharmony_ci   ctx->Program.ErrorPos = -1;
90bf215546Sopenharmony_ci   ctx->Program.ErrorString = strdup("");
91bf215546Sopenharmony_ci
92bf215546Sopenharmony_ci   ctx->VertexProgram.Enabled = GL_FALSE;
93bf215546Sopenharmony_ci   ctx->VertexProgram.PointSizeEnabled =
94bf215546Sopenharmony_ci      (ctx->API == API_OPENGLES2) ? GL_TRUE : GL_FALSE;
95bf215546Sopenharmony_ci   ctx->VertexProgram.TwoSideEnabled = GL_FALSE;
96bf215546Sopenharmony_ci   _mesa_reference_program(ctx, &ctx->VertexProgram.Current,
97bf215546Sopenharmony_ci                           ctx->Shared->DefaultVertexProgram);
98bf215546Sopenharmony_ci   assert(ctx->VertexProgram.Current);
99bf215546Sopenharmony_ci   ctx->VertexProgram.Cache = _mesa_new_program_cache();
100bf215546Sopenharmony_ci
101bf215546Sopenharmony_ci   ctx->FragmentProgram.Enabled = GL_FALSE;
102bf215546Sopenharmony_ci   _mesa_reference_program(ctx, &ctx->FragmentProgram.Current,
103bf215546Sopenharmony_ci                           ctx->Shared->DefaultFragmentProgram);
104bf215546Sopenharmony_ci   assert(ctx->FragmentProgram.Current);
105bf215546Sopenharmony_ci   ctx->FragmentProgram.Cache = _mesa_new_program_cache();
106bf215546Sopenharmony_ci   _mesa_reset_vertex_processing_mode(ctx);
107bf215546Sopenharmony_ci
108bf215546Sopenharmony_ci   /* XXX probably move this stuff */
109bf215546Sopenharmony_ci   ctx->ATIFragmentShader.Enabled = GL_FALSE;
110bf215546Sopenharmony_ci   ctx->ATIFragmentShader.Current = ctx->Shared->DefaultFragmentShader;
111bf215546Sopenharmony_ci   assert(ctx->ATIFragmentShader.Current);
112bf215546Sopenharmony_ci   ctx->ATIFragmentShader.Current->RefCount++;
113bf215546Sopenharmony_ci}
114bf215546Sopenharmony_ci
115bf215546Sopenharmony_ci
116bf215546Sopenharmony_ci/**
117bf215546Sopenharmony_ci * Free a context's vertex/fragment program state
118bf215546Sopenharmony_ci */
119bf215546Sopenharmony_civoid
120bf215546Sopenharmony_ci_mesa_free_program_data(struct gl_context *ctx)
121bf215546Sopenharmony_ci{
122bf215546Sopenharmony_ci   _mesa_reference_program(ctx, &ctx->VertexProgram.Current, NULL);
123bf215546Sopenharmony_ci   _mesa_delete_program_cache(ctx, ctx->VertexProgram.Cache);
124bf215546Sopenharmony_ci   _mesa_reference_program(ctx, &ctx->FragmentProgram.Current, NULL);
125bf215546Sopenharmony_ci   _mesa_delete_shader_cache(ctx, ctx->FragmentProgram.Cache);
126bf215546Sopenharmony_ci
127bf215546Sopenharmony_ci   /* XXX probably move this stuff */
128bf215546Sopenharmony_ci   if (ctx->ATIFragmentShader.Current) {
129bf215546Sopenharmony_ci      ctx->ATIFragmentShader.Current->RefCount--;
130bf215546Sopenharmony_ci      if (ctx->ATIFragmentShader.Current->RefCount <= 0) {
131bf215546Sopenharmony_ci         free(ctx->ATIFragmentShader.Current);
132bf215546Sopenharmony_ci      }
133bf215546Sopenharmony_ci   }
134bf215546Sopenharmony_ci
135bf215546Sopenharmony_ci   free((void *) ctx->Program.ErrorString);
136bf215546Sopenharmony_ci}
137bf215546Sopenharmony_ci
138bf215546Sopenharmony_ci
139bf215546Sopenharmony_ci/**
140bf215546Sopenharmony_ci * Update the default program objects in the given context to reference those
141bf215546Sopenharmony_ci * specified in the shared state and release those referencing the old
142bf215546Sopenharmony_ci * shared state.
143bf215546Sopenharmony_ci */
144bf215546Sopenharmony_civoid
145bf215546Sopenharmony_ci_mesa_update_default_objects_program(struct gl_context *ctx)
146bf215546Sopenharmony_ci{
147bf215546Sopenharmony_ci   _mesa_reference_program(ctx, &ctx->VertexProgram.Current,
148bf215546Sopenharmony_ci                           ctx->Shared->DefaultVertexProgram);
149bf215546Sopenharmony_ci   assert(ctx->VertexProgram.Current);
150bf215546Sopenharmony_ci
151bf215546Sopenharmony_ci   _mesa_reference_program(ctx, &ctx->FragmentProgram.Current,
152bf215546Sopenharmony_ci                            ctx->Shared->DefaultFragmentProgram);
153bf215546Sopenharmony_ci   assert(ctx->FragmentProgram.Current);
154bf215546Sopenharmony_ci
155bf215546Sopenharmony_ci   /* XXX probably move this stuff */
156bf215546Sopenharmony_ci   if (ctx->ATIFragmentShader.Current) {
157bf215546Sopenharmony_ci      ctx->ATIFragmentShader.Current->RefCount--;
158bf215546Sopenharmony_ci      if (ctx->ATIFragmentShader.Current->RefCount <= 0) {
159bf215546Sopenharmony_ci         free(ctx->ATIFragmentShader.Current);
160bf215546Sopenharmony_ci      }
161bf215546Sopenharmony_ci   }
162bf215546Sopenharmony_ci   ctx->ATIFragmentShader.Current = (struct ati_fragment_shader *) ctx->Shared->DefaultFragmentShader;
163bf215546Sopenharmony_ci   assert(ctx->ATIFragmentShader.Current);
164bf215546Sopenharmony_ci   ctx->ATIFragmentShader.Current->RefCount++;
165bf215546Sopenharmony_ci}
166bf215546Sopenharmony_ci
167bf215546Sopenharmony_ci
168bf215546Sopenharmony_ci/**
169bf215546Sopenharmony_ci * Set the vertex/fragment program error state (position and error string).
170bf215546Sopenharmony_ci * This is generally called from within the parsers.
171bf215546Sopenharmony_ci */
172bf215546Sopenharmony_civoid
173bf215546Sopenharmony_ci_mesa_set_program_error(struct gl_context *ctx, GLint pos, const char *string)
174bf215546Sopenharmony_ci{
175bf215546Sopenharmony_ci   ctx->Program.ErrorPos = pos;
176bf215546Sopenharmony_ci   free((void *) ctx->Program.ErrorString);
177bf215546Sopenharmony_ci   if (!string)
178bf215546Sopenharmony_ci      string = "";
179bf215546Sopenharmony_ci   ctx->Program.ErrorString = strdup(string);
180bf215546Sopenharmony_ci}
181bf215546Sopenharmony_ci
182bf215546Sopenharmony_ci
183bf215546Sopenharmony_ci/**
184bf215546Sopenharmony_ci * Initialize a new gl_program object.
185bf215546Sopenharmony_ci */
186bf215546Sopenharmony_cistruct gl_program *
187bf215546Sopenharmony_ci_mesa_init_gl_program(struct gl_program *prog, gl_shader_stage stage,
188bf215546Sopenharmony_ci                      GLuint id, bool is_arb_asm)
189bf215546Sopenharmony_ci{
190bf215546Sopenharmony_ci   if (!prog)
191bf215546Sopenharmony_ci      return NULL;
192bf215546Sopenharmony_ci
193bf215546Sopenharmony_ci   memset(prog, 0, sizeof(*prog));
194bf215546Sopenharmony_ci   prog->Id = id;
195bf215546Sopenharmony_ci   prog->Target = _mesa_shader_stage_to_program(stage);
196bf215546Sopenharmony_ci   prog->RefCount = 1;
197bf215546Sopenharmony_ci   prog->Format = GL_PROGRAM_FORMAT_ASCII_ARB;
198bf215546Sopenharmony_ci   prog->info.stage = stage;
199bf215546Sopenharmony_ci   prog->info.use_legacy_math_rules = is_arb_asm;
200bf215546Sopenharmony_ci
201bf215546Sopenharmony_ci   /* Uniforms that lack an initializer in the shader code have an initial
202bf215546Sopenharmony_ci    * value of zero.  This includes sampler uniforms.
203bf215546Sopenharmony_ci    *
204bf215546Sopenharmony_ci    * Page 24 (page 30 of the PDF) of the GLSL 1.20 spec says:
205bf215546Sopenharmony_ci    *
206bf215546Sopenharmony_ci    *     "The link time initial value is either the value of the variable's
207bf215546Sopenharmony_ci    *     initializer, if present, or 0 if no initializer is present. Sampler
208bf215546Sopenharmony_ci    *     types cannot have initializers."
209bf215546Sopenharmony_ci    *
210bf215546Sopenharmony_ci    * So we only initialise ARB assembly style programs.
211bf215546Sopenharmony_ci    */
212bf215546Sopenharmony_ci   if (is_arb_asm) {
213bf215546Sopenharmony_ci      /* default mapping from samplers to texture units */
214bf215546Sopenharmony_ci      for (unsigned i = 0; i < MAX_SAMPLERS; i++)
215bf215546Sopenharmony_ci         prog->SamplerUnits[i] = i;
216bf215546Sopenharmony_ci   }
217bf215546Sopenharmony_ci
218bf215546Sopenharmony_ci   return prog;
219bf215546Sopenharmony_ci}
220bf215546Sopenharmony_ci
221bf215546Sopenharmony_cistruct gl_program *
222bf215546Sopenharmony_ci_mesa_new_program(struct gl_context *ctx, gl_shader_stage stage, GLuint id,
223bf215546Sopenharmony_ci                  bool is_arb_asm)
224bf215546Sopenharmony_ci{
225bf215546Sopenharmony_ci   struct gl_program *prog;
226bf215546Sopenharmony_ci
227bf215546Sopenharmony_ci   switch (stage) {
228bf215546Sopenharmony_ci   case MESA_SHADER_VERTEX:
229bf215546Sopenharmony_ci      prog = (struct gl_program*)rzalloc(NULL, struct gl_vertex_program);
230bf215546Sopenharmony_ci      break;
231bf215546Sopenharmony_ci   default:
232bf215546Sopenharmony_ci      prog = rzalloc(NULL, struct gl_program);
233bf215546Sopenharmony_ci      break;
234bf215546Sopenharmony_ci   }
235bf215546Sopenharmony_ci
236bf215546Sopenharmony_ci   return _mesa_init_gl_program(prog, stage, id, is_arb_asm);
237bf215546Sopenharmony_ci}
238bf215546Sopenharmony_ci
239bf215546Sopenharmony_ci/**
240bf215546Sopenharmony_ci * Delete a program and remove it from the hash table, ignoring the
241bf215546Sopenharmony_ci * reference count.
242bf215546Sopenharmony_ci */
243bf215546Sopenharmony_civoid
244bf215546Sopenharmony_ci_mesa_delete_program(struct gl_context *ctx, struct gl_program *prog)
245bf215546Sopenharmony_ci{
246bf215546Sopenharmony_ci   struct st_context *st = st_context(ctx);
247bf215546Sopenharmony_ci   assert(prog);
248bf215546Sopenharmony_ci   assert(prog->RefCount==0);
249bf215546Sopenharmony_ci
250bf215546Sopenharmony_ci   st_release_variants(st, prog);
251bf215546Sopenharmony_ci
252bf215546Sopenharmony_ci   free(prog->serialized_nir);
253bf215546Sopenharmony_ci
254bf215546Sopenharmony_ci   if (prog == &_mesa_DummyProgram)
255bf215546Sopenharmony_ci      return;
256bf215546Sopenharmony_ci
257bf215546Sopenharmony_ci   if (prog->Parameters) {
258bf215546Sopenharmony_ci      _mesa_free_parameter_list(prog->Parameters);
259bf215546Sopenharmony_ci   }
260bf215546Sopenharmony_ci
261bf215546Sopenharmony_ci   if (prog->nir) {
262bf215546Sopenharmony_ci      ralloc_free(prog->nir);
263bf215546Sopenharmony_ci   }
264bf215546Sopenharmony_ci
265bf215546Sopenharmony_ci   if (prog->sh.BindlessSamplers) {
266bf215546Sopenharmony_ci      ralloc_free(prog->sh.BindlessSamplers);
267bf215546Sopenharmony_ci   }
268bf215546Sopenharmony_ci
269bf215546Sopenharmony_ci   if (prog->sh.BindlessImages) {
270bf215546Sopenharmony_ci      ralloc_free(prog->sh.BindlessImages);
271bf215546Sopenharmony_ci   }
272bf215546Sopenharmony_ci
273bf215546Sopenharmony_ci   if (prog->driver_cache_blob) {
274bf215546Sopenharmony_ci      ralloc_free(prog->driver_cache_blob);
275bf215546Sopenharmony_ci   }
276bf215546Sopenharmony_ci
277bf215546Sopenharmony_ci   ralloc_free(prog);
278bf215546Sopenharmony_ci}
279bf215546Sopenharmony_ci
280bf215546Sopenharmony_ci
281bf215546Sopenharmony_ci/**
282bf215546Sopenharmony_ci * Return the gl_program object for a given ID.
283bf215546Sopenharmony_ci * Basically just a wrapper for _mesa_HashLookup() to avoid a lot of
284bf215546Sopenharmony_ci * casts elsewhere.
285bf215546Sopenharmony_ci */
286bf215546Sopenharmony_cistruct gl_program *
287bf215546Sopenharmony_ci_mesa_lookup_program(struct gl_context *ctx, GLuint id)
288bf215546Sopenharmony_ci{
289bf215546Sopenharmony_ci   if (id)
290bf215546Sopenharmony_ci      return (struct gl_program *) _mesa_HashLookup(ctx->Shared->Programs, id);
291bf215546Sopenharmony_ci   else
292bf215546Sopenharmony_ci      return NULL;
293bf215546Sopenharmony_ci}
294bf215546Sopenharmony_ci
295bf215546Sopenharmony_ci
296bf215546Sopenharmony_ci/**
297bf215546Sopenharmony_ci * Reference counting for vertex/fragment programs
298bf215546Sopenharmony_ci * This is normally only called from the _mesa_reference_program() macro
299bf215546Sopenharmony_ci * when there's a real pointer change.
300bf215546Sopenharmony_ci */
301bf215546Sopenharmony_civoid
302bf215546Sopenharmony_ci_mesa_reference_program_(struct gl_context *ctx,
303bf215546Sopenharmony_ci                         struct gl_program **ptr,
304bf215546Sopenharmony_ci                         struct gl_program *prog)
305bf215546Sopenharmony_ci{
306bf215546Sopenharmony_ci#ifndef NDEBUG
307bf215546Sopenharmony_ci   assert(ptr);
308bf215546Sopenharmony_ci   if (*ptr && prog) {
309bf215546Sopenharmony_ci      /* sanity check */
310bf215546Sopenharmony_ci      if ((*ptr)->Target == GL_VERTEX_PROGRAM_ARB)
311bf215546Sopenharmony_ci         assert(prog->Target == GL_VERTEX_PROGRAM_ARB);
312bf215546Sopenharmony_ci      else if ((*ptr)->Target == GL_FRAGMENT_PROGRAM_ARB)
313bf215546Sopenharmony_ci         assert(prog->Target == GL_FRAGMENT_PROGRAM_ARB ||
314bf215546Sopenharmony_ci                prog->Target == GL_FRAGMENT_PROGRAM_NV);
315bf215546Sopenharmony_ci      else if ((*ptr)->Target == GL_GEOMETRY_PROGRAM_NV)
316bf215546Sopenharmony_ci         assert(prog->Target == GL_GEOMETRY_PROGRAM_NV);
317bf215546Sopenharmony_ci   }
318bf215546Sopenharmony_ci#endif
319bf215546Sopenharmony_ci
320bf215546Sopenharmony_ci   if (*ptr) {
321bf215546Sopenharmony_ci      struct gl_program *oldProg = *ptr;
322bf215546Sopenharmony_ci
323bf215546Sopenharmony_ci      assert(oldProg->RefCount > 0);
324bf215546Sopenharmony_ci
325bf215546Sopenharmony_ci      if (p_atomic_dec_zero(&oldProg->RefCount)) {
326bf215546Sopenharmony_ci         assert(ctx);
327bf215546Sopenharmony_ci         _mesa_reference_shader_program_data(&oldProg->sh.data, NULL);
328bf215546Sopenharmony_ci         _mesa_delete_program(ctx, oldProg);
329bf215546Sopenharmony_ci      }
330bf215546Sopenharmony_ci
331bf215546Sopenharmony_ci      *ptr = NULL;
332bf215546Sopenharmony_ci   }
333bf215546Sopenharmony_ci
334bf215546Sopenharmony_ci   assert(!*ptr);
335bf215546Sopenharmony_ci   if (prog) {
336bf215546Sopenharmony_ci      p_atomic_inc(&prog->RefCount);
337bf215546Sopenharmony_ci   }
338bf215546Sopenharmony_ci
339bf215546Sopenharmony_ci   *ptr = prog;
340bf215546Sopenharmony_ci}
341bf215546Sopenharmony_ci
342bf215546Sopenharmony_ci/* Gets the minimum number of shader invocations per fragment.
343bf215546Sopenharmony_ci * This function is useful to determine if we need to do per
344bf215546Sopenharmony_ci * sample shading or per fragment shading.
345bf215546Sopenharmony_ci */
346bf215546Sopenharmony_ciGLint
347bf215546Sopenharmony_ci_mesa_get_min_invocations_per_fragment(struct gl_context *ctx,
348bf215546Sopenharmony_ci                                       const struct gl_program *prog)
349bf215546Sopenharmony_ci{
350bf215546Sopenharmony_ci   /* From ARB_sample_shading specification:
351bf215546Sopenharmony_ci    * "Using gl_SampleID in a fragment shader causes the entire shader
352bf215546Sopenharmony_ci    *  to be evaluated per-sample."
353bf215546Sopenharmony_ci    *
354bf215546Sopenharmony_ci    * "Using gl_SamplePosition in a fragment shader causes the entire
355bf215546Sopenharmony_ci    *  shader to be evaluated per-sample."
356bf215546Sopenharmony_ci    *
357bf215546Sopenharmony_ci    * "If MULTISAMPLE or SAMPLE_SHADING_ARB is disabled, sample shading
358bf215546Sopenharmony_ci    *  has no effect."
359bf215546Sopenharmony_ci    */
360bf215546Sopenharmony_ci   if (ctx->Multisample.Enabled) {
361bf215546Sopenharmony_ci      /* The ARB_gpu_shader5 specification says:
362bf215546Sopenharmony_ci       *
363bf215546Sopenharmony_ci       * "Use of the "sample" qualifier on a fragment shader input
364bf215546Sopenharmony_ci       *  forces per-sample shading"
365bf215546Sopenharmony_ci       */
366bf215546Sopenharmony_ci      if (prog->info.fs.uses_sample_qualifier ||
367bf215546Sopenharmony_ci          BITSET_TEST(prog->info.system_values_read, SYSTEM_VALUE_SAMPLE_ID) ||
368bf215546Sopenharmony_ci          BITSET_TEST(prog->info.system_values_read, SYSTEM_VALUE_SAMPLE_POS))
369bf215546Sopenharmony_ci         return MAX2(_mesa_geometric_samples(ctx->DrawBuffer), 1);
370bf215546Sopenharmony_ci      else if (ctx->Multisample.SampleShading)
371bf215546Sopenharmony_ci         return MAX2(ceilf(ctx->Multisample.MinSampleShadingValue *
372bf215546Sopenharmony_ci                          _mesa_geometric_samples(ctx->DrawBuffer)), 1);
373bf215546Sopenharmony_ci      else
374bf215546Sopenharmony_ci         return 1;
375bf215546Sopenharmony_ci   }
376bf215546Sopenharmony_ci   return 1;
377bf215546Sopenharmony_ci}
378bf215546Sopenharmony_ci
379bf215546Sopenharmony_ci
380bf215546Sopenharmony_ciGLbitfield
381bf215546Sopenharmony_cigl_external_samplers(const struct gl_program *prog)
382bf215546Sopenharmony_ci{
383bf215546Sopenharmony_ci   GLbitfield external_samplers = 0;
384bf215546Sopenharmony_ci   GLbitfield mask = prog->SamplersUsed;
385bf215546Sopenharmony_ci
386bf215546Sopenharmony_ci   while (mask) {
387bf215546Sopenharmony_ci      int idx = u_bit_scan(&mask);
388bf215546Sopenharmony_ci      if (prog->sh.SamplerTargets[idx] == TEXTURE_EXTERNAL_INDEX)
389bf215546Sopenharmony_ci         external_samplers |= (1 << idx);
390bf215546Sopenharmony_ci   }
391bf215546Sopenharmony_ci
392bf215546Sopenharmony_ci   return external_samplers;
393bf215546Sopenharmony_ci}
394bf215546Sopenharmony_ci
395bf215546Sopenharmony_cistatic int compare_state_var(const void *a1, const void *a2)
396bf215546Sopenharmony_ci{
397bf215546Sopenharmony_ci   const struct gl_program_parameter *p1 =
398bf215546Sopenharmony_ci      (const struct gl_program_parameter *)a1;
399bf215546Sopenharmony_ci   const struct gl_program_parameter *p2 =
400bf215546Sopenharmony_ci      (const struct gl_program_parameter *)a2;
401bf215546Sopenharmony_ci
402bf215546Sopenharmony_ci   for (unsigned i = 0; i < STATE_LENGTH; i++) {
403bf215546Sopenharmony_ci      if (p1->StateIndexes[i] != p2->StateIndexes[i])
404bf215546Sopenharmony_ci         return p1->StateIndexes[i] - p2->StateIndexes[i];
405bf215546Sopenharmony_ci   }
406bf215546Sopenharmony_ci   return 0;
407bf215546Sopenharmony_ci}
408bf215546Sopenharmony_ci
409bf215546Sopenharmony_civoid
410bf215546Sopenharmony_ci_mesa_add_separate_state_parameters(struct gl_program *prog,
411bf215546Sopenharmony_ci                                    struct gl_program_parameter_list *state_params)
412bf215546Sopenharmony_ci{
413bf215546Sopenharmony_ci   unsigned num_state_params = state_params->NumParameters;
414bf215546Sopenharmony_ci
415bf215546Sopenharmony_ci   /* All state parameters should be vec4s. */
416bf215546Sopenharmony_ci   for (unsigned i = 0; i < num_state_params; i++) {
417bf215546Sopenharmony_ci      assert(state_params->Parameters[i].Type == PROGRAM_STATE_VAR);
418bf215546Sopenharmony_ci      assert(state_params->Parameters[i].Size == 4);
419bf215546Sopenharmony_ci      assert(state_params->Parameters[i].ValueOffset == i * 4);
420bf215546Sopenharmony_ci   }
421bf215546Sopenharmony_ci
422bf215546Sopenharmony_ci   /* Sort state parameters to facilitate better parameter merging. */
423bf215546Sopenharmony_ci   qsort(state_params->Parameters, num_state_params,
424bf215546Sopenharmony_ci         sizeof(state_params->Parameters[0]), compare_state_var);
425bf215546Sopenharmony_ci   unsigned *remap = malloc(num_state_params * sizeof(unsigned));
426bf215546Sopenharmony_ci
427bf215546Sopenharmony_ci   /* Add state parameters to the end of the parameter list. */
428bf215546Sopenharmony_ci   for (unsigned i = 0; i < num_state_params; i++) {
429bf215546Sopenharmony_ci      unsigned old_index = state_params->Parameters[i].ValueOffset / 4;
430bf215546Sopenharmony_ci
431bf215546Sopenharmony_ci      remap[old_index] =
432bf215546Sopenharmony_ci         _mesa_add_parameter(prog->Parameters, PROGRAM_STATE_VAR,
433bf215546Sopenharmony_ci                             state_params->Parameters[i].Name,
434bf215546Sopenharmony_ci                             state_params->Parameters[i].Size,
435bf215546Sopenharmony_ci                             GL_NONE, NULL,
436bf215546Sopenharmony_ci                             state_params->Parameters[i].StateIndexes,
437bf215546Sopenharmony_ci                             state_params->Parameters[i].Padded);
438bf215546Sopenharmony_ci
439bf215546Sopenharmony_ci      prog->Parameters->StateFlags |=
440bf215546Sopenharmony_ci         _mesa_program_state_flags(state_params->Parameters[i].StateIndexes);
441bf215546Sopenharmony_ci   }
442bf215546Sopenharmony_ci
443bf215546Sopenharmony_ci   /* Fix up state parameter offsets in instructions. */
444bf215546Sopenharmony_ci   int num_instr = prog->arb.NumInstructions;
445bf215546Sopenharmony_ci   struct prog_instruction *instrs = prog->arb.Instructions;
446bf215546Sopenharmony_ci
447bf215546Sopenharmony_ci   /* Fix src indices after sorting. */
448bf215546Sopenharmony_ci   for (unsigned i = 0; i < num_instr; i++) {
449bf215546Sopenharmony_ci      struct prog_instruction *inst = instrs + i;
450bf215546Sopenharmony_ci      unsigned num_src = _mesa_num_inst_src_regs(inst->Opcode);
451bf215546Sopenharmony_ci
452bf215546Sopenharmony_ci      for (unsigned j = 0; j < num_src; j++) {
453bf215546Sopenharmony_ci         if (inst->SrcReg[j].File == PROGRAM_STATE_VAR)
454bf215546Sopenharmony_ci            inst->SrcReg[j].Index = remap[inst->SrcReg[j].Index];
455bf215546Sopenharmony_ci      }
456bf215546Sopenharmony_ci   }
457bf215546Sopenharmony_ci   free(remap);
458bf215546Sopenharmony_ci}
459