summaryrefslogtreecommitdiffstats
path: root/src/mesa/slang
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/slang')
-rw-r--r--src/mesa/slang/library/Makefile5
-rw-r--r--src/mesa/slang/library/SConscript14
-rw-r--r--src/mesa/slang/library/slang_geometry_builtin.gc56
-rw-r--r--src/mesa/slang/slang_builtin.c54
-rw-r--r--src/mesa/slang/slang_builtin.h3
-rw-r--r--src/mesa/slang/slang_codegen.c50
-rw-r--r--src/mesa/slang/slang_compile.c84
-rw-r--r--src/mesa/slang/slang_compile.h4
-rw-r--r--src/mesa/slang/slang_emit.c11
-rw-r--r--src/mesa/slang/slang_ir.c2
-rw-r--r--src/mesa/slang/slang_ir.h5
-rw-r--r--src/mesa/slang/slang_link.c134
-rw-r--r--src/mesa/slang/slang_typeinfo.h6
13 files changed, 382 insertions, 46 deletions
diff --git a/src/mesa/slang/library/Makefile b/src/mesa/slang/library/Makefile
index 5a767742081..f546a039072 100644
--- a/src/mesa/slang/library/Makefile
+++ b/src/mesa/slang/library/Makefile
@@ -23,7 +23,7 @@ builtin: builtin_110 builtin_120
# builtin library sources
#
-builtin_110: slang_common_builtin_gc.h slang_core_gc.h slang_fragment_builtin_gc.h slang_vertex_builtin_gc.h
+builtin_110: slang_common_builtin_gc.h slang_core_gc.h slang_fragment_builtin_gc.h slang_vertex_builtin_gc.h slang_geometry_builtin_gc.h
builtin_120: slang_120_core_gc.h slang_builtin_120_common_gc.h slang_builtin_120_fragment_gc.h
@@ -49,3 +49,6 @@ slang_fragment_builtin_gc.h: slang_fragment_builtin.gc
slang_vertex_builtin_gc.h: slang_vertex_builtin.gc
$(GLSL_CL) vertex slang_vertex_builtin.gc slang_vertex_builtin_gc.h
+slang_geometry_builtin_gc.h: slang_geometry_builtin.gc
+ $(GLSL_CL) geometry slang_geometry_builtin.gc slang_geometry_builtin_gc.h
+
diff --git a/src/mesa/slang/library/SConscript b/src/mesa/slang/library/SConscript
index 792a7953d34..5112cefb3eb 100644
--- a/src/mesa/slang/library/SConscript
+++ b/src/mesa/slang/library/SConscript
@@ -10,21 +10,28 @@ env = env.Clone()
def glsl_compile_emitter(target, source, env):
env.Depends(target, glsl_compile)
return (target, source)
-
+
bld_frag = Builder(
action = Action(glsl_compile[0].abspath + ' fragment $SOURCE $TARGET', '$CODEGENCODESTR'),
emitter = glsl_compile_emitter,
suffix = '.gc',
src_suffix = '_gc.h')
-
+
bld_vert = Builder(
action = Action(glsl_compile[0].abspath + ' vertex $SOURCE $TARGET', '$CODEGENCODESTR'),
emitter = glsl_compile_emitter,
suffix = '.gc',
src_suffix = '_gc.h')
+bld_geom = Builder(
+ action = Action(glsl_compile[0].abspath + ' geometry $SOURCE $TARGET', '$CODEGENCODESTR'),
+ emitter = glsl_compile_emitter,
+ suffix = '.gc',
+ src_suffix = '_gc.h')
+
env['BUILDERS']['bld_frag'] = bld_frag
env['BUILDERS']['bld_vert'] = bld_vert
+env['BUILDERS']['bld_geom'] = bld_geom
# Generate GLSL builtin library binaries
env.bld_frag(
@@ -39,6 +46,9 @@ env.bld_frag(
env.bld_vert(
'#src/mesa/slang/library/slang_vertex_builtin_gc.h',
'#src/mesa/slang/library/slang_vertex_builtin.gc')
+env.bld_geom(
+ '#src/mesa/slang/library/slang_geometry_builtin_gc.h',
+ '#src/mesa/slang/library/slang_geometry_builtin.gc')
# Generate GLSL 1.20 builtin library binaries
env.bld_frag(
diff --git a/src/mesa/slang/library/slang_geometry_builtin.gc b/src/mesa/slang/library/slang_geometry_builtin.gc
new file mode 100644
index 00000000000..c349a6acc04
--- /dev/null
+++ b/src/mesa/slang/library/slang_geometry_builtin.gc
@@ -0,0 +1,56 @@
+/*
+ * Mesa 3-D graphics library
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+const int _mesa_VerticesInMax = 6;
+
+__fixed_input int gl_VerticesIn;
+__fixed_input int gl_PrimitiveIDIn;
+__fixed_output int gl_PrimitiveID;
+__fixed_output int gl_Layer;
+
+
+varying in vec4 gl_FrontColorIn[_mesa_VerticesInMax];
+varying in vec4 gl_BackColorIn[_mesa_VerticesInMax];
+varying in vec4 gl_FrontSecondaryColorIn[_mesa_VerticesInMax];
+varying in vec4 gl_BackSecondaryColorIn[_mesa_VerticesInMax];
+/*varying in vec4 gl_TexCoordIn[_mesa_VerticesInMax][gl_MaxTextureCoords];*/
+varying in float gl_FogFragCoordIn[_mesa_VerticesInMax];
+varying in vec4 gl_PositionIn[_mesa_VerticesInMax];
+varying in float gl_PointSizeIn[_mesa_VerticesInMax];
+varying in vec4 gl_ClipVertexIn[_mesa_VerticesInMax];
+
+varying out vec4 gl_Position;
+varying out vec4 gl_FrontColor;
+varying out vec4 gl_BackColor;
+varying out vec4 gl_FrontSecondaryColor;
+varying out vec4 gl_BackSecondaryColor;
+varying out vec4 gl_TexCoord[gl_MaxTextureCoords];
+varying out float gl_FogFragCoord;
+
+void EmitVertex()
+{
+ __asm emit_vertex;
+}
+
+void EndPrimitive()
+{
+ __asm end_primitive;
+}
diff --git a/src/mesa/slang/slang_builtin.c b/src/mesa/slang/slang_builtin.c
index 610e793c1d9..95f07efca56 100644
--- a/src/mesa/slang/slang_builtin.c
+++ b/src/mesa/slang/slang_builtin.c
@@ -746,6 +746,21 @@ static const struct input_info vertInputs[] = {
{ NULL, 0, GL_NONE, SWIZZLE_NOOP }
};
+static const struct input_info geomInputs[] = {
+ { "gl_VerticesIn", GEOM_ATTRIB_VERTICES, GL_FLOAT, SWIZZLE_NOOP },
+ { "gl_PrimitiveIDIn", GEOM_ATTRIB_PRIMITIVE_ID, GL_FLOAT, SWIZZLE_NOOP },
+ { "gl_FrontColorIn", GEOM_ATTRIB_COLOR0, GL_FLOAT_VEC4, SWIZZLE_NOOP },
+ { "gl_BackColorIn", GEOM_ATTRIB_COLOR1, GL_FLOAT_VEC4, SWIZZLE_NOOP },
+ { "gl_FrontSecondaryColorIn", GEOM_ATTRIB_SECONDARY_COLOR0, GL_FLOAT_VEC4, SWIZZLE_NOOP },
+ { "gl_BackSecondaryColorIn", GEOM_ATTRIB_SECONDARY_COLOR1, GL_FLOAT_VEC4, SWIZZLE_NOOP },
+ { "gl_TexCoordIn", GEOM_ATTRIB_TEX_COORD, GL_FLOAT_VEC4, SWIZZLE_NOOP },
+ { "gl_FogFragCoordIn", GEOM_ATTRIB_FOG_FRAG_COORD, GL_FLOAT, SWIZZLE_NOOP },
+ { "gl_PositionIn", GEOM_ATTRIB_POSITION, GL_FLOAT_VEC4, SWIZZLE_NOOP },
+ { "gl_ClipVertexIn", GEOM_ATTRIB_CLIP_VERTEX, GL_FLOAT_VEC4, SWIZZLE_NOOP },
+ { "gl_PointSizeIn", GEOM_ATTRIB_POINT_SIZE, GL_FLOAT, SWIZZLE_NOOP },
+ { NULL, 0, GL_NONE, SWIZZLE_NOOP }
+};
+
/** Predefined fragment shader inputs */
static const struct input_info fragInputs[] = {
{ "gl_FragCoord", FRAG_ATTRIB_WPOS, GL_FLOAT_VEC4, SWIZZLE_NOOP },
@@ -778,7 +793,9 @@ _slang_input_index(const char *name, GLenum target, GLuint *swizzleOut)
case GL_FRAGMENT_PROGRAM_ARB:
inputs = fragInputs;
break;
- /* XXX geom program */
+ case MESA_GEOMETRY_PROGRAM:
+ inputs = geomInputs;
+ break;
default:
_mesa_problem(NULL, "bad target in _slang_input_index");
return -1;
@@ -854,6 +871,22 @@ static const struct output_info vertOutputs[] = {
{ NULL, 0, GL_NONE }
};
+/** Predefined geometry shader outputs */
+static const struct output_info geomOutputs[] = {
+ { "gl_Position", GEOM_RESULT_POS, GL_FLOAT_VEC4 },
+ { "gl_FrontColor", GEOM_RESULT_COL0, GL_FLOAT_VEC4 },
+ { "gl_BackColor", GEOM_RESULT_COL1, GL_FLOAT_VEC4 },
+ { "gl_FrontSecondaryColor", GEOM_RESULT_SCOL0, GL_FLOAT_VEC4 },
+ { "gl_BackSecondaryColor", GEOM_RESULT_SCOL1, GL_FLOAT_VEC4 },
+ { "gl_TexCoord", GEOM_RESULT_TEX0, GL_FLOAT_VEC4 },
+ { "gl_FogFragCoord", GEOM_RESULT_FOGC, GL_FLOAT },
+ { "gl_ClipVertex", GEOM_RESULT_CLPV, GL_FLOAT_VEC4 },
+ { "gl_PointSize", GEOM_RESULT_PSIZ, GL_FLOAT },
+ { "gl_PrimitiveID", GEOM_RESULT_PRID, GL_FLOAT },
+ { "gl_Layer", GEOM_RESULT_LAYR, GL_FLOAT },
+ { NULL, 0, GL_NONE }
+};
+
/** Predefined fragment shader outputs */
static const struct output_info fragOutputs[] = {
{ "gl_FragColor", FRAG_RESULT_COLOR, GL_FLOAT_VEC4 },
@@ -864,7 +897,7 @@ static const struct output_info fragOutputs[] = {
/**
- * Return the VERT_RESULT_* or FRAG_RESULT_* value that corresponds to
+ * Return the VERT_RESULT_*, GEOM_RESULT_* or FRAG_RESULT_* value that corresponds to
* a vertex or fragment program output variable. Return -1 for an invalid
* output name.
*/
@@ -881,7 +914,9 @@ _slang_output_index(const char *name, GLenum target)
case GL_FRAGMENT_PROGRAM_ARB:
outputs = fragOutputs;
break;
- /* XXX geom program */
+ case MESA_GEOMETRY_PROGRAM:
+ outputs = geomOutputs;
+ break;
default:
_mesa_problem(NULL, "bad target in _slang_output_index");
return -1;
@@ -911,6 +946,19 @@ _slang_vertex_output_name(gl_vert_result index)
/**
+ * Given a GEOM_RESULT_x index, return the corresponding string name.
+ */
+const char *
+_slang_geometry_output_name(gl_geom_result index)
+{
+ if (index < Elements(geomOutputs))
+ return geomOutputs[index].Name;
+ else
+ return NULL;
+}
+
+
+/**
* Given a FRAG_RESULT_x index, return the corresponding string name.
*/
const char *
diff --git a/src/mesa/slang/slang_builtin.h b/src/mesa/slang/slang_builtin.h
index b04b584041b..cef18afdd55 100644
--- a/src/mesa/slang/slang_builtin.h
+++ b/src/mesa/slang/slang_builtin.h
@@ -57,6 +57,9 @@ _slang_vertex_output_name(gl_vert_result index);
const char *
_slang_fragment_output_name(gl_frag_result index);
+const char *
+_slang_geometry_output_name(gl_geom_result index);
+
GLenum
_slang_vertex_output_type(gl_vert_result index);
diff --git a/src/mesa/slang/slang_codegen.c b/src/mesa/slang/slang_codegen.c
index 18a0932e4fc..494901dc1c8 100644
--- a/src/mesa/slang/slang_codegen.c
+++ b/src/mesa/slang/slang_codegen.c
@@ -503,6 +503,9 @@ static slang_asm_info AsmInfo[] = {
{ "float_noise3", IR_NOISE3, 1, 1},
{ "float_noise4", IR_NOISE4, 1, 1},
+ { "emit_vertex", IR_EMIT_VERTEX, 0, 0},
+ { "end_primitive", IR_END_PRIMITIVE, 0, 0},
+
{ NULL, IR_NOP, 0, 0 }
};
@@ -4239,7 +4242,8 @@ is_store_writable(const slang_assemble_ctx *A, const slang_ir_storage *store)
if (!(store->File == PROGRAM_OUTPUT ||
store->File == PROGRAM_TEMPORARY ||
(store->File == PROGRAM_VARYING &&
- A->program->Target == GL_VERTEX_PROGRAM_ARB))) {
+ (A->program->Target == GL_VERTEX_PROGRAM_ARB ||
+ A->program->Target == MESA_GEOMETRY_PROGRAM)))) {
return GL_FALSE;
}
else {
@@ -5148,8 +5152,7 @@ _slang_codegen_global_variable(slang_assemble_ctx *A, slang_variable *var,
assert(index < FRAG_ATTRIB_MAX);
store = _slang_new_ir_storage_swz(PROGRAM_INPUT, index,
size, swizzle);
- }
- else {
+ } else if (type == SLANG_UNIT_VERTEX_BUILTIN) {
/* vertex program output */
GLint index = _slang_output_index(varName, GL_VERTEX_PROGRAM_ARB);
GLuint swizzle = _slang_var_swizzle(size, 0);
@@ -5158,6 +5161,27 @@ _slang_codegen_global_variable(slang_assemble_ctx *A, slang_variable *var,
assert(type == SLANG_UNIT_VERTEX_BUILTIN);
store = _slang_new_ir_storage_swz(PROGRAM_OUTPUT, index,
size, swizzle);
+ } else {
+ /* geometry program input */
+ GLuint swizzle;
+ GLint index = _slang_input_index(varName, MESA_GEOMETRY_PROGRAM,
+ &swizzle);
+ if (index < 0) {
+ /* geometry program output */
+ index = _slang_output_index(varName, MESA_GEOMETRY_PROGRAM);
+ swizzle = _slang_var_swizzle(size, 0);
+
+ assert(index >= 0);
+ assert(index < GEOM_RESULT_MAX);
+
+ store = _slang_new_ir_storage_swz(PROGRAM_OUTPUT, index,
+ size, swizzle);
+ } else {
+ assert(index >= 0);
+ /* assert(index < GEOM_ATTRIB_MAX); */
+ store = _slang_new_ir_storage_swz(PROGRAM_INPUT, index,
+ size, swizzle);
+ }
}
if (dbg) printf("V/F ");
}
@@ -5193,21 +5217,31 @@ _slang_codegen_global_variable(slang_assemble_ctx *A, slang_variable *var,
}
else if (var->type.qualifier == SLANG_QUAL_FIXEDINPUT) {
GLuint swizzle = SWIZZLE_XYZW; /* silence compiler warning */
- GLint index = _slang_input_index(varName, GL_FRAGMENT_PROGRAM_ARB,
- &swizzle);
- store = _slang_new_ir_storage_swz(PROGRAM_INPUT, index, size, swizzle);
+ if (type == SLANG_UNIT_FRAGMENT_BUILTIN) {
+ GLint index = _slang_input_index(varName, GL_FRAGMENT_PROGRAM_ARB,
+ &swizzle);
+ store = _slang_new_ir_storage_swz(PROGRAM_INPUT, index, size, swizzle);
+ } else if (type == SLANG_UNIT_GEOMETRY_BUILTIN) {
+ GLint index = _slang_input_index(varName, MESA_GEOMETRY_PROGRAM,
+ &swizzle);
+ store = _slang_new_ir_storage_swz(PROGRAM_INPUT, index, size, swizzle);
+ }
if (dbg) printf("INPUT ");
}
else if (var->type.qualifier == SLANG_QUAL_FIXEDOUTPUT) {
if (type == SLANG_UNIT_VERTEX_BUILTIN) {
GLint index = _slang_output_index(varName, GL_VERTEX_PROGRAM_ARB);
store = _slang_new_ir_storage(PROGRAM_OUTPUT, index, size);
- }
- else {
+ } else if (type == SLANG_UNIT_FRAGMENT_BUILTIN) {
GLint index = _slang_output_index(varName, GL_FRAGMENT_PROGRAM_ARB);
GLint specialSize = 4; /* treat all fragment outputs as float[4] */
assert(type == SLANG_UNIT_FRAGMENT_BUILTIN);
store = _slang_new_ir_storage(PROGRAM_OUTPUT, index, specialSize);
+ } else {
+ GLint index = _slang_output_index(varName, MESA_GEOMETRY_PROGRAM);
+ GLint specialSize = 4; /* treat all fragment outputs as float[4] */
+ assert(type == SLANG_UNIT_GEOMETRY_BUILTIN);
+ store = _slang_new_ir_storage(PROGRAM_OUTPUT, index, specialSize);
}
if (dbg) printf("OUTPUT ");
}
diff --git a/src/mesa/slang/slang_compile.c b/src/mesa/slang/slang_compile.c
index af672599ed9..12ab4666aed 100644
--- a/src/mesa/slang/slang_compile.c
+++ b/src/mesa/slang/slang_compile.c
@@ -952,6 +952,40 @@ parse_type_precision(slang_parse_ctx *C,
}
}
+
+/* parameter qualifier */
+#define PARAM_QUALIFIER_IN 0
+#define PARAM_QUALIFIER_OUT 1
+#define PARAM_QUALIFIER_INOUT 2
+#define PARAM_QUALIFIER_NONE 3
+static int
+parse_varying_qualifier(slang_parse_ctx * C, slang_fully_specified_type *type)
+{
+ int param_qual = *C->I++;
+
+ if (type->qualifier != SLANG_QUAL_VARYING &&
+ param_qual != PARAM_QUALIFIER_NONE) {
+ slang_info_log_error(C->L, "Invalid type qualifier.");
+ RETURN0;
+ }
+ switch (param_qual) {
+ case PARAM_QUALIFIER_IN:
+ case PARAM_QUALIFIER_NONE:
+ type->varying_kind = SLANG_VARYING_IN;
+ break;
+ case PARAM_QUALIFIER_OUT:
+ type->varying_kind = SLANG_VARYING_OUT;
+ break;
+ case PARAM_QUALIFIER_INOUT:
+ slang_info_log_error(C->L, "Invalid type qualifier.");
+ RETURN0;
+ break;
+ default:
+ RETURN0;
+ }
+ return 1;
+}
+
static int
parse_fully_specified_type(slang_parse_ctx * C, slang_output_ctx * O,
slang_fully_specified_type * type)
@@ -968,6 +1002,9 @@ parse_fully_specified_type(slang_parse_ctx * C, slang_output_ctx * O,
if (!parse_type_qualifier(C, &type->qualifier))
RETURN0;
+ if (!parse_varying_qualifier(C, type))
+ RETURN0;
+
if (!parse_type_precision(C, &type->precision))
RETURN0;
@@ -1684,11 +1721,6 @@ parse_expression(slang_parse_ctx * C, slang_output_ctx * O,
return 1;
}
-/* parameter qualifier */
-#define PARAM_QUALIFIER_IN 0
-#define PARAM_QUALIFIER_OUT 1
-#define PARAM_QUALIFIER_INOUT 2
-
/* function parameter array presence */
#define PARAMETER_ARRAY_NOT_PRESENT 0
#define PARAMETER_ARRAY_PRESENT 1
@@ -1730,6 +1762,9 @@ parse_parameter_declaration(slang_parse_ctx * C, slang_output_ctx * O,
RETURN0;
}
break;
+ case PARAM_QUALIFIER_NONE:
+ /* like IN but doesn't throw error */
+ break;
default:
RETURN0;
}
@@ -2154,6 +2189,7 @@ parse_init_declarator(slang_parse_ctx * C, slang_output_ctx * O,
var->type.variant = type->variant;
var->type.layout = type->layout;
var->type.array_len = type->array_len;
+ var->type.varying_kind = type->varying_kind;
var->a_name = a_name;
if (var->a_name == SLANG_ATOM_NULL)
RETURN0;
@@ -2499,7 +2535,7 @@ init_default_precision(slang_output_ctx *O, slang_unit_type type)
#endif
}
- if (type == SLANG_UNIT_VERTEX_SHADER) {
+ if (type == SLANG_UNIT_VERTEX_SHADER || type == SLANG_UNIT_GEOMETRY_SHADER) {
O->default_precision[TYPE_SPECIFIER_FLOAT] = PRECISION_HIGH;
O->default_precision[TYPE_SPECIFIER_INT] = PRECISION_HIGH;
}
@@ -2547,10 +2583,13 @@ parse_code_unit(slang_parse_ctx * C, slang_code_unit * unit,
unit->type == SLANG_UNIT_FRAGMENT_SHADER) {
maxRegs = ctx->Const.FragmentProgram.MaxTemps;
}
- else {
- assert(unit->type == SLANG_UNIT_VERTEX_BUILTIN ||
- unit->type == SLANG_UNIT_VERTEX_SHADER);
+ else if (unit->type == SLANG_UNIT_VERTEX_BUILTIN ||
+ unit->type == SLANG_UNIT_VERTEX_SHADER) {
maxRegs = ctx->Const.VertexProgram.MaxTemps;
+ } else {
+ assert(unit->type == SLANG_UNIT_GEOMETRY_BUILTIN ||
+ unit->type == SLANG_UNIT_GEOMETRY_SHADER);
+ maxRegs = ctx->Const.GeometryProgram.MaxTemps;
}
/* setup output context */
@@ -2829,6 +2868,10 @@ static const unsigned char slang_vertex_builtin_gc[] = {
#include "library/slang_vertex_builtin_gc.h"
};
+static const unsigned char slang_geometry_builtin_gc[] = {
+#include "library/slang_geometry_builtin_gc.h"
+};
+
static GLboolean
compile_object(const char *source,
slang_code_object *object,
@@ -2853,7 +2896,8 @@ compile_object(const char *source,
parsing_builtin = 1;
/* if parsing user-specified shader, load built-in library */
- if (type == SLANG_UNIT_FRAGMENT_SHADER || type == SLANG_UNIT_VERTEX_SHADER) {
+ if (type == SLANG_UNIT_FRAGMENT_SHADER || type == SLANG_UNIT_VERTEX_SHADER ||
+ type == SLANG_UNIT_GEOMETRY_SHADER) {
/* compile core functionality first */
if (!compile_binary(slang_core_gc,
&object->builtin[SLANG_BUILTIN_CORE],
@@ -2913,6 +2957,16 @@ compile_object(const char *source,
&object->builtin[SLANG_BUILTIN_COMMON], NULL))
return GL_FALSE;
}
+#if FEATURE_ARB_geometry_shader4
+ else if (type == SLANG_UNIT_GEOMETRY_SHADER) {
+ if (!compile_binary(slang_geometry_builtin_gc,
+ &object->builtin[SLANG_BUILTIN_TARGET],
+ base_version,
+ SLANG_UNIT_GEOMETRY_BUILTIN, infolog, NULL,
+ &object->builtin[SLANG_BUILTIN_COMMON], NULL))
+ return GL_FALSE;
+ }
+#endif
/* disable language extensions */
parsing_builtin = 0;
@@ -2945,9 +2999,11 @@ _slang_compile(GLcontext *ctx, struct gl_shader *shader)
if (shader->Type == GL_VERTEX_SHADER) {
type = SLANG_UNIT_VERTEX_SHADER;
}
- else {
- assert(shader->Type == GL_FRAGMENT_SHADER);
+ else if (shader->Type == GL_FRAGMENT_SHADER) {
type = SLANG_UNIT_FRAGMENT_SHADER;
+ } else {
+ assert(shader->Type == GL_GEOMETRY_SHADER_ARB);
+ type = SLANG_UNIT_GEOMETRY_SHADER;
}
if (!shader->Source)
@@ -2963,8 +3019,10 @@ _slang_compile(GLcontext *ctx, struct gl_shader *shader)
/* allocate new GPU program, parameter lists, etc. */
if (shader->Type == GL_VERTEX_SHADER)
progTarget = GL_VERTEX_PROGRAM_ARB;
- else
+ else if (shader->Type == GL_FRAGMENT_SHADER)
progTarget = GL_FRAGMENT_PROGRAM_ARB;
+ else
+ progTarget = MESA_GEOMETRY_PROGRAM;
shader->Program = ctx->Driver.NewProgram(ctx, progTarget, 1);
shader->Program->Parameters = _mesa_new_parameter_list();
shader->Program->Varying = _mesa_new_parameter_list();
diff --git a/src/mesa/slang/slang_compile.h b/src/mesa/slang/slang_compile.h
index 7fb549d33d2..71fcaa39931 100644
--- a/src/mesa/slang/slang_compile.h
+++ b/src/mesa/slang/slang_compile.h
@@ -48,8 +48,10 @@ typedef enum slang_unit_type_
{
SLANG_UNIT_FRAGMENT_SHADER,
SLANG_UNIT_VERTEX_SHADER,
+ SLANG_UNIT_GEOMETRY_SHADER,
SLANG_UNIT_FRAGMENT_BUILTIN,
- SLANG_UNIT_VERTEX_BUILTIN
+ SLANG_UNIT_VERTEX_BUILTIN,
+ SLANG_UNIT_GEOMETRY_BUILTIN
} slang_unit_type;
diff --git a/src/mesa/slang/slang_emit.c b/src/mesa/slang/slang_emit.c
index 9997d5b0a07..aa9d6624d5b 100644
--- a/src/mesa/slang/slang_emit.c
+++ b/src/mesa/slang/slang_emit.c
@@ -2506,6 +2506,11 @@ emit(slang_emit_info *emitInfo, slang_ir_node *n)
case IR_NOP:
return NULL;
+ case IR_EMIT_VERTEX:
+ return new_instruction(emitInfo, OPCODE_EMIT_VERTEX);
+ case IR_END_PRIMITIVE:
+ return new_instruction(emitInfo, OPCODE_END_PRIMITIVE);
+
default:
_mesa_problem(NULL, "Unexpected IR opcode in emit()\n");
}
@@ -2630,9 +2635,11 @@ _slang_emit_code(slang_ir_node *n, slang_var_table *vt,
if (prog->Target == GL_FRAGMENT_PROGRAM_ARB) {
maxUniforms = ctx->Const.FragmentProgram.MaxUniformComponents / 4;
}
- else {
- assert(prog->Target == GL_VERTEX_PROGRAM_ARB);
+ else if (prog->Target == GL_VERTEX_PROGRAM_ARB) {
maxUniforms = ctx->Const.VertexProgram.MaxUniformComponents / 4;
+ } else {
+ assert(prog->Target == MESA_GEOMETRY_PROGRAM);
+ maxUniforms = ctx->Const.GeometryProgram.MaxUniformComponents / 4;
}
if (prog->Parameters->NumParameters > maxUniforms) {
slang_info_log_error(log, "Constant/uniform register limit exceeded "
diff --git a/src/mesa/slang/slang_ir.c b/src/mesa/slang/slang_ir.c
index e9aef9878ef..d78ba52505a 100644
--- a/src/mesa/slang/slang_ir.c
+++ b/src/mesa/slang/slang_ir.c
@@ -103,6 +103,8 @@ static const slang_ir_info IrInfo[] = {
{ IR_ELEMENT, "IR_ELEMENT", OPCODE_NOP, 0, 0 },
{ IR_SWIZZLE, "IR_SWIZZLE", OPCODE_NOP, 0, 0 },
{ IR_NOP, "IR_NOP", OPCODE_NOP, 0, 0 },
+ { IR_EMIT_VERTEX, "IR_EMIT_VERTEX", OPCODE_EMIT_VERTEX, 0, 0 },
+ { IR_END_PRIMITIVE, "IR_END_PRIMITIVE", OPCODE_END_PRIMITIVE, 0, 0 },
{ 0, NULL, 0, 0, 0 }
};
diff --git a/src/mesa/slang/slang_ir.h b/src/mesa/slang/slang_ir.h
index 166b4e80436..e9af079a1e3 100644
--- a/src/mesa/slang/slang_ir.h
+++ b/src/mesa/slang/slang_ir.h
@@ -140,7 +140,10 @@ typedef enum
IR_I_TO_F, /* int[4] to float[4] conversion */
IR_F_TO_I, /* float[4] to int[4] conversion */
- IR_KILL /* fragment kill/discard */
+ IR_KILL, /* fragment kill/discard */
+
+ IR_EMIT_VERTEX, /* geometry shader: emit vertex */
+ IR_END_PRIMITIVE /* geometry shader: end primitive */
} slang_ir_opcode;
diff --git a/src/mesa/slang/slang_link.c b/src/mesa/slang/slang_link.c
index 2f47cba1ce3..d4656ed493c 100644
--- a/src/mesa/slang/slang_link.c
+++ b/src/mesa/slang/slang_link.c
@@ -62,6 +62,12 @@ fragment_program(struct gl_program *prog)
return (struct gl_fragment_program *) prog;
}
+static struct gl_geometry_program *
+geometry_program(struct gl_program *prog)
+{
+ assert(prog->Target == MESA_GEOMETRY_PROGRAM);
+ return (struct gl_geometry_program *)prog;
+}
/**
* Record a linking error.
@@ -109,6 +115,18 @@ update_varying_var_list(GLcontext *ctx, struct gl_shader_program *shProg)
}
}
}
+ if (shProg->GeometryProgram) {
+ GLbitfield64 written = shProg->GeometryProgram->Base.OutputsWritten;
+ GLuint i;
+ for (i = 0; written && i < GEOM_RESULT_MAX; i++) {
+ if (written & BITFIELD64_BIT(i)) {
+ const char *name = _slang_geometry_output_name(i);
+ if (name)
+ _mesa_add_varying(shProg->Varying, name, 1, GL_FLOAT_VEC4, 0x0);
+ written &= ~BITFIELD64_BIT(i);
+ }
+ }
+ }
}
@@ -203,7 +221,7 @@ static GLboolean
link_varying_vars(GLcontext *ctx,
struct gl_shader_program *shProg, struct gl_program *prog)
{
- GLuint *map, i, firstVarying, newFile;
+ GLuint *map, i, firstSrcVarying, firstDstVarying, newSrcFile, newDstFile;
GLbitfield *inOutFlags;
map = (GLuint *) malloc(prog->Varying->NumParameters * sizeof(GLuint));
@@ -216,14 +234,20 @@ link_varying_vars(GLcontext *ctx,
* Also, replace File=PROGRAM_VARYING with File=PROGRAM_INPUT/OUTPUT.
*/
if (prog->Target == GL_VERTEX_PROGRAM_ARB) {
- firstVarying = VERT_RESULT_VAR0;
- newFile = PROGRAM_OUTPUT;
+ firstSrcVarying = firstDstVarying = VERT_RESULT_VAR0;
+ newSrcFile = newDstFile = PROGRAM_OUTPUT;
inOutFlags = prog->OutputFlags;
}
+ else if (prog->Target == MESA_GEOMETRY_PROGRAM) {
+ firstSrcVarying = GEOM_ATTRIB_VAR0;
+ newSrcFile = PROGRAM_INPUT;
+ firstDstVarying = GEOM_RESULT_VAR0;
+ newDstFile = PROGRAM_OUTPUT;
+ }
else {
assert(prog->Target == GL_FRAGMENT_PROGRAM_ARB);
- firstVarying = FRAG_ATTRIB_VAR0;
- newFile = PROGRAM_INPUT;
+ firstSrcVarying = firstDstVarying = FRAG_ATTRIB_VAR0;
+ newSrcFile = newDstFile = PROGRAM_INPUT;
inOutFlags = prog->InputFlags;
}
@@ -275,7 +299,7 @@ link_varying_vars(GLcontext *ctx,
{
GLint sz = var->Size;
while (sz > 0) {
- inOutFlags[firstVarying + j] = var->Flags;
+ inOutFlags[firstDstVarying + j] = var->Flags;
/*printf("Link varying from %d to %d\n", i, j);*/
map[i++] = j++;
sz -= 4;
@@ -293,14 +317,14 @@ link_varying_vars(GLcontext *ctx,
GLuint j;
if (inst->DstReg.File == PROGRAM_VARYING) {
- inst->DstReg.File = newFile;
- inst->DstReg.Index = map[ inst->DstReg.Index ] + firstVarying;
+ inst->DstReg.File = newDstFile;
+ inst->DstReg.Index = map[ inst->DstReg.Index ] + firstDstVarying;
}
for (j = 0; j < 3; j++) {
if (inst->SrcReg[j].File == PROGRAM_VARYING) {
- inst->SrcReg[j].File = newFile;
- inst->SrcReg[j].Index = map[ inst->SrcReg[j].Index ] + firstVarying;
+ inst->SrcReg[j].File = newSrcFile;
+ inst->SrcReg[j].Index = map[ inst->SrcReg[j].Index ] + firstSrcVarying;
}
}
}
@@ -634,6 +658,16 @@ get_inputs_read_mask(GLenum target, GLuint index, GLboolean relAddr)
; /* a non-array input attribute */
}
}
+ else if (target == MESA_GEOMETRY_PROGRAM) {
+ switch (index) {
+ case GEOM_ATTRIB_VAR0:
+ mask = ((1U << (GEOM_ATTRIB_VAR0 + MAX_VARYING)) - 1)
+ - ((1U << GEOM_ATTRIB_VAR0) - 1);
+ break;
+ default:
+ ; /* a non-array input attribute */
+ }
+ }
else {
assert(0 && "bad program target");
}
@@ -685,6 +719,21 @@ get_outputs_written_mask(GLenum target, GLuint index, GLboolean relAddr)
; /* a non-array output attribute */
}
}
+ else if (target == MESA_GEOMETRY_PROGRAM) {
+ switch (index) {
+ case GEOM_RESULT_TEX0:
+ mask = BITFIELD64_RANGE(GEOM_RESULT_TEX0,
+ (GEOM_RESULT_TEX0
+ + MAX_TEXTURE_COORD_UNITS - 1));
+ break;
+ case GEOM_RESULT_VAR0:
+ mask = BITFIELD64_RANGE(GEOM_RESULT_VAR0,
+ (GEOM_RESULT_VAR0 + MAX_VARYING - 1));
+ break;
+ default:
+ ; /* a non-array output attribute */
+ }
+ }
else {
assert(0 && "bad program target");
}
@@ -902,7 +951,8 @@ _slang_link(GLcontext *ctx,
{
const struct gl_vertex_program *vertProg = NULL;
const struct gl_fragment_program *fragProg = NULL;
- GLboolean vertNotify = GL_TRUE, fragNotify = GL_TRUE;
+ const struct gl_geometry_program *geomProg = NULL;
+ GLboolean vertNotify = GL_TRUE, fragNotify = GL_TRUE, geomNotify = GL_TRUE;
GLuint numSamplers = 0;
GLuint i;
@@ -926,11 +976,15 @@ _slang_link(GLcontext *ctx,
* Find the vertex and fragment shaders which define main()
*/
{
- struct gl_shader *vertShader, *fragShader;
+ struct gl_shader *vertShader, *fragShader, *geomShader;
vertShader = get_main_shader(ctx, shProg, GL_VERTEX_SHADER);
+ geomShader = get_main_shader(ctx, shProg, GL_GEOMETRY_SHADER_ARB);
fragShader = get_main_shader(ctx, shProg, GL_FRAGMENT_SHADER);
+
if (vertShader)
vertProg = vertex_program(vertShader->Program);
+ if (geomShader)
+ geomProg = geometry_program(geomShader->Program);
if (fragShader)
fragProg = fragment_program(fragShader->Program);
if (!shProg->LinkStatus)
@@ -964,7 +1018,14 @@ _slang_link(GLcontext *ctx,
shProg->VertexProgram->Base.Id = shProg->Name;
ASSERT(shProg->VertexProgram->Base.RefCount == 1);
}
-
+ _mesa_reference_geomprog(ctx, &shProg->GeometryProgram, NULL);
+ if (geomProg) {
+ struct gl_geometry_program *linked_gprog =
+ _mesa_clone_geometry_program(ctx, geomProg);
+ shProg->GeometryProgram = linked_gprog; /* refcount OK */
+ shProg->GeometryProgram->Base.Id = shProg->Name;
+ ASSERT(shProg->GeometryProgram->Base.RefCount == 1);
+ }
_mesa_reference_fragprog(ctx, &shProg->FragmentProgram, NULL);
if (fragProg) {
struct gl_fragment_program *linked_fprog =
@@ -980,6 +1041,10 @@ _slang_link(GLcontext *ctx,
if (!link_varying_vars(ctx, shProg, &shProg->VertexProgram->Base))
return;
}
+ if (shProg->GeometryProgram) {
+ if (!link_varying_vars(ctx, shProg, &shProg->GeometryProgram->Base))
+ return;
+ }
if (shProg->FragmentProgram) {
if (!link_varying_vars(ctx, shProg, &shProg->FragmentProgram->Base))
return;
@@ -992,6 +1057,12 @@ _slang_link(GLcontext *ctx,
return;
}
}
+ if (shProg->GeometryProgram) {
+ if (!link_uniform_vars(ctx, shProg, &shProg->GeometryProgram->Base,
+ &numSamplers)) {
+ return;
+ }
+ }
if (shProg->FragmentProgram) {
if (!link_uniform_vars(ctx, shProg, &shProg->FragmentProgram->Base,
&numSamplers)) {
@@ -1019,6 +1090,21 @@ _slang_link(GLcontext *ctx,
return;
}
}
+ if (shProg->GeometryProgram) {
+ if (!shProg->VertexProgram) {
+ link_error(shProg,
+ "Geometry shader without a vertex shader is illegal!\n");
+ return;
+ }
+ if (shProg->GeometryProgram->VerticesOut == 0) {
+ link_error(shProg,
+ "GEOMETRY_VERTICES_OUT is zero\n");
+ return;
+ }
+
+ _slang_count_temporaries(&shProg->GeometryProgram->Base);
+ _slang_update_inputs_outputs(&shProg->GeometryProgram->Base);
+ }
if (shProg->FragmentProgram) {
_slang_count_temporaries(&shProg->FragmentProgram->Base);
_slang_update_inputs_outputs(&shProg->FragmentProgram->Base);
@@ -1076,6 +1162,24 @@ _slang_link(GLcontext *ctx,
}
}
+ if (geomProg && shProg->GeometryProgram) {
+ /* Compute initial program's TexturesUsed info */
+ _mesa_update_shader_textures_used(&shProg->GeometryProgram->Base);
+
+ /* notify driver that a new fragment program has been compiled/linked */
+ geomNotify = ctx->Driver.ProgramStringNotify(ctx, MESA_GEOMETRY_PROGRAM,
+ &shProg->GeometryProgram->Base);
+ if (ctx->Shader.Flags & GLSL_DUMP) {
+ printf("Mesa pre-link geometry program:\n");
+ _mesa_print_program(&geomProg->Base);
+ _mesa_print_program_parameters(ctx, &geomProg->Base);
+
+ printf("Mesa post-link geometry program:\n");
+ _mesa_print_program(&shProg->GeometryProgram->Base);
+ _mesa_print_program_parameters(ctx, &shProg->GeometryProgram->Base);
+ }
+ }
+
if (vertProg && shProg->VertexProgram) {
/* Compute initial program's TexturesUsed info */
_mesa_update_shader_textures_used(&shProg->VertexProgram->Base);
@@ -1110,11 +1214,11 @@ _slang_link(GLcontext *ctx,
}
}
- if (!vertNotify || !fragNotify) {
+ if (!vertNotify || !fragNotify || !geomNotify) {
/* driver rejected one/both of the vertex/fragment programs */
if (!shProg->InfoLog) {
link_error(shProg,
- "Vertex and/or fragment program rejected by driver\n");
+ "Vertex, geometry and/or fragment program rejected by driver\n");
}
}
else {
diff --git a/src/mesa/slang/slang_typeinfo.h b/src/mesa/slang/slang_typeinfo.h
index 9a6407a31bf..2251b063253 100644
--- a/src/mesa/slang/slang_typeinfo.h
+++ b/src/mesa/slang/slang_typeinfo.h
@@ -93,6 +93,11 @@ typedef enum slang_type_qualifier_
SLANG_QUAL_FIXEDINPUT /* internal */
} slang_type_qualifier;
+typedef enum slang_varying_kind_
+{
+ SLANG_VARYING_IN,
+ SLANG_VARYING_OUT,
+} slang_varying_kind;
typedef enum slang_type_precision_
{
@@ -199,6 +204,7 @@ typedef struct slang_fully_specified_type_
slang_type_centroid centroid;
slang_layout_qualifier layout;
GLint array_len; /**< -1 if not an array type */
+ slang_varying_kind varying_kind;
} slang_fully_specified_type;
extern int