1848b8605Smrg/* 2848b8605Smrg * Mesa 3-D graphics library 3848b8605Smrg * 4848b8605Smrg * Copyright (C) 2004-2008 Brian Paul All Rights Reserved. 5848b8605Smrg * Copyright (C) 2009-2010 VMware, Inc. All Rights Reserved. 6848b8605Smrg * 7848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a 8848b8605Smrg * copy of this software and associated documentation files (the "Software"), 9848b8605Smrg * to deal in the Software without restriction, including without limitation 10848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the 12848b8605Smrg * Software is furnished to do so, subject to the following conditions: 13848b8605Smrg * 14848b8605Smrg * The above copyright notice and this permission notice shall be included 15848b8605Smrg * in all copies or substantial portions of the Software. 16848b8605Smrg * 17848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21848b8605Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22848b8605Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23848b8605Smrg * OTHER DEALINGS IN THE SOFTWARE. 24848b8605Smrg */ 25848b8605Smrg 26848b8605Smrg/** 27848b8605Smrg * \file shaderobj.c 28848b8605Smrg * \author Brian Paul 29848b8605Smrg * 30848b8605Smrg */ 31848b8605Smrg 32848b8605Smrg 33b8e80941Smrg#include "compiler/glsl/string_to_uint_map.h" 34848b8605Smrg#include "main/glheader.h" 35848b8605Smrg#include "main/context.h" 36b8e80941Smrg#include "main/glspirv.h" 37848b8605Smrg#include "main/hash.h" 38848b8605Smrg#include "main/mtypes.h" 39848b8605Smrg#include "main/shaderapi.h" 40848b8605Smrg#include "main/shaderobj.h" 41848b8605Smrg#include "main/uniforms.h" 42848b8605Smrg#include "program/program.h" 43848b8605Smrg#include "program/prog_parameter.h" 44848b8605Smrg#include "util/ralloc.h" 45b8e80941Smrg#include "util/u_atomic.h" 46848b8605Smrg 47848b8605Smrg/**********************************************************************/ 48848b8605Smrg/*** Shader object functions ***/ 49848b8605Smrg/**********************************************************************/ 50848b8605Smrg 51848b8605Smrg 52848b8605Smrg/** 53848b8605Smrg * Set ptr to point to sh. 54848b8605Smrg * If ptr is pointing to another shader, decrement its refcount (and delete 55848b8605Smrg * if refcount hits zero). 56848b8605Smrg * Then set ptr to point to sh, incrementing its refcount. 57848b8605Smrg */ 58848b8605Smrgvoid 59848b8605Smrg_mesa_reference_shader(struct gl_context *ctx, struct gl_shader **ptr, 60848b8605Smrg struct gl_shader *sh) 61848b8605Smrg{ 62848b8605Smrg assert(ptr); 63848b8605Smrg if (*ptr == sh) { 64848b8605Smrg /* no-op */ 65848b8605Smrg return; 66848b8605Smrg } 67848b8605Smrg if (*ptr) { 68848b8605Smrg /* Unreference the old shader */ 69848b8605Smrg struct gl_shader *old = *ptr; 70848b8605Smrg 71b8e80941Smrg assert(old->RefCount > 0); 72848b8605Smrg 73b8e80941Smrg if (p_atomic_dec_zero(&old->RefCount)) { 74848b8605Smrg if (old->Name != 0) 75848b8605Smrg _mesa_HashRemove(ctx->Shared->ShaderObjects, old->Name); 76b8e80941Smrg _mesa_delete_shader(ctx, old); 77848b8605Smrg } 78848b8605Smrg 79848b8605Smrg *ptr = NULL; 80848b8605Smrg } 81848b8605Smrg assert(!*ptr); 82848b8605Smrg 83848b8605Smrg if (sh) { 84848b8605Smrg /* reference new */ 85b8e80941Smrg p_atomic_inc(&sh->RefCount); 86848b8605Smrg *ptr = sh; 87848b8605Smrg } 88848b8605Smrg} 89848b8605Smrg 90b8e80941Smrgstatic void 91b8e80941Smrg_mesa_init_shader(struct gl_shader *shader) 92848b8605Smrg{ 93848b8605Smrg shader->RefCount = 1; 94b8e80941Smrg shader->info.Geom.VerticesOut = -1; 95b8e80941Smrg shader->info.Geom.InputType = GL_TRIANGLES; 96b8e80941Smrg shader->info.Geom.OutputType = GL_TRIANGLE_STRIP; 97848b8605Smrg} 98848b8605Smrg 99848b8605Smrg/** 100848b8605Smrg * Allocate a new gl_shader object, initialize it. 101848b8605Smrg */ 102848b8605Smrgstruct gl_shader * 103b8e80941Smrg_mesa_new_shader(GLuint name, gl_shader_stage stage) 104848b8605Smrg{ 105848b8605Smrg struct gl_shader *shader; 106848b8605Smrg shader = rzalloc(NULL, struct gl_shader); 107848b8605Smrg if (shader) { 108b8e80941Smrg shader->Stage = stage; 109848b8605Smrg shader->Name = name; 110b8e80941Smrg#ifdef DEBUG 111b8e80941Smrg shader->SourceChecksum = 0xa110c; /* alloc */ 112b8e80941Smrg#endif 113b8e80941Smrg _mesa_init_shader(shader); 114848b8605Smrg } 115848b8605Smrg return shader; 116848b8605Smrg} 117848b8605Smrg 118848b8605Smrg 119848b8605Smrg/** 120848b8605Smrg * Delete a shader object. 121848b8605Smrg */ 122b8e80941Smrgvoid 123848b8605Smrg_mesa_delete_shader(struct gl_context *ctx, struct gl_shader *sh) 124848b8605Smrg{ 125b8e80941Smrg _mesa_shader_spirv_data_reference(&sh->spirv_data, NULL); 126848b8605Smrg free((void *)sh->Source); 127b8e80941Smrg free((void *)sh->FallbackSource); 128848b8605Smrg free(sh->Label); 129b8e80941Smrg ralloc_free(sh); 130b8e80941Smrg} 131b8e80941Smrg 132b8e80941Smrg 133b8e80941Smrg/** 134b8e80941Smrg * Delete a shader object. 135b8e80941Smrg */ 136b8e80941Smrgvoid 137b8e80941Smrg_mesa_delete_linked_shader(struct gl_context *ctx, 138b8e80941Smrg struct gl_linked_shader *sh) 139b8e80941Smrg{ 140b8e80941Smrg _mesa_shader_spirv_data_reference(&sh->spirv_data, NULL); 141848b8605Smrg _mesa_reference_program(ctx, &sh->Program, NULL); 142848b8605Smrg ralloc_free(sh); 143848b8605Smrg} 144848b8605Smrg 145848b8605Smrg 146848b8605Smrg/** 147848b8605Smrg * Lookup a GLSL shader object. 148848b8605Smrg */ 149848b8605Smrgstruct gl_shader * 150848b8605Smrg_mesa_lookup_shader(struct gl_context *ctx, GLuint name) 151848b8605Smrg{ 152848b8605Smrg if (name) { 153848b8605Smrg struct gl_shader *sh = (struct gl_shader *) 154848b8605Smrg _mesa_HashLookup(ctx->Shared->ShaderObjects, name); 155848b8605Smrg /* Note that both gl_shader and gl_shader_program objects are kept 156848b8605Smrg * in the same hash table. Check the object's type to be sure it's 157848b8605Smrg * what we're expecting. 158848b8605Smrg */ 159848b8605Smrg if (sh && sh->Type == GL_SHADER_PROGRAM_MESA) { 160848b8605Smrg return NULL; 161848b8605Smrg } 162848b8605Smrg return sh; 163848b8605Smrg } 164848b8605Smrg return NULL; 165848b8605Smrg} 166848b8605Smrg 167848b8605Smrg 168848b8605Smrg/** 169848b8605Smrg * As above, but record an error if shader is not found. 170848b8605Smrg */ 171848b8605Smrgstruct gl_shader * 172848b8605Smrg_mesa_lookup_shader_err(struct gl_context *ctx, GLuint name, const char *caller) 173848b8605Smrg{ 174848b8605Smrg if (!name) { 175848b8605Smrg _mesa_error(ctx, GL_INVALID_VALUE, "%s", caller); 176848b8605Smrg return NULL; 177848b8605Smrg } 178848b8605Smrg else { 179848b8605Smrg struct gl_shader *sh = (struct gl_shader *) 180848b8605Smrg _mesa_HashLookup(ctx->Shared->ShaderObjects, name); 181848b8605Smrg if (!sh) { 182848b8605Smrg _mesa_error(ctx, GL_INVALID_VALUE, "%s", caller); 183848b8605Smrg return NULL; 184848b8605Smrg } 185848b8605Smrg if (sh->Type == GL_SHADER_PROGRAM_MESA) { 186848b8605Smrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s", caller); 187848b8605Smrg return NULL; 188848b8605Smrg } 189848b8605Smrg return sh; 190848b8605Smrg } 191848b8605Smrg} 192848b8605Smrg 193848b8605Smrg 194848b8605Smrg 195848b8605Smrg/**********************************************************************/ 196848b8605Smrg/*** Shader Program object functions ***/ 197848b8605Smrg/**********************************************************************/ 198848b8605Smrg 199b8e80941Smrgvoid 200b8e80941Smrg_mesa_reference_shader_program_data(struct gl_context *ctx, 201b8e80941Smrg struct gl_shader_program_data **ptr, 202b8e80941Smrg struct gl_shader_program_data *data) 203b8e80941Smrg{ 204b8e80941Smrg if (*ptr == data) 205b8e80941Smrg return; 206b8e80941Smrg 207b8e80941Smrg if (*ptr) { 208b8e80941Smrg struct gl_shader_program_data *oldData = *ptr; 209b8e80941Smrg 210b8e80941Smrg assert(oldData->RefCount > 0); 211b8e80941Smrg 212b8e80941Smrg if (p_atomic_dec_zero(&oldData->RefCount)) { 213b8e80941Smrg assert(ctx); 214b8e80941Smrg assert(oldData->NumUniformStorage == 0 || 215b8e80941Smrg oldData->UniformStorage); 216b8e80941Smrg 217b8e80941Smrg for (unsigned i = 0; i < oldData->NumUniformStorage; ++i) 218b8e80941Smrg _mesa_uniform_detach_all_driver_storage(&oldData->UniformStorage[i]); 219b8e80941Smrg 220b8e80941Smrg ralloc_free(oldData); 221b8e80941Smrg } 222b8e80941Smrg 223b8e80941Smrg *ptr = NULL; 224b8e80941Smrg } 225b8e80941Smrg 226b8e80941Smrg if (data) 227b8e80941Smrg p_atomic_inc(&data->RefCount); 228b8e80941Smrg 229b8e80941Smrg *ptr = data; 230b8e80941Smrg} 231848b8605Smrg 232848b8605Smrg/** 233848b8605Smrg * Set ptr to point to shProg. 234848b8605Smrg * If ptr is pointing to another object, decrement its refcount (and delete 235848b8605Smrg * if refcount hits zero). 236848b8605Smrg * Then set ptr to point to shProg, incrementing its refcount. 237848b8605Smrg */ 238848b8605Smrgvoid 239b8e80941Smrg_mesa_reference_shader_program_(struct gl_context *ctx, 240b8e80941Smrg struct gl_shader_program **ptr, 241b8e80941Smrg struct gl_shader_program *shProg) 242848b8605Smrg{ 243848b8605Smrg assert(ptr); 244848b8605Smrg if (*ptr == shProg) { 245848b8605Smrg /* no-op */ 246848b8605Smrg return; 247848b8605Smrg } 248848b8605Smrg if (*ptr) { 249848b8605Smrg /* Unreference the old shader program */ 250848b8605Smrg struct gl_shader_program *old = *ptr; 251848b8605Smrg 252b8e80941Smrg assert(old->RefCount > 0); 253848b8605Smrg 254b8e80941Smrg if (p_atomic_dec_zero(&old->RefCount)) { 255848b8605Smrg if (old->Name != 0) 256848b8605Smrg _mesa_HashRemove(ctx->Shared->ShaderObjects, old->Name); 257b8e80941Smrg _mesa_delete_shader_program(ctx, old); 258848b8605Smrg } 259848b8605Smrg 260848b8605Smrg *ptr = NULL; 261848b8605Smrg } 262848b8605Smrg assert(!*ptr); 263848b8605Smrg 264848b8605Smrg if (shProg) { 265b8e80941Smrg p_atomic_inc(&shProg->RefCount); 266848b8605Smrg *ptr = shProg; 267848b8605Smrg } 268848b8605Smrg} 269848b8605Smrg 270b8e80941Smrgstruct gl_shader_program_data * 271b8e80941Smrg_mesa_create_shader_program_data() 272b8e80941Smrg{ 273b8e80941Smrg struct gl_shader_program_data *data; 274b8e80941Smrg data = rzalloc(NULL, struct gl_shader_program_data); 275b8e80941Smrg if (data) { 276b8e80941Smrg data->RefCount = 1; 277b8e80941Smrg data->InfoLog = ralloc_strdup(data, ""); 278b8e80941Smrg } 279b8e80941Smrg 280b8e80941Smrg return data; 281b8e80941Smrg} 282b8e80941Smrg 283b8e80941Smrgstatic void 284b8e80941Smrginit_shader_program(struct gl_shader_program *prog) 285848b8605Smrg{ 286848b8605Smrg prog->Type = GL_SHADER_PROGRAM_MESA; 287848b8605Smrg prog->RefCount = 1; 288848b8605Smrg 289848b8605Smrg prog->AttributeBindings = string_to_uint_map_ctor(); 290848b8605Smrg prog->FragDataBindings = string_to_uint_map_ctor(); 291848b8605Smrg prog->FragDataIndexBindings = string_to_uint_map_ctor(); 292848b8605Smrg 293848b8605Smrg prog->Geom.UsesEndPrimitive = false; 294848b8605Smrg prog->Geom.UsesStreams = false; 295848b8605Smrg 296848b8605Smrg prog->TransformFeedback.BufferMode = GL_INTERLEAVED_ATTRIBS; 297848b8605Smrg 298b8e80941Smrg exec_list_make_empty(&prog->EmptyUniformLocations); 299848b8605Smrg} 300848b8605Smrg 301848b8605Smrg/** 302848b8605Smrg * Allocate a new gl_shader_program object, initialize it. 303848b8605Smrg */ 304b8e80941Smrgstruct gl_shader_program * 305b8e80941Smrg_mesa_new_shader_program(GLuint name) 306848b8605Smrg{ 307848b8605Smrg struct gl_shader_program *shProg; 308848b8605Smrg shProg = rzalloc(NULL, struct gl_shader_program); 309848b8605Smrg if (shProg) { 310848b8605Smrg shProg->Name = name; 311b8e80941Smrg shProg->data = _mesa_create_shader_program_data(); 312b8e80941Smrg if (!shProg->data) { 313b8e80941Smrg ralloc_free(shProg); 314b8e80941Smrg return NULL; 315b8e80941Smrg } 316b8e80941Smrg init_shader_program(shProg); 317848b8605Smrg } 318848b8605Smrg return shProg; 319848b8605Smrg} 320848b8605Smrg 321848b8605Smrg 322848b8605Smrg/** 323848b8605Smrg * Clear (free) the shader program state that gets produced by linking. 324848b8605Smrg */ 325848b8605Smrgvoid 326848b8605Smrg_mesa_clear_shader_program_data(struct gl_context *ctx, 327848b8605Smrg struct gl_shader_program *shProg) 328848b8605Smrg{ 329b8e80941Smrg for (gl_shader_stage sh = 0; sh < MESA_SHADER_STAGES; sh++) { 330b8e80941Smrg if (shProg->_LinkedShaders[sh] != NULL) { 331b8e80941Smrg _mesa_delete_linked_shader(ctx, shProg->_LinkedShaders[sh]); 332b8e80941Smrg shProg->_LinkedShaders[sh] = NULL; 333b8e80941Smrg } 334848b8605Smrg } 335848b8605Smrg 336848b8605Smrg if (shProg->UniformRemapTable) { 337848b8605Smrg ralloc_free(shProg->UniformRemapTable); 338848b8605Smrg shProg->NumUniformRemapTable = 0; 339848b8605Smrg shProg->UniformRemapTable = NULL; 340848b8605Smrg } 341848b8605Smrg 342848b8605Smrg if (shProg->UniformHash) { 343848b8605Smrg string_to_uint_map_dtor(shProg->UniformHash); 344848b8605Smrg shProg->UniformHash = NULL; 345848b8605Smrg } 346848b8605Smrg 347b8e80941Smrg _mesa_reference_shader_program_data(ctx, &shProg->data, NULL); 348848b8605Smrg} 349848b8605Smrg 350848b8605Smrg 351848b8605Smrg/** 352848b8605Smrg * Free all the data that hangs off a shader program object, but not the 353848b8605Smrg * object itself. 354848b8605Smrg */ 355848b8605Smrgvoid 356848b8605Smrg_mesa_free_shader_program_data(struct gl_context *ctx, 357848b8605Smrg struct gl_shader_program *shProg) 358848b8605Smrg{ 359848b8605Smrg GLuint i; 360848b8605Smrg 361848b8605Smrg assert(shProg->Type == GL_SHADER_PROGRAM_MESA); 362848b8605Smrg 363848b8605Smrg _mesa_clear_shader_program_data(ctx, shProg); 364848b8605Smrg 365848b8605Smrg if (shProg->AttributeBindings) { 366848b8605Smrg string_to_uint_map_dtor(shProg->AttributeBindings); 367848b8605Smrg shProg->AttributeBindings = NULL; 368848b8605Smrg } 369848b8605Smrg 370848b8605Smrg if (shProg->FragDataBindings) { 371848b8605Smrg string_to_uint_map_dtor(shProg->FragDataBindings); 372848b8605Smrg shProg->FragDataBindings = NULL; 373848b8605Smrg } 374848b8605Smrg 375848b8605Smrg if (shProg->FragDataIndexBindings) { 376848b8605Smrg string_to_uint_map_dtor(shProg->FragDataIndexBindings); 377848b8605Smrg shProg->FragDataIndexBindings = NULL; 378848b8605Smrg } 379848b8605Smrg 380848b8605Smrg /* detach shaders */ 381848b8605Smrg for (i = 0; i < shProg->NumShaders; i++) { 382848b8605Smrg _mesa_reference_shader(ctx, &shProg->Shaders[i], NULL); 383848b8605Smrg } 384848b8605Smrg shProg->NumShaders = 0; 385848b8605Smrg 386848b8605Smrg free(shProg->Shaders); 387848b8605Smrg shProg->Shaders = NULL; 388848b8605Smrg 389848b8605Smrg /* Transform feedback varying vars */ 390848b8605Smrg for (i = 0; i < shProg->TransformFeedback.NumVarying; i++) { 391848b8605Smrg free(shProg->TransformFeedback.VaryingNames[i]); 392848b8605Smrg } 393848b8605Smrg free(shProg->TransformFeedback.VaryingNames); 394848b8605Smrg shProg->TransformFeedback.VaryingNames = NULL; 395848b8605Smrg shProg->TransformFeedback.NumVarying = 0; 396848b8605Smrg 397848b8605Smrg free(shProg->Label); 398848b8605Smrg shProg->Label = NULL; 399848b8605Smrg} 400848b8605Smrg 401848b8605Smrg 402848b8605Smrg/** 403848b8605Smrg * Free/delete a shader program object. 404848b8605Smrg */ 405b8e80941Smrgvoid 406b8e80941Smrg_mesa_delete_shader_program(struct gl_context *ctx, 407b8e80941Smrg struct gl_shader_program *shProg) 408848b8605Smrg{ 409848b8605Smrg _mesa_free_shader_program_data(ctx, shProg); 410848b8605Smrg ralloc_free(shProg); 411848b8605Smrg} 412848b8605Smrg 413848b8605Smrg 414848b8605Smrg/** 415848b8605Smrg * Lookup a GLSL program object. 416848b8605Smrg */ 417848b8605Smrgstruct gl_shader_program * 418848b8605Smrg_mesa_lookup_shader_program(struct gl_context *ctx, GLuint name) 419848b8605Smrg{ 420848b8605Smrg struct gl_shader_program *shProg; 421848b8605Smrg if (name) { 422848b8605Smrg shProg = (struct gl_shader_program *) 423848b8605Smrg _mesa_HashLookup(ctx->Shared->ShaderObjects, name); 424848b8605Smrg /* Note that both gl_shader and gl_shader_program objects are kept 425848b8605Smrg * in the same hash table. Check the object's type to be sure it's 426848b8605Smrg * what we're expecting. 427848b8605Smrg */ 428848b8605Smrg if (shProg && shProg->Type != GL_SHADER_PROGRAM_MESA) { 429848b8605Smrg return NULL; 430848b8605Smrg } 431848b8605Smrg return shProg; 432848b8605Smrg } 433848b8605Smrg return NULL; 434848b8605Smrg} 435848b8605Smrg 436848b8605Smrg 437848b8605Smrg/** 438848b8605Smrg * As above, but record an error if program is not found. 439848b8605Smrg */ 440848b8605Smrgstruct gl_shader_program * 441848b8605Smrg_mesa_lookup_shader_program_err(struct gl_context *ctx, GLuint name, 442848b8605Smrg const char *caller) 443848b8605Smrg{ 444848b8605Smrg if (!name) { 445848b8605Smrg _mesa_error(ctx, GL_INVALID_VALUE, "%s", caller); 446848b8605Smrg return NULL; 447848b8605Smrg } 448848b8605Smrg else { 449848b8605Smrg struct gl_shader_program *shProg = (struct gl_shader_program *) 450848b8605Smrg _mesa_HashLookup(ctx->Shared->ShaderObjects, name); 451848b8605Smrg if (!shProg) { 452848b8605Smrg _mesa_error(ctx, GL_INVALID_VALUE, "%s", caller); 453848b8605Smrg return NULL; 454848b8605Smrg } 455848b8605Smrg if (shProg->Type != GL_SHADER_PROGRAM_MESA) { 456848b8605Smrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s", caller); 457848b8605Smrg return NULL; 458848b8605Smrg } 459848b8605Smrg return shProg; 460848b8605Smrg } 461848b8605Smrg} 462848b8605Smrg 463848b8605Smrg 464848b8605Smrgvoid 465848b8605Smrg_mesa_init_shader_object_functions(struct dd_function_table *driver) 466848b8605Smrg{ 467848b8605Smrg driver->LinkShader = _mesa_ir_link_shader; 468848b8605Smrg} 469