X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fmain%2Fshaderapi.c;h=41c3202148e88dad27acf4d9b9cb85e5090a0553;hb=95c48391ee16654ca3038c89dcb50d8ea9861e1f;hp=82a1ec371303cb88c2dabc831cb3a260f137a848;hpb=7147f7098e55e3d2e62516a54c1ff8e77c9052d0;p=mesa.git diff --git a/src/mesa/main/shaderapi.c b/src/mesa/main/shaderapi.c index 82a1ec37130..41c3202148e 100644 --- a/src/mesa/main/shaderapi.c +++ b/src/mesa/main/shaderapi.c @@ -49,10 +49,10 @@ #include "main/shaderobj.h" #include "main/transformfeedback.h" #include "main/uniforms.h" -#include "glsl/glsl_parser_extras.h" -#include "glsl/ir.h" -#include "glsl/ir_uniform.h" -#include "glsl/program.h" +#include "compiler/glsl/glsl_parser_extras.h" +#include "compiler/glsl/ir.h" +#include "compiler/glsl/ir_uniform.h" +#include "compiler/glsl/program.h" #include "program/program.h" #include "program/prog_print.h" #include "program/prog_parameter.h" @@ -60,6 +60,10 @@ #include "util/hash_table.h" #include "util/mesa-sha1.h" +#ifdef _MSC_VER +#include +#define PATH_MAX _MAX_PATH +#endif /** * Return mask of GLSL_x flags by examining the MESA_GLSL env var. @@ -96,6 +100,29 @@ _mesa_get_shader_flags(void) return flags; } +/** + * Memoized version of getenv("MESA_SHADER_CAPTURE_PATH"). + */ +const char * +_mesa_get_shader_capture_path(void) +{ + static bool read_env_var = false; + static const char *path = NULL; + + if (!read_env_var) { + path = getenv("MESA_SHADER_CAPTURE_PATH"); + read_env_var = true; + if (path && + strlen(path) > PATH_MAX - strlen("/fp-4294967295.shader_test")) { + GET_CURRENT_CONTEXT(ctx); + _mesa_warning(ctx, "MESA_SHADER_CAPTURE_PATH too long; ignoring " + "request to capture shaders"); + path = NULL; + } + } + + return path; +} /** * Initialize context's shader state. @@ -208,7 +235,7 @@ _mesa_validate_shader_target(const struct gl_context *ctx, GLenum type) case GL_TESS_EVALUATION_SHADER: return ctx == NULL || _mesa_has_tessellation(ctx); case GL_COMPUTE_SHADER: - return ctx == NULL || ctx->Extensions.ARB_compute_shader; + return ctx == NULL || _mesa_has_compute_shaders(ctx); default: return false; } @@ -264,7 +291,7 @@ attach_shader(struct gl_context *ctx, GLuint program, GLuint shader) _mesa_error(ctx, GL_INVALID_OPERATION, "glAttachShader"); return; } else if (same_type_disallowed && - shProg->Shaders[i]->Type == sh->Type) { + shProg->Shaders[i]->Stage == sh->Stage) { /* Shader with the same type is already attached to this program, * OpenGL ES 2.0 and 3.0 specs say: * @@ -300,13 +327,17 @@ create_shader(struct gl_context *ctx, GLenum type) GLuint name; if (!_mesa_validate_shader_target(ctx, type)) { - _mesa_error(ctx, GL_INVALID_ENUM, "CreateShader(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 = ctx->Driver.NewShader(ctx, name, type); - _mesa_HashInsert(ctx->Shared->ShaderObjects, name, sh); + sh = _mesa_new_shader(name, _mesa_shader_enum_to_shader_stage(type)); + sh->Type = type; + _mesa_HashInsertLocked(ctx->Shared->ShaderObjects, name, sh); + _mesa_HashUnlockMutex(ctx->Shared->ShaderObjects); return name; } @@ -318,14 +349,18 @@ create_shader_program(struct gl_context *ctx) GLuint name; struct gl_shader_program *shProg; + _mesa_HashLockMutex(ctx->Shared->ShaderObjects); + name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1); - shProg = ctx->Driver.NewShaderProgram(name); + shProg = _mesa_new_shader_program(name); - _mesa_HashInsert(ctx->Shared->ShaderObjects, name, shProg); + _mesa_HashInsertLocked(ctx->Shared->ShaderObjects, name, shProg); assert(shProg->RefCount == 1); + _mesa_HashUnlockMutex(ctx->Shared->ShaderObjects); + return name; } @@ -422,11 +457,11 @@ detach_shader(struct gl_context *ctx, GLuint program, GLuint shader) #ifdef DEBUG /* sanity check - make sure the new list's entries are sensible */ for (j = 0; j < shProg->NumShaders; j++) { - assert(shProg->Shaders[j]->Type == GL_VERTEX_SHADER || - shProg->Shaders[j]->Type == GL_TESS_CONTROL_SHADER || - shProg->Shaders[j]->Type == GL_TESS_EVALUATION_SHADER || - shProg->Shaders[j]->Type == GL_GEOMETRY_SHADER || - shProg->Shaders[j]->Type == GL_FRAGMENT_SHADER); + assert(shProg->Shaders[j]->Stage == MESA_SHADER_VERTEX || + shProg->Shaders[j]->Stage == MESA_SHADER_TESS_CTRL || + shProg->Shaders[j]->Stage == MESA_SHADER_TESS_EVAL || + shProg->Shaders[j]->Stage == MESA_SHADER_GEOMETRY || + shProg->Shaders[j]->Stage == MESA_SHADER_FRAGMENT); assert(shProg->Shaders[j]->RefCount > 0); } #endif @@ -630,9 +665,16 @@ get_programiv(struct gl_context *ctx, GLuint program, GLenum pname, case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH: *params = _mesa_longest_attribute_name_length(shProg); return; - case GL_ACTIVE_UNIFORMS: - *params = shProg->NumUniformStorage - shProg->NumHiddenUniforms; + case GL_ACTIVE_UNIFORMS: { + unsigned i; + const unsigned num_uniforms = + shProg->NumUniformStorage - shProg->NumHiddenUniforms; + for (*params = 0, i = 0; i < num_uniforms; i++) { + if (!shProg->UniformStorage[i].is_shader_storage) + (*params)++; + } return; + } case GL_ACTIVE_UNIFORM_MAX_LENGTH: { unsigned i; GLint max_len = 0; @@ -640,6 +682,9 @@ get_programiv(struct gl_context *ctx, GLuint program, GLenum pname, shProg->NumUniformStorage - shProg->NumHiddenUniforms; for (i = 0; i < num_uniforms; i++) { + if (shProg->UniformStorage[i].is_shader_storage) + continue; + /* Add one for the terminating NUL character for a non-array, and * 4 for the "[0]" and the NUL for an array. */ @@ -685,26 +730,34 @@ get_programiv(struct gl_context *ctx, GLuint program, GLenum pname, case GL_GEOMETRY_VERTICES_OUT: if (!has_core_gs) break; - if (check_gs_query(ctx, shProg)) - *params = shProg->Geom.VerticesOut; + if (check_gs_query(ctx, shProg)) { + *params = shProg->_LinkedShaders[MESA_SHADER_GEOMETRY]-> + info.Geom.VerticesOut; + } return; case GL_GEOMETRY_SHADER_INVOCATIONS: if (!has_core_gs || !ctx->Extensions.ARB_gpu_shader5) break; - if (check_gs_query(ctx, shProg)) - *params = shProg->Geom.Invocations; + if (check_gs_query(ctx, shProg)) { + *params = shProg->_LinkedShaders[MESA_SHADER_GEOMETRY]-> + info.Geom.Invocations; + } return; case GL_GEOMETRY_INPUT_TYPE: if (!has_core_gs) break; - if (check_gs_query(ctx, shProg)) - *params = shProg->Geom.InputType; + if (check_gs_query(ctx, shProg)) { + *params = shProg->_LinkedShaders[MESA_SHADER_GEOMETRY]-> + info.Geom.InputType; + } return; case GL_GEOMETRY_OUTPUT_TYPE: if (!has_core_gs) break; - if (check_gs_query(ctx, shProg)) - *params = shProg->Geom.OutputType; + if (check_gs_query(ctx, shProg)) { + *params = shProg->_LinkedShaders[MESA_SHADER_GEOMETRY]-> + info.Geom.OutputType; + } return; case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH: { unsigned i; @@ -713,7 +766,7 @@ get_programiv(struct gl_context *ctx, GLuint program, GLenum pname, if (!has_ubo) break; - for (i = 0; i < shProg->NumBufferInterfaceBlocks; i++) { + for (i = 0; i < shProg->NumUniformBlocks; i++) { /* Add one for the terminating NUL character. */ const GLint len = strlen(shProg->UniformBlocks[i].Name) + 1; @@ -729,11 +782,7 @@ get_programiv(struct gl_context *ctx, GLuint program, GLenum pname, if (!has_ubo) break; - *params = 0; - for (unsigned i = 0; i < shProg->NumBufferInterfaceBlocks; i++) { - if (!shProg->UniformBlocks[i].IsShaderStorage) - (*params)++; - } + *params = shProg->NumUniformBlocks; return; case GL_PROGRAM_BINARY_RETRIEVABLE_HINT: /* This enum isn't part of the OES extension for OpenGL ES 2.0. It is @@ -783,32 +832,42 @@ get_programiv(struct gl_context *ctx, GLuint program, GLenum pname, case GL_TESS_CONTROL_OUTPUT_VERTICES: if (!has_tess) break; - if (check_tcs_query(ctx, shProg)) - *params = shProg->TessCtrl.VerticesOut; + if (check_tcs_query(ctx, shProg)) { + *params = shProg->_LinkedShaders[MESA_SHADER_TESS_CTRL]-> + info.TessCtrl.VerticesOut; + } return; case GL_TESS_GEN_MODE: if (!has_tess) break; - if (check_tes_query(ctx, shProg)) - *params = shProg->TessEval.PrimitiveMode; + if (check_tes_query(ctx, shProg)) { + *params = shProg->_LinkedShaders[MESA_SHADER_TESS_EVAL]-> + info.TessEval.PrimitiveMode; + } return; case GL_TESS_GEN_SPACING: if (!has_tess) break; - if (check_tes_query(ctx, shProg)) - *params = shProg->TessEval.Spacing; + if (check_tes_query(ctx, shProg)) { + *params = shProg->_LinkedShaders[MESA_SHADER_TESS_EVAL]-> + info.TessEval.Spacing; + } return; case GL_TESS_GEN_VERTEX_ORDER: if (!has_tess) break; - if (check_tes_query(ctx, shProg)) - *params = shProg->TessEval.VertexOrder; + if (check_tes_query(ctx, shProg)) { + *params = shProg->_LinkedShaders[MESA_SHADER_TESS_EVAL]-> + info.TessEval.VertexOrder; + } return; case GL_TESS_GEN_POINT_MODE: if (!has_tess) break; - if (check_tes_query(ctx, shProg)) - *params = shProg->TessEval.PointMode; + if (check_tes_query(ctx, shProg)) { + *params = shProg->_LinkedShaders[MESA_SHADER_TESS_EVAL]-> + info.TessEval.PointMode; + } return; default: break; @@ -942,7 +1001,6 @@ shader_source(struct gl_shader *sh, const GLchar *source) /* free old shader source string and install new one */ free((void *)sh->Source); sh->Source = source; - sh->CompileStatus = GL_FALSE; #ifdef DEBUG sh->SourceChecksum = _mesa_str_checksum(sh->Source); #endif @@ -952,12 +1010,9 @@ shader_source(struct gl_shader *sh, const GLchar *source) /** * Compile a shader. */ -static void -compile_shader(struct gl_context *ctx, GLuint shaderObj) +void +_mesa_compile_shader(struct gl_context *ctx, struct gl_shader *sh) { - struct gl_shader *sh; - - sh = _mesa_lookup_shader_err(ctx, shaderObj, "glCompileShader"); if (!sh) return; @@ -1016,12 +1071,9 @@ compile_shader(struct gl_context *ctx, GLuint shaderObj) /** * Link a program's shaders. */ -static void -link_program(struct gl_context *ctx, GLuint program) +void +_mesa_link_program(struct gl_context *ctx, struct gl_shader_program *shProg) { - struct gl_shader_program *shProg; - - shProg = _mesa_lookup_shader_program_err(ctx, program, "glLinkProgram"); if (!shProg) return; @@ -1040,6 +1092,35 @@ link_program(struct gl_context *ctx, GLuint program) _mesa_glsl_link_shader(ctx, shProg); + /* Capture .shader_test files. */ + const char *capture_path = _mesa_get_shader_capture_path(); + if (shProg->Name != 0 && shProg->Name != ~0 && capture_path != NULL) { + FILE *file; + char filename[PATH_MAX]; + + _mesa_snprintf(filename, sizeof(filename), "%s/%u.shader_test", + capture_path, shProg->Name); + + file = fopen(filename, "w"); + if (file) { + fprintf(file, "[require]\nGLSL%s >= %u.%02u\n", + shProg->IsES ? " ES" : "", + shProg->Version / 100, shProg->Version % 100); + if (shProg->SeparateShader) + fprintf(file, "GL_ARB_separate_shader_objects\nSSO ENABLED\n"); + fprintf(file, "\n"); + + for (unsigned i = 0; i < shProg->NumShaders; i++) { + fprintf(file, "[%s shader]\n%s\n", + _mesa_shader_stage_to_string(shProg->Shaders[i]->Stage), + shProg->Shaders[i]->Source); + } + fclose(file); + } else { + _mesa_warning(ctx, "Failed to open %s", filename); + } + } + if (shProg->LinkStatus == GL_FALSE && (ctx->_Shader->Flags & GLSL_REPORT_ERRORS)) { _mesa_debug(ctx, "Error linking program %u:\n%s\n", @@ -1055,9 +1136,9 @@ link_program(struct gl_context *ctx, GLuint program) shProg->LinkStatus ? "Success" : "Failed"); for (i = 0; i < shProg->NumShaders; i++) { - printf(" shader %u, type 0x%x\n", + printf(" shader %u, stage %u\n", shProg->Shaders[i]->Name, - shProg->Shaders[i]->Type); + shProg->Shaders[i]->Stage); } } } @@ -1126,6 +1207,9 @@ use_shader_program(struct gl_context *ctx, gl_shader_stage stage, if ((shProg != NULL) && (shProg->_LinkedShaders[stage] == NULL)) shProg = NULL; + if (shProg) + _mesa_shader_program_init_subroutine_defaults(shProg); + if (*target != shProg) { /* Program is current, flush it */ if (shTarget == ctx->_Shader) { @@ -1170,7 +1254,6 @@ _mesa_use_program(struct gl_context *ctx, struct gl_shader_program *shProg) use_shader_program(ctx, i, shProg, &ctx->Shader); _mesa_active_program(ctx, shProg, "glUseProgram"); - _mesa_shader_program_init_subroutine_defaults(shProg); if (ctx->Driver.UseProgram) ctx->Driver.UseProgram(ctx, shProg); } @@ -1258,12 +1341,13 @@ _mesa_AttachShader(GLuint program, GLuint shader) void GLAPIENTRY -_mesa_CompileShader(GLhandleARB shaderObj) +_mesa_CompileShader(GLuint shaderObj) { GET_CURRENT_CONTEXT(ctx); if (MESA_VERBOSE & VERBOSE_API) _mesa_debug(ctx, "glCompileShader %u\n", shaderObj); - compile_shader(ctx, shaderObj); + _mesa_compile_shader(ctx, _mesa_lookup_shader_err(ctx, shaderObj, + "glCompileShader")); } @@ -1308,7 +1392,7 @@ _mesa_DeleteObjectARB(GLhandleARB obj) { if (MESA_VERBOSE & VERBOSE_API) { GET_CURRENT_CONTEXT(ctx); - _mesa_debug(ctx, "glDeleteObjectARB(%u)\n", obj); + _mesa_debug(ctx, "glDeleteObjectARB(%lu)\n", (unsigned long)obj); } if (obj) { @@ -1472,8 +1556,8 @@ _mesa_GetShaderInfoLog(GLuint shader, GLsizei bufSize, void GLAPIENTRY -_mesa_GetShaderSource(GLhandleARB shader, GLsizei maxLength, - GLsizei *length, GLcharARB *sourceOut) +_mesa_GetShaderSource(GLuint shader, GLsizei maxLength, + GLsizei *length, GLchar *sourceOut) { GET_CURRENT_CONTEXT(ctx); get_shader_source(ctx, shader, maxLength, length, sourceOut); @@ -1505,10 +1589,13 @@ _mesa_IsShader(GLuint name) void GLAPIENTRY -_mesa_LinkProgram(GLhandleARB programObj) +_mesa_LinkProgram(GLuint programObj) { GET_CURRENT_CONTEXT(ctx); - link_program(ctx, programObj); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glLinkProgram %u\n", programObj); + _mesa_link_program(ctx, _mesa_lookup_shader_program_err(ctx, programObj, + "glLinkProgram")); } #if defined(HAVE_SHA1) @@ -1632,8 +1719,8 @@ read_shader(const gl_shader_stage stage, const char *source) * and pass it to _mesa_shader_source(). */ void GLAPIENTRY -_mesa_ShaderSource(GLhandleARB shaderObj, GLsizei count, - const GLcharARB * const * string, const GLint * length) +_mesa_ShaderSource(GLuint shaderObj, GLsizei count, + const GLchar * const * string, const GLint * length) { GET_CURRENT_CONTEXT(ctx); GLint *offsets; @@ -1720,11 +1807,14 @@ _mesa_ShaderSource(GLhandleARB shaderObj, GLsizei count, void GLAPIENTRY -_mesa_UseProgram(GLhandleARB program) +_mesa_UseProgram(GLuint program) { GET_CURRENT_CONTEXT(ctx); struct gl_shader_program *shProg; + 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)"); @@ -1779,7 +1869,7 @@ _mesa_UseProgram(GLhandleARB program) void GLAPIENTRY -_mesa_ValidateProgram(GLhandleARB program) +_mesa_ValidateProgram(GLuint program) { GET_CURRENT_CONTEXT(ctx); validate_program(ctx, program); @@ -2072,32 +2162,42 @@ _mesa_copy_linked_program_data(gl_shader_stage type, { switch (type) { case MESA_SHADER_VERTEX: - dst->UsesClipDistanceOut = src->Vert.UsesClipDistance; + dst->ClipDistanceArraySize = src->Vert.ClipDistanceArraySize; + dst->CullDistanceArraySize = src->Vert.CullDistanceArraySize; break; case MESA_SHADER_TESS_CTRL: { struct gl_tess_ctrl_program *dst_tcp = (struct gl_tess_ctrl_program *) dst; - dst_tcp->VerticesOut = src->TessCtrl.VerticesOut; + dst_tcp->VerticesOut = src->_LinkedShaders[MESA_SHADER_TESS_CTRL]-> + info.TessCtrl.VerticesOut; break; } case MESA_SHADER_TESS_EVAL: { struct gl_tess_eval_program *dst_tep = (struct gl_tess_eval_program *) dst; - dst_tep->PrimitiveMode = src->TessEval.PrimitiveMode; - dst_tep->Spacing = src->TessEval.Spacing; - dst_tep->VertexOrder = src->TessEval.VertexOrder; - dst_tep->PointMode = src->TessEval.PointMode; - dst->UsesClipDistanceOut = src->TessEval.UsesClipDistance; + struct gl_linked_shader *tes_sh = + src->_LinkedShaders[MESA_SHADER_TESS_EVAL]; + + dst_tep->PrimitiveMode = tes_sh->info.TessEval.PrimitiveMode; + dst_tep->Spacing = tes_sh->info.TessEval.Spacing; + dst_tep->VertexOrder = tes_sh->info.TessEval.VertexOrder; + dst_tep->PointMode = tes_sh->info.TessEval.PointMode; + dst->ClipDistanceArraySize = src->TessEval.ClipDistanceArraySize; + dst->CullDistanceArraySize = src->TessEval.CullDistanceArraySize; break; } case MESA_SHADER_GEOMETRY: { struct gl_geometry_program *dst_gp = (struct gl_geometry_program *) dst; + struct gl_linked_shader *geom_sh = + src->_LinkedShaders[MESA_SHADER_GEOMETRY]; + dst_gp->VerticesIn = src->Geom.VerticesIn; - dst_gp->VerticesOut = src->Geom.VerticesOut; - dst_gp->Invocations = src->Geom.Invocations; - dst_gp->InputType = src->Geom.InputType; - dst_gp->OutputType = src->Geom.OutputType; - dst->UsesClipDistanceOut = src->Geom.UsesClipDistance; + dst_gp->VerticesOut = geom_sh->info.Geom.VerticesOut; + dst_gp->Invocations = geom_sh->info.Geom.Invocations; + dst_gp->InputType = geom_sh->info.Geom.InputType; + dst_gp->OutputType = geom_sh->info.Geom.OutputType; + dst->ClipDistanceArraySize = src->Geom.ClipDistanceArraySize; + dst->CullDistanceArraySize = src->Geom.CullDistanceArraySize; dst_gp->UsesEndPrimitive = src->Geom.UsesEndPrimitive; dst_gp->UsesStreams = src->Geom.UsesStreams; break; @@ -2112,6 +2212,7 @@ _mesa_copy_linked_program_data(gl_shader_stage type, int i; for (i = 0; i < 3; i++) dst_cp->LocalSize[i] = src->Comp.LocalSize[i]; + dst_cp->SharedSize = src->Comp.SharedSize; break; } default: @@ -2141,25 +2242,24 @@ _mesa_CreateShaderProgramv(GLenum type, GLsizei count, } if (shader) { - _mesa_ShaderSource(shader, count, strings, NULL); + struct gl_shader *sh = _mesa_lookup_shader(ctx, shader); - compile_shader(ctx, shader); + _mesa_ShaderSource(shader, count, strings, NULL); + _mesa_compile_shader(ctx, sh); program = create_shader_program(ctx); if (program) { struct gl_shader_program *shProg; - struct gl_shader *sh; GLint compiled = GL_FALSE; shProg = _mesa_lookup_shader_program(ctx, program); - sh = _mesa_lookup_shader(ctx, shader); shProg->SeparateShader = GL_TRUE; get_shaderiv(ctx, shader, GL_COMPILE_STATUS, &compiled); if (compiled) { attach_shader(ctx, program, shader); - link_program(ctx, program); + _mesa_link_program(ctx, shProg); detach_shader(ctx, program, shader); #if 0 @@ -2308,7 +2408,6 @@ _mesa_GetSubroutineIndex(GLuint program, GLenum shadertype, resource_type = _mesa_shader_stage_to_subroutine(stage); res = _mesa_program_resource_find_name(shProg, resource_type, name, NULL); if (!res) { - _mesa_error(ctx, GL_INVALID_OPERATION, "%s", api_name); return -1; } @@ -2323,7 +2422,7 @@ _mesa_GetActiveSubroutineUniformiv(GLuint program, GLenum shadertype, GET_CURRENT_CONTEXT(ctx); const char *api_name = "glGetActiveSubroutineUniformiv"; struct gl_shader_program *shProg; - struct gl_shader *sh; + struct gl_linked_shader *sh; gl_shader_stage stage; struct gl_program_resource *res; const struct gl_uniform_storage *uni; @@ -2353,6 +2452,11 @@ _mesa_GetActiveSubroutineUniformiv(GLuint program, GLenum shadertype, return; } + if (index >= sh->NumSubroutineUniforms) { + _mesa_error(ctx, GL_INVALID_VALUE, "%s: invalid index greater than GL_ACTIVE_SUBROUTINE_UNIFORMS", api_name); + return; + } + switch (pname) { case GL_NUM_COMPATIBLE_SUBROUTINES: { res = _mesa_program_resource_find_index(shProg, resource_type, index); @@ -2390,7 +2494,7 @@ _mesa_GetActiveSubroutineUniformiv(GLuint program, GLenum shadertype, res = _mesa_program_resource_find_index(shProg, resource_type, index); if (res) { values[0] = strlen(_mesa_program_resource_name(res)) + 1 - + ((_mesa_program_resource_array_size(res) != 0) ? 3 : 0);; + + ((_mesa_program_resource_array_size(res) != 0) ? 3 : 0); } break; default: @@ -2483,7 +2587,7 @@ _mesa_UniformSubroutinesuiv(GLenum shadertype, GLsizei count, GET_CURRENT_CONTEXT(ctx); const char *api_name = "glUniformSubroutinesuiv"; struct gl_shader_program *shProg; - struct gl_shader *sh; + struct gl_linked_shader *sh; gl_shader_stage stage; int i; @@ -2518,17 +2622,30 @@ _mesa_UniformSubroutinesuiv(GLenum shadertype, GLsizei count, i = 0; do { struct gl_uniform_storage *uni = sh->SubroutineUniformRemapTable[i]; + if (uni == NULL) { + i++; + continue; + } + int uni_count = uni->array_elements ? uni->array_elements : 1; - int j, k; + int j, k, f; for (j = i; j < i + uni_count; j++) { - struct gl_subroutine_function *subfn; - if (indices[j] >= sh->NumSubroutineFunctions) { + struct gl_subroutine_function *subfn = NULL; + if (indices[j] > sh->MaxSubroutineFunctionIndex) { _mesa_error(ctx, GL_INVALID_VALUE, "%s", api_name); return; } - subfn = &sh->SubroutineFunctions[indices[j]]; + for (f = 0; f < sh->NumSubroutineFunctions; f++) { + if (sh->SubroutineFunctions[f].index == indices[j]) + subfn = &sh->SubroutineFunctions[f]; + } + + if (!subfn) { + continue; + } + for (k = 0; k < subfn->num_compat_types; k++) { if (subfn->types[k] == uni->type) break; @@ -2545,12 +2662,16 @@ _mesa_UniformSubroutinesuiv(GLenum shadertype, GLsizei count, i = 0; do { struct gl_uniform_storage *uni = sh->SubroutineUniformRemapTable[i]; + if (uni == NULL) { + i++; + continue; + } + int uni_count = uni->array_elements ? uni->array_elements : 1; memcpy(&uni->storage[0], &indices[i], sizeof(GLuint) * uni_count); - uni->initialized = true; _mesa_propagate_uniforms_to_driver_storage(uni, 0, uni_count); i += uni_count; } while(i < count); @@ -2564,7 +2685,7 @@ _mesa_GetUniformSubroutineuiv(GLenum shadertype, GLint location, GET_CURRENT_CONTEXT(ctx); const char *api_name = "glGetUniformSubroutineuiv"; struct gl_shader_program *shProg; - struct gl_shader *sh; + struct gl_linked_shader *sh; gl_shader_stage stage; if (!_mesa_has_shader_subroutine(ctx)) { @@ -2597,7 +2718,7 @@ _mesa_GetUniformSubroutineuiv(GLenum shadertype, GLint location, { struct gl_uniform_storage *uni = sh->SubroutineUniformRemapTable[location]; - int offset = location - uni->subroutine[stage].index; + int offset = location - uni->opaque[stage].index; memcpy(params, &uni->storage[offset], sizeof(GLuint)); } @@ -2611,7 +2732,7 @@ _mesa_GetProgramStageiv(GLuint program, GLenum shadertype, GET_CURRENT_CONTEXT(ctx); const char *api_name = "glGetProgramStageiv"; struct gl_shader_program *shProg; - struct gl_shader *sh; + struct gl_linked_shader *sh; gl_shader_stage stage; if (!_mesa_has_shader_subroutine(ctx)) { @@ -2643,7 +2764,7 @@ _mesa_GetProgramStageiv(GLuint program, GLenum shadertype, values[0] = sh->NumSubroutineUniformRemapTable; break; case GL_ACTIVE_SUBROUTINE_UNIFORMS: - values[0] = sh->NumSubroutineUniformTypes; + values[0] = sh->NumSubroutineUniforms; break; case GL_ACTIVE_SUBROUTINE_MAX_LENGTH: { @@ -2693,7 +2814,8 @@ _mesa_GetProgramStageiv(GLuint program, GLenum shadertype, } static int -find_compat_subroutine(struct gl_shader *sh, const struct glsl_type *type) +find_compat_subroutine(struct gl_linked_shader *sh, + const struct glsl_type *type) { int i, j; @@ -2708,7 +2830,7 @@ find_compat_subroutine(struct gl_shader *sh, const struct glsl_type *type) } static void -_mesa_shader_init_subroutine_defaults(struct gl_shader *sh) +_mesa_shader_init_subroutine_defaults(struct gl_linked_shader *sh) { int i, j; @@ -2724,7 +2846,7 @@ _mesa_shader_init_subroutine_defaults(struct gl_shader *sh) for (j = 0; j < uni_count; j++) memcpy(&uni->storage[j], &val, sizeof(int)); - uni->initialized = true; + _mesa_propagate_uniforms_to_driver_storage(uni, 0, uni_count); } }