1 /************************************************************************** 2 * 3 * Copyright 2007 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 (at) vmware.com> 31 * Brian Paul 32 */ 33 34 #include "main/imports.h" 35 #include "program/prog_parameter.h" 36 #include "program/prog_print.h" 37 #include "main/shaderapi.h" 38 #include "pipe/p_context.h" 39 #include "pipe/p_defines.h" 40 #include "util/u_inlines.h" 41 #include "util/u_upload_mgr.h" 42 #include "cso_cache/cso_context.h" 43 44 #include "st_debug.h" 45 #include "st_context.h" 46 #include "st_atom.h" 47 #include "st_atom_constbuf.h" 48 #include "st_program.h" 49 #include "st_cb_bufferobjects.h" 50 51 /** 52 * Pass the given program parameters to the graphics pipe as a 53 * constant buffer. 54 * \param shader_type either PIPE_SHADER_VERTEX or PIPE_SHADER_FRAGMENT 55 */ 56 void st_upload_constants( struct st_context *st, 57 struct gl_program_parameter_list *params, 58 gl_shader_stage stage) 59 { 60 enum pipe_shader_type shader_type = st_shader_stage_to_ptarget(stage); 61 62 assert(shader_type == PIPE_SHADER_VERTEX || 63 shader_type == PIPE_SHADER_FRAGMENT || 64 shader_type == PIPE_SHADER_GEOMETRY || 65 shader_type == PIPE_SHADER_TESS_CTRL || 66 shader_type == PIPE_SHADER_TESS_EVAL || 67 shader_type == PIPE_SHADER_COMPUTE); 68 69 /* update the ATI constants before rendering */ 70 if (shader_type == PIPE_SHADER_FRAGMENT && st->fp->ati_fs) { 71 struct ati_fragment_shader *ati_fs = st->fp->ati_fs; 72 unsigned c; 73 74 for (c = 0; c < MAX_NUM_FRAGMENT_CONSTANTS_ATI; c++) { 75 if (ati_fs->LocalConstDef & (1 << c)) 76 memcpy(params->ParameterValues[c], 77 ati_fs->Constants[c], sizeof(GLfloat) * 4); 78 else 79 memcpy(params->ParameterValues[c], 80 st->ctx->ATIFragmentShader.GlobalConstants[c], sizeof(GLfloat) * 4); 81 } 82 } 83 84 /* update constants */ 85 if (params && params->NumParameters) { 86 struct pipe_constant_buffer cb; 87 const uint paramBytes = params->NumParameters * sizeof(GLfloat) * 4; 88 89 /* Update the constants which come from fixed-function state, such as 90 * transformation matrices, fog factors, etc. The rest of the values in 91 * the parameters list are explicitly set by the user with glUniform, 92 * glProgramParameter(), etc. 93 */ 94 if (params->StateFlags) 95 _mesa_load_state_parameters(st->ctx, params); 96 97 _mesa_shader_write_subroutine_indices(st->ctx, stage); 98 99 /* We always need to get a new buffer, to keep the drivers simple and 100 * avoid gratuitous rendering synchronization. 101 * Let's use a user buffer to avoid an unnecessary copy. 102 */ 103 if (st->constbuf_uploader) { 104 cb.buffer = NULL; 105 cb.user_buffer = NULL; 106 u_upload_data(st->constbuf_uploader, 0, paramBytes, 107 st->ctx->Const.UniformBufferOffsetAlignment, 108 params->ParameterValues, &cb.buffer_offset, &cb.buffer); 109 u_upload_unmap(st->constbuf_uploader); 110 } else { 111 cb.buffer = NULL; 112 cb.user_buffer = params->ParameterValues; 113 cb.buffer_offset = 0; 114 } 115 cb.buffer_size = paramBytes; 116 117 if (ST_DEBUG & DEBUG_CONSTANTS) { 118 debug_printf("%s(shader=%d, numParams=%d, stateFlags=0x%x)\n", 119 __func__, shader_type, params->NumParameters, 120 params->StateFlags); 121 _mesa_print_parameter_list(params); 122 } 123 124 cso_set_constant_buffer(st->cso_context, shader_type, 0, &cb); 125 pipe_resource_reference(&cb.buffer, NULL); 126 127 st->state.constants[shader_type].ptr = params->ParameterValues; 128 st->state.constants[shader_type].size = paramBytes; 129 } 130 else if (st->state.constants[shader_type].ptr) { 131 /* Unbind. */ 132 st->state.constants[shader_type].ptr = NULL; 133 st->state.constants[shader_type].size = 0; 134 cso_set_constant_buffer(st->cso_context, shader_type, 0, NULL); 135 } 136 } 137 138 139 /** 140 * Vertex shader: 141 */ 142 static void update_vs_constants(struct st_context *st ) 143 { 144 struct st_vertex_program *vp = st->vp; 145 struct gl_program_parameter_list *params = vp->Base.Parameters; 146 147 st_upload_constants( st, params, MESA_SHADER_VERTEX ); 148 } 149 150 151 const struct st_tracked_state st_update_vs_constants = { 152 update_vs_constants /* update */ 153 }; 154 155 156 157 /** 158 * Fragment shader: 159 */ 160 static void update_fs_constants(struct st_context *st ) 161 { 162 struct st_fragment_program *fp = st->fp; 163 struct gl_program_parameter_list *params = fp->Base.Parameters; 164 165 st_upload_constants( st, params, MESA_SHADER_FRAGMENT ); 166 } 167 168 169 const struct st_tracked_state st_update_fs_constants = { 170 update_fs_constants /* update */ 171 }; 172 173 /* Geometry shader: 174 */ 175 static void update_gs_constants(struct st_context *st ) 176 { 177 struct st_geometry_program *gp = st->gp; 178 struct gl_program_parameter_list *params; 179 180 if (gp) { 181 params = gp->Base.Parameters; 182 st_upload_constants( st, params, MESA_SHADER_GEOMETRY ); 183 } 184 } 185 186 const struct st_tracked_state st_update_gs_constants = { 187 update_gs_constants /* update */ 188 }; 189 190 /* Tessellation control shader: 191 */ 192 static void update_tcs_constants(struct st_context *st ) 193 { 194 struct st_tessctrl_program *tcp = st->tcp; 195 struct gl_program_parameter_list *params; 196 197 if (tcp) { 198 params = tcp->Base.Parameters; 199 st_upload_constants( st, params, MESA_SHADER_TESS_CTRL ); 200 } 201 } 202 203 const struct st_tracked_state st_update_tcs_constants = { 204 update_tcs_constants /* update */ 205 }; 206 207 /* Tessellation evaluation shader: 208 */ 209 static void update_tes_constants(struct st_context *st ) 210 { 211 struct st_tesseval_program *tep = st->tep; 212 struct gl_program_parameter_list *params; 213 214 if (tep) { 215 params = tep->Base.Parameters; 216 st_upload_constants( st, params, MESA_SHADER_TESS_EVAL ); 217 } 218 } 219 220 const struct st_tracked_state st_update_tes_constants = { 221 update_tes_constants /* update */ 222 }; 223 224 /* Compute shader: 225 */ 226 static void update_cs_constants(struct st_context *st ) 227 { 228 struct st_compute_program *cp = st->cp; 229 struct gl_program_parameter_list *params; 230 231 if (cp) { 232 params = cp->Base.Parameters; 233 st_upload_constants( st, params, MESA_SHADER_COMPUTE ); 234 } 235 } 236 237 const struct st_tracked_state st_update_cs_constants = { 238 update_cs_constants /* update */ 239 }; 240 241 static void st_bind_ubos(struct st_context *st, struct gl_program *prog, 242 unsigned shader_type) 243 { 244 unsigned i; 245 struct pipe_constant_buffer cb = { 0 }; 246 247 if (!prog) 248 return; 249 250 for (i = 0; i < prog->info.num_ubos; i++) { 251 struct gl_uniform_buffer_binding *binding; 252 struct st_buffer_object *st_obj; 253 254 binding = 255 &st->ctx->UniformBufferBindings[prog->sh.UniformBlocks[i]->Binding]; 256 st_obj = st_buffer_object(binding->BufferObject); 257 258 cb.buffer = st_obj->buffer; 259 260 if (cb.buffer) { 261 cb.buffer_offset = binding->Offset; 262 cb.buffer_size = cb.buffer->width0 - binding->Offset; 263 264 /* AutomaticSize is FALSE if the buffer was set with BindBufferRange. 265 * Take the minimum just to be sure. 266 */ 267 if (!binding->AutomaticSize) 268 cb.buffer_size = MIN2(cb.buffer_size, (unsigned) binding->Size); 269 } 270 else { 271 cb.buffer_offset = 0; 272 cb.buffer_size = 0; 273 } 274 275 cso_set_constant_buffer(st->cso_context, shader_type, 1 + i, &cb); 276 } 277 } 278 279 static void bind_vs_ubos(struct st_context *st) 280 { 281 struct gl_shader_program *prog = 282 st->ctx->_Shader->CurrentProgram[MESA_SHADER_VERTEX]; 283 284 if (!prog || !prog->_LinkedShaders[MESA_SHADER_VERTEX]) 285 return; 286 287 st_bind_ubos(st, prog->_LinkedShaders[MESA_SHADER_VERTEX]->Program, PIPE_SHADER_VERTEX); 288 } 289 290 const struct st_tracked_state st_bind_vs_ubos = { 291 bind_vs_ubos 292 }; 293 294 static void bind_fs_ubos(struct st_context *st) 295 { 296 struct gl_shader_program *prog = 297 st->ctx->_Shader->CurrentProgram[MESA_SHADER_FRAGMENT]; 298 299 if (!prog || !prog->_LinkedShaders[MESA_SHADER_FRAGMENT]) 300 return; 301 302 st_bind_ubos(st, prog->_LinkedShaders[MESA_SHADER_FRAGMENT]->Program, PIPE_SHADER_FRAGMENT); 303 } 304 305 const struct st_tracked_state st_bind_fs_ubos = { 306 bind_fs_ubos 307 }; 308 309 static void bind_gs_ubos(struct st_context *st) 310 { 311 struct gl_shader_program *prog = 312 st->ctx->_Shader->CurrentProgram[MESA_SHADER_GEOMETRY]; 313 314 if (!prog || !prog->_LinkedShaders[MESA_SHADER_GEOMETRY]) 315 return; 316 317 st_bind_ubos(st, prog->_LinkedShaders[MESA_SHADER_GEOMETRY]->Program, PIPE_SHADER_GEOMETRY); 318 } 319 320 const struct st_tracked_state st_bind_gs_ubos = { 321 bind_gs_ubos 322 }; 323 324 static void bind_tcs_ubos(struct st_context *st) 325 { 326 struct gl_shader_program *prog = 327 st->ctx->_Shader->CurrentProgram[MESA_SHADER_TESS_CTRL]; 328 329 if (!prog || !prog->_LinkedShaders[MESA_SHADER_TESS_CTRL]) 330 return; 331 332 st_bind_ubos(st, prog->_LinkedShaders[MESA_SHADER_TESS_CTRL]->Program, PIPE_SHADER_TESS_CTRL); 333 } 334 335 const struct st_tracked_state st_bind_tcs_ubos = { 336 bind_tcs_ubos 337 }; 338 339 static void bind_tes_ubos(struct st_context *st) 340 { 341 struct gl_shader_program *prog = 342 st->ctx->_Shader->CurrentProgram[MESA_SHADER_TESS_EVAL]; 343 344 if (!prog || !prog->_LinkedShaders[MESA_SHADER_TESS_EVAL]) 345 return; 346 347 st_bind_ubos(st, prog->_LinkedShaders[MESA_SHADER_TESS_EVAL]->Program, PIPE_SHADER_TESS_EVAL); 348 } 349 350 const struct st_tracked_state st_bind_tes_ubos = { 351 bind_tes_ubos 352 }; 353 354 static void bind_cs_ubos(struct st_context *st) 355 { 356 struct gl_shader_program *prog = 357 st->ctx->_Shader->CurrentProgram[MESA_SHADER_COMPUTE]; 358 359 if (!prog || !prog->_LinkedShaders[MESA_SHADER_COMPUTE]) 360 return; 361 362 st_bind_ubos(st, prog->_LinkedShaders[MESA_SHADER_COMPUTE]->Program, 363 PIPE_SHADER_COMPUTE); 364 } 365 366 const struct st_tracked_state st_bind_cs_ubos = { 367 bind_cs_ubos 368 }; 369