X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fmain%2Fshaderapi.c;h=0e46a09e7db1a5d74f06ed3dea93e7e48e554928;hb=edd50828618ed2efe799013c2723d67c407d86b4;hp=7771b7ce7da2f3ec674621b70307940895eba461;hpb=a4fd84ef5f247f50a3683ecdf7f9d801a6e3cf15;p=mesa.git diff --git a/src/mesa/main/shaderapi.c b/src/mesa/main/shaderapi.c index 7771b7ce7da..0e46a09e7db 100644 --- a/src/mesa/main/shaderapi.c +++ b/src/mesa/main/shaderapi.c @@ -77,14 +77,14 @@ _mesa_get_shader_flags(void) flags |= GLSL_DUMP; if (strstr(env, "log")) flags |= GLSL_LOG; + if (strstr(env, "cache_fb")) + flags |= GLSL_CACHE_FALLBACK; + if (strstr(env, "cache_info")) + flags |= GLSL_CACHE_INFO; if (strstr(env, "nopvert")) flags |= GLSL_NOP_VERT; if (strstr(env, "nopfrag")) flags |= GLSL_NOP_FRAG; - if (strstr(env, "nopt")) - flags |= GLSL_NO_OPT; - else if (strstr(env, "opt")) - flags |= GLSL_OPT; if (strstr(env, "uniform")) flags |= GLSL_UNIFORMS; if (strstr(env, "useprog")) @@ -140,8 +140,6 @@ _mesa_init_shader_state(struct gl_context *ctx) /* Extended for ARB_separate_shader_objects */ ctx->Shader.RefCount = 1; - mtx_init(&ctx->Shader.Mutex, mtx_plain); - ctx->TessCtrlProgram.patch_vertices = 3; for (i = 0; i < 4; ++i) ctx->TessCtrlProgram.patch_default_outer_level[i] = 1.0; @@ -156,19 +154,15 @@ _mesa_init_shader_state(struct gl_context *ctx) void _mesa_free_shader_state(struct gl_context *ctx) { - int i; - for (i = 0; i < MESA_SHADER_STAGES; i++) { - _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentProgram[i], - NULL); + for (int i = 0; i < MESA_SHADER_STAGES; i++) { + _mesa_reference_program(ctx, &ctx->Shader.CurrentProgram[i], NULL); } - _mesa_reference_program(ctx, &ctx->Shader._CurrentFragmentProgram, NULL); _mesa_reference_shader_program(ctx, &ctx->Shader.ActiveProgram, NULL); /* Extended for ARB_separate_shader_objects */ _mesa_reference_pipeline_object(ctx, &ctx->_Shader, NULL); assert(ctx->Shader.RefCount == 1); - mtx_destroy(&ctx->Shader.Mutex); } @@ -250,7 +244,27 @@ is_shader(struct gl_context *ctx, GLuint name) * Attach shader to a shader program. */ static void -attach_shader(struct gl_context *ctx, GLuint program, GLuint shader) +attach_shader(struct gl_context *ctx, struct gl_shader_program *shProg, + struct gl_shader *sh) +{ + GLuint n = shProg->NumShaders; + + shProg->Shaders = realloc(shProg->Shaders, + (n + 1) * sizeof(struct gl_shader *)); + if (!shProg->Shaders) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glAttachShader"); + return; + } + + /* append */ + shProg->Shaders[n] = NULL; /* since realloc() didn't zero the new space */ + _mesa_reference_shader(ctx, &shProg->Shaders[n], sh); + shProg->NumShaders++; +} + +static void +attach_shader_err(struct gl_context *ctx, GLuint program, GLuint shader, + const char *caller) { struct gl_shader_program *shProg; struct gl_shader *sh; @@ -258,11 +272,11 @@ attach_shader(struct gl_context *ctx, GLuint program, GLuint shader) const bool same_type_disallowed = _mesa_is_gles(ctx); - shProg = _mesa_lookup_shader_program_err(ctx, program, "glAttachShader"); + shProg = _mesa_lookup_shader_program_err(ctx, program, caller); if (!shProg) return; - sh = _mesa_lookup_shader_err(ctx, shader, "glAttachShader"); + sh = _mesa_lookup_shader_err(ctx, shader, caller); if (!sh) { return; } @@ -276,7 +290,7 @@ attach_shader(struct gl_context *ctx, GLuint program, GLuint shader) * "The error INVALID_OPERATION is generated by AttachObjectARB * if is already attached to ." */ - _mesa_error(ctx, GL_INVALID_OPERATION, "glAttachShader"); + _mesa_error(ctx, GL_INVALID_OPERATION, caller); return; } else if (same_type_disallowed && shProg->Shaders[i]->Stage == sh->Stage) { @@ -288,25 +302,25 @@ attach_shader(struct gl_context *ctx, GLuint program, GLuint shader) * is generated if [...] another shader object of the same type * as shader is already attached to program." */ - _mesa_error(ctx, GL_INVALID_OPERATION, "glAttachShader"); + _mesa_error(ctx, GL_INVALID_OPERATION, caller); return; } } - /* grow list */ - shProg->Shaders = realloc(shProg->Shaders, - (n + 1) * sizeof(struct gl_shader *)); - if (!shProg->Shaders) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glAttachShader"); - return; - } - - /* append */ - shProg->Shaders[n] = NULL; /* since realloc() didn't zero the new space */ - _mesa_reference_shader(ctx, &shProg->Shaders[n], sh); - shProg->NumShaders++; + attach_shader(ctx, shProg, sh); } +static void +attach_shader_no_error(struct gl_context *ctx, GLuint program, GLuint shader) +{ + struct gl_shader_program *shProg; + struct gl_shader *sh; + + shProg = _mesa_lookup_shader_program(ctx, program); + sh = _mesa_lookup_shader(ctx, shader); + + attach_shader(ctx, shProg, sh); +} static GLuint create_shader(struct gl_context *ctx, GLenum type) @@ -314,12 +328,6 @@ create_shader(struct gl_context *ctx, GLenum type) struct gl_shader *sh; GLuint name; - if (!_mesa_validate_shader_target(ctx, type)) { - _mesa_error(ctx, GL_INVALID_ENUM, "CreateShader(%s)", - _mesa_enum_to_string(type)); - return 0; - } - _mesa_HashLockMutex(ctx->Shared->ShaderObjects); name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1); sh = _mesa_new_shader(name, _mesa_shader_enum_to_shader_stage(type)); @@ -331,6 +339,19 @@ create_shader(struct gl_context *ctx, GLenum type) } +static GLuint +create_shader_err(struct gl_context *ctx, GLenum type, const char *caller) +{ + if (!_mesa_validate_shader_target(ctx, type)) { + _mesa_error(ctx, GL_INVALID_ENUM, "%s(%s)", + caller, _mesa_enum_to_string(type)); + return 0; + } + + return create_shader(ctx, type); +} + + static GLuint create_shader_program(struct gl_context *ctx) { @@ -636,7 +657,7 @@ get_programiv(struct gl_context *ctx, GLuint program, GLenum pname, *params = shProg->DeletePending; return; case GL_LINK_STATUS: - *params = shProg->data->LinkStatus; + *params = shProg->data->LinkStatus ? GL_TRUE : GL_FALSE; return; case GL_VALIDATE_STATUS: *params = shProg->data->Validated; @@ -721,7 +742,7 @@ get_programiv(struct gl_context *ctx, GLuint program, GLenum pname, break; if (check_gs_query(ctx, shProg)) { *params = shProg->_LinkedShaders[MESA_SHADER_GEOMETRY]-> - info.Geom.VerticesOut; + Program->info.gs.vertices_out; } return; case GL_GEOMETRY_SHADER_INVOCATIONS: @@ -729,7 +750,7 @@ get_programiv(struct gl_context *ctx, GLuint program, GLenum pname, break; if (check_gs_query(ctx, shProg)) { *params = shProg->_LinkedShaders[MESA_SHADER_GEOMETRY]-> - info.Geom.Invocations; + Program->info.gs.invocations; } return; case GL_GEOMETRY_INPUT_TYPE: @@ -737,7 +758,7 @@ get_programiv(struct gl_context *ctx, GLuint program, GLenum pname, break; if (check_gs_query(ctx, shProg)) { *params = shProg->_LinkedShaders[MESA_SHADER_GEOMETRY]-> - info.Geom.InputType; + Program->info.gs.input_primitive; } return; case GL_GEOMETRY_OUTPUT_TYPE: @@ -745,7 +766,7 @@ get_programiv(struct gl_context *ctx, GLuint program, GLenum pname, break; if (check_gs_query(ctx, shProg)) { *params = shProg->_LinkedShaders[MESA_SHADER_GEOMETRY]-> - info.Geom.OutputType; + Program->info.gs.output_primitive; } return; case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH: { @@ -809,12 +830,13 @@ get_programiv(struct gl_context *ctx, GLuint program, GLenum pname, return; } for (i = 0; i < 3; i++) - params[i] = shProg->Comp.LocalSize[i]; + params[i] = shProg->_LinkedShaders[MESA_SHADER_COMPUTE]-> + Program->info.cs.local_size[i]; return; } case GL_PROGRAM_SEPARABLE: /* If the program has not been linked, return initial value 0. */ - *params = (shProg->data->LinkStatus == GL_FALSE) ? 0 : shProg->SeparateShader; + *params = (shProg->data->LinkStatus == linking_failure) ? 0 : shProg->SeparateShader; return; /* ARB_tessellation_shader */ @@ -823,7 +845,7 @@ get_programiv(struct gl_context *ctx, GLuint program, GLenum pname, break; if (check_tcs_query(ctx, shProg)) { *params = shProg->_LinkedShaders[MESA_SHADER_TESS_CTRL]-> - info.TessCtrl.VerticesOut; + Program->info.tess.tcs_vertices_out; } return; case GL_TESS_GEN_MODE: @@ -831,7 +853,7 @@ get_programiv(struct gl_context *ctx, GLuint program, GLenum pname, break; if (check_tes_query(ctx, shProg)) { *params = shProg->_LinkedShaders[MESA_SHADER_TESS_EVAL]-> - info.TessEval.PrimitiveMode; + Program->info.tess.primitive_mode; } return; case GL_TESS_GEN_SPACING: @@ -840,7 +862,7 @@ get_programiv(struct gl_context *ctx, GLuint program, GLenum pname, if (check_tes_query(ctx, shProg)) { const struct gl_linked_shader *tes = shProg->_LinkedShaders[MESA_SHADER_TESS_EVAL]; - switch (tes->info.TessEval.Spacing) { + switch (tes->Program->info.tess.spacing) { case TESS_SPACING_EQUAL: *params = GL_EQUAL; break; @@ -861,7 +883,7 @@ get_programiv(struct gl_context *ctx, GLuint program, GLenum pname, break; if (check_tes_query(ctx, shProg)) { *params = shProg->_LinkedShaders[MESA_SHADER_TESS_EVAL]-> - info.TessEval.VertexOrder; + Program->info.tess.ccw ? GL_CCW : GL_CW; } return; case GL_TESS_GEN_POINT_MODE: @@ -869,7 +891,7 @@ get_programiv(struct gl_context *ctx, GLuint program, GLenum pname, break; if (check_tes_query(ctx, shProg)) { *params = shProg->_LinkedShaders[MESA_SHADER_TESS_EVAL]-> - info.TessEval.PointMode; + Program->info.tess.point_mode ? GL_TRUE : GL_FALSE; } return; default: @@ -902,7 +924,7 @@ get_shaderiv(struct gl_context *ctx, GLuint name, GLenum pname, GLint *params) *params = shader->DeletePending; break; case GL_COMPILE_STATUS: - *params = shader->CompileStatus; + *params = shader->CompileStatus ? GL_TRUE : GL_FALSE; break; case GL_INFO_LOG_LENGTH: *params = (shader->InfoLog && shader->InfoLog[0] != '\0') ? @@ -1002,9 +1024,18 @@ shader_source(struct gl_shader *sh, const GLchar *source) { assert(sh); - /* free old shader source string and install new one */ - free((void *)sh->Source); - sh->Source = source; + if (sh->CompileStatus == compile_skipped && !sh->FallbackSource) { + /* If shader was previously compiled back-up the source in case of cache + * fallback. + */ + sh->FallbackSource = sh->Source; + sh->Source = source; + } else { + /* free old shader source string and install new one */ + free((void *)sh->Source); + sh->Source = source; + } + #ifdef DEBUG sh->SourceChecksum = util_hash_crc32(sh->Source, strlen(sh->Source)); #endif @@ -1024,7 +1055,7 @@ _mesa_compile_shader(struct gl_context *ctx, struct gl_shader *sh) /* If the user called glCompileShader without first calling * glShaderSource, we should fail to compile, but not raise a GL_ERROR. */ - sh->CompileStatus = GL_FALSE; + sh->CompileStatus = compile_failure; } else { if (ctx->_Shader->Flags & GLSL_DUMP) { _mesa_log("GLSL source for %s shader %d:\n", @@ -1035,7 +1066,7 @@ _mesa_compile_shader(struct gl_context *ctx, struct gl_shader *sh) /* this call will set the shader->CompileStatus field to indicate if * compilation was successful. */ - _mesa_glsl_compile_shader(ctx, sh, false, false); + _mesa_glsl_compile_shader(ctx, sh, false, false, false); if (ctx->_Shader->Flags & GLSL_LOG) { _mesa_write_shader_to_file(sh); @@ -1097,10 +1128,40 @@ _mesa_link_program(struct gl_context *ctx, struct gl_shader_program *shProg) return; } - FLUSH_VERTICES(ctx, _NEW_PROGRAM); + unsigned programs_in_use = 0; + if (ctx->_Shader) + for (unsigned stage = 0; stage < MESA_SHADER_STAGES; stage++) { + if (ctx->_Shader->CurrentProgram[stage] && + ctx->_Shader->CurrentProgram[stage]->Id == shProg->Name) { + programs_in_use |= 1 << stage; + } + } + FLUSH_VERTICES(ctx, 0); _mesa_glsl_link_shader(ctx, shProg); + /* From section 7.3 (Program Objects) of the OpenGL 4.5 spec: + * + * "If LinkProgram or ProgramBinary successfully re-links a program + * object that is active for any shader stage, then the newly generated + * executable code will be installed as part of the current rendering + * state for all shader stages where the program is active. + * Additionally, the newly generated executable code is made part of + * the state of any program pipeline for all stages where the program + * is attached." + */ + if (shProg->data->LinkStatus && programs_in_use) { + while (programs_in_use) { + const int stage = u_bit_scan(&programs_in_use); + + struct gl_program *prog = NULL; + if (shProg->_LinkedShaders[stage]) + prog = shProg->_LinkedShaders[stage]->Program; + + _mesa_use_program(ctx, stage, shProg, prog, ctx->_Shader); + } + } + /* Capture .shader_test files. */ const char *capture_path = _mesa_get_shader_capture_path(); if (shProg->Name != 0 && shProg->Name != ~0 && capture_path != NULL) { @@ -1129,7 +1190,7 @@ _mesa_link_program(struct gl_context *ctx, struct gl_shader_program *shProg) ralloc_free(filename); } - if (shProg->data->LinkStatus == GL_FALSE && + if (shProg->data->LinkStatus == linking_failure && (ctx->_Shader->Flags & GLSL_REPORT_ERRORS)) { _mesa_debug(ctx, "Error linking program %u:\n%s\n", shProg->Name, shProg->data->InfoLog); @@ -1210,65 +1271,19 @@ _mesa_active_program(struct gl_context *ctx, struct gl_shader_program *shProg, } -static void -use_shader_program(struct gl_context *ctx, gl_shader_stage stage, - struct gl_shader_program *shProg, - struct gl_pipeline_object *shTarget) -{ - struct gl_shader_program **target; - - target = &shTarget->CurrentProgram[stage]; - if ((shProg != NULL) && (shProg->_LinkedShaders[stage] == NULL)) - shProg = NULL; - - if (shProg) - _mesa_shader_program_init_subroutine_defaults(ctx, shProg); - - if (*target != shProg) { - /* Program is current, flush it */ - if (shTarget == ctx->_Shader) { - FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS); - } - - /* If the shader is also bound as the current rendering shader, unbind - * it from that binding point as well. This ensures that the correct - * semantics of glDeleteProgram are maintained. - */ - switch (stage) { - case MESA_SHADER_VERTEX: - case MESA_SHADER_TESS_CTRL: - case MESA_SHADER_TESS_EVAL: - case MESA_SHADER_GEOMETRY: - case MESA_SHADER_COMPUTE: - /* Empty for now. */ - break; - case MESA_SHADER_FRAGMENT: - if (*target != NULL && - ((*target)->_LinkedShaders[MESA_SHADER_FRAGMENT] && - (*target)->_LinkedShaders[MESA_SHADER_FRAGMENT]->Program == - ctx->_Shader->_CurrentFragmentProgram)) { - _mesa_reference_program(ctx, - &ctx->_Shader->_CurrentFragmentProgram, - NULL); - } - break; - } - - _mesa_reference_shader_program(ctx, target, shProg); - return; - } -} - - /** * Use the named shader program for subsequent rendering. */ void -_mesa_use_program(struct gl_context *ctx, struct gl_shader_program *shProg) +_mesa_use_shader_program(struct gl_context *ctx, + struct gl_shader_program *shProg) { - int i; - for (i = 0; i < MESA_SHADER_STAGES; i++) - use_shader_program(ctx, i, shProg, &ctx->Shader); + for (int i = 0; i < MESA_SHADER_STAGES; i++) { + struct gl_program *new_prog = NULL; + if (shProg && shProg->_LinkedShaders[i]) + new_prog = shProg->_LinkedShaders[i]->Program; + _mesa_use_program(ctx, i, shProg, new_prog, &ctx->Shader); + } _mesa_active_program(ctx, shProg, "glUseProgram"); } @@ -1337,12 +1352,27 @@ validate_program(struct gl_context *ctx, GLuint program) } +void GLAPIENTRY +_mesa_AttachObjectARB_no_error(GLhandleARB program, GLhandleARB shader) +{ + GET_CURRENT_CONTEXT(ctx); + attach_shader_no_error(ctx, program, shader); +} + void GLAPIENTRY _mesa_AttachObjectARB(GLhandleARB program, GLhandleARB shader) { GET_CURRENT_CONTEXT(ctx); - attach_shader(ctx, program, shader); + attach_shader_err(ctx, program, shader, "glAttachObjectARB"); +} + + +void GLAPIENTRY +_mesa_AttachShader_no_error(GLuint program, GLuint shader) +{ + GET_CURRENT_CONTEXT(ctx); + attach_shader_no_error(ctx, program, shader); } @@ -1350,7 +1380,7 @@ void GLAPIENTRY _mesa_AttachShader(GLuint program, GLuint shader) { GET_CURRENT_CONTEXT(ctx); - attach_shader(ctx, program, shader); + attach_shader_err(ctx, program, shader, "glAttachShader"); } @@ -1365,12 +1395,30 @@ _mesa_CompileShader(GLuint shaderObj) } +GLuint GLAPIENTRY +_mesa_CreateShader_no_error(GLenum type) +{ + GET_CURRENT_CONTEXT(ctx); + return create_shader(ctx, type); +} + + GLuint GLAPIENTRY _mesa_CreateShader(GLenum type) { GET_CURRENT_CONTEXT(ctx); + if (MESA_VERBOSE & VERBOSE_API) _mesa_debug(ctx, "glCreateShader %s\n", _mesa_enum_to_string(type)); + + return create_shader_err(ctx, type, "glCreateShader"); +} + + +GLhandleARB GLAPIENTRY +_mesa_CreateShaderObjectARB_no_error(GLenum type) +{ + GET_CURRENT_CONTEXT(ctx); return create_shader(ctx, type); } @@ -1379,7 +1427,7 @@ GLhandleARB GLAPIENTRY _mesa_CreateShaderObjectARB(GLenum type) { GET_CURRENT_CONTEXT(ctx); - return create_shader(ctx, type); + return create_shader_err(ctx, type, "glCreateShaderObjectARB"); } @@ -1612,7 +1660,7 @@ _mesa_LinkProgram(GLuint programObj) "glLinkProgram")); } -#if defined(HAVE_SHA1) +#ifdef ENABLE_SHADER_CACHE /** * Generate a SHA-1 hash value string for given source string. */ @@ -1723,7 +1771,8 @@ read_shader(const gl_shader_stage stage, const char *source) return buffer; } -#endif /* HAVE_SHA1 */ + +#endif /* ENABLE_SHADER_CACHE */ /** * Called via glShaderSource() and glShaderSourceARB() API functions. @@ -1740,10 +1789,6 @@ _mesa_ShaderSource(GLuint shaderObj, GLsizei count, GLcharARB *source; struct gl_shader *sh; -#if defined(HAVE_SHA1) - GLcharARB *replacement; -#endif /* HAVE_SHA1 */ - sh = _mesa_lookup_shader_err(ctx, shaderObj, "glShaderSourceARB"); if (!sh) return; @@ -1799,7 +1844,9 @@ _mesa_ShaderSource(GLuint shaderObj, GLsizei count, source[totalLength - 1] = '\0'; source[totalLength - 2] = '\0'; -#if defined(HAVE_SHA1) +#ifdef ENABLE_SHADER_CACHE + GLcharARB *replacement; + /* Dump original shader source to MESA_SHADER_DUMP_PATH and replace * if corresponding entry found from MESA_SHADER_READ_PATH. */ @@ -1810,7 +1857,7 @@ _mesa_ShaderSource(GLuint shaderObj, GLsizei count, free(source); source = replacement; } -#endif /* HAVE_SHA1 */ +#endif /* ENABLE_SHADER_CACHE */ shader_source(sh, source); @@ -1818,40 +1865,44 @@ _mesa_ShaderSource(GLuint shaderObj, GLsizei count, } -void GLAPIENTRY -_mesa_UseProgram(GLuint program) +static ALWAYS_INLINE void +use_program(GLuint program, bool no_error) { GET_CURRENT_CONTEXT(ctx); - struct gl_shader_program *shProg; + struct gl_shader_program *shProg = NULL; if (MESA_VERBOSE & VERBOSE_API) _mesa_debug(ctx, "glUseProgram %u\n", program); - if (_mesa_is_xfb_active_and_unpaused(ctx)) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glUseProgram(transform feedback active)"); - return; - } - - if (program) { - shProg = _mesa_lookup_shader_program_err(ctx, program, "glUseProgram"); - if (!shProg) { - return; + if (no_error) { + if (program) { + shProg = _mesa_lookup_shader_program(ctx, program); } - if (!shProg->data->LinkStatus) { + } else { + if (_mesa_is_xfb_active_and_unpaused(ctx)) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glUseProgram(program %u not linked)", program); + "glUseProgram(transform feedback active)"); return; } - /* debug code */ - if (ctx->_Shader->Flags & GLSL_USE_PROG) { - print_shader_info(shProg); + if (program) { + shProg = + _mesa_lookup_shader_program_err(ctx, program, "glUseProgram"); + if (!shProg) + return; + + if (!shProg->data->LinkStatus) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glUseProgram(program %u not linked)", program); + return; + } + + /* debug code */ + if (ctx->_Shader->Flags & GLSL_USE_PROG) { + print_shader_info(shProg); + } } } - else { - shProg = NULL; - } /* The ARB_separate_shader_object spec says: * @@ -1862,24 +1913,42 @@ _mesa_UseProgram(GLuint program) * object (section 2.14.PPO), the program bound to the appropriate * stage of the pipeline object is considered current." */ - if (program) { + if (shProg) { /* Attach shader state to the binding point */ _mesa_reference_pipeline_object(ctx, &ctx->_Shader, &ctx->Shader); /* Update the program */ - _mesa_use_program(ctx, shProg); + _mesa_use_shader_program(ctx, shProg); } else { /* Must be done first: detach the progam */ - _mesa_use_program(ctx, shProg); + _mesa_use_shader_program(ctx, shProg); /* Unattach shader_state binding point */ - _mesa_reference_pipeline_object(ctx, &ctx->_Shader, ctx->Pipeline.Default); + _mesa_reference_pipeline_object(ctx, &ctx->_Shader, + ctx->Pipeline.Default); /* If a pipeline was bound, rebind it */ if (ctx->Pipeline.Current) { - _mesa_BindProgramPipeline(ctx->Pipeline.Current->Name); + if (no_error) + _mesa_BindProgramPipeline_no_error(ctx->Pipeline.Current->Name); + else + _mesa_BindProgramPipeline(ctx->Pipeline.Current->Name); } } } +void GLAPIENTRY +_mesa_UseProgram_no_error(GLuint program) +{ + use_program(program, true); +} + + +void GLAPIENTRY +_mesa_UseProgram(GLuint program) +{ + use_program(program, false); +} + + void GLAPIENTRY _mesa_ValidateProgram(GLuint program) { @@ -2067,7 +2136,7 @@ _mesa_ProgramBinary(GLuint program, GLenum binaryFormat, * Since any value of binaryFormat passed "is not one of those specified as * allowable for [this] command, an INVALID_ENUM error is generated." */ - shProg->data->LinkStatus = GL_FALSE; + shProg->data->LinkStatus = linking_failure; _mesa_error(ctx, GL_INVALID_ENUM, "glProgramBinary"); } @@ -2151,12 +2220,30 @@ invalid_value: void -_mesa_use_shader_program(struct gl_context *ctx, GLenum type, - struct gl_shader_program *shProg, - struct gl_pipeline_object *shTarget) +_mesa_use_program(struct gl_context *ctx, gl_shader_stage stage, + struct gl_shader_program *shProg, struct gl_program *prog, + struct gl_pipeline_object *shTarget) { - gl_shader_stage stage = _mesa_shader_enum_to_shader_stage(type); - use_shader_program(ctx, stage, shProg, shTarget); + struct gl_program **target; + + target = &shTarget->CurrentProgram[stage]; + if (prog) { + _mesa_program_init_subroutine_defaults(ctx, prog); + } + + if (*target != prog) { + /* Program is current, flush it */ + if (shTarget == ctx->_Shader) { + FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS); + } + + _mesa_reference_shader_program(ctx, + &shTarget->ReferencedPrograms[stage], + shProg); + _mesa_reference_program(ctx, target, prog); + return; + } + } @@ -2175,51 +2262,21 @@ _mesa_copy_linked_program_data(const struct gl_shader_program *src, struct gl_program *dst = dst_sh->Program; - dst->info.num_images = dst_sh->NumImages; dst->info.separate_shader = src->SeparateShader; switch (dst_sh->Stage) { - case MESA_SHADER_VERTEX: - dst->ClipDistanceArraySize = src->Vert.ClipDistanceArraySize; - dst->CullDistanceArraySize = src->Vert.CullDistanceArraySize; - break; - case MESA_SHADER_TESS_CTRL: { - dst->info.tcs.vertices_out = dst_sh->info.TessCtrl.VerticesOut; - break; - } - case MESA_SHADER_TESS_EVAL: { - dst->info.tes.primitive_mode = dst_sh->info.TessEval.PrimitiveMode; - dst->info.tes.spacing = dst_sh->info.TessEval.Spacing; - dst->info.tes.ccw = dst_sh->info.TessEval.VertexOrder == GL_CCW; - dst->info.tes.point_mode = dst_sh->info.TessEval.PointMode; - dst->ClipDistanceArraySize = src->TessEval.ClipDistanceArraySize; - dst->CullDistanceArraySize = src->TessEval.CullDistanceArraySize; - break; - } case MESA_SHADER_GEOMETRY: { dst->info.gs.vertices_in = src->Geom.VerticesIn; - dst->info.gs.vertices_out = dst_sh->info.Geom.VerticesOut; - dst->info.gs.invocations = dst_sh->info.Geom.Invocations; - dst->info.gs.input_primitive = dst_sh->info.Geom.InputType; - dst->info.gs.output_primitive = dst_sh->info.Geom.OutputType; - dst->ClipDistanceArraySize = src->Geom.ClipDistanceArraySize; - dst->CullDistanceArraySize = src->Geom.CullDistanceArraySize; dst->info.gs.uses_end_primitive = src->Geom.UsesEndPrimitive; dst->info.gs.uses_streams = src->Geom.UsesStreams; break; } case MESA_SHADER_FRAGMENT: { dst->info.fs.depth_layout = src->FragDepthLayout; - dst->info.fs.early_fragment_tests = dst_sh->info.EarlyFragmentTests; - dst->info.fs.inner_coverage = dst_sh->info.InnerCoverage; - dst->info.fs.post_depth_coverage = dst_sh->info.PostDepthCoverage; break; } case MESA_SHADER_COMPUTE: { - for (int i = 0; i < 3; i++) - dst->info.cs.local_size[i] = src->Comp.LocalSize[i]; dst->info.cs.shared_size = src->Comp.SharedSize; - dst->info.cs.local_size_variable = src->Comp.LocalSizeVariable; break; } default: @@ -2236,7 +2293,7 @@ _mesa_CreateShaderProgramv(GLenum type, GLsizei count, { GET_CURRENT_CONTEXT(ctx); - const GLuint shader = create_shader(ctx, type); + const GLuint shader = create_shader_err(ctx, type, "glCreateShaderProgramv"); GLuint program = 0; /* @@ -2265,7 +2322,7 @@ _mesa_CreateShaderProgramv(GLenum type, GLsizei count, get_shaderiv(ctx, shader, GL_COMPILE_STATUS, &compiled); if (compiled) { - attach_shader(ctx, program, shader); + attach_shader_err(ctx, program, shader, "glCreateShaderProgramv"); _mesa_link_program(ctx, shProg); detach_shader(ctx, program, shader); @@ -2273,7 +2330,7 @@ _mesa_CreateShaderProgramv(GLenum type, GLsizei count, /* Possibly... */ if (active-user-defined-varyings-in-linked-program) { append-error-to-info-log; - shProg->data->LinkStatus = GL_FALSE; + shProg->data->LinkStatus = linking_failure; } #endif } @@ -2357,11 +2414,6 @@ _mesa_GetSubroutineUniformLocation(GLuint program, GLenum shadertype, GLenum resource_type; gl_shader_stage stage; - if (!_mesa_has_ARB_shader_subroutine(ctx)) { - _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name); - return -1; - } - if (!_mesa_validate_shader_target(ctx, shadertype)) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name); return -1; @@ -2392,11 +2444,6 @@ _mesa_GetSubroutineIndex(GLuint program, GLenum shadertype, GLenum resource_type; gl_shader_stage stage; - if (!_mesa_has_ARB_shader_subroutine(ctx)) { - _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name); - return -1; - } - if (!_mesa_validate_shader_target(ctx, shadertype)) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name); return -1; @@ -2436,11 +2483,6 @@ _mesa_GetActiveSubroutineUniformiv(GLuint program, GLenum shadertype, GLenum resource_type; int count, i, j; - if (!_mesa_has_ARB_shader_subroutine(ctx)) { - _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name); - return; - } - if (!_mesa_validate_shader_target(ctx, shadertype)) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name); return; @@ -2523,11 +2565,6 @@ _mesa_GetActiveSubroutineUniformName(GLuint program, GLenum shadertype, GLenum resource_type; gl_shader_stage stage; - if (!_mesa_has_ARB_shader_subroutine(ctx)) { - _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name); - return; - } - if (!_mesa_validate_shader_target(ctx, shadertype)) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name); return; @@ -2562,11 +2599,6 @@ _mesa_GetActiveSubroutineName(GLuint program, GLenum shadertype, GLenum resource_type; gl_shader_stage stage; - if (!_mesa_has_ARB_shader_subroutine(ctx)) { - _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name); - return; - } - if (!_mesa_validate_shader_target(ctx, shadertype)) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name); return; @@ -2593,41 +2625,28 @@ _mesa_UniformSubroutinesuiv(GLenum shadertype, GLsizei count, { GET_CURRENT_CONTEXT(ctx); const char *api_name = "glUniformSubroutinesuiv"; - struct gl_shader_program *shProg; - struct gl_linked_shader *sh; gl_shader_stage stage; int i; - if (!_mesa_has_ARB_shader_subroutine(ctx)) { - _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name); - return; - } - if (!_mesa_validate_shader_target(ctx, shadertype)) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name); return; } stage = _mesa_shader_enum_to_shader_stage(shadertype); - shProg = ctx->_Shader->CurrentProgram[stage]; - if (!shProg) { - _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name); - return; - } - - sh = shProg->_LinkedShaders[stage]; - if (!sh) { + struct gl_program *p = ctx->_Shader->CurrentProgram[stage]; + if (!p) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name); return; } - struct gl_program *p = shProg->_LinkedShaders[stage]->Program; if (count != p->sh.NumSubroutineUniformRemapTable) { _mesa_error(ctx, GL_INVALID_VALUE, "%s", api_name); return; } i = 0; + bool flushed = false; do { struct gl_uniform_storage *uni = p->sh.SubroutineUniformRemapTable[i]; if (uni == NULL) { @@ -2635,6 +2654,11 @@ _mesa_UniformSubroutinesuiv(GLenum shadertype, GLsizei count, continue; } + if (!flushed) { + _mesa_flush_vertices_for_uniforms(ctx, uni); + flushed = true; + } + int uni_count = uni->array_elements ? uni->array_elements : 1; int j, k, f; @@ -2667,8 +2691,6 @@ _mesa_UniformSubroutinesuiv(GLenum shadertype, GLsizei count, } i += uni_count; } while(i < count); - - FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS); } @@ -2678,34 +2700,20 @@ _mesa_GetUniformSubroutineuiv(GLenum shadertype, GLint location, { GET_CURRENT_CONTEXT(ctx); const char *api_name = "glGetUniformSubroutineuiv"; - struct gl_shader_program *shProg; - struct gl_linked_shader *sh; gl_shader_stage stage; - if (!_mesa_has_ARB_shader_subroutine(ctx)) { - _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name); - return; - } - if (!_mesa_validate_shader_target(ctx, shadertype)) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name); return; } stage = _mesa_shader_enum_to_shader_stage(shadertype); - shProg = ctx->_Shader->CurrentProgram[stage]; - if (!shProg) { + struct gl_program *p = ctx->_Shader->CurrentProgram[stage]; + if (!p) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name); return; } - sh = shProg->_LinkedShaders[stage]; - if (!sh) { - _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name); - return; - } - - struct gl_program *p = sh->Program; if (location >= p->sh.NumSubroutineUniformRemapTable) { _mesa_error(ctx, GL_INVALID_VALUE, "%s", api_name); return; @@ -2725,11 +2733,6 @@ _mesa_GetProgramStageiv(GLuint program, GLenum shadertype, struct gl_linked_shader *sh; gl_shader_stage stage; - if (!_mesa_has_ARB_shader_subroutine(ctx)) { - _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name); - return; - } - if (!_mesa_validate_shader_target(ctx, shadertype)) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name); return; @@ -2871,13 +2874,12 @@ void _mesa_shader_write_subroutine_indices(struct gl_context *ctx, gl_shader_stage stage) { - if (ctx->_Shader->CurrentProgram[stage] && - ctx->_Shader->CurrentProgram[stage]->_LinkedShaders[stage]) + if (ctx->_Shader->CurrentProgram[stage]) _mesa_shader_write_subroutine_index(ctx, - ctx->_Shader->CurrentProgram[stage]->_LinkedShaders[stage]->Program); + ctx->_Shader->CurrentProgram[stage]); } -static void +void _mesa_program_init_subroutine_defaults(struct gl_context *ctx, struct gl_program *p) { @@ -2899,20 +2901,3 @@ _mesa_program_init_subroutine_defaults(struct gl_context *ctx, binding->IndexPtr[i] = find_compat_subroutine(p, uni->type); } } - -void -_mesa_shader_program_init_subroutine_defaults(struct gl_context *ctx, - struct gl_shader_program *shProg) -{ - int i; - - if (!shProg) - return; - - for (i = 0; i < MESA_SHADER_STAGES; i++) { - if (!shProg->_LinkedShaders[i]) - continue; - - _mesa_program_init_subroutine_defaults(ctx, shProg->_LinkedShaders[i]->Program); - } -}