diff options
Diffstat (limited to 'src/mesa/shader')
-rw-r--r-- | src/mesa/shader/prog_parameter.c | 5 | ||||
-rw-r--r-- | src/mesa/shader/prog_parameter.h | 3 | ||||
-rw-r--r-- | src/mesa/shader/shader_api.c | 29 | ||||
-rw-r--r-- | src/mesa/shader/shader_api.h | 3 | ||||
-rw-r--r-- | src/mesa/shader/slang/slang_builtin.c | 68 | ||||
-rw-r--r-- | src/mesa/shader/slang/slang_builtin.h | 10 | ||||
-rw-r--r-- | src/mesa/shader/slang/slang_codegen.c | 2 | ||||
-rw-r--r-- | src/mesa/shader/slang/slang_link.c | 109 |
8 files changed, 203 insertions, 26 deletions
diff --git a/src/mesa/shader/prog_parameter.c b/src/mesa/shader/prog_parameter.c index 25bb4f3d44..aac488c79a 100644 --- a/src/mesa/shader/prog_parameter.c +++ b/src/mesa/shader/prog_parameter.c @@ -376,7 +376,8 @@ _mesa_add_sampler(struct gl_program_parameter_list *paramList, */ GLint _mesa_add_varying(struct gl_program_parameter_list *paramList, - const char *name, GLuint size, GLbitfield flags) + const char *name, GLuint size, GLenum datatype, + GLbitfield flags) { GLint i = _mesa_lookup_parameter_index(paramList, -1, name); if (i >= 0 && paramList->Parameters[i].Type == PROGRAM_VARYING) { @@ -386,7 +387,7 @@ _mesa_add_varying(struct gl_program_parameter_list *paramList, else { /*assert(size == 4);*/ i = _mesa_add_parameter(paramList, PROGRAM_VARYING, name, - size, GL_NONE, NULL, NULL, flags); + size, datatype, NULL, NULL, flags); return i; } } diff --git a/src/mesa/shader/prog_parameter.h b/src/mesa/shader/prog_parameter.h index 1111c85976..cc3378ae20 100644 --- a/src/mesa/shader/prog_parameter.h +++ b/src/mesa/shader/prog_parameter.h @@ -146,7 +146,8 @@ _mesa_add_sampler(struct gl_program_parameter_list *paramList, extern GLint _mesa_add_varying(struct gl_program_parameter_list *paramList, - const char *name, GLuint size, GLbitfield flags); + const char *name, GLuint size, GLenum datatype, + GLbitfield flags); extern GLint _mesa_add_attribute(struct gl_program_parameter_list *paramList, diff --git a/src/mesa/shader/shader_api.c b/src/mesa/shader/shader_api.c index 36fe0a1bb7..4ff032d4ec 100644 --- a/src/mesa/shader/shader_api.c +++ b/src/mesa/shader/shader_api.c @@ -782,8 +782,11 @@ _mesa_detach_shader(GLcontext *ctx, GLuint program, GLuint shader) } -static GLint -sizeof_glsl_type(GLenum type) +/** + * Return the size of the given GLSL datatype, in floats (components). + */ +GLint +_mesa_sizeof_glsl_type(GLenum type) { switch (type) { case GL_FLOAT: @@ -828,7 +831,7 @@ sizeof_glsl_type(GLenum type) case GL_FLOAT_MAT4x3: return 16; /* four float[4] vectors */ default: - _mesa_problem(NULL, "Invalid type in sizeof_glsl_type()"); + _mesa_problem(NULL, "Invalid type in _mesa_sizeof_glsl_type()"); return 1; } } @@ -912,7 +915,7 @@ _mesa_get_active_attrib(GLcontext *ctx, GLuint program, GLuint index, if (size) *size = attribs->Parameters[index].Size - / sizeof_glsl_type(attribs->Parameters[index].DataType); + / _mesa_sizeof_glsl_type(attribs->Parameters[index].DataType); if (type) *type = attribs->Parameters[index].DataType; @@ -987,7 +990,7 @@ _mesa_get_active_uniform(GLcontext *ctx, GLuint program, GLuint index, } if (size) { - GLint typeSize = sizeof_glsl_type(param->DataType); + GLint typeSize = _mesa_sizeof_glsl_type(param->DataType); if ((GLint) param->Size > typeSize) { /* This is an array. * Array elements are placed on vector[4] boundaries so they're @@ -1519,6 +1522,12 @@ _mesa_link_program(GLcontext *ctx, GLuint program) if (!shProg) return; + if (ctx->TransformFeedback.Active && shProg == ctx->Shader.CurrentProgram) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glLinkProgram(transform feedback active"); + return; + } + FLUSH_VERTICES(ctx, _NEW_PROGRAM); _slang_link(ctx, program, shProg); @@ -1583,6 +1592,12 @@ _mesa_use_program(GLcontext *ctx, GLuint program) { struct gl_shader_program *shProg; + if (ctx->TransformFeedback.Active) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glUseProgram(transform feedback active)"); + return; + } + if (ctx->Shader.CurrentProgram && ctx->Shader.CurrentProgram->Name == program) { /* no-op */ @@ -1771,7 +1786,7 @@ set_program_uniform(GLcontext *ctx, struct gl_program *program, const GLboolean isUniformBool = is_boolean_type(param->DataType); const GLboolean areIntValues = is_integer_type(type); const GLint slots = (param->Size + 3) / 4; - const GLint typeSize = sizeof_glsl_type(param->DataType); + const GLint typeSize = _mesa_sizeof_glsl_type(param->DataType); GLsizei k, i; if ((GLint) param->Size > typeSize) { @@ -1960,7 +1975,7 @@ set_program_uniform_matrix(GLcontext *ctx, struct gl_program *program, GLuint src = 0; const struct gl_program_parameter * param = &program->Parameters->Parameters[index]; const GLuint slots = (param->Size + 3) / 4; - const GLint typeSize = sizeof_glsl_type(param->DataType); + const GLint typeSize = _mesa_sizeof_glsl_type(param->DataType); GLint nr, nc; /* check that the number of rows, columns is correct */ diff --git a/src/mesa/shader/shader_api.h b/src/mesa/shader/shader_api.h index 3ed52747cd..597f0b8e75 100644 --- a/src/mesa/shader/shader_api.h +++ b/src/mesa/shader/shader_api.h @@ -47,6 +47,9 @@ extern void _mesa_copy_string(GLchar *dst, GLsizei maxLength, GLsizei *length, const GLchar *src); +extern GLint +_mesa_sizeof_glsl_type(GLenum type); + /* extern struct gl_shader_program * diff --git a/src/mesa/shader/slang/slang_builtin.c b/src/mesa/shader/slang/slang_builtin.c index 791e751526..b7bf4e06dc 100644 --- a/src/mesa/shader/slang/slang_builtin.c +++ b/src/mesa/shader/slang/slang_builtin.c @@ -752,7 +752,6 @@ static const struct input_info fragInputs[] = { { "gl_Color", FRAG_ATTRIB_COL0, GL_FLOAT_VEC4, SWIZZLE_NOOP }, { "gl_SecondaryColor", FRAG_ATTRIB_COL1, GL_FLOAT_VEC4, SWIZZLE_NOOP }, { "gl_TexCoord", FRAG_ATTRIB_TEX0, GL_FLOAT_VEC4, SWIZZLE_NOOP }, - /* note: we're packing several quantities into the fogcoord vector */ { "gl_FogFragCoord", FRAG_ATTRIB_FOGC, GL_FLOAT, SWIZZLE_XXXX }, { "gl_FrontFacing", FRAG_ATTRIB_FACE, GL_FLOAT, SWIZZLE_XXXX }, { "gl_PointCoord", FRAG_ATTRIB_PNTC, GL_FLOAT_VEC2, SWIZZLE_XYZW }, @@ -839,27 +838,28 @@ struct output_info { const char *Name; GLuint Attrib; + GLenum Type; }; /** Predefined vertex shader outputs */ static const struct output_info vertOutputs[] = { - { "gl_Position", VERT_RESULT_HPOS }, - { "gl_FrontColor", VERT_RESULT_COL0 }, - { "gl_BackColor", VERT_RESULT_BFC0 }, - { "gl_FrontSecondaryColor", VERT_RESULT_COL1 }, - { "gl_BackSecondaryColor", VERT_RESULT_BFC1 }, - { "gl_TexCoord", VERT_RESULT_TEX0 }, - { "gl_FogFragCoord", VERT_RESULT_FOGC }, - { "gl_PointSize", VERT_RESULT_PSIZ }, - { NULL, 0 } + { "gl_Position", VERT_RESULT_HPOS, GL_FLOAT_VEC4 }, + { "gl_FrontColor", VERT_RESULT_COL0, GL_FLOAT_VEC4 }, + { "gl_BackColor", VERT_RESULT_BFC0, GL_FLOAT_VEC4 }, + { "gl_FrontSecondaryColor", VERT_RESULT_COL1, GL_FLOAT_VEC4 }, + { "gl_BackSecondaryColor", VERT_RESULT_BFC1, GL_FLOAT_VEC4 }, + { "gl_TexCoord", VERT_RESULT_TEX0, GL_FLOAT_VEC4 }, + { "gl_FogFragCoord", VERT_RESULT_FOGC, GL_FLOAT }, + { "gl_PointSize", VERT_RESULT_PSIZ, GL_FLOAT }, + { NULL, 0, GL_NONE } }; /** Predefined fragment shader outputs */ static const struct output_info fragOutputs[] = { - { "gl_FragColor", FRAG_RESULT_COLOR }, - { "gl_FragDepth", FRAG_RESULT_DEPTH }, - { "gl_FragData", FRAG_RESULT_DATA0 }, - { NULL, 0 } + { "gl_FragColor", FRAG_RESULT_COLOR, GL_FLOAT_VEC4 }, + { "gl_FragDepth", FRAG_RESULT_DEPTH, GL_FLOAT }, + { "gl_FragData", FRAG_RESULT_DATA0, GL_FLOAT_VEC4 }, + { NULL, 0, GL_NONE } }; @@ -895,3 +895,43 @@ _slang_output_index(const char *name, GLenum target) } return -1; } + + +/** + * Given a VERT_RESULT_x index, return the corresponding string name. + */ +const char * +_slang_vertex_output_name(gl_vert_result index) +{ + if (index < Elements(vertOutputs)) + return vertOutputs[index].Name; + else + return NULL; +} + + +/** + * Given a FRAG_RESULT_x index, return the corresponding string name. + */ +const char * +_slang_fragment_output_name(gl_frag_result index) +{ + if (index < Elements(fragOutputs)) + return fragOutputs[index].Name; + else + return NULL; +} + + +/** + * Given a VERT_RESULT_x index, return the corresponding varying + * var's datatype. + */ +GLenum +_slang_vertex_output_type(gl_vert_result index) +{ + if (index < Elements(vertOutputs)) + return vertOutputs[index].Type; + else + return GL_NONE; +} diff --git a/src/mesa/shader/slang/slang_builtin.h b/src/mesa/shader/slang/slang_builtin.h index f814d11ac7..c3021ca33c 100644 --- a/src/mesa/shader/slang/slang_builtin.h +++ b/src/mesa/shader/slang/slang_builtin.h @@ -51,4 +51,14 @@ extern GLenum _slang_vert_attrib_type(GLuint attrib); +const char * +_slang_vertex_output_name(gl_vert_result index); + +const char * +_slang_fragment_output_name(gl_frag_result index); + +GLenum +_slang_vertex_output_type(gl_vert_result index); + + #endif /* SLANG_BUILTIN_H */ diff --git a/src/mesa/shader/slang/slang_codegen.c b/src/mesa/shader/slang/slang_codegen.c index ecb2f6d5c1..fa79632c18 100644 --- a/src/mesa/shader/slang/slang_codegen.c +++ b/src/mesa/shader/slang/slang_codegen.c @@ -5130,7 +5130,7 @@ _slang_codegen_global_variable(slang_assemble_ctx *A, slang_variable *var, flags |= PROG_PARAM_BIT_INVARIANT; varyingLoc = _mesa_add_varying(prog->Varying, varName, - totalSize, flags); + totalSize, GL_NONE, flags); swizzle = _slang_var_swizzle(size, 0); store = _slang_new_ir_storage_swz(PROGRAM_VARYING, varyingLoc, totalSize, swizzle); diff --git a/src/mesa/shader/slang/slang_link.c b/src/mesa/shader/slang/slang_link.c index 7c7bfbdbc5..f71fde1d72 100644 --- a/src/mesa/shader/slang/slang_link.c +++ b/src/mesa/shader/slang/slang_link.c @@ -87,6 +87,107 @@ bits_agree(GLbitfield flags1, GLbitfield flags2, GLbitfield bit) /** + * Examine the outputs/varyings written by the vertex shader and + * append the names of those outputs onto the Varyings list. + * This will only capture the pre-defined/built-in varyings like + * gl_Position, not user-defined varyings. + */ +static void +update_varying_var_list(GLcontext *ctx, struct gl_shader_program *shProg) +{ + if (shProg->VertexProgram) { + GLbitfield64 written = shProg->VertexProgram->Base.OutputsWritten; + GLuint i; + for (i = 0; written && i < VERT_RESULT_MAX; i++) { + if (written & BITFIELD64_BIT(i)) { + const char *name = _slang_vertex_output_name(i); + if (name) + _mesa_add_varying(shProg->Varying, name, 1, GL_FLOAT_VEC4, 0x0); + written &= ~BITFIELD64_BIT(i); + } + } + } +} + + +/** + * Do link error checking related to transform feedback. + */ +static GLboolean +link_transform_feedback(GLcontext *ctx, struct gl_shader_program *shProg) +{ + GLbitfield varyingMask; + GLuint totalComps, maxComps, i; + + if (shProg->TransformFeedback.NumVarying == 0) { + /* nothing to do */ + return GL_TRUE; + } + + /* Check that there's a vertex shader */ + if (shProg->TransformFeedback.NumVarying > 0 && + !shProg->VertexProgram) { + link_error(shProg, "Transform feedback without vertex shader"); + return GL_FALSE; + } + + /* Check that all named variables exist, and that none are duplicated. + * Also, build a count of the number of varying components to feedback. + */ + totalComps = 0; + varyingMask = 0x0; + for (i = 0; i < shProg->TransformFeedback.NumVarying; i++) { + const GLchar *name = shProg->TransformFeedback.VaryingNames[i]; + GLint v = _mesa_lookup_parameter_index(shProg->Varying, -1, name); + struct gl_program_parameter *p; + + if (v < 0) { + char msg[100]; + _mesa_snprintf(msg, sizeof(msg), + "vertex shader does not emit %s", name); + link_error(shProg, msg); + return GL_FALSE; + } + + assert(v < MAX_VARYING); + + /* already seen this varying name? */ + if (varyingMask & (1 << v)) { + char msg[100]; + _mesa_snprintf(msg, sizeof(msg), + "duplicated transform feedback varying name: %s", + name); + link_error(shProg, msg); + return GL_FALSE; + } + + varyingMask |= (1 << v); + + p = &shProg->Varying->Parameters[v]; + + totalComps += _mesa_sizeof_glsl_type(p->DataType); + } + + if (shProg->TransformFeedback.BufferMode == GL_INTERLEAVED_ATTRIBS) + maxComps = ctx->Const.MaxTransformFeedbackInterleavedComponents; + else + maxComps = ctx->Const.MaxTransformFeedbackSeparateComponents; + + /* check max varying components against the limit */ + if (totalComps > maxComps) { + char msg[100]; + _mesa_snprintf(msg, sizeof(msg), + "Too many feedback components: %u, max is %u", + totalComps, maxComps); + link_error(shProg, msg); + return GL_FALSE; + } + + return GL_TRUE; +} + + +/** * Linking varying vars involves rearranging varying vars so that the * vertex program's output varyings matches the order of the fragment * program's input varyings. @@ -157,7 +258,7 @@ link_varying_vars(GLcontext *ctx, else { /* not already in linked list */ j = _mesa_add_varying(shProg->Varying, var->Name, var->Size, - var->Flags); + var->DataType, var->Flags); } if (shProg->Varying->NumParameters > ctx->Const.MaxVarying) { @@ -866,6 +967,12 @@ _slang_link(GLcontext *ctx, } } + update_varying_var_list(ctx, shProg); + + /* checks related to transform feedback */ + if (!link_transform_feedback(ctx, shProg)) { + return; + } if (fragProg && shProg->FragmentProgram) { /* Compute initial program's TexturesUsed info */ |