1/************************************************************************** 2 * 3 * Copyright 2003 VMware, Inc. 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sub license, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial portions 16 * of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 * 26 **************************************************************************/ 27 28 /* 29 * Authors: 30 * Keith Whitwell <keithw@vmware.com> 31 */ 32 33#include "main/glheader.h" 34#include "main/macros.h" 35#include "main/enums.h" 36#include "main/shaderapi.h" 37#include "program/prog_instruction.h" 38#include "program/program.h" 39 40#include "cso_cache/cso_context.h" 41#include "draw/draw_context.h" 42 43#include "st_context.h" 44#include "st_debug.h" 45#include "st_program.h" 46#include "st_cb_program.h" 47#include "st_glsl_to_ir.h" 48#include "st_atifs_to_nir.h" 49#include "st_util.h" 50 51 52/** 53 * Called via ctx->Driver.NewProgram() to allocate a new vertex or 54 * fragment program. 55 */ 56static struct gl_program * 57st_new_program(struct gl_context *ctx, gl_shader_stage stage, GLuint id, 58 bool is_arb_asm) 59{ 60 struct st_program *prog; 61 62 switch (stage) { 63 case MESA_SHADER_VERTEX: 64 prog = (struct st_program*)rzalloc(NULL, struct st_vertex_program); 65 break; 66 default: 67 prog = rzalloc(NULL, struct st_program); 68 break; 69 } 70 71 return _mesa_init_gl_program(&prog->Base, stage, id, is_arb_asm); 72} 73 74 75/** 76 * Called via ctx->Driver.DeleteProgram() 77 */ 78static void 79st_delete_program(struct gl_context *ctx, struct gl_program *prog) 80{ 81 struct st_context *st = st_context(ctx); 82 struct st_program *stp = st_program(prog); 83 84 st_release_variants(st, stp); 85 86 if (stp->glsl_to_tgsi) 87 free_glsl_to_tgsi_visitor(stp->glsl_to_tgsi); 88 89 free(stp->serialized_nir); 90 91 /* delete base class */ 92 _mesa_delete_program( ctx, prog ); 93} 94 95/** 96 * Called via ctx->Driver.ProgramStringNotify() 97 * Called when the program's text/code is changed. We have to free 98 * all shader variants and corresponding gallium shaders when this happens. 99 */ 100static GLboolean 101st_program_string_notify( struct gl_context *ctx, 102 GLenum target, 103 struct gl_program *prog ) 104{ 105 struct st_context *st = st_context(ctx); 106 struct st_program *stp = (struct st_program *) prog; 107 108 /* GLSL-to-NIR should not end up here. */ 109 assert(!stp->shader_program); 110 111 st_release_variants(st, stp); 112 113 if (target == GL_FRAGMENT_PROGRAM_ARB || 114 target == GL_FRAGMENT_SHADER_ATI) { 115 if (target == GL_FRAGMENT_SHADER_ATI) { 116 assert(stp->ati_fs); 117 assert(stp->ati_fs->Program == prog); 118 119 st_init_atifs_prog(ctx, prog); 120 } 121 122 if (!st_translate_fragment_program(st, stp)) 123 return false; 124 } else if (target == GL_VERTEX_PROGRAM_ARB) { 125 if (!st_translate_vertex_program(st, stp)) 126 return false; 127 } else { 128 if (!st_translate_common_program(st, stp)) 129 return false; 130 } 131 132 st_finalize_program(st, prog); 133 return GL_TRUE; 134} 135 136/** 137 * Called via ctx->Driver.NewATIfs() 138 * Called in glEndFragmentShaderATI() 139 */ 140static struct gl_program * 141st_new_ati_fs(struct gl_context *ctx, struct ati_fragment_shader *curProg) 142{ 143 struct gl_program *prog = ctx->Driver.NewProgram(ctx, MESA_SHADER_FRAGMENT, 144 curProg->Id, true); 145 struct st_program *stfp = (struct st_program *)prog; 146 stfp->ati_fs = curProg; 147 return prog; 148} 149 150static void 151st_max_shader_compiler_threads(struct gl_context *ctx, unsigned count) 152{ 153 struct pipe_screen *screen = st_context(ctx)->screen; 154 155 if (screen->set_max_shader_compiler_threads) 156 screen->set_max_shader_compiler_threads(screen, count); 157} 158 159static bool 160st_get_shader_program_completion_status(struct gl_context *ctx, 161 struct gl_shader_program *shprog) 162{ 163 struct pipe_screen *screen = st_context(ctx)->screen; 164 165 if (!screen->is_parallel_shader_compilation_finished) 166 return true; 167 168 for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) { 169 struct gl_linked_shader *linked = shprog->_LinkedShaders[i]; 170 void *sh = NULL; 171 172 if (!linked || !linked->Program) 173 continue; 174 175 if (st_program(linked->Program)->variants) 176 sh = st_program(linked->Program)->variants->driver_shader; 177 178 unsigned type = pipe_shader_type_from_mesa(i); 179 180 if (sh && 181 !screen->is_parallel_shader_compilation_finished(screen, sh, type)) 182 return false; 183 } 184 return true; 185} 186 187/** 188 * Plug in the program and shader-related device driver functions. 189 */ 190void 191st_init_program_functions(struct dd_function_table *functions) 192{ 193 functions->NewProgram = st_new_program; 194 functions->DeleteProgram = st_delete_program; 195 functions->ProgramStringNotify = st_program_string_notify; 196 functions->NewATIfs = st_new_ati_fs; 197 functions->LinkShader = st_link_shader; 198 functions->SetMaxShaderCompilerThreads = st_max_shader_compiler_threads; 199 functions->GetShaderProgramCompletionStatus = 200 st_get_shader_program_completion_status; 201} 202