shader.cpp revision 8e399777f3d6c0e02a31af9e231e7547d3fdbb7d
1/* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16#include "src/pixelflinger2/pixelflinger2.h" 17 18#include <assert.h> 19#include <stdio.h> 20#include <string.h> 21#include <map> 22 23#include <llvm/LLVMContext.h> 24#include <llvm/Module.h> 25#include <bcc/bcc.h> 26#include <dlfcn.h> 27 28 29#include "src/talloc/hieralloc.h" 30#include "src/mesa/main/shaderobj.h" 31#include "src/mesa/program/prog_parameter.h" 32#include "src/mesa/program/prog_uniform.h" 33#include "src/glsl/glsl_types.h" 34#include "src/glsl/ir_to_llvm.h" 35 36static void InitializeGLContext(struct gl_context *ctx) 37{ 38 memset(ctx, 0, sizeof(*ctx)); 39 ctx->API = API_OPENGLES2; 40 ctx->Extensions.ARB_draw_buffers = GL_TRUE; 41 ctx->Extensions.ARB_fragment_coord_conventions = GL_TRUE; 42 ctx->Extensions.EXT_texture_array = GL_TRUE; 43 ctx->Extensions.NV_texture_rectangle = GL_TRUE; 44 45 /* 1.10 minimums. */ 46 ctx->Const.MaxLights = 8; 47 ctx->Const.MaxClipPlanes = 8; 48 ctx->Const.MaxTextureUnits = 2; 49 50 /* More than the 1.10 minimum to appease parser tests taken from 51 * apps that (hopefully) already checked the number of coords. 52 */ 53 ctx->Const.MaxTextureCoordUnits = 4; 54 55 ctx->Const.VertexProgram.MaxAttribs = 16; 56 ctx->Const.VertexProgram.MaxUniformComponents = 512; 57 ctx->Const.MaxVarying = 8; 58 ctx->Const.MaxVertexTextureImageUnits = 0; 59 ctx->Const.MaxCombinedTextureImageUnits = 2; 60 ctx->Const.MaxTextureImageUnits = 2; 61 ctx->Const.FragmentProgram.MaxUniformComponents = 64; 62 63 ctx->Const.MaxDrawBuffers = 2; 64} 65 66void * llvmCtx = NULL; 67static const struct GLContext { 68 const gl_context * ctx; 69 GLContext() { 70 ctx = hieralloc_zero(NULL, gl_context); 71// ctx = (const gl_context*)calloc(1,sizeof(gl_context)); 72 InitializeGLContext(const_cast<gl_context *>(ctx)); 73 llvmCtx = new llvm::LLVMContext(); 74 } 75 ~GLContext() { 76 _mesa_glsl_release_types(); // TODO: find when to release to minize memory 77 _mesa_glsl_release_functions(); // the IR has pointers to types 78 hieralloc_free(const_cast<gl_context *>(ctx)); 79// free(const_cast<gl_context *>(ctx)); 80 ctx = NULL; 81 delete (llvm::LLVMContext *)llvmCtx; 82 } 83} glContext; 84 85extern "C" void GLContextDctr() 86{ 87 _mesa_glsl_release_types(); // TODO: find when to release to minize memory 88 _mesa_glsl_release_functions(); 89 //glContext.~GLContext(); 90} 91 92struct ShaderKey { 93 struct ScanLineKey { 94 GGLStencilState frontStencil, backStencil; 95 GGLBufferState bufferState; 96 GGLBlendState blendState; 97 } scanLineKey; 98 GGLPixelFormat textureFormats[GGL_MAXCOMBINEDTEXTUREIMAGEUNITS]; 99 unsigned char textureParameters[GGL_MAXCOMBINEDTEXTUREIMAGEUNITS]; // wrap and filter 100 bool operator <(const ShaderKey & rhs) const { 101 return memcmp(this, &rhs, sizeof(*this)) < 0; 102 } 103}; 104 105struct Instance { 106 llvm::Module * module; 107 struct BCCOpaqueScript * script; 108 void (* function)(); 109 ~Instance() { 110 // TODO: check bccDisposeScript, which seems to dispose llvm::Module 111 if (script) 112 bccDisposeScript(script); 113 else if (module) 114 delete module; 115 } 116}; 117 118struct Executable { // codegen info 119 std::map<ShaderKey, Instance *> instances; 120}; 121 122bool do_mat_op_to_vec(exec_list *instructions); 123 124extern void link_shaders(const struct gl_context *ctx, struct gl_shader_program *prog); 125 126extern "C" void compile_shader(const struct gl_context *ctx, struct gl_shader *shader); 127 128gl_shader * GGLShaderCreate(GLenum type) 129{ 130 return _mesa_new_shader(NULL, 0, type); 131} 132 133static gl_shader * ShaderCreate(const GGLInterface * iface, GLenum type) 134{ 135 GGL_GET_CONST_CONTEXT(ctx, iface); 136 if (GL_VERTEX_SHADER != type && GL_FRAGMENT_SHADER != type) { 137 gglError(GL_INVALID_ENUM); 138 return NULL; 139 } 140 gl_shader * shader = _mesa_new_shader(NULL, 0, type); 141 if (!shader) 142 gglError(GL_OUT_OF_MEMORY); 143 assert(1 == shader->RefCount); 144 return shader; 145} 146 147void GGLShaderSource(gl_shader_t * shader, GLsizei count, const char ** string, const int * length) 148{ 149 hieralloc_free(const_cast<GLchar *>(shader->Source)); 150 for (unsigned i = 0; i < count; i++) 151 { 152 int len = strlen(string[i]); 153 if (length && length[i] >= 0) 154 len = length[i]; 155 shader->Source = hieralloc_strndup_append(const_cast<GLchar *>(shader->Source), string[i], len); 156 } 157 printf("pf2: GGLShaderSource: \n '%s' \n", shader->Source); 158} 159 160GLboolean GGLShaderCompile(gl_shader * shader, const char * glsl, const char ** infoLog) 161{ 162 if (glsl) 163 shader->Source = glsl; 164 assert(shader->Source); 165 compile_shader(glContext.ctx, shader); 166 shader->Source = NULL; 167 if (infoLog) 168 *infoLog = shader->InfoLog; 169 return shader->CompileStatus; 170} 171 172static GLboolean ShaderCompile(const GGLInterface * iface, gl_shader * shader, 173 const char * glsl, const char ** infoLog) 174{ 175 GGL_GET_CONST_CONTEXT(ctx, iface); 176 if (!glsl && !shader->Source) { 177 gglError(GL_INVALID_VALUE); 178 assert(0); 179 return GL_FALSE; 180 } 181 return GGLShaderCompile(shader, glsl, infoLog); 182} 183 184void GGLShaderDelete(gl_shader * shader) 185{ 186 if (shader && shader->executable) { 187 for (std::map<ShaderKey, Instance *>::iterator it=shader->executable->instances.begin(); 188 it != shader->executable->instances.end(); it++) 189 (*it).second->~Instance(); 190 shader->executable->instances.~map(); 191 } 192 _mesa_delete_shader(NULL, shader); 193} 194 195static void ShaderDelete(const GGLInterface * iface, gl_shader * shader) 196{ 197 GGLShaderDelete(shader); 198} 199 200gl_shader_program * GGLShaderProgramCreate() 201{ 202 gl_shader_program * program = hieralloc_zero(NULL, struct gl_shader_program); 203 if (!program) 204 return NULL; 205 program->Attributes = hieralloc_zero(program, gl_program_parameter_list); 206 if (!program->Attributes) { 207 hieralloc_free(program); 208 return NULL; 209 } 210 program->Varying = hieralloc_zero(program, gl_program_parameter_list); 211 if (!program->Varying) { 212 hieralloc_free(program); 213 return NULL; 214 } 215 return program; 216} 217 218static gl_shader_program * ShaderProgramCreate(const GGLInterface * iface) 219{ 220 GGL_GET_CONST_CONTEXT(ctx, iface); 221 gl_shader_program * program = GGLShaderProgramCreate(); 222 if (!program) 223 gglError(GL_OUT_OF_MEMORY); 224 return program; 225} 226 227unsigned GGLShaderAttach(gl_shader_program * program, gl_shader * shader) 228{ 229 for (unsigned i = 0; i < program->NumShaders; i++) 230 if (program->Shaders[i]->Type == shader->Type || program->Shaders[i] == shader) 231 return GL_INVALID_OPERATION; 232 233 program->Shaders = (gl_shader **)hieralloc_realloc 234 (program, program->Shaders, gl_shader *, program->NumShaders + 1); 235 if (!program->Shaders) { 236 assert(0); 237 return GL_OUT_OF_MEMORY; 238 } 239 program->Shaders[program->NumShaders] = shader; 240 program->NumShaders++; 241 shader->RefCount++; 242 return GL_NO_ERROR; 243} 244 245static void ShaderAttach(const GGLInterface * iface, gl_shader_program * program, 246 gl_shader * shader) 247{ 248 unsigned error = GGLShaderAttach(program, shader); 249 if (GL_NO_ERROR != error) 250 gglError(error); 251} 252 253GLboolean GGLShaderProgramLink(gl_shader_program * program, const char ** infoLog) 254{ 255 link_shaders(glContext.ctx, program); 256 if (infoLog) 257 *infoLog = program->InfoLog; 258 if (!program->LinkStatus) 259 return program->LinkStatus; 260 printf("slots: attribute=%d varying=%d uniforms=%d \n", program->AttributeSlots, program->VaryingSlots, program->Uniforms->Slots); 261 for (unsigned i = 0; i < program->Attributes->NumParameters; i++) { 262 const gl_program_parameter & attribute = program->Attributes->Parameters[i]; 263 printf("attribute '%s': location=%d slots=%d \n", attribute.Name, attribute.Location, attribute.Slots); 264 } 265 for (unsigned i = 0; i < program->Varying->NumParameters; i++) { 266 const gl_program_parameter & varying = program->Varying->Parameters[i]; 267 printf("varying '%s': vs_location=%d fs_location=%d \n", varying.Name, varying.BindLocation, varying.Location); 268 } 269 for (unsigned i = 0; i < program->Uniforms->NumUniforms; i++) { 270 const gl_uniform & uniform = program->Uniforms->Uniforms[i]; 271 printf("uniform '%s': location=%d type=%s \n", uniform.Name, uniform.Pos, uniform.Type->name); 272 } 273 return program->LinkStatus; 274} 275 276static GLboolean ShaderProgramLink(gl_shader_program * program, const char ** infoLog) 277{ 278 return GGLShaderProgramLink(program, infoLog); 279} 280 281static void GetShaderKey(const GGLState * ctx, const gl_shader * shader, ShaderKey * key) 282{ 283 memset(key, 0, sizeof(*key)); 284 if (GL_FRAGMENT_SHADER == shader->Type) { 285 key->scanLineKey.frontStencil = ctx->frontStencil; 286 key->scanLineKey.backStencil = ctx->backStencil; 287 key->scanLineKey.bufferState = ctx->bufferState; 288 key->scanLineKey.blendState = ctx->blendState; 289 } 290 291 for (unsigned i = 0; i < GGL_MAXCOMBINEDTEXTUREIMAGEUNITS; i++) 292 if (shader->SamplersUsed & (1 << i)) { 293 const GGLTexture & texture = ctx->textureState.textures[i]; 294 key->textureFormats[i] = texture.format; 295 assert((1 << 2) > texture.wrapS); 296 key->textureParameters[i] |= texture.wrapS; 297 assert((1 << 2) > texture.wrapT); 298 key->textureParameters[i] |= texture.wrapT << 2; 299 assert((1 << 3) > texture.minFilter); 300 key->textureParameters[i] |= texture.minFilter << (2 + 2); 301 assert((1 << 1) > texture.magFilter); 302 key->textureParameters[i] |= texture.magFilter << (2 + 2 + 3); 303 } 304} 305 306static inline char HexDigit(unsigned char d) 307{ 308 return (d > 9 ? d + 'A' - 10 : d + '0'); 309} 310 311static const unsigned SHADER_KEY_STRING_LEN = GGL_MAXCOMBINEDTEXTUREIMAGEUNITS * 4 + 2; 312 313static void GetShaderKeyString(const GLenum type, const ShaderKey * key, 314 char * buffer, const unsigned bufferSize) 315{ 316 assert(1 == sizeof(char)); 317 assert(0xff >= GGL_PIXEL_FORMAT_COUNT); 318 assert(SHADER_KEY_STRING_LEN <= bufferSize); 319 char * str = buffer; 320 if (GL_VERTEX_SHADER == type) 321 *str++ = 'v'; 322 else if (GL_FRAGMENT_SHADER == type) 323 *str++ = 'f'; 324 else 325 assert(0); 326 for (unsigned i = 0; i < GGL_MAXCOMBINEDTEXTUREIMAGEUNITS; i++) { 327 *str++ = HexDigit(key->textureFormats[i] / 16); 328 *str++ = HexDigit(key->textureFormats[i] % 16); 329 *str++ = HexDigit(key->textureParameters[i] / 16); 330 *str++ = HexDigit(key->textureParameters[i] % 16); 331 } 332 *str++ = '\0'; 333} 334 335static const unsigned SCANLINE_KEY_STRING_LEN = 2 * sizeof(ShaderKey::scanLineKey) + 3 + SHADER_KEY_STRING_LEN; 336 337static char * GetScanlineKeyString(const ShaderKey * key, char * buffer, 338 const unsigned bufferSize) 339{ 340 assert(1 == sizeof(char)); 341 assert(0xff >= GGL_PIXEL_FORMAT_COUNT); 342 assert(SCANLINE_KEY_STRING_LEN <= bufferSize); 343 char * str = buffer; 344 *str++ = 's'; 345 const unsigned char * start = (const unsigned char *)&key->scanLineKey; 346 const unsigned char * const end = start + sizeof(key->scanLineKey); 347 for (; start < end; start++) { 348 *str++ = HexDigit(*start / 16); 349 *str++ = HexDigit(*start % 16); 350 } 351 GetShaderKeyString(GL_FRAGMENT_SHADER, key, str, bufferSize - (str - buffer)); 352 return buffer; 353} 354 355struct SymbolLookupContext { 356 const GGLState * gglCtx; 357 const gl_shader_program * program; 358 const gl_shader * shader; 359}; 360 361static void* SymbolLookup(void* pContext, const char* name) 362{ 363 SymbolLookupContext * ctx = (SymbolLookupContext *)pContext; 364// const gl_shader * shader = ctx->shader; 365// const gl_shader_program * program = ctx->program; 366 const GGLState * gglCtx = ctx->gglCtx; 367 const void * symbol = (void*)dlsym(RTLD_DEFAULT, name); 368 if (NULL == symbol) { 369 if (!strcmp(_PF2_TEXTURE_DATA_NAME_, name)) 370 symbol = (void *)gglCtx->textureState.textureData; 371 else if (!strcmp(_PF2_TEXTURE_DIMENSIONS_NAME_, name)) 372 symbol = (void *)gglCtx->textureState.textureDimensions; 373 else // attributes, varyings and uniforms are mapped to locations in pointers 374 assert(0); 375 } 376 printf("symbolLookup '%s'=%p \n", name, symbol); 377 assert(symbol); 378 return (void *)symbol; 379} 380 381static void CodeGen(Instance * instance, const char * mainName, gl_shader * shader, 382 gl_shader_program * program, const GGLState * gglCtx) 383{ 384 SymbolLookupContext ctx = {gglCtx, program, shader}; 385 int result = 0; 386 387 BCCScriptRef & script = instance->script; 388 script = bccCreateScript(); 389 result = bccReadModule(script, "glsl", (LLVMModuleRef)instance->module, 0); 390 assert(0 == result); 391 result = bccRegisterSymbolCallback(script, SymbolLookup, &ctx); 392 assert(0 == result); 393 result = bccPrepareExecutable(script, NULL, 0); 394 395 result = bccGetError(script); 396 if (result != 0) { 397 puts("failed bcc_compile"); 398 assert(0); 399 return; 400 } 401 402 instance->function = (void (*)())bccGetFuncAddr(script, mainName); 403 assert(instance->function); 404 result = bccGetError(script); 405 if (result != BCC_NO_ERROR) 406 fprintf(stderr, "Could not find '%s': %d\n", "main", result); 407 else 408 printf("bcc_compile %s=%p \n", mainName, instance->function); 409} 410 411void GenerateScanLine(const GGLState * gglCtx, const gl_shader_program * program, llvm::Module * mod, 412 const char * shaderName, const char * scanlineName); 413 414void GGLShaderUse(void * llvmCtx, const GGLState * gglState, gl_shader_program * program) 415{ 416 for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) { 417 if (!program->_LinkedShaders[i]) 418 continue; 419 gl_shader * shader = program->_LinkedShaders[i]; 420 shader->function = NULL; 421 if (!shader->executable) { 422 shader->executable = hieralloc_zero(shader, Executable); 423 shader->executable->instances = std::map<ShaderKey, Instance *>(); 424 } 425 426 ShaderKey shaderKey; 427 GetShaderKey(gglState, shader, &shaderKey); 428 Instance * instance = shader->executable->instances[shaderKey]; 429 if (!instance) { 430 puts("begin jit new shader"); 431 instance = hieralloc_zero(shader->executable, Instance); 432 instance->module = new llvm::Module("glsl", *(llvm::LLVMContext *)llvmCtx); 433 434 char shaderName [SHADER_KEY_STRING_LEN] = {0}; 435 GetShaderKeyString(shader->Type, &shaderKey, shaderName, sizeof shaderName / sizeof *shaderName); 436 437 char mainName [SHADER_KEY_STRING_LEN + 6] = {"main"}; 438 strcat(mainName, shaderName); 439 440 do_mat_op_to_vec(shader->ir); // TODO: move these passes to link? 441 442 llvm::Module * module = glsl_ir_to_llvm_module(shader->ir, instance->module, gglState, shaderName); 443 if (!module) 444 assert(0); 445#if USE_LLVM_SCANLINE 446 if (GL_FRAGMENT_SHADER == shader->Type) { 447 char scanlineName [SCANLINE_KEY_STRING_LEN] = {0}; 448 GetScanlineKeyString(&shaderKey, scanlineName, sizeof scanlineName / sizeof *scanlineName); 449 GenerateScanLine(gglState, program, module, mainName, scanlineName); 450 CodeGen(instance, scanlineName, shader, program, gglState); 451 } else 452#endif 453 CodeGen(instance, mainName, shader, program, gglState); 454 shader->executable->instances[shaderKey] = instance; 455 debug_printf("jit new shader '%s'(%p) \n", mainName, instance->function); 456 } else 457// debug_printf("use cached shader %p \n", instance->function); 458 ; 459 460 shader->function = instance->function; 461 } 462 puts("pf2: GGLShaderUse end"); 463} 464 465static void ShaderUse(GGLInterface * iface, gl_shader_program * program) 466{ 467 GGL_GET_CONTEXT(ctx, iface); 468 // so drawing calls will do nothing until ShaderUse with a program 469 SetShaderVerifyFunctions(iface); 470 if (!program) { 471 ctx->CurrentProgram = NULL; 472 return; 473 } 474 475 GGLShaderUse(ctx->llvmCtx, &ctx->state, program); 476 for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) { 477 if (!program->_LinkedShaders[i]) 478 continue; 479 if (!program->_LinkedShaders[i]->function) 480 continue; 481 if (GL_VERTEX_SHADER == program->_LinkedShaders[i]->Type) 482 ctx->PickRaster(iface); 483 else if (GL_FRAGMENT_SHADER == program->_LinkedShaders[i]->Type) 484 ctx->PickScanLine(iface); 485 else 486 assert(0); 487 } 488 ctx->CurrentProgram = program; 489} 490 491unsigned GGLShaderDetach(gl_shader_program * program, gl_shader * shader) 492{ 493 for (unsigned i = 0; i < program->NumShaders; i++) 494 if (program->Shaders[i] == shader) { 495 program->NumShaders--; 496 // just swap end to deleted shader 497 program->Shaders[i] = program->Shaders[program->NumShaders]; 498 shader->RefCount--; 499 if (1 == shader->RefCount && shader->DeletePending) 500 GGLShaderDelete(shader); 501 return GL_NO_ERROR; 502 } 503 return (GL_INVALID_OPERATION); 504} 505 506static void ShaderDetach(const GGLInterface * iface, gl_shader_program * program, 507 gl_shader * shader) 508{ 509 unsigned error = GGLShaderDetach(program, shader); 510 if (GL_NO_ERROR != error) 511 gglError(error); 512} 513 514void GGLShaderProgramDelete(gl_shader_program * program) 515{ 516 for (unsigned i = 0; i < program->NumShaders; i++) { 517 GGLShaderDelete(program->Shaders[i]); // actually just mark for delete 518 GGLShaderDetach(program, program->Shaders[i]); // detach will delete if ref == 1 519 i--; // GGLShaderDetach just swaps end to detached shader 520 } 521 522 for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) 523 GGLShaderDelete(program->_LinkedShaders[i]); 524 525 hieralloc_free(program); 526} 527 528static void ShaderProgramDelete(GGLInterface * iface, gl_shader_program * program) 529{ 530 GGL_GET_CONTEXT(ctx, iface); 531 if (ctx->CurrentProgram == program) { 532 ctx->CurrentProgram = NULL; 533 SetShaderVerifyFunctions(iface); 534 } 535 GGLShaderProgramDelete(program); 536} 537 538void GGLShaderGetiv(gl_shader_t * shader, const GLenum pname, GLint * params) 539{ 540 switch (pname) { 541 case GL_SHADER_TYPE: 542 *params = shader->Type; 543 break; 544 case GL_DELETE_STATUS: 545 *params = shader->DeletePending; 546 break; 547 case GL_COMPILE_STATUS: 548 *params = shader->CompileStatus; 549 break; 550 case GL_INFO_LOG_LENGTH: 551 *params = shader->InfoLog ? strlen(shader->InfoLog) + 1 : 0; 552 break; 553 case GL_SHADER_SOURCE_LENGTH: 554 *params = shader->Source ? strlen(shader->Source) + 1 : 0; 555 break; 556 default: 557 assert(0); 558 break; 559 } 560} 561 562void GGLShaderProgramGetiv(gl_shader_program_t * program, const GLenum pname, GLint * params) 563{ 564 switch (pname) { 565 case GL_DELETE_STATUS: 566 *params = program->DeletePending; 567 break; 568 case GL_LINK_STATUS: 569 *params = program->LinkStatus; 570 break; 571 case GL_VALIDATE_STATUS: 572 *params = program->LinkStatus; 573 break; 574 case GL_INFO_LOG_LENGTH: 575 *params = program->InfoLog ? strlen(program->InfoLog) + 1 : 0; 576 break; 577 case GL_ATTACHED_SHADERS: 578 *params = program->NumShaders; 579 break; 580 case GL_ACTIVE_ATTRIBUTES: 581 *params = program->AttributeSlots; 582 break; 583 case GL_ACTIVE_UNIFORMS: 584 *params = program->Uniforms->Slots; 585 break; 586 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH: 587 case GL_ACTIVE_UNIFORM_MAX_LENGTH: 588 printf("pf2:GGLShaderProgramGetiv not implemented: %d \n", pname); 589 default: 590 assert(0); 591 break; 592 } 593} 594 595void GGLShaderAttributeBind(const gl_shader_program * program, GLuint index, const GLchar * name) 596{ 597 int i = _mesa_add_parameter(program->Attributes, name); 598 program->Attributes->Parameters[i].BindLocation = index; 599} 600 601GLint GGLShaderAttributeLocation(const gl_shader_program * program, const char * name) 602{ 603 int i = _mesa_get_parameter(program->Attributes, name); 604 if (i >= 0) 605 return program->Attributes->Parameters[i].Location; 606 return -1; 607} 608 609GLint GGLShaderVaryingLocation(const gl_shader_program_t * program, 610 const char * name, GLint * vertexOutputLocation) 611{ 612 for (unsigned int i = 0; i < program->Varying->NumParameters; i++) 613 if (!strcmp(program->Varying->Parameters[i].Name, name)) { 614 if (vertexOutputLocation) 615 *vertexOutputLocation = program->Varying->Parameters[i].BindLocation; 616 return program->Varying->Parameters[i].Location; 617 } 618 return -1; 619} 620 621GLint GGLShaderUniformLocation(const gl_shader_program * program, 622 const char * name) 623{ 624 for (unsigned i = 0; i < program->Uniforms->NumUniforms; i++) 625 if (!strcmp(program->Uniforms->Uniforms[i].Name, name)) 626 return i; 627 return -1; 628} 629 630void GGLShaderUniformGetfv(gl_shader_program * program, GLint location, GLfloat * params) 631{ 632 assert(0 <= location && program->Uniforms->NumUniforms > location); 633 int index = program->Uniforms->Uniforms[location].Pos; 634 assert(0 <= index && program->Uniforms->Slots > index); 635 memcpy(params, program->ValuesUniform + index, sizeof(*program->ValuesUniform)); 636} 637 638void GGLShaderUniformGetiv(gl_shader_program * program, GLint location, GLint * params) 639{ 640 assert(0 <= location && program->Uniforms->NumUniforms > location); 641 int index = program->Uniforms->Uniforms[location].Pos; 642 assert(0 <= index && program->Uniforms->Slots > index); 643 const float * uniform = program->ValuesUniform[index]; 644 params[0] = uniform[0]; 645 params[1] = uniform[1]; 646 params[2] = uniform[2]; 647 params[3] = uniform[3]; 648} 649 650void GGLShaderUniformGetSamplers(const gl_shader_program_t * program, 651 int sampler2tmu[GGL_MAXCOMBINEDTEXTUREIMAGEUNITS]) 652{ 653 memset(sampler2tmu, 0xff, sizeof sampler2tmu); 654 for (unsigned i = 0; i < program->Uniforms->NumUniforms; i++) 655 { 656 const gl_uniform & uniform = program->Uniforms->Uniforms[i]; 657 if (uniform.Type->is_sampler()) 658 sampler2tmu[uniform.Pos] = program->ValuesUniform[i][0]; 659 else if (uniform.Type->is_array() && uniform.Type->fields.array->is_sampler()) 660 assert(0); 661 } 662} 663 664GLint GGLShaderUniform(gl_shader_program * program, GLint location, GLsizei count, 665 const GLvoid *values, GLenum type) 666{ 667 // TODO: sampler uniform and type checking 668 if (!program) { 669 //gglError(GL_INVALID_OPERATION); 670 return -2; 671 } 672 assert(0 <= location && program->Uniforms->NumUniforms > location); 673 const gl_uniform & unifrom = program->Uniforms->Uniforms[location]; 674 int start = unifrom.Pos; 675 int slots = 0, elems = 0; 676 switch (type) { 677 case GL_INT: 678 case GL_FLOAT: 679 case GL_BOOL: 680 slots = count; 681 elems = 1; 682 break; 683 case GL_FLOAT_VEC2: // fall through 684 case GL_INT_VEC2: // fall through 685 case GL_BOOL_VEC2: 686 slots = count; 687 elems = 2; 688 break; 689 case GL_INT_VEC3: // fall through 690 case GL_BOOL_VEC3: // fall through 691 case GL_FLOAT_VEC3: // fall through 692 slots = count; 693 elems = 3; 694 break; 695 case GL_INT_VEC4: // fall through 696 case GL_FLOAT_VEC4: // fall through 697 case GL_BOOL_VEC4: // fall through 698 slots = count; 699 elems = 4; 700 break; 701 default: 702 assert(0); 703 } 704 if (0 < start) 705 return -2; 706 if (start + slots > program->Uniforms->Slots) 707 return -2; 708 for (int i = 0; i < slots; i++) 709 memcpy(program->ValuesUniform + start + i, values, elems * sizeof(float)); 710 if (unifrom.Type->is_sampler()) 711 return program->ValuesUniform[start][0]; 712 else if (unifrom.Type->is_array() && unifrom.Type->fields.array->is_sampler()) 713 assert(0); 714 return -2; 715} 716 717void GGLShaderUniformMatrix(gl_shader_program * program, GLint cols, GLint rows, 718 GLint location, GLsizei count, GLboolean transpose, const GLfloat *values) 719{ 720 if (location == -1) 721 return; 722 assert(cols == rows); 723 assert(0 <= location && program->Uniforms->NumUniforms > location); 724 int start = program->Uniforms->Uniforms[location].Pos; 725 unsigned slots = cols * count; 726 if (start < 0 || start + slots > program->Uniforms->Slots) 727 return gglError(GL_INVALID_OPERATION); 728 for (unsigned i = 0; i < slots; i++) { 729 float * column = program->ValuesUniform[start + i]; 730 for (unsigned j = 0; j < rows; j++) 731 column[j] = *(values++); 732 } 733} 734 735static void ShaderVerifyProcessVertex(const GGLInterface * iface, const VertexInput * input, 736 VertexOutput * output) 737{ 738 GGL_GET_CONST_CONTEXT(ctx, iface); 739 if (ctx->CurrentProgram) { 740 ShaderUse(const_cast<GGLInterface *>(iface), ctx->CurrentProgram); 741 if (ShaderVerifyProcessVertex != iface->ProcessVertex) 742 iface->ProcessVertex(iface, input, output); 743 } 744} 745 746static void ShaderVerifyDrawTriangle(const GGLInterface * iface, const VertexInput * v0, 747 const VertexInput * v1, const VertexInput * v2) 748{ 749 GGL_GET_CONST_CONTEXT(ctx, iface); 750 if (ctx->CurrentProgram) { 751 ShaderUse(const_cast<GGLInterface *>(iface), ctx->CurrentProgram); 752 if (ShaderVerifyDrawTriangle != iface->DrawTriangle) 753 iface->DrawTriangle(iface, v0, v1, v2); 754 } 755} 756 757static void ShaderVerifyRasterTriangle(const GGLInterface * iface, const VertexOutput * v1, 758 const VertexOutput * v2, const VertexOutput * v3) 759{ 760 GGL_GET_CONST_CONTEXT(ctx, iface); 761 if (ctx->CurrentProgram) { 762 ShaderUse(const_cast<GGLInterface *>(iface), ctx->CurrentProgram); 763 if (ShaderVerifyRasterTriangle != iface->RasterTriangle) 764 iface->RasterTriangle(iface, v1, v2, v3); 765 } 766} 767 768static void ShaderVerifyRasterTrapezoid(const GGLInterface * iface, const VertexOutput * tl, 769 const VertexOutput * tr, const VertexOutput * bl, 770 const VertexOutput * br) 771{ 772 GGL_GET_CONST_CONTEXT(ctx, iface); 773 if (ctx->CurrentProgram) { 774 ShaderUse(const_cast<GGLInterface *>(iface), ctx->CurrentProgram); 775 if (ShaderVerifyRasterTrapezoid != iface->RasterTrapezoid) 776 iface->RasterTrapezoid(iface, tl, tr, bl, br); 777 } 778} 779 780static void ShaderVerifyScanLine(const GGLInterface * iface, const VertexOutput * v1, 781 const VertexOutput * v2) 782{ 783 GGL_GET_CONST_CONTEXT(ctx, iface); 784 if (ctx->CurrentProgram) { 785 ShaderUse(const_cast<GGLInterface *>(iface), ctx->CurrentProgram); 786 if (ShaderVerifyScanLine != iface->ScanLine) 787 iface->ScanLine(iface, v1, v2); 788 } 789} 790 791// called after state changes so that drawing calls will trigger JIT 792void SetShaderVerifyFunctions(struct GGLInterface * iface) 793{ 794 iface->ProcessVertex = ShaderVerifyProcessVertex; 795 iface->DrawTriangle = ShaderVerifyDrawTriangle; 796 iface->RasterTriangle = ShaderVerifyRasterTriangle; 797 iface->RasterTrapezoid = ShaderVerifyRasterTrapezoid; 798 iface->ScanLine = ShaderVerifyScanLine; 799} 800 801void InitializeShaderFunctions(struct GGLInterface * iface) 802{ 803 GGL_GET_CONTEXT(ctx, iface); 804 ctx->llvmCtx = new llvm::LLVMContext(); 805 806 iface->ShaderCreate = ShaderCreate; 807 iface->ShaderSource = GGLShaderSource; 808 iface->ShaderCompile = ShaderCompile; 809 iface->ShaderDelete = ShaderDelete; 810 iface->ShaderProgramCreate = ShaderProgramCreate; 811 iface->ShaderAttach = ShaderAttach; 812 iface->ShaderDetach = ShaderDetach; 813 iface->ShaderProgramLink = ShaderProgramLink; 814 iface->ShaderUse = ShaderUse; 815 iface->ShaderProgramDelete = ShaderProgramDelete; 816 iface->ShaderGetiv = GGLShaderGetiv; 817 iface->ShaderProgramGetiv = GGLShaderProgramGetiv; 818 iface->ShaderAttributeBind = GGLShaderAttributeBind; 819 iface->ShaderAttributeLocation = GGLShaderAttributeLocation; 820 iface->ShaderVaryingLocation = GGLShaderVaryingLocation; 821 iface->ShaderUniformLocation = GGLShaderUniformLocation; 822 iface->ShaderUniformGetfv = GGLShaderUniformGetfv; 823 iface->ShaderUniformGetiv = GGLShaderUniformGetiv; 824 iface->ShaderUniformGetSamplers = GGLShaderUniformGetSamplers; 825 iface->ShaderUniform = GGLShaderUniform; 826 iface->ShaderUniformMatrix = GGLShaderUniformMatrix; 827} 828 829void DestroyShaderFunctions(GGLInterface * iface) 830{ 831 GGL_GET_CONTEXT(ctx, iface); 832 _mesa_glsl_release_types(); 833 _mesa_glsl_release_functions(); 834 delete ctx->llvmCtx; 835 ctx->llvmCtx = NULL; 836} 837