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