diff options
Diffstat (limited to 'mesalib')
65 files changed, 2087 insertions, 417 deletions
diff --git a/mesalib/configure.ac b/mesalib/configure.ac index 91b9871d7..f94c9b979 100644 --- a/mesalib/configure.ac +++ b/mesalib/configure.ac @@ -1005,21 +1005,14 @@ if test "x$enable_dri" = xyes; then DRI_DIRS=`echo "$DRI_DIRS" | $SED 's/ */ /g'` # Check for expat - EXPAT_INCLUDES="" - EXPAT_LIB=-lexpat - AC_ARG_WITH([expat], - [AS_HELP_STRING([--with-expat=DIR], - [expat install directory])],[ - EXPAT_INCLUDES="-I$withval/include" - CPPFLAGS="$CPPFLAGS $EXPAT_INCLUDES" - LDFLAGS="$LDFLAGS -L$withval/$LIB_DIR" - EXPAT_LIB="-L$withval/$LIB_DIR -lexpat" - ]) - AC_CHECK_HEADER([expat.h],[],[AC_MSG_ERROR([Expat required for DRI.])]) - save_LIBS="$LIBS" - AC_CHECK_LIB([expat],[XML_ParserCreate],[], - [AC_MSG_ERROR([Expat required for DRI.])]) - LIBS="$save_LIBS" + PKG_CHECK_EXISTS([EXPAT], [have_expat=yes], [have_expat=no]) + if test "x$have_expat" = "xyes"; then + PKG_CHECK_MODULES([EXPAT], [expat], [], + AC_MSG_ERROR([Expat required for DRI.])) + else + # expat version 2.0 and earlier do not provide expat.pc + EXPAT_LIBS=-lexpat + fi # If we are building any DRI driver other than swrast. if test -n "$DRI_DIRS"; then @@ -1035,8 +1028,8 @@ if test "x$enable_dri" = xyes; then fi # put all the necessary libs together - DRI_LIB_DEPS="$DRI_LIB_DEPS $SELINUX_LIBS $LIBDRM_LIBS $EXPAT_LIB -lm $PTHREAD_LIBS $DLOPEN_LIBS" - GALLIUM_DRI_LIB_DEPS="$GALLIUM_DRI_LIB_DEPS $SELINUX_LIBS $LIBDRM_LIBS $EXPAT_LIB -lm $CLOCK_LIB $PTHREAD_LIBS $DLOPEN_LIBS" + DRI_LIB_DEPS="$DRI_LIB_DEPS $SELINUX_LIBS $LIBDRM_LIBS $EXPAT_LIBS -lm $PTHREAD_LIBS $DLOPEN_LIBS" + GALLIUM_DRI_LIB_DEPS="$GALLIUM_DRI_LIB_DEPS $SELINUX_LIBS $LIBDRM_LIBS $EXPAT_LIBS -lm $CLOCK_LIB $PTHREAD_LIBS $DLOPEN_LIBS" DRI_DRIVER_LDFLAGS="-module -avoid-version -shared -Wl,-Bsymbolic" fi @@ -1045,7 +1038,6 @@ AM_CONDITIONAL(NEED_MEGADRIVER, test -n "$DRI_DIRS") AM_CONDITIONAL(NEED_LIBMESA, test "x$enable_xlib_glx" = xyes -o \ "x$enable_osmesa" = xyes -o \ -n "$DRI_DIRS") -AC_SUBST([EXPAT_INCLUDES]) AC_SUBST([DRI_LIB_DEPS]) AC_SUBST([DRI_DRIVER_LDFLAGS]) AC_SUBST([GALLIUM_DRI_LIB_DEPS]) @@ -1358,8 +1350,8 @@ if test "x$enable_opencl" = xyes; then PKG_CONFIG_PATH environment variable. By default libclc.pc is installed to /usr/local/share/pkgconfig/]) else - LIBCLC_INCLUDEDIR=`pkg-config --variable=includedir libclc` - LIBCLC_LIBEXECDIR=`pkg-config --variable=libexecdir libclc` + LIBCLC_INCLUDEDIR=`$PKG_CONFIG --variable=includedir libclc` + LIBCLC_LIBEXECDIR=`$PKG_CONFIG --variable=libexecdir libclc` AC_SUBST([LIBCLC_INCLUDEDIR]) AC_SUBST([LIBCLC_LIBEXECDIR]) fi diff --git a/mesalib/src/gallium/auxiliary/Makefile.sources b/mesalib/src/gallium/auxiliary/Makefile.sources index acbcef7e2..c89cbddd0 100644 --- a/mesalib/src/gallium/auxiliary/Makefile.sources +++ b/mesalib/src/gallium/auxiliary/Makefile.sources @@ -43,6 +43,7 @@ C_SOURCES := \ hud/hud_cpu.c \ hud/hud_fps.c \ hud/hud_driver_query.c \ + indices/u_primconvert.c \ os/os_misc.c \ os/os_process.c \ os/os_time.c \ diff --git a/mesalib/src/gallium/auxiliary/util/u_format.c b/mesalib/src/gallium/auxiliary/util/u_format.c index a8aa5719d..9ef3bb53f 100644 --- a/mesalib/src/gallium/auxiliary/util/u_format.c +++ b/mesalib/src/gallium/auxiliary/util/u_format.c @@ -208,6 +208,47 @@ util_format_is_supported(enum pipe_format format, unsigned bind) } +/** + * Calculates the MRD for the depth format. MRD is used in depth bias + * for UNORM and unbound depth buffers. When the depth buffer is floating + * point, the depth bias calculation does not use the MRD. However, the + * default MRD will be 1.0 / ((1 << 24) - 1). + */ +double +util_get_depth_format_mrd(enum pipe_format format) +{ + struct util_format_description *format_desc; + /* + * Depth buffer formats without a depth component OR scenarios + * without a bound depth buffer default to D24. + */ + double mrd = 1.0 / ((1 << 24) - 1); + unsigned depth_channel; + + format_desc = (struct util_format_description *) + util_format_description(format); + + assert(format_desc); + + /* + * Some depth formats do not store the depth component in the first + * channel, detect the format and adjust the depth channel. Get the + * swizzled depth component channel. + */ + depth_channel = format_desc->swizzle[0]; + + if (format_desc->channel[depth_channel].type == UTIL_FORMAT_TYPE_UNSIGNED && + format_desc->channel[depth_channel].normalized) { + int depth_bits; + + depth_bits = format_desc->channel[depth_channel].size; + mrd = 1.0 / ((1ULL << depth_bits) - 1); + } + + return mrd; +} + + void util_format_read_4f(enum pipe_format format, float *dst, unsigned dst_stride, diff --git a/mesalib/src/gallium/auxiliary/util/u_format.h b/mesalib/src/gallium/auxiliary/util/u_format.h index 84f16d503..dc777c35c 100644 --- a/mesalib/src/gallium/auxiliary/util/u_format.h +++ b/mesalib/src/gallium/auxiliary/util/u_format.h @@ -544,6 +544,17 @@ util_format_is_depth_and_stencil(enum pipe_format format) util_format_has_stencil(desc); } + +/** + * Calculates the MRD for the depth format. MRD is used in depth bias + * for UNORM and unbound depth buffers. When the depth buffer is floating + * point, the depth bias calculation does not use the MRD. However, the + * default MRD will be 1.0 / ((1 << 24) - 1). + */ +double +util_get_depth_format_mrd(enum pipe_format format); + + /** * Return whether this is an RGBA, Z, S, or combined ZS format. * Useful for initializing pipe_blit_info::mask. diff --git a/mesalib/src/glsl/ast_array_index.cpp b/mesalib/src/glsl/ast_array_index.cpp index b457ec899..f7b5e8350 100644 --- a/mesalib/src/glsl/ast_array_index.cpp +++ b/mesalib/src/glsl/ast_array_index.cpp @@ -143,7 +143,7 @@ _mesa_ast_array_index_to_hir(void *mem_ctx, bound = array->type->vector_elements; } } else { - /* glsl_type::array_size() returns 0 for non-array types. This means + /* glsl_type::array_size() returns -1 for non-array types. This means * that we don't need to verify that the type is an array before * doing the bounds checking. */ @@ -165,7 +165,7 @@ _mesa_ast_array_index_to_hir(void *mem_ctx, if (array->type->is_array()) update_max_array_access(array, idx, &loc, state); } else if (const_index == NULL && array->type->is_array()) { - if (array->type->array_size() == 0) { + if (array->type->is_unsized_array()) { _mesa_glsl_error(&loc, state, "unsized array index must be constant"); } else if (array->type->fields.array->is_interface() && array->variable_referenced()->mode == ir_var_uniform) { diff --git a/mesalib/src/glsl/ast_function.cpp b/mesalib/src/glsl/ast_function.cpp index 02aad4f8f..2707522ef 100644 --- a/mesalib/src/glsl/ast_function.cpp +++ b/mesalib/src/glsl/ast_function.cpp @@ -732,21 +732,21 @@ process_array_constructor(exec_list *instructions, exec_list actual_parameters; const unsigned parameter_count = process_parameters(instructions, &actual_parameters, parameters, state); + bool is_unsized_array = constructor_type->is_unsized_array(); - if ((parameter_count == 0) - || ((constructor_type->length != 0) - && (constructor_type->length != parameter_count))) { - const unsigned min_param = (constructor_type->length == 0) - ? 1 : constructor_type->length; + if ((parameter_count == 0) || + (!is_unsized_array && (constructor_type->length != parameter_count))) { + const unsigned min_param = is_unsized_array + ? 1 : constructor_type->length; _mesa_glsl_error(loc, state, "array constructor must have %s %u " "parameter%s", - (constructor_type->length == 0) ? "at least" : "exactly", + is_unsized_array ? "at least" : "exactly", min_param, (min_param <= 1) ? "" : "s"); return ir_rvalue::error_value(ctx); } - if (constructor_type->length == 0) { + if (is_unsized_array) { constructor_type = glsl_type::get_array_instance(constructor_type->element_type(), parameter_count); diff --git a/mesalib/src/glsl/ast_to_hir.cpp b/mesalib/src/glsl/ast_to_hir.cpp index 3551a5956..f75e68ce1 100644 --- a/mesalib/src/glsl/ast_to_hir.cpp +++ b/mesalib/src/glsl/ast_to_hir.cpp @@ -675,8 +675,8 @@ shift_result_type(const struct glsl_type *type_a, */ ir_rvalue * validate_assignment(struct _mesa_glsl_parse_state *state, - const glsl_type *lhs_type, ir_rvalue *rhs, - bool is_initializer) + YYLTYPE loc, const glsl_type *lhs_type, + ir_rvalue *rhs, bool is_initializer) { /* If there is already some error in the RHS, just return it. Anything * else will lead to an avalanche of error message back to the user. @@ -689,16 +689,15 @@ validate_assignment(struct _mesa_glsl_parse_state *state, if (rhs->type == lhs_type) return rhs; - /* If the array element types are the same and the size of the LHS is zero, + /* If the array element types are the same and the LHS is unsized, * the assignment is okay for initializers embedded in variable * declarations. * * Note: Whole-array assignments are not permitted in GLSL 1.10, but this * is handled by ir_dereference::is_lvalue. */ - if (is_initializer && lhs_type->is_array() && rhs->type->is_array() - && (lhs_type->element_type() == rhs->type->element_type()) - && (lhs_type->array_size() == 0)) { + if (is_initializer && lhs_type->is_unsized_array() && rhs->type->is_array() + && (lhs_type->element_type() == rhs->type->element_type())) { return rhs; } @@ -708,6 +707,12 @@ validate_assignment(struct _mesa_glsl_parse_state *state, return rhs; } + _mesa_glsl_error(&loc, state, + "%s of type %s cannot be assigned to " + "variable of type %s", + is_initializer ? "initializer" : "value", + rhs->type->name, lhs_type->name); + return NULL; } @@ -738,10 +743,10 @@ do_assignment(exec_list *instructions, struct _mesa_glsl_parse_state *state, if (unlikely(expr->operation == ir_binop_vector_extract)) { ir_rvalue *new_rhs = - validate_assignment(state, lhs->type, rhs, is_initializer); + validate_assignment(state, lhs_loc, lhs->type, + rhs, is_initializer); if (new_rhs == NULL) { - _mesa_glsl_error(& lhs_loc, state, "type mismatch"); return lhs; } else { rhs = new(ctx) ir_expression(ir_triop_vector_insert, @@ -790,10 +795,8 @@ do_assignment(exec_list *instructions, struct _mesa_glsl_parse_state *state, } ir_rvalue *new_rhs = - validate_assignment(state, lhs->type, rhs, is_initializer); - if (new_rhs == NULL) { - _mesa_glsl_error(& lhs_loc, state, "type mismatch"); - } else { + validate_assignment(state, lhs_loc, lhs->type, rhs, is_initializer); + if (new_rhs != NULL) { rhs = new_rhs; /* If the LHS array was not declared with a size, it takes it size from @@ -801,7 +804,7 @@ do_assignment(exec_list *instructions, struct _mesa_glsl_parse_state *state, * dereference of a variable. Any other case would require that the LHS * is either not an l-value or not a whole array. */ - if (lhs->type->array_size() == 0) { + if (lhs->type->is_unsized_array()) { ir_dereference *const d = lhs->as_dereference(); assert(d != NULL); @@ -940,6 +943,7 @@ do_comparison(void *mem_ctx, int operation, ir_rvalue *op0, ir_rvalue *op1) case GLSL_TYPE_VOID: case GLSL_TYPE_SAMPLER: case GLSL_TYPE_INTERFACE: + case GLSL_TYPE_ATOMIC_UINT: /* I assume a comparison of a struct containing a sampler just * ignores the sampler present in the type. */ @@ -1234,6 +1238,10 @@ ast_expression::hir(exec_list *instructions, !state->check_version(120, 300, &loc, "array comparisons forbidden")) { error_emitted = true; + } else if ((op[0]->type->contains_opaque() || + op[1]->type->contains_opaque())) { + _mesa_glsl_error(&loc, state, "opaque type comparisons forbidden"); + error_emitted = true; } if (error_emitted) { @@ -2039,6 +2047,96 @@ interpret_interpolation_qualifier(const struct ast_type_qualifier *qual, static void +validate_explicit_location(const struct ast_type_qualifier *qual, + ir_variable *var, + struct _mesa_glsl_parse_state *state, + YYLTYPE *loc) +{ + bool fail = false; + + /* In the vertex shader only shader inputs can be given explicit + * locations. + * + * In the fragment shader only shader outputs can be given explicit + * locations. + */ + switch (state->target) { + case vertex_shader: + if (var->mode == ir_var_shader_in) { + if (!state->check_explicit_attrib_location_allowed(loc, var)) + return; + + break; + } + + fail = true; + break; + + case geometry_shader: + _mesa_glsl_error(loc, state, + "geometry shader variables cannot be given " + "explicit locations"); + return; + + case fragment_shader: + if (var->mode == ir_var_shader_out) { + if (!state->check_explicit_attrib_location_allowed(loc, var)) + return; + + break; + } + + fail = true; + break; + }; + + if (fail) { + _mesa_glsl_error(loc, state, + "%s cannot be given an explicit location in %s shader", + mode_string(var), + _mesa_glsl_shader_target_name(state->target)); + } else { + var->explicit_location = true; + + /* This bit of silliness is needed because invalid explicit locations + * are supposed to be flagged during linking. Small negative values + * biased by VERT_ATTRIB_GENERIC0 or FRAG_RESULT_DATA0 could alias + * built-in values (e.g., -16+VERT_ATTRIB_GENERIC0 = VERT_ATTRIB_POS). + * The linker needs to be able to differentiate these cases. This + * ensures that negative values stay negative. + */ + if (qual->location >= 0) { + var->location = (state->target == vertex_shader) + ? (qual->location + VERT_ATTRIB_GENERIC0) + : (qual->location + FRAG_RESULT_DATA0); + } else { + var->location = qual->location; + } + + if (qual->flags.q.explicit_index) { + /* From the GLSL 4.30 specification, section 4.4.2 (Output + * Layout Qualifiers): + * + * "It is also a compile-time error if a fragment shader + * sets a layout index to less than 0 or greater than 1." + * + * Older specifications don't mandate a behavior; we take + * this as a clarification and always generate the error. + */ + if (qual->index < 0 || qual->index > 1) { + _mesa_glsl_error(loc, state, + "explicit index may only be 0 or 1"); + } else { + var->explicit_index = true; + var->index = qual->index; + } + } + } + + return; +} + +static void apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual, ir_variable *var, struct _mesa_glsl_parse_state *state, @@ -2190,81 +2288,7 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual, } if (qual->flags.q.explicit_location) { - const bool global_scope = (state->current_function == NULL); - bool fail = false; - const char *string = ""; - - /* In the vertex shader only shader inputs can be given explicit - * locations. - * - * In the fragment shader only shader outputs can be given explicit - * locations. - */ - switch (state->target) { - case vertex_shader: - if (!global_scope || (var->mode != ir_var_shader_in)) { - fail = true; - string = "input"; - } - break; - - case geometry_shader: - _mesa_glsl_error(loc, state, - "geometry shader variables cannot be given " - "explicit locations"); - break; - - case fragment_shader: - if (!global_scope || (var->mode != ir_var_shader_out)) { - fail = true; - string = "output"; - } - break; - }; - - if (fail) { - _mesa_glsl_error(loc, state, - "only %s shader %s variables can be given an " - "explicit location", - _mesa_glsl_shader_target_name(state->target), - string); - } else { - var->explicit_location = true; - - /* This bit of silliness is needed because invalid explicit locations - * are supposed to be flagged during linking. Small negative values - * biased by VERT_ATTRIB_GENERIC0 or FRAG_RESULT_DATA0 could alias - * built-in values (e.g., -16+VERT_ATTRIB_GENERIC0 = VERT_ATTRIB_POS). - * The linker needs to be able to differentiate these cases. This - * ensures that negative values stay negative. - */ - if (qual->location >= 0) { - var->location = (state->target == vertex_shader) - ? (qual->location + VERT_ATTRIB_GENERIC0) - : (qual->location + FRAG_RESULT_DATA0); - } else { - var->location = qual->location; - } - - if (qual->flags.q.explicit_index) { - /* From the GLSL 4.30 specification, section 4.4.2 (Output - * Layout Qualifiers): - * - * "It is also a compile-time error if a fragment shader - * sets a layout index to less than 0 or greater than 1." - * - * Older specifications don't mandate a behavior; we take - * this as a clarification and always generate the error. - */ - if (qual->index < 0 || qual->index > 1) { - _mesa_glsl_error(loc, state, - "explicit index may only be 0 or 1"); - } else { - var->explicit_index = true; - var->index = qual->index; - } - } - } + validate_explicit_location(qual, var, state, loc); } else if (qual->flags.q.explicit_index) { _mesa_glsl_error(loc, state, "explicit index requires explicit location"); @@ -2403,8 +2427,7 @@ get_variable_being_redeclared(ir_variable *var, YYLTYPE loc, * later re-declare the same name as an array of the same * type and specify a size." */ - if ((earlier->type->array_size() == 0) - && var->type->is_array() + if (earlier->type->is_unsized_array() && var->type->is_array() && (var->type->element_type() == earlier->type->element_type())) { /* FINISHME: This doesn't match the qualifiers on the two * FINISHME: declarations. It's not 100% clear whether this is @@ -2547,7 +2570,8 @@ process_initializer(ir_variable *var, ast_declaration *decl, */ if (type->qualifier.flags.q.constant || type->qualifier.flags.q.uniform) { - ir_rvalue *new_rhs = validate_assignment(state, var->type, rhs, true); + ir_rvalue *new_rhs = validate_assignment(state, initializer_loc, + var->type, rhs, true); if (new_rhs != NULL) { rhs = new_rhs; @@ -2576,10 +2600,6 @@ process_initializer(ir_variable *var, ast_declaration *decl, var->constant_value = constant_value; } } else { - _mesa_glsl_error(&initializer_loc, state, - "initializer of type %s cannot be assigned to " - "variable of type %s", - rhs->type->name, var->type->name); if (var->type->is_numeric()) { /* Reduce cascading errors. */ var->constant_value = ir_constant::zero(state, var->type); @@ -2659,7 +2679,7 @@ handle_geometry_shader_input_decl(struct _mesa_glsl_parse_state *state, return; } - if (var->type->length == 0) { + if (var->type->is_unsized_array()) { /* Section 4.3.8.1 (Input Layout Qualifiers) of the GLSL 1.50 spec says: * * All geometry shader input unsized array declarations will be @@ -3308,7 +3328,7 @@ ast_declarator_list::hir(exec_list *instructions, const glsl_type *const t = (earlier == NULL) ? var->type : earlier->type; - if (t->is_array() && t->length == 0) + if (t->is_unsized_array()) /* Section 10.17 of the GLSL ES 1.00 specification states that * unsized array declarations have been removed from the language. * Arrays that are sized using an initializer are still explicitly @@ -3441,7 +3461,7 @@ ast_parameter_declarator::hir(exec_list *instructions, type = process_array_type(&loc, type, this->array_size, state); } - if (!type->is_error() && type->array_size() == 0) { + if (!type->is_error() && type->is_unsized_array()) { _mesa_glsl_error(&loc, state, "arrays passed as parameters must have " "a declared size"); type = glsl_type::error_type; @@ -3613,7 +3633,7 @@ ast_function::hir(exec_list *instructions, * "Arrays are allowed as arguments and as the return type. In both * cases, the array must be explicitly sized." */ - if (return_type->is_array() && return_type->length == 0) { + if (return_type->is_unsized_array()) { YYLTYPE loc = this->get_location(); _mesa_glsl_error(& loc, state, "function `%s' return type array must be explicitly " @@ -5099,10 +5119,8 @@ ast_gs_input_layout::hir(exec_list *instructions, /* Note: gl_PrimitiveIDIn has mode ir_var_shader_in, but it's not an * array; skip it. */ - if (!var->type->is_array()) - continue; - if (var->type->length == 0) { + if (var->type->is_unsized_array()) { if (var->max_array_access >= num_vertices) { _mesa_glsl_error(&loc, state, "this geometry shader input layout implies %u" diff --git a/mesalib/src/glsl/builtin_functions.cpp b/mesalib/src/glsl/builtin_functions.cpp index d40888d38..3fa0cb5ad 100644 --- a/mesalib/src/glsl/builtin_functions.cpp +++ b/mesalib/src/glsl/builtin_functions.cpp @@ -277,6 +277,17 @@ texture_gather(const _mesa_glsl_parse_state *state) state->ARB_gpu_shader5_enable; } +/* Only ARB_texture_gather but not GLSL 4.0 or ARB_gpu_shader5. + * used for relaxation of const offset requirements. + */ +static bool +texture_gather_only(const _mesa_glsl_parse_state *state) +{ + return !state->is_version(400, 0) && + !state->ARB_gpu_shader5_enable && + state->ARB_texture_gather_enable; +} + /* Desktop GL or OES_standard_derivatives + fragment shader only */ static bool fs_oes_derivatives(const _mesa_glsl_parse_state *state) @@ -315,6 +326,13 @@ tex3d_lod(const _mesa_glsl_parse_state *state) { return tex3d(state) && lod_exists_in_stage(state); } + +static bool +shader_atomic_counters(const _mesa_glsl_parse_state *state) +{ + return state->ARB_shader_atomic_counters_enable; +} + /** @} */ /******************************************************************************/ @@ -354,6 +372,7 @@ private: ir_variable *gl_Vertex; void create_shader(); + void create_intrinsics(); void create_builtins(); /** @@ -375,6 +394,14 @@ private: ir_expression *asin_expr(ir_variable *x); + /** + * Call function \param f with parameters specified as the linked + * list \param params of \c ir_variable objects. \param ret should + * point to the ir_variable that will hold the function return + * value, or be \c NULL if the function has void return type. + */ + ir_call *call(ir_function *f, ir_variable *ret, exec_list params); + /** Create a new function and add the given signatures. */ void add_function(const char *name, ...); @@ -495,6 +522,8 @@ private: #define TEX_PROJECT 1 #define TEX_OFFSET 2 #define TEX_COMPONENT 4 +#define TEX_OFFSET_NONCONST 8 +#define TEX_OFFSET_ARRAY 16 ir_function_signature *_texture(ir_texture_opcode opcode, builtin_available_predicate avail, @@ -534,6 +563,11 @@ private: B1(uaddCarry) B1(usubBorrow) B1(mulExtended) + + ir_function_signature *_atomic_intrinsic(builtin_available_predicate avail); + ir_function_signature *_atomic_op(const char *intrinsic, + builtin_available_predicate avail); + #undef B0 #undef B1 #undef B2 @@ -596,6 +630,7 @@ builtin_builder::initialize() mem_ctx = ralloc_context(NULL); create_shader(); + create_intrinsics(); create_builtins(); } @@ -633,6 +668,24 @@ builtin_builder::create_shader() /** @} */ /** + * Create ir_function and ir_function_signature objects for each + * intrinsic. + */ +void +builtin_builder::create_intrinsics() +{ + add_function("__intrinsic_atomic_read", + _atomic_intrinsic(shader_atomic_counters), + NULL); + add_function("__intrinsic_atomic_increment", + _atomic_intrinsic(shader_atomic_counters), + NULL); + add_function("__intrinsic_atomic_predecrement", + _atomic_intrinsic(shader_atomic_counters), + NULL); +} + +/** * Create ir_function and ir_function_signature objects for each built-in. * * Contains a list of every available built-in. @@ -1909,16 +1962,80 @@ builtin_builder::create_builtins() _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::samplerCubeArray_type, glsl_type::vec4_type, TEX_COMPONENT), _texture(ir_tg4, gpu_shader5, glsl_type::ivec4_type, glsl_type::isamplerCubeArray_type, glsl_type::vec4_type, TEX_COMPONENT), _texture(ir_tg4, gpu_shader5, glsl_type::uvec4_type, glsl_type::usamplerCubeArray_type, glsl_type::vec4_type, TEX_COMPONENT), + + _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2DShadow_type, glsl_type::vec2_type), + _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2DArrayShadow_type, glsl_type::vec3_type), + _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::samplerCubeShadow_type, glsl_type::vec3_type), + _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::samplerCubeArrayShadow_type, glsl_type::vec4_type), + _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2DRectShadow_type, glsl_type::vec2_type), NULL); add_function("textureGatherOffset", - _texture(ir_tg4, texture_gather, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec2_type, TEX_OFFSET), - _texture(ir_tg4, texture_gather, glsl_type::ivec4_type, glsl_type::isampler2D_type, glsl_type::vec2_type, TEX_OFFSET), - _texture(ir_tg4, texture_gather, glsl_type::uvec4_type, glsl_type::usampler2D_type, glsl_type::vec2_type, TEX_OFFSET), + _texture(ir_tg4, texture_gather_only, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec2_type, TEX_OFFSET), + _texture(ir_tg4, texture_gather_only, glsl_type::ivec4_type, glsl_type::isampler2D_type, glsl_type::vec2_type, TEX_OFFSET), + _texture(ir_tg4, texture_gather_only, glsl_type::uvec4_type, glsl_type::usampler2D_type, glsl_type::vec2_type, TEX_OFFSET), + + _texture(ir_tg4, texture_gather_only, glsl_type::vec4_type, glsl_type::sampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET), + _texture(ir_tg4, texture_gather_only, glsl_type::ivec4_type, glsl_type::isampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET), + _texture(ir_tg4, texture_gather_only, glsl_type::uvec4_type, glsl_type::usampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET), + + _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec2_type, TEX_OFFSET_NONCONST), + _texture(ir_tg4, gpu_shader5, glsl_type::ivec4_type, glsl_type::isampler2D_type, glsl_type::vec2_type, TEX_OFFSET_NONCONST), + _texture(ir_tg4, gpu_shader5, glsl_type::uvec4_type, glsl_type::usampler2D_type, glsl_type::vec2_type, TEX_OFFSET_NONCONST), + + _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET_NONCONST), + _texture(ir_tg4, gpu_shader5, glsl_type::ivec4_type, glsl_type::isampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET_NONCONST), + _texture(ir_tg4, gpu_shader5, glsl_type::uvec4_type, glsl_type::usampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET_NONCONST), + + _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2DRect_type, glsl_type::vec2_type, TEX_OFFSET_NONCONST), + _texture(ir_tg4, gpu_shader5, glsl_type::ivec4_type, glsl_type::isampler2DRect_type, glsl_type::vec2_type, TEX_OFFSET_NONCONST), + _texture(ir_tg4, gpu_shader5, glsl_type::uvec4_type, glsl_type::usampler2DRect_type, glsl_type::vec2_type, TEX_OFFSET_NONCONST), + + _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec2_type, TEX_OFFSET_NONCONST | TEX_COMPONENT), + _texture(ir_tg4, gpu_shader5, glsl_type::ivec4_type, glsl_type::isampler2D_type, glsl_type::vec2_type, TEX_OFFSET_NONCONST | TEX_COMPONENT), + _texture(ir_tg4, gpu_shader5, glsl_type::uvec4_type, glsl_type::usampler2D_type, glsl_type::vec2_type, TEX_OFFSET_NONCONST | TEX_COMPONENT), + + _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET_NONCONST | TEX_COMPONENT), + _texture(ir_tg4, gpu_shader5, glsl_type::ivec4_type, glsl_type::isampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET_NONCONST | TEX_COMPONENT), + _texture(ir_tg4, gpu_shader5, glsl_type::uvec4_type, glsl_type::usampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET_NONCONST | TEX_COMPONENT), + + _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2DRect_type, glsl_type::vec2_type, TEX_OFFSET_NONCONST | TEX_COMPONENT), + _texture(ir_tg4, gpu_shader5, glsl_type::ivec4_type, glsl_type::isampler2DRect_type, glsl_type::vec2_type, TEX_OFFSET_NONCONST | TEX_COMPONENT), + _texture(ir_tg4, gpu_shader5, glsl_type::uvec4_type, glsl_type::usampler2DRect_type, glsl_type::vec2_type, TEX_OFFSET_NONCONST | TEX_COMPONENT), + + _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2DShadow_type, glsl_type::vec2_type, TEX_OFFSET_NONCONST), + _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2DArrayShadow_type, glsl_type::vec3_type, TEX_OFFSET_NONCONST), + _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2DRectShadow_type, glsl_type::vec2_type, TEX_OFFSET_NONCONST), + NULL); + + add_function("textureGatherOffsets", + _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec2_type, TEX_OFFSET_ARRAY), + _texture(ir_tg4, gpu_shader5, glsl_type::ivec4_type, glsl_type::isampler2D_type, glsl_type::vec2_type, TEX_OFFSET_ARRAY), + _texture(ir_tg4, gpu_shader5, glsl_type::uvec4_type, glsl_type::usampler2D_type, glsl_type::vec2_type, TEX_OFFSET_ARRAY), + + _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2D_type, glsl_type::vec2_type, TEX_OFFSET_ARRAY | TEX_COMPONENT), + _texture(ir_tg4, gpu_shader5, glsl_type::ivec4_type, glsl_type::isampler2D_type, glsl_type::vec2_type, TEX_OFFSET_ARRAY | TEX_COMPONENT), + _texture(ir_tg4, gpu_shader5, glsl_type::uvec4_type, glsl_type::usampler2D_type, glsl_type::vec2_type, TEX_OFFSET_ARRAY | TEX_COMPONENT), + + _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET_ARRAY), + _texture(ir_tg4, gpu_shader5, glsl_type::ivec4_type, glsl_type::isampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET_ARRAY), + _texture(ir_tg4, gpu_shader5, glsl_type::uvec4_type, glsl_type::usampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET_ARRAY), - _texture(ir_tg4, texture_gather, glsl_type::vec4_type, glsl_type::sampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET), - _texture(ir_tg4, texture_gather, glsl_type::ivec4_type, glsl_type::isampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET), - _texture(ir_tg4, texture_gather, glsl_type::uvec4_type, glsl_type::usampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET), + _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET_ARRAY | TEX_COMPONENT), + _texture(ir_tg4, gpu_shader5, glsl_type::ivec4_type, glsl_type::isampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET_ARRAY | TEX_COMPONENT), + _texture(ir_tg4, gpu_shader5, glsl_type::uvec4_type, glsl_type::usampler2DArray_type, glsl_type::vec3_type, TEX_OFFSET_ARRAY | TEX_COMPONENT), + + _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2DRect_type, glsl_type::vec2_type, TEX_OFFSET_ARRAY), + _texture(ir_tg4, gpu_shader5, glsl_type::ivec4_type, glsl_type::isampler2DRect_type, glsl_type::vec2_type, TEX_OFFSET_ARRAY), + _texture(ir_tg4, gpu_shader5, glsl_type::uvec4_type, glsl_type::usampler2DRect_type, glsl_type::vec2_type, TEX_OFFSET_ARRAY), + + _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2DRect_type, glsl_type::vec2_type, TEX_OFFSET_ARRAY | TEX_COMPONENT), + _texture(ir_tg4, gpu_shader5, glsl_type::ivec4_type, glsl_type::isampler2DRect_type, glsl_type::vec2_type, TEX_OFFSET_ARRAY | TEX_COMPONENT), + _texture(ir_tg4, gpu_shader5, glsl_type::uvec4_type, glsl_type::usampler2DRect_type, glsl_type::vec2_type, TEX_OFFSET_ARRAY | TEX_COMPONENT), + + _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2DShadow_type, glsl_type::vec2_type, TEX_OFFSET_ARRAY), + _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2DArrayShadow_type, glsl_type::vec3_type, TEX_OFFSET_ARRAY), + _texture(ir_tg4, gpu_shader5, glsl_type::vec4_type, glsl_type::sampler2DRectShadow_type, glsl_type::vec2_type, TEX_OFFSET_ARRAY), NULL); F(dFdx) @@ -1974,6 +2091,20 @@ builtin_builder::create_builtins() _mulExtended(glsl_type::uvec3_type), _mulExtended(glsl_type::uvec4_type), NULL); + + add_function("atomicCounter", + _atomic_op("__intrinsic_atomic_read", + shader_atomic_counters), + NULL); + add_function("atomicCounterIncrement", + _atomic_op("__intrinsic_atomic_increment", + shader_atomic_counters), + NULL); + add_function("atomicCounterDecrement", + _atomic_op("__intrinsic_atomic_predecrement", + shader_atomic_counters), + NULL); + #undef F #undef FI #undef FIU @@ -1994,8 +2125,6 @@ builtin_builder::add_function(const char *name, ...) if (sig == NULL) break; - sig->is_defined = true; - if (false) { exec_list stuff; stuff.push_tail(sig); @@ -2093,7 +2222,13 @@ builtin_builder::new_sig(const glsl_type *return_type, #define MAKE_SIG(return_type, avail, ...) \ ir_function_signature *sig = \ new_sig(return_type, avail, __VA_ARGS__); \ - ir_factory body(&sig->body, mem_ctx); + ir_factory body(&sig->body, mem_ctx); \ + sig->is_defined = true; + +#define MAKE_INTRINSIC(return_type, avail, ...) \ + ir_function_signature *sig = \ + new_sig(return_type, avail, __VA_ARGS__); \ + sig->is_intrinsic = true; ir_function_signature * builtin_builder::unop(builtin_available_predicate avail, @@ -2185,6 +2320,26 @@ builtin_builder::asin_expr(ir_variable *x) mul(abs(x), imm(-0.03102955f)))))))))); } +ir_call * +builtin_builder::call(ir_function *f, ir_variable *ret, exec_list params) +{ + exec_list actual_params; + + foreach_iter(exec_list_iterator, it, params) { + ir_variable *var = ((ir_instruction *)it.get())->as_variable(); + actual_params.push_tail(var_ref(var)); + } + + ir_function_signature *sig = + f->exact_matching_signature(NULL, &actual_params); + if (!sig) + return NULL; + + ir_dereference_variable *deref = + (sig->return_type->is_void() ? NULL : var_ref(ret)); + + return new(mem_ctx) ir_call(sig, deref, &actual_params); +} ir_function_signature * builtin_builder::_asin(const glsl_type *type) @@ -3347,11 +3502,21 @@ builtin_builder::_texture(ir_texture_opcode opcode, if (flags & TEX_PROJECT) tex->projector = swizzle(P, coord_type->vector_elements - 1, 1); - /* The shadow comparitor is normally in the Z component, but a few types - * have sufficiently large coordinates that it's in W. - */ - if (sampler_type->sampler_shadow) - tex->shadow_comparitor = swizzle(P, MAX2(coord_size, SWIZZLE_Z), 1); + if (sampler_type->sampler_shadow) { + if (opcode == ir_tg4) { + /* gather has refz as a separate parameter, immediately after the + * coordinate + */ + ir_variable *refz = in_var(glsl_type::float_type, "refz"); + sig->parameters.push_tail(refz); + tex->shadow_comparitor = var_ref(refz); + } else { + /* The shadow comparitor is normally in the Z component, but a few types + * have sufficiently large coordinates that it's in W. + */ + tex->shadow_comparitor = swizzle(P, MAX2(coord_size, SWIZZLE_Z), 1); + } + } if (opcode == ir_txl) { ir_variable *lod = in_var(glsl_type::float_type, "lod"); @@ -3367,14 +3532,23 @@ builtin_builder::_texture(ir_texture_opcode opcode, tex->lod_info.grad.dPdy = var_ref(dPdy); } - if (flags & TEX_OFFSET) { + if (flags & (TEX_OFFSET | TEX_OFFSET_NONCONST)) { int offset_size = coord_size - (sampler_type->sampler_array ? 1 : 0); ir_variable *offset = - new(mem_ctx) ir_variable(glsl_type::ivec(offset_size), "offset", ir_var_const_in); + new(mem_ctx) ir_variable(glsl_type::ivec(offset_size), "offset", + (flags & TEX_OFFSET) ? ir_var_const_in : ir_var_function_in); sig->parameters.push_tail(offset); tex->offset = var_ref(offset); } + if (flags & TEX_OFFSET_ARRAY) { + ir_variable *offsets = + new(mem_ctx) ir_variable(glsl_type::get_array_instance(glsl_type::ivec2_type, 4), + "offsets", ir_var_const_in); + sig->parameters.push_tail(offsets); + tex->offset = var_ref(offsets); + } + if (opcode == ir_tg4) { if (flags & TEX_COMPONENT) { ir_variable *component = @@ -3793,6 +3967,29 @@ builtin_builder::_mulExtended(const glsl_type *type) return sig; } + +ir_function_signature * +builtin_builder::_atomic_intrinsic(builtin_available_predicate avail) +{ + ir_variable *counter = in_var(glsl_type::atomic_uint_type, "counter"); + MAKE_INTRINSIC(glsl_type::uint_type, avail, 1, counter); + return sig; +} + +ir_function_signature * +builtin_builder::_atomic_op(const char *intrinsic, + builtin_available_predicate avail) +{ + ir_variable *counter = in_var(glsl_type::atomic_uint_type, "atomic_counter"); + MAKE_SIG(glsl_type::uint_type, avail, 1, counter); + + ir_variable *retval = body.make_temp(glsl_type::uint_type, "atomic_retval"); + body.emit(call(shader->symbols->get_function(intrinsic), retval, + sig->parameters)); + body.emit(ret(retval)); + return sig; +} + /** @} */ /******************************************************************************/ diff --git a/mesalib/src/glsl/builtin_type_macros.h b/mesalib/src/glsl/builtin_type_macros.h index fec38da12..263fd83ff 100644 --- a/mesalib/src/glsl/builtin_type_macros.h +++ b/mesalib/src/glsl/builtin_type_macros.h @@ -110,6 +110,8 @@ DECL_TYPE(sampler2DRectShadow, GL_SAMPLER_2D_RECT_SHADOW, GLSL_SAMPLER DECL_TYPE(samplerExternalOES, GL_SAMPLER_EXTERNAL_OES, GLSL_SAMPLER_DIM_EXTERNAL, 0, 0, GLSL_TYPE_FLOAT) +DECL_TYPE(atomic_uint, GL_UNSIGNED_INT_ATOMIC_COUNTER, GLSL_TYPE_ATOMIC_UINT, 1, 1) + STRUCT_TYPE(gl_DepthRangeParameters) STRUCT_TYPE(gl_PointParameters) STRUCT_TYPE(gl_MaterialParameters) diff --git a/mesalib/src/glsl/builtin_types.cpp b/mesalib/src/glsl/builtin_types.cpp index 1a5e5a190..92e386057 100644 --- a/mesalib/src/glsl/builtin_types.cpp +++ b/mesalib/src/glsl/builtin_types.cpp @@ -203,6 +203,8 @@ const static struct builtin_type_versions { T(sampler2DRectShadow, 140, 999) T(struct_gl_DepthRangeParameters, 110, 100) + + T(atomic_uint, 420, 999) }; const glsl_type *const deprecated_types[] = { @@ -284,5 +286,9 @@ _mesa_glsl_initialize_types(struct _mesa_glsl_parse_state *state) if (state->OES_texture_3D_enable) { add_type(symbols, glsl_type::sampler3D_type); } + + if (state->ARB_shader_atomic_counters_enable) { + add_type(symbols, glsl_type::atomic_uint_type); + } } /** @} */ diff --git a/mesalib/src/glsl/builtin_variables.cpp b/mesalib/src/glsl/builtin_variables.cpp index 018daf67f..7a3505ace 100644 --- a/mesalib/src/glsl/builtin_variables.cpp +++ b/mesalib/src/glsl/builtin_variables.cpp @@ -638,6 +638,21 @@ builtin_variable_generator::generate_constants() */ add_const("gl_MaxTextureCoords", state->Const.MaxTextureCoords); } + + if (state->ARB_shader_atomic_counters_enable) { + add_const("gl_MaxVertexAtomicCounters", + state->Const.MaxVertexAtomicCounters); + add_const("gl_MaxGeometryAtomicCounters", + state->Const.MaxGeometryAtomicCounters); + add_const("gl_MaxFragmentAtomicCounters", + state->Const.MaxFragmentAtomicCounters); + add_const("gl_MaxCombinedAtomicCounters", + state->Const.MaxCombinedAtomicCounters); + add_const("gl_MaxAtomicCounterBindings", + state->Const.MaxAtomicBufferBindings); + add_const("gl_MaxTessControlAtomicCounters", 0); + add_const("gl_MaxTessEvaluationAtomicCounters", 0); + } } diff --git a/mesalib/src/glsl/glcpp/glcpp-parse.y b/mesalib/src/glsl/glcpp/glcpp-parse.y index 02100ab0c..86f3cd5aa 100644 --- a/mesalib/src/glsl/glcpp/glcpp-parse.y +++ b/mesalib/src/glsl/glcpp/glcpp-parse.y @@ -1254,6 +1254,9 @@ glcpp_parser_create (const struct gl_extensions *extensions, int api) if (extensions->ARB_texture_gather) add_builtin_define(parser, "GL_ARB_texture_gather", 1); + + if (extensions->ARB_shader_atomic_counters) + add_builtin_define(parser, "GL_ARB_shader_atomic_counters", 1); } } diff --git a/mesalib/src/glsl/glsl_parser.yy b/mesalib/src/glsl/glsl_parser.yy index 0a0708e95..14420f8a3 100644 --- a/mesalib/src/glsl/glsl_parser.yy +++ b/mesalib/src/glsl/glsl_parser.yy @@ -66,14 +66,8 @@ static bool match_layout_qualifier(const char *s1, const char *s2, */ if (state->es_shader) return strcmp(s1, s2); - else { -#if defined(_MSC_VER) - /* MSVC doesn't have a strcasecmp() function; instead it has _stricmp. */ - return _stricmp(s1, s2); -#else + else return strcasecmp(s1, s2); -#endif - } } %} @@ -1308,29 +1302,25 @@ layout_qualifier_id: { memset(& $$, 0, sizeof($$)); - if (state->has_explicit_attrib_location()) { - if (match_layout_qualifier("location", $1, state) == 0) { - $$.flags.q.explicit_location = 1; + if (match_layout_qualifier("location", $1, state) == 0) { + $$.flags.q.explicit_location = 1; - if ($3 >= 0) { - $$.location = $3; - } else { - _mesa_glsl_error(& @3, state, - "invalid location %d specified", $3); - YYERROR; - } + if ($3 >= 0) { + $$.location = $3; + } else { + _mesa_glsl_error(& @3, state, "invalid location %d specified", $3); + YYERROR; } + } - if (match_layout_qualifier("index", $1, state) == 0) { - $$.flags.q.explicit_index = 1; + if (match_layout_qualifier("index", $1, state) == 0) { + $$.flags.q.explicit_index = 1; - if ($3 >= 0) { - $$.index = $3; - } else { - _mesa_glsl_error(& @3, state, - "invalid index %d specified", $3); - YYERROR; - } + if ($3 >= 0) { + $$.index = $3; + } else { + _mesa_glsl_error(& @3, state, "invalid index %d specified", $3); + YYERROR; } } diff --git a/mesalib/src/glsl/glsl_parser_extras.cpp b/mesalib/src/glsl/glsl_parser_extras.cpp index be17109e1..77e8816c4 100644 --- a/mesalib/src/glsl/glsl_parser_extras.cpp +++ b/mesalib/src/glsl/glsl_parser_extras.cpp @@ -118,6 +118,12 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx, this->Const.MaxGeometryTotalOutputComponents = ctx->Const.MaxGeometryTotalOutputComponents; this->Const.MaxGeometryUniformComponents = ctx->Const.GeometryProgram.MaxUniformComponents; + this->Const.MaxVertexAtomicCounters = ctx->Const.VertexProgram.MaxAtomicCounters; + this->Const.MaxGeometryAtomicCounters = ctx->Const.GeometryProgram.MaxAtomicCounters; + this->Const.MaxFragmentAtomicCounters = ctx->Const.FragmentProgram.MaxAtomicCounters; + this->Const.MaxCombinedAtomicCounters = ctx->Const.MaxCombinedAtomicCounters; + this->Const.MaxAtomicBufferBindings = ctx->Const.MaxAtomicBufferBindings; + this->current_function = NULL; this->toplevel_ir = NULL; this->found_return = false; @@ -533,6 +539,7 @@ static const _mesa_glsl_extension _mesa_glsl_supported_extensions[] = { EXT(AMD_vertex_shader_layer, true, false, AMD_vertex_shader_layer), EXT(EXT_shader_integer_mix, true, true, EXT_shader_integer_mix), EXT(ARB_texture_gather, true, false, ARB_texture_gather), + EXT(ARB_shader_atomic_counters, true, false, ARB_shader_atomic_counters), }; #undef EXT diff --git a/mesalib/src/glsl/glsl_parser_extras.h b/mesalib/src/glsl/glsl_parser_extras.h index 01000b445..32f26c7f0 100755 --- a/mesalib/src/glsl/glsl_parser_extras.h +++ b/mesalib/src/glsl/glsl_parser_extras.h @@ -69,6 +69,10 @@ typedef struct YYLTYPE { # define YYLTYPE_IS_DECLARED 1 # define YYLTYPE_IS_TRIVIAL 1 +extern void _mesa_glsl_error(YYLTYPE *locp, _mesa_glsl_parse_state *state, + const char *fmt, ...); + + struct _mesa_glsl_parse_state { _mesa_glsl_parse_state(struct gl_context *_ctx, GLenum target, void *mem_ctx); @@ -125,6 +129,22 @@ struct _mesa_glsl_parse_state { return check_version(130, 300, locp, "bit-wise operations are forbidden"); } + bool check_explicit_attrib_location_allowed(YYLTYPE *locp, + const ir_variable *var) + { + if (!this->has_explicit_attrib_location()) { + const char *const requirement = this->es_shader + ? "GLSL ES 300" + : "GL_ARB_explicit_attrib_location extension or GLSL 330"; + + _mesa_glsl_error(locp, this, "%s explicit location requires %s", + mode_string(var), requirement); + return false; + } + + return true; + } + bool has_explicit_attrib_location() const { return ARB_explicit_attrib_location_enable || is_version(330, 300); @@ -233,6 +253,13 @@ struct _mesa_glsl_parse_state { unsigned MaxGeometryOutputVertices; unsigned MaxGeometryTotalOutputComponents; unsigned MaxGeometryUniformComponents; + + /* ARB_shader_atomic_counters */ + unsigned MaxVertexAtomicCounters; + unsigned MaxGeometryAtomicCounters; + unsigned MaxFragmentAtomicCounters; + unsigned MaxCombinedAtomicCounters; + unsigned MaxAtomicBufferBindings; } Const; /** @@ -329,6 +356,8 @@ struct _mesa_glsl_parse_state { bool ARB_shading_language_420pack_warn; bool EXT_shader_integer_mix_enable; bool EXT_shader_integer_mix_warn; + bool ARB_shader_atomic_counters_enable; + bool ARB_shader_atomic_counters_warn; /*@}*/ /** Extensions supported by the OpenGL implementation. */ @@ -367,9 +396,6 @@ do { \ (Current).source = 0; \ } while (0) -extern void _mesa_glsl_error(YYLTYPE *locp, _mesa_glsl_parse_state *state, - const char *fmt, ...); - /** * Emit a warning to the shader log * diff --git a/mesalib/src/glsl/glsl_types.cpp b/mesalib/src/glsl/glsl_types.cpp index bc8d87f5f..f74013096 100644 --- a/mesalib/src/glsl/glsl_types.cpp +++ b/mesalib/src/glsl/glsl_types.cpp @@ -168,6 +168,24 @@ glsl_type::contains_integer() const } } +bool +glsl_type::contains_opaque() const { + switch (base_type) { + case GLSL_TYPE_SAMPLER: + case GLSL_TYPE_ATOMIC_UINT: + return true; + case GLSL_TYPE_ARRAY: + return element_type()->contains_opaque(); + case GLSL_TYPE_STRUCT: + for (unsigned int i = 0; i < length; i++) { + if (fields.structure[i].type->contains_opaque()) + return true; + } + return false; + default: + return false; + } +} gl_texture_index glsl_type::sampler_index() const @@ -601,6 +619,7 @@ glsl_type::component_slots() const return this->length * this->fields.array->component_slots(); case GLSL_TYPE_SAMPLER: + case GLSL_TYPE_ATOMIC_UINT: case GLSL_TYPE_VOID: case GLSL_TYPE_ERROR: break; @@ -889,6 +908,7 @@ glsl_type::count_attribute_slots() const return this->length * this->fields.array->count_attribute_slots(); case GLSL_TYPE_SAMPLER: + case GLSL_TYPE_ATOMIC_UINT: case GLSL_TYPE_VOID: case GLSL_TYPE_ERROR: break; diff --git a/mesalib/src/glsl/glsl_types.h b/mesalib/src/glsl/glsl_types.h index 4b5b6efb3..fdb1f3a6e 100644 --- a/mesalib/src/glsl/glsl_types.h +++ b/mesalib/src/glsl/glsl_types.h @@ -53,6 +53,7 @@ enum glsl_base_type { GLSL_TYPE_FLOAT, GLSL_TYPE_BOOL, GLSL_TYPE_SAMPLER, + GLSL_TYPE_ATOMIC_UINT, GLSL_TYPE_STRUCT, GLSL_TYPE_INTERFACE, GLSL_TYPE_ARRAY, @@ -441,6 +442,32 @@ struct glsl_type { } /** + * Return the amount of atomic counter storage required for a type. + */ + unsigned atomic_size() const + { + if (base_type == GLSL_TYPE_ATOMIC_UINT) + return ATOMIC_COUNTER_SIZE; + else if (is_array()) + return length * element_type()->atomic_size(); + else + return 0; + } + + /** + * Return whether a type contains any atomic counters. + */ + bool contains_atomic() const + { + return atomic_size(); + } + + /** + * Return whether a type contains any opaque types. + */ + bool contains_opaque() const; + + /** * Query the full type of a matrix row * * \return @@ -468,7 +495,6 @@ struct glsl_type { : error_type; } - /** * Get the type of a structure field * @@ -478,13 +504,11 @@ struct glsl_type { */ const glsl_type *field_type(const char *name) const; - /** * Get the location of a filed within a record type */ int field_index(const char *name) const; - /** * Query the number of elements in an array type * @@ -499,6 +523,14 @@ struct glsl_type { } /** + * Query whether the array size for all dimensions has been declared. + */ + bool is_unsized_array() const + { + return is_array() && length == 0; + } + + /** * Return the number of coordinate components needed for this sampler type. * * This is based purely on the sampler's dimensionality. For example, this diff --git a/mesalib/src/glsl/hir_field_selection.cpp b/mesalib/src/glsl/hir_field_selection.cpp index 08be74365..1e92c89ae 100644 --- a/mesalib/src/glsl/hir_field_selection.cpp +++ b/mesalib/src/glsl/hir_field_selection.cpp @@ -72,7 +72,7 @@ _mesa_ast_field_selection_to_hir(const ast_expression *expr, _mesa_glsl_error(&loc, state, "length method takes no arguments"); if (op->type->is_array()) { - if (op->type->array_size() == 0) + if (op->type->is_unsized_array()) _mesa_glsl_error(&loc, state, "length called on unsized array"); result = new(ctx) ir_constant(op->type->array_size()); diff --git a/mesalib/src/glsl/ir.cpp b/mesalib/src/glsl/ir.cpp index c682e3ed5..1b4973612 100644 --- a/mesalib/src/glsl/ir.cpp +++ b/mesalib/src/glsl/ir.cpp @@ -1586,7 +1586,7 @@ ir_variable::ir_variable(const struct glsl_type *type, const char *name, ir_variable_mode mode) : max_array_access(0), max_ifc_array_access(NULL), read_only(false), centroid(false), invariant(false), - mode(mode), interpolation(INTERP_QUALIFIER_NONE) + mode(mode), interpolation(INTERP_QUALIFIER_NONE), atomic() { this->ir_type = ir_type_variable; this->type = type; @@ -1647,8 +1647,8 @@ ir_variable::determine_interpolation_mode(bool flat_shade) ir_function_signature::ir_function_signature(const glsl_type *return_type, builtin_available_predicate b) - : return_type(return_type), is_defined(false), builtin_avail(b), - _function(NULL) + : return_type(return_type), is_defined(false), is_intrinsic(false), + builtin_avail(b), _function(NULL) { this->ir_type = ir_type_function_signature; this->origin = NULL; @@ -1891,3 +1891,46 @@ vertices_per_prim(GLenum prim) return 3; } } + +/** + * Generate a string describing the mode of a variable + */ +const char * +mode_string(const ir_variable *var) +{ + switch (var->mode) { + case ir_var_auto: + return (var->read_only) ? "global constant" : "global variable"; + + case ir_var_uniform: + return "uniform"; + + case ir_var_shader_in: + return "shader input"; + + case ir_var_shader_out: + return "shader output"; + + case ir_var_function_in: + case ir_var_const_in: + return "function input"; + + case ir_var_function_out: + return "function output"; + + case ir_var_function_inout: + return "function inout"; + + case ir_var_system_value: + return "shader input"; + + case ir_var_temporary: + return "compiler temporary"; + + case ir_var_mode_count: + break; + } + + assert(!"Should not get here."); + return "invalid variable"; +} diff --git a/mesalib/src/glsl/ir.h b/mesalib/src/glsl/ir.h index 8d5bec9c1..5b30fe59b 100644 --- a/mesalib/src/glsl/ir.h +++ b/mesalib/src/glsl/ir.h @@ -639,6 +639,14 @@ public: int binding; /** + * Location an atomic counter is stored at. + */ + struct { + unsigned buffer_index; + unsigned offset; + } atomic; + + /** * Built-in state that backs this uniform * * Once set at variable creation, \c state_slots must remain invariant. @@ -779,6 +787,12 @@ public: /** Whether or not this function signature is a built-in. */ bool is_builtin() const; + /** + * Whether or not this function is an intrinsic to be implemented + * by the driver. + */ + bool is_intrinsic; + /** Whether or not a built-in is available for this shader. */ bool is_builtin_available(const _mesa_glsl_parse_state *state) const; @@ -2292,6 +2306,9 @@ extern char * prototype_string(const glsl_type *return_type, const char *name, exec_list *parameters); +const char * +mode_string(const ir_variable *var); + extern "C" { #endif /* __cplusplus */ diff --git a/mesalib/src/glsl/ir_clone.cpp b/mesalib/src/glsl/ir_clone.cpp index 105f9063a..b0f173a62 100644 --- a/mesalib/src/glsl/ir_clone.cpp +++ b/mesalib/src/glsl/ir_clone.cpp @@ -57,6 +57,8 @@ ir_variable::clone(void *mem_ctx, struct hash_table *ht) const var->location = this->location; var->index = this->index; var->binding = this->binding; + var->atomic.buffer_index = this->atomic.buffer_index; + var->atomic.offset = this->atomic.offset; var->warn_extension = this->warn_extension; var->origin_upper_left = this->origin_upper_left; var->pixel_center_integer = this->pixel_center_integer; @@ -395,6 +397,7 @@ ir_constant::clone(void *mem_ctx, struct hash_table *ht) const } case GLSL_TYPE_SAMPLER: + case GLSL_TYPE_ATOMIC_UINT: case GLSL_TYPE_VOID: case GLSL_TYPE_ERROR: case GLSL_TYPE_INTERFACE: diff --git a/mesalib/src/glsl/ir_uniform.h b/mesalib/src/glsl/ir_uniform.h index 8198c4819..13faab7c0 100644 --- a/mesalib/src/glsl/ir_uniform.h +++ b/mesalib/src/glsl/ir_uniform.h @@ -166,6 +166,13 @@ struct gl_uniform_storage { bool row_major; /** @} */ + + /** + * Index within gl_shader_program::AtomicBuffers[] of the atomic + * counter buffer this uniform is stored in, or -1 if this is not + * an atomic counter. + */ + int atomic_buffer_index; }; #ifdef __cplusplus diff --git a/mesalib/src/glsl/link_functions.cpp b/mesalib/src/glsl/link_functions.cpp index fd8009998..68aa62032 100644 --- a/mesalib/src/glsl/link_functions.cpp +++ b/mesalib/src/glsl/link_functions.cpp @@ -155,14 +155,17 @@ public: linked_sig->replace_parameters(&formal_parameters); - foreach_list_const(node, &sig->body) { - const ir_instruction *const original = (ir_instruction *) node; + if (sig->is_defined) { + foreach_list_const(node, &sig->body) { + const ir_instruction *const original = (ir_instruction *) node; - ir_instruction *copy = original->clone(linked, ht); - linked_sig->body.push_tail(copy); + ir_instruction *copy = original->clone(linked, ht); + linked_sig->body.push_tail(copy); + } + + linked_sig->is_defined = true; } - linked_sig->is_defined = true; hash_table_dtor(ht); /* Patch references inside the function to things outside the function @@ -307,7 +310,8 @@ find_matching_signature(const char *name, const exec_list *actual_parameters, ir_function_signature *sig = f->matching_signature(NULL, actual_parameters); - if ((sig == NULL) || !sig->is_defined) + if ((sig == NULL) || + (!sig->is_defined && !sig->is_intrinsic)) continue; /* If this function expects to bind to a built-in function and the diff --git a/mesalib/src/glsl/link_uniform_initializers.cpp b/mesalib/src/glsl/link_uniform_initializers.cpp index 3f6671047..786aaf0b4 100644 --- a/mesalib/src/glsl/link_uniform_initializers.cpp +++ b/mesalib/src/glsl/link_uniform_initializers.cpp @@ -69,6 +69,7 @@ copy_constant_to_storage(union gl_constant_value *storage, break; case GLSL_TYPE_ARRAY: case GLSL_TYPE_STRUCT: + case GLSL_TYPE_ATOMIC_UINT: case GLSL_TYPE_INTERFACE: case GLSL_TYPE_VOID: case GLSL_TYPE_ERROR: diff --git a/mesalib/src/glsl/link_uniforms.cpp b/mesalib/src/glsl/link_uniforms.cpp index 51ca593ff..95e75d73d 100644 --- a/mesalib/src/glsl/link_uniforms.cpp +++ b/mesalib/src/glsl/link_uniforms.cpp @@ -513,6 +513,7 @@ private: this->uniforms[id].num_driver_storage = 0; this->uniforms[id].driver_storage = NULL; this->uniforms[id].storage = this->values; + this->uniforms[id].atomic_buffer_index = -1; if (this->ubo_block_index != -1) { this->uniforms[id].block_index = this->ubo_block_index; diff --git a/mesalib/src/glsl/linker.cpp b/mesalib/src/glsl/linker.cpp index d8f655c39..49bb142a8 100644 --- a/mesalib/src/glsl/linker.cpp +++ b/mesalib/src/glsl/linker.cpp @@ -558,29 +558,6 @@ validate_geometry_shader_executable(struct gl_shader_program *prog, /** - * Generate a string describing the mode of a variable - */ -static const char * -mode_string(const ir_variable *var) -{ - switch (var->mode) { - case ir_var_auto: - return (var->read_only) ? "global constant" : "global variable"; - - case ir_var_uniform: return "uniform"; - case ir_var_shader_in: return "shader input"; - case ir_var_shader_out: return "shader output"; - - case ir_var_const_in: - case ir_var_temporary: - default: - assert(!"Should not get here."); - return "invalid variable"; - } -} - - -/** * Perform validation of global variables used across multiple shaders */ void @@ -1108,7 +1085,7 @@ private: */ static void fixup_type(const glsl_type **type, unsigned max_array_access) { - if ((*type)->is_array() && (*type)->length == 0) { + if ((*type)->is_unsized_array()) { *type = glsl_type::get_array_instance((*type)->fields.array, max_array_access + 1); assert(*type != NULL); @@ -1123,7 +1100,7 @@ private: { for (unsigned i = 0; i < type->length; i++) { const glsl_type *elem_type = type->fields.structure[i].type; - if (elem_type->is_array() && elem_type->length == 0) + if (elem_type->is_unsized_array()) return true; } return false; diff --git a/mesalib/src/glsl/opt_algebraic.cpp b/mesalib/src/glsl/opt_algebraic.cpp index 37b2f02c6..a07e153ae 100644 --- a/mesalib/src/glsl/opt_algebraic.cpp +++ b/mesalib/src/glsl/opt_algebraic.cpp @@ -32,8 +32,11 @@ #include "ir_visitor.h" #include "ir_rvalue_visitor.h" #include "ir_optimization.h" +#include "ir_builder.h" #include "glsl_types.h" +using namespace ir_builder; + namespace { /** @@ -194,7 +197,6 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir) { ir_constant *op_const[4] = {NULL, NULL, NULL, NULL}; ir_expression *op_expr[4] = {NULL, NULL, NULL, NULL}; - ir_expression *temp; unsigned int i; assert(ir->get_num_operands() <= 4); @@ -217,12 +219,7 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir) switch (op_expr[0]->operation) { case ir_unop_abs: case ir_unop_neg: - this->progress = true; - temp = new(mem_ctx) ir_expression(ir_unop_abs, - ir->type, - op_expr[0]->operands[0], - NULL); - return swizzle_if_required(ir, temp); + return abs(op_expr[0]->operands[0]); default: break; } @@ -233,8 +230,7 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir) break; if (op_expr[0]->operation == ir_unop_neg) { - this->progress = true; - return swizzle_if_required(ir, op_expr[0]->operands[0]); + return op_expr[0]->operands[0]; } break; @@ -261,7 +257,6 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir) } if (new_op != ir_unop_logic_not) { - this->progress = true; return new(mem_ctx) ir_expression(new_op, ir->type, op_expr[0]->operands[0], @@ -272,14 +267,10 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir) } case ir_binop_add: - if (is_vec_zero(op_const[0])) { - this->progress = true; - return swizzle_if_required(ir, ir->operands[1]); - } - if (is_vec_zero(op_const[1])) { - this->progress = true; - return swizzle_if_required(ir, ir->operands[0]); - } + if (is_vec_zero(op_const[0])) + return ir->operands[1]; + if (is_vec_zero(op_const[1])) + return ir->operands[0]; /* Reassociate addition of constants so that we can do constant * folding. @@ -291,50 +282,25 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir) break; case ir_binop_sub: - if (is_vec_zero(op_const[0])) { - this->progress = true; - temp = new(mem_ctx) ir_expression(ir_unop_neg, - ir->operands[1]->type, - ir->operands[1], - NULL); - return swizzle_if_required(ir, temp); - } - if (is_vec_zero(op_const[1])) { - this->progress = true; - return swizzle_if_required(ir, ir->operands[0]); - } + if (is_vec_zero(op_const[0])) + return neg(ir->operands[1]); + if (is_vec_zero(op_const[1])) + return ir->operands[0]; break; case ir_binop_mul: - if (is_vec_one(op_const[0])) { - this->progress = true; - return swizzle_if_required(ir, ir->operands[1]); - } - if (is_vec_one(op_const[1])) { - this->progress = true; - return swizzle_if_required(ir, ir->operands[0]); - } + if (is_vec_one(op_const[0])) + return ir->operands[1]; + if (is_vec_one(op_const[1])) + return ir->operands[0]; - if (is_vec_zero(op_const[0]) || is_vec_zero(op_const[1])) { - this->progress = true; + if (is_vec_zero(op_const[0]) || is_vec_zero(op_const[1])) return ir_constant::zero(ir, ir->type); - } - if (is_vec_negative_one(op_const[0])) { - this->progress = true; - temp = new(mem_ctx) ir_expression(ir_unop_neg, - ir->operands[1]->type, - ir->operands[1], - NULL); - return swizzle_if_required(ir, temp); - } - if (is_vec_negative_one(op_const[1])) { - this->progress = true; - temp = new(mem_ctx) ir_expression(ir_unop_neg, - ir->operands[0]->type, - ir->operands[0], - NULL); - return swizzle_if_required(ir, temp); - } + + if (is_vec_negative_one(op_const[0])) + return neg(ir->operands[1]); + if (is_vec_negative_one(op_const[1])) + return neg(ir->operands[0]); /* Reassociate multiplication of constants so that we can do @@ -349,26 +315,20 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir) case ir_binop_div: if (is_vec_one(op_const[0]) && ir->type->base_type == GLSL_TYPE_FLOAT) { - this->progress = true; - temp = new(mem_ctx) ir_expression(ir_unop_rcp, + return new(mem_ctx) ir_expression(ir_unop_rcp, ir->operands[1]->type, ir->operands[1], NULL); - return swizzle_if_required(ir, temp); - } - if (is_vec_one(op_const[1])) { - this->progress = true; - return swizzle_if_required(ir, ir->operands[0]); } + if (is_vec_one(op_const[1])) + return ir->operands[0]; break; case ir_binop_dot: - if (is_vec_zero(op_const[0]) || is_vec_zero(op_const[1])) { - this->progress = true; + if (is_vec_zero(op_const[0]) || is_vec_zero(op_const[1])) return ir_constant::zero(mem_ctx, ir->type); - } + if (is_vec_basis(op_const[0])) { - this->progress = true; unsigned component = 0; for (unsigned c = 0; c < op_const[0]->type->vector_elements; c++) { if (op_const[0]->value.f[c] == 1.0) @@ -377,7 +337,6 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir) return new(mem_ctx) ir_swizzle(ir->operands[1], component, 0, 0, 0, 1); } if (is_vec_basis(op_const[1])) { - this->progress = true; unsigned component = 0; for (unsigned c = 0; c < op_const[1]->type->vector_elements; c++) { if (op_const[1]->value.f[c] == 1.0) @@ -387,46 +346,52 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir) } break; + case ir_binop_rshift: + case ir_binop_lshift: + /* 0 >> x == 0 */ + if (is_vec_zero(op_const[0])) + return ir->operands[0]; + /* x >> 0 == x */ + if (is_vec_zero(op_const[1])) + return ir->operands[0]; + break; + case ir_binop_logic_and: /* FINISHME: Also simplify (a && a) to (a). */ if (is_vec_one(op_const[0])) { - this->progress = true; return ir->operands[1]; } else if (is_vec_one(op_const[1])) { - this->progress = true; return ir->operands[0]; } else if (is_vec_zero(op_const[0]) || is_vec_zero(op_const[1])) { - this->progress = true; return ir_constant::zero(mem_ctx, ir->type); + } else if (op_expr[0] && op_expr[0]->operation == ir_unop_logic_not && + op_expr[1] && op_expr[1]->operation == ir_unop_logic_not) { + /* De Morgan's Law: + * (not A) and (not B) === not (A or B) + */ + return logic_not(logic_or(op_expr[0]->operands[0], + op_expr[1]->operands[0])); } break; case ir_binop_logic_xor: /* FINISHME: Also simplify (a ^^ a) to (false). */ if (is_vec_zero(op_const[0])) { - this->progress = true; return ir->operands[1]; } else if (is_vec_zero(op_const[1])) { - this->progress = true; return ir->operands[0]; } else if (is_vec_one(op_const[0])) { - this->progress = true; - return new(mem_ctx) ir_expression(ir_unop_logic_not, ir->type, - ir->operands[1], NULL); + return logic_not(ir->operands[1]); } else if (is_vec_one(op_const[1])) { - this->progress = true; - return new(mem_ctx) ir_expression(ir_unop_logic_not, ir->type, - ir->operands[0], NULL); + return logic_not(ir->operands[0]); } break; case ir_binop_logic_or: /* FINISHME: Also simplify (a || a) to (a). */ if (is_vec_zero(op_const[0])) { - this->progress = true; return ir->operands[1]; } else if (is_vec_zero(op_const[1])) { - this->progress = true; return ir->operands[0]; } else if (is_vec_one(op_const[0]) || is_vec_one(op_const[1])) { ir_constant_data data; @@ -434,16 +399,20 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir) for (unsigned i = 0; i < 16; i++) data.b[i] = true; - this->progress = true; return new(mem_ctx) ir_constant(ir->type, &data); + } else if (op_expr[0] && op_expr[0]->operation == ir_unop_logic_not && + op_expr[1] && op_expr[1]->operation == ir_unop_logic_not) { + /* De Morgan's Law: + * (not A) or (not B) === not (A and B) + */ + return logic_not(logic_and(op_expr[0]->operands[0], + op_expr[1]->operands[0])); } break; case ir_unop_rcp: - if (op_expr[0] && op_expr[0]->operation == ir_unop_rcp) { - this->progress = true; + if (op_expr[0] && op_expr[0]->operation == ir_unop_rcp) return op_expr[0]->operands[0]; - } /* FINISHME: We should do rcp(rsq(x)) -> sqrt(x) for some * backends, except that some backends will have done sqrt -> @@ -452,12 +421,7 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir) /* As far as we know, all backends are OK with rsq. */ if (op_expr[0] && op_expr[0]->operation == ir_unop_sqrt) { - this->progress = true; - temp = new(mem_ctx) ir_expression(ir_unop_rsq, - op_expr[0]->operands[0]->type, - op_expr[0]->operands[0], - NULL); - return swizzle_if_required(ir, temp); + return rsq(op_expr[0]->operands[0]); } break; @@ -465,11 +429,9 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir) case ir_triop_lrp: /* Operands are (x, y, a). */ if (is_vec_zero(op_const[2])) { - this->progress = true; - return swizzle_if_required(ir, ir->operands[0]); + return ir->operands[0]; } else if (is_vec_one(op_const[2])) { - this->progress = true; - return swizzle_if_required(ir, ir->operands[1]); + return ir->operands[1]; } break; @@ -490,7 +452,17 @@ ir_algebraic_visitor::handle_rvalue(ir_rvalue **rvalue) if (!expr || expr->operation == ir_quadop_vector) return; - *rvalue = handle_expression(expr); + ir_rvalue *new_rvalue = handle_expression(expr); + if (new_rvalue == *rvalue) + return; + + /* If the expr used to be some vec OP scalar returning a vector, and the + * optimization gave us back a scalar, we still need to turn it into a + * vector. + */ + *rvalue = swizzle_if_required(expr, new_rvalue); + + this->progress = true; } bool diff --git a/mesalib/src/glsl/opt_array_splitting.cpp b/mesalib/src/glsl/opt_array_splitting.cpp index 34ac836ae..c7c5f6712 100644 --- a/mesalib/src/glsl/opt_array_splitting.cpp +++ b/mesalib/src/glsl/opt_array_splitting.cpp @@ -132,7 +132,7 @@ ir_array_reference_visitor::get_variable_entry(ir_variable *var) /* If the array hasn't been sized yet, we can't split it. After * linking, this should be resolved. */ - if (var->type->is_array() && var->type->length == 0) + if (var->type->is_unsized_array()) return NULL; foreach_iter(exec_list_iterator, iter, this->variable_list) { diff --git a/mesalib/src/glsl/opt_dead_builtin_varyings.cpp b/mesalib/src/glsl/opt_dead_builtin_varyings.cpp index 7e8cd4372..b336bc0a8 100644 --- a/mesalib/src/glsl/opt_dead_builtin_varyings.cpp +++ b/mesalib/src/glsl/opt_dead_builtin_varyings.cpp @@ -42,9 +42,11 @@ * If any texture coordinate slots can be eliminated, the gl_TexCoord array is * broken down into separate vec4 variables with locations equal to * VARYING_SLOT_TEX0 + i. + * + * The same is done for the gl_FragData fragment shader output. */ -#include "main/imports.h" /* for snprintf */ +#include "main/core.h" /* for snprintf and ARRAY_SIZE */ #include "ir.h" #include "ir_rvalue_visitor.h" #include "ir_optimization.h" @@ -60,10 +62,14 @@ namespace { class varying_info_visitor : public ir_hierarchical_visitor { public: /* "mode" can be either ir_var_shader_in or ir_var_shader_out */ - varying_info_visitor(ir_variable_mode mode) + varying_info_visitor(ir_variable_mode mode, bool find_frag_outputs = false) : lower_texcoord_array(true), texcoord_array(NULL), texcoord_usage(0), + find_frag_outputs(find_frag_outputs), + lower_fragdata_array(true), + fragdata_array(NULL), + fragdata_usage(0), color_usage(0), tfeedback_color_usage(0), fog(NULL), @@ -79,8 +85,27 @@ public: { ir_variable *var = ir->variable_referenced(); - if (var && var->mode == this->mode && - var->location == VARYING_SLOT_TEX0) { + if (!var || var->mode != this->mode) + return visit_continue; + + if (this->find_frag_outputs && var->location == FRAG_RESULT_DATA0) { + this->fragdata_array = var; + + ir_constant *index = ir->array_index->as_constant(); + if (index == NULL) { + /* This is variable indexing. */ + this->fragdata_usage |= (1 << var->type->array_size()) - 1; + this->lower_fragdata_array = false; + } + else { + this->fragdata_usage |= 1 << index->get_uint_component(0); + } + + /* Don't visit the leaves of ir_dereference_array. */ + return visit_continue_with_parent; + } + + if (!this->find_frag_outputs && var->location == VARYING_SLOT_TEX0) { this->texcoord_array = var; ir_constant *index = ir->array_index->as_constant(); @@ -105,8 +130,17 @@ public: { ir_variable *var = ir->variable_referenced(); - if (var->mode == this->mode && var->type->is_array() && - var->location == VARYING_SLOT_TEX0) { + if (var->mode != this->mode || !var->type->is_array()) + return visit_continue; + + if (this->find_frag_outputs && var->location == FRAG_RESULT_DATA0) { + /* This is a whole array dereference. */ + this->fragdata_usage |= (1 << var->type->array_size()) - 1; + this->lower_fragdata_array = false; + return visit_continue; + } + + if (!this->find_frag_outputs && var->location == VARYING_SLOT_TEX0) { /* This is a whole array dereference like "gl_TexCoord = x;", * there's probably no point in lowering that. */ @@ -121,6 +155,10 @@ public: if (var->mode != this->mode) return visit_continue; + /* Nothing to do here for fragment outputs. */ + if (this->find_frag_outputs) + return visit_continue; + /* Handle colors and fog. */ switch (var->location) { case VARYING_SLOT_COL0: @@ -185,12 +223,20 @@ public: if (!this->texcoord_array) { this->lower_texcoord_array = false; } + if (!this->fragdata_array) { + this->lower_fragdata_array = false; + } } bool lower_texcoord_array; ir_variable *texcoord_array; unsigned texcoord_usage; /* bitmask */ + bool find_frag_outputs; /* false if it's looking for varyings */ + bool lower_fragdata_array; + ir_variable *fragdata_array; + unsigned fragdata_usage; /* bitmask */ + ir_variable *color[2]; ir_variable *backcolor[2]; unsigned color_usage; /* bitmask */ @@ -222,6 +268,7 @@ public: { void *const ctx = ir; + memset(this->new_fragdata, 0, sizeof(this->new_fragdata)); memset(this->new_texcoord, 0, sizeof(this->new_texcoord)); memset(this->new_color, 0, sizeof(this->new_color)); memset(this->new_backcolor, 0, sizeof(this->new_backcolor)); @@ -236,31 +283,16 @@ public: * occurences of gl_TexCoord will be replaced with. */ if (info->lower_texcoord_array) { - for (int i = MAX_TEXTURE_COORD_UNITS-1; i >= 0; i--) { - if (info->texcoord_usage & (1 << i)) { - char name[32]; - - if (!(external_texcoord_usage & (1 << i))) { - /* This varying is unused in the next stage. Declare - * a temporary instead of an output. */ - snprintf(name, 32, "gl_%s_TexCoord%i_dummy", mode_str, i); - this->new_texcoord[i] = - new (ctx) ir_variable(glsl_type::vec4_type, name, - ir_var_temporary); - } - else { - snprintf(name, 32, "gl_%s_TexCoord%i", mode_str, i); - this->new_texcoord[i] = - new(ctx) ir_variable(glsl_type::vec4_type, name, - info->mode); - this->new_texcoord[i]->location = VARYING_SLOT_TEX0 + i; - this->new_texcoord[i]->explicit_location = true; - this->new_texcoord[i]->explicit_index = 0; - } - - ir->head->insert_before(new_texcoord[i]); - } - } + prepare_array(ir, this->new_texcoord, ARRAY_SIZE(this->new_texcoord), + VARYING_SLOT_TEX0, "TexCoord", mode_str, + info->texcoord_usage, external_texcoord_usage); + } + + /* Handle gl_FragData in the same way like gl_TexCoord. */ + if (info->lower_fragdata_array) { + prepare_array(ir, this->new_fragdata, ARRAY_SIZE(this->new_fragdata), + FRAG_RESULT_DATA0, "FragData", mode_str, + info->fragdata_usage, (1 << MAX_DRAW_BUFFERS) - 1); } /* Create dummy variables which will replace set-but-unused color and @@ -301,6 +333,41 @@ public: visit_list_elements(this, ir); } + void prepare_array(exec_list *ir, + struct ir_variable **new_var, + int max_elements, unsigned start_location, + const char *var_name, const char *mode_str, + unsigned usage, unsigned external_usage) + { + void *const ctx = ir; + + for (int i = max_elements-1; i >= 0; i--) { + if (usage & (1 << i)) { + char name[32]; + + if (!(external_usage & (1 << i))) { + /* This varying is unused in the next stage. Declare + * a temporary instead of an output. */ + snprintf(name, 32, "gl_%s_%s%i_dummy", mode_str, var_name, i); + new_var[i] = + new (ctx) ir_variable(glsl_type::vec4_type, name, + ir_var_temporary); + } + else { + snprintf(name, 32, "gl_%s_%s%i", mode_str, var_name, i); + new_var[i] = + new(ctx) ir_variable(glsl_type::vec4_type, name, + this->info->mode); + new_var[i]->location = start_location + i; + new_var[i]->explicit_location = true; + new_var[i]->explicit_index = 0; + } + + ir->head->insert_before(new_var[i]); + } + } + } + virtual ir_visitor_status visit(ir_variable *var) { /* Remove the gl_TexCoord array. */ @@ -309,6 +376,12 @@ public: var->remove(); } + /* Remove the gl_FragData array. */ + if (this->info->lower_fragdata_array && + var == this->info->fragdata_array) { + var->remove(); + } + /* Replace set-but-unused color and fog outputs with dummy variables. */ for (int i = 0; i < 2; i++) { if (var == this->info->color[i] && this->new_color[i]) { @@ -350,6 +423,19 @@ public: } } + /* Same for gl_FragData. */ + if (this->info->lower_fragdata_array) { + /* gl_FragData[i] occurence */ + ir_dereference_array *const da = (*rvalue)->as_dereference_array(); + + if (da && da->variable_referenced() == this->info->fragdata_array) { + unsigned i = da->array_index->as_constant()->get_uint_component(0); + + *rvalue = new(ctx) ir_dereference_variable(this->new_fragdata[i]); + return; + } + } + /* Replace set-but-unused color and fog outputs with dummy variables. */ ir_dereference_variable *const dv = (*rvalue)->as_dereference_variable(); if (!dv) @@ -392,6 +478,7 @@ public: private: const varying_info_visitor *info; + ir_variable *new_fragdata[MAX_DRAW_BUFFERS]; ir_variable *new_texcoord[MAX_TEXTURE_COORD_UNITS]; ir_variable *new_color[2]; ir_variable *new_backcolor[2]; @@ -408,6 +495,15 @@ lower_texcoord_array(exec_list *ir, const varying_info_visitor *info) 1 | 2, true); } +static void +lower_fragdata_array(exec_list *ir) +{ + varying_info_visitor info(ir_var_shader_out, true); + info.get(ir, 0, NULL); + + replace_varyings_visitor(ir, &info, 0, 0, 0); +} + void do_dead_builtin_varyings(struct gl_context *ctx, @@ -415,8 +511,13 @@ do_dead_builtin_varyings(struct gl_context *ctx, unsigned num_tfeedback_decls, tfeedback_decl *tfeedback_decls) { - /* This optimization has no effect with the core context and GLES2, because - * the built-in varyings we're eliminating here are not available there. + /* Lower the gl_FragData array to separate variables. */ + if (consumer && consumer->Type == GL_FRAGMENT_SHADER) { + lower_fragdata_array(consumer->ir); + } + + /* Lowering of built-in varyings has no effect with the core context and + * GLES2, because they are not available there. * * EXT_separate_shader_objects doesn't allow this optimization, * because a program object can be bound partially (e.g. only one diff --git a/mesalib/src/glsl/opt_function_inlining.cpp b/mesalib/src/glsl/opt_function_inlining.cpp index 0733d5180..f8033a095 100644 --- a/mesalib/src/glsl/opt_function_inlining.cpp +++ b/mesalib/src/glsl/opt_function_inlining.cpp @@ -35,9 +35,9 @@ #include "program/hash_table.h" static void -do_sampler_replacement(exec_list *instructions, - ir_variable *sampler, - ir_dereference *deref); +do_variable_replacement(exec_list *instructions, + ir_variable *orig, + ir_dereference *repl); namespace { @@ -123,11 +123,11 @@ ir_call::generate_inline(ir_instruction *next_ir) ir_rvalue *param = (ir_rvalue *) param_iter.get(); /* Generate a new variable for the parameter. */ - if (sig_param->type->base_type == GLSL_TYPE_SAMPLER) { - /* For samplers, we want the inlined sampler references - * referencing the passed in sampler variable, since that - * will have the location information, which an assignment of - * a sampler wouldn't. Fix it up below. + if (sig_param->type->contains_opaque()) { + /* For opaque types, we want the inlined variable references + * referencing the passed in variable, since that will have + * the location information, which an assignment of an opaque + * variable wouldn't. Fix it up below. */ parameters[i] = NULL; } else { @@ -169,8 +169,8 @@ ir_call::generate_inline(ir_instruction *next_ir) visit_tree(new_ir, replace_return_with_assignment, this->return_deref); } - /* If any samplers were passed in, replace any deref of the sampler - * with a deref of the sampler argument. + /* If any opaque types were passed in, replace any deref of the + * opaque variable with a deref of the argument. */ param_iter = this->actual_parameters.iterator(); sig_param_iter = this->callee->parameters.iterator(); @@ -178,11 +178,11 @@ ir_call::generate_inline(ir_instruction *next_ir) ir_instruction *const param = (ir_instruction *) param_iter.get(); ir_variable *sig_param = (ir_variable *) sig_param_iter.get(); - if (sig_param->type->base_type == GLSL_TYPE_SAMPLER) { + if (sig_param->type->contains_opaque()) { ir_dereference *deref = param->as_dereference(); assert(deref); - do_sampler_replacement(&new_instructions, sig_param, deref); + do_variable_replacement(&new_instructions, sig_param, deref); } param_iter.next(); sig_param_iter.next(); @@ -268,23 +268,23 @@ ir_function_inlining_visitor::visit_enter(ir_call *ir) /** - * Replaces references to the "sampler" variable with a clone of "deref." + * Replaces references to the "orig" variable with a clone of "repl." * - * From the spec, samplers can appear in the tree as function + * From the spec, opaque types can appear in the tree as function * (non-out) parameters and as the result of array indexing and * structure field selection. In our builtin implementation, they * also appear in the sampler field of an ir_tex instruction. */ -class ir_sampler_replacement_visitor : public ir_hierarchical_visitor { +class ir_variable_replacement_visitor : public ir_hierarchical_visitor { public: - ir_sampler_replacement_visitor(ir_variable *sampler, ir_dereference *deref) + ir_variable_replacement_visitor(ir_variable *orig, ir_dereference *repl) { - this->sampler = sampler; - this->deref = deref; + this->orig = orig; + this->repl = repl; } - virtual ~ir_sampler_replacement_visitor() + virtual ~ir_variable_replacement_visitor() { } @@ -296,21 +296,21 @@ public: void replace_deref(ir_dereference **deref); void replace_rvalue(ir_rvalue **rvalue); - ir_variable *sampler; - ir_dereference *deref; + ir_variable *orig; + ir_dereference *repl; }; void -ir_sampler_replacement_visitor::replace_deref(ir_dereference **deref) +ir_variable_replacement_visitor::replace_deref(ir_dereference **deref) { ir_dereference_variable *deref_var = (*deref)->as_dereference_variable(); - if (deref_var && deref_var->var == this->sampler) { - *deref = this->deref->clone(ralloc_parent(*deref), NULL); + if (deref_var && deref_var->var == this->orig) { + *deref = this->repl->clone(ralloc_parent(*deref), NULL); } } void -ir_sampler_replacement_visitor::replace_rvalue(ir_rvalue **rvalue) +ir_variable_replacement_visitor::replace_rvalue(ir_rvalue **rvalue) { if (!*rvalue) return; @@ -325,7 +325,7 @@ ir_sampler_replacement_visitor::replace_rvalue(ir_rvalue **rvalue) } ir_visitor_status -ir_sampler_replacement_visitor::visit_leave(ir_texture *ir) +ir_variable_replacement_visitor::visit_leave(ir_texture *ir) { replace_deref(&ir->sampler); @@ -333,21 +333,21 @@ ir_sampler_replacement_visitor::visit_leave(ir_texture *ir) } ir_visitor_status -ir_sampler_replacement_visitor::visit_leave(ir_dereference_array *ir) +ir_variable_replacement_visitor::visit_leave(ir_dereference_array *ir) { replace_rvalue(&ir->array); return visit_continue; } ir_visitor_status -ir_sampler_replacement_visitor::visit_leave(ir_dereference_record *ir) +ir_variable_replacement_visitor::visit_leave(ir_dereference_record *ir) { replace_rvalue(&ir->record); return visit_continue; } ir_visitor_status -ir_sampler_replacement_visitor::visit_leave(ir_call *ir) +ir_variable_replacement_visitor::visit_leave(ir_call *ir) { foreach_iter(exec_list_iterator, iter, *ir) { ir_rvalue *param = (ir_rvalue *)iter.get(); @@ -362,11 +362,11 @@ ir_sampler_replacement_visitor::visit_leave(ir_call *ir) } static void -do_sampler_replacement(exec_list *instructions, - ir_variable *sampler, - ir_dereference *deref) +do_variable_replacement(exec_list *instructions, + ir_variable *orig, + ir_dereference *repl) { - ir_sampler_replacement_visitor v(sampler, deref); + ir_variable_replacement_visitor v(orig, repl); visit_list_elements(&v, instructions); } diff --git a/mesalib/src/glsl/ralloc.h b/mesalib/src/glsl/ralloc.h index 31682d515..4581a7a4e 100644 --- a/mesalib/src/glsl/ralloc.h +++ b/mesalib/src/glsl/ralloc.h @@ -415,15 +415,29 @@ bool ralloc_vasprintf_append(char **str, const char *fmt, va_list args); * which is more idiomatic in C++ than calling ralloc. */ #define DECLARE_RALLOC_CXX_OPERATORS(TYPE) \ +private: \ + static void _ralloc_destructor(void *p) \ + { \ + reinterpret_cast<TYPE *>(p)->~TYPE(); \ + } \ +public: \ static void* operator new(size_t size, void *mem_ctx) \ { \ void *p = ralloc_size(mem_ctx, size); \ assert(p != NULL); \ + if (!HAS_TRIVIAL_DESTRUCTOR(TYPE)) \ + ralloc_set_destructor(p, _ralloc_destructor); \ return p; \ } \ \ static void operator delete(void *p) \ { \ + /* The object's destructor is guaranteed to have already been \ + * called by the delete operator at this point -- Make sure it's \ + * not called again. \ + */ \ + if (!HAS_TRIVIAL_DESTRUCTOR(TYPE)) \ + ralloc_set_destructor(p, NULL); \ ralloc_free(p); \ } diff --git a/mesalib/src/mapi/glapi/SConscript b/mesalib/src/mapi/glapi/SConscript index c4ac080aa..152818d22 100644 --- a/mesalib/src/mapi/glapi/SConscript +++ b/mesalib/src/mapi/glapi/SConscript @@ -52,6 +52,7 @@ for s in mapi_sources: if (env['gcc'] or env['clang']) and \ env['platform'] not in ('cygwin', 'darwin', 'windows'): GLAPI = '#src/mapi/glapi/' + sources = [GLAPI + 'gen/gl_and_es_API.xml'] + env.Glob(GLAPI + 'gen/*.xml') if env['machine'] == 'x86': env.Append(CPPDEFINES = [ @@ -63,7 +64,7 @@ if (env['gcc'] or env['clang']) and \ env.CodeGenerate( target = 'glapi_x86.S', script = GLAPI + 'gen/gl_x86_asm.py', - source = GLAPI + 'gen/gl_and_es_API.xml', + source = sources, command = python_cmd + ' $SCRIPT -f $SOURCE > $TARGET' ) elif env['machine'] == 'x86_64': @@ -76,7 +77,7 @@ if (env['gcc'] or env['clang']) and \ env.CodeGenerate( target = 'glapi_x86-64.S', script = GLAPI + 'gen/gl_x86-64_asm.py', - source = GLAPI + 'gen/gl_and_es_API.xml', + source = sources, command = python_cmd + ' $SCRIPT -f $SOURCE > $TARGET' ) elif env['machine'] == 'sparc': @@ -89,7 +90,7 @@ if (env['gcc'] or env['clang']) and \ env.CodeGenerate( target = 'glapi_sparc.S', script = GLAPI + 'gen/gl_SPARC_asm.py', - source = GLAPI + 'gen/gl_and_es_API.xml', + source = sources, command = python_cmd + ' $SCRIPT -f $SOURCE > $TARGET' ) else: diff --git a/mesalib/src/mapi/glapi/gen/ARB_shader_atomic_counters.xml b/mesalib/src/mapi/glapi/gen/ARB_shader_atomic_counters.xml new file mode 100644 index 000000000..f3b74e9c2 --- /dev/null +++ b/mesalib/src/mapi/glapi/gen/ARB_shader_atomic_counters.xml @@ -0,0 +1,47 @@ +<?xml version="1.0"?> +<!DOCTYPE OpenGLAPI SYSTEM "gl_API.dtd"> + +<OpenGLAPI> + +<category name="GL_ARB_shader_atomic_counters" number="114"> + +<enum name="ATOMIC_COUNTER_BUFFER" value="0x92C0"/> +<enum name="ATOMIC_COUNTER_BUFFER_BINDING" value="0x92C1"/> +<enum name="ATOMIC_COUNTER_BUFFER_START" value="0x92C2"/> +<enum name="ATOMIC_COUNTER_BUFFER_SIZE" value="0x92C3"/> +<enum name="ATOMIC_COUNTER_BUFFER_DATA_SIZE" value="0x92C4"/> +<enum name="ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTERS" value="0x92C5"/> +<enum name="ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTER_INDICES" value="0x92C6"/> +<enum name="ATOMIC_COUNTER_BUFFER_REFERENCED_BY_VERTEX_SHADER" value="0x92C7"/> +<enum name="ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_CONTROL_SHADER" value="0x92C8"/> +<enum name="ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_EVALUATION_SHADER" value="0x92C9"/> +<enum name="ATOMIC_COUNTER_BUFFER_REFERENCED_BY_GEOMETRY_SHADER" value="0x92CA"/> +<enum name="ATOMIC_COUNTER_BUFFER_REFERENCED_BY_FRAGMENT_SHADER" value="0x92CB"/> +<enum name="MAX_VERTEX_ATOMIC_COUNTER_BUFFERS" value="0x92CC"/> +<enum name="MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS" value="0x92CD"/> +<enum name="MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS" value="0x92CE"/> +<enum name="MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS" value="0x92CF"/> +<enum name="MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS" value="0x92D0"/> +<enum name="MAX_COMBINED_ATOMIC_COUNTER_BUFFERS" value="0x92D1"/> +<enum name="MAX_VERTEX_ATOMIC_COUNTERS" value="0x92D2"/> +<enum name="MAX_TESS_CONTROL_ATOMIC_COUNTERS" value="0x92D3"/> +<enum name="MAX_TESS_EVALUATION_ATOMIC_COUNTERS" value="0x92D4"/> +<enum name="MAX_GEOMETRY_ATOMIC_COUNTERS" value="0x92D5"/> +<enum name="MAX_FRAGMENT_ATOMIC_COUNTERS" value="0x92D6"/> +<enum name="MAX_COMBINED_ATOMIC_COUNTERS" value="0x92D7"/> +<enum name="MAX_ATOMIC_COUNTER_BUFFER_SIZE" value="0x92D8"/> +<enum name="ACTIVE_ATOMIC_COUNTER_BUFFERS" value="0x92D9"/> +<enum name="UNIFORM_ATOMIC_COUNTER_BUFFER_INDEX" value="0x92DA"/> +<enum name="UNSIGNED_INT_ATOMIC_COUNTER" value="0x92DB"/> +<enum name="MAX_ATOMIC_COUNTER_BUFFER_BINDINGS" value="0x92DC"/> + +<function name="GetActiveAtomicCounterBufferiv" offset="assign"> + <param name="program" type="GLuint" /> + <param name="bufferIndex" type="GLuint" /> + <param name="pname" type="GLenum" /> + <param name="params" type="GLint *" /> +</function> + +</category> + +</OpenGLAPI> diff --git a/mesalib/src/mapi/glapi/gen/Makefile.am b/mesalib/src/mapi/glapi/gen/Makefile.am index d71d5d2a8..390245216 100644 --- a/mesalib/src/mapi/glapi/gen/Makefile.am +++ b/mesalib/src/mapi/glapi/gen/Makefile.am @@ -110,6 +110,7 @@ API_XML = \ ARB_robustness.xml \ ARB_sampler_objects.xml \ ARB_seamless_cube_map.xml \ + ARB_shader_atomic_counters.xml \ ARB_sync.xml \ ARB_texture_buffer_object.xml \ ARB_texture_buffer_range.xml \ @@ -141,6 +142,7 @@ API_XML = \ NV_conditional_render.xml \ NV_primitive_restart.xml \ NV_texture_barrier.xml \ + NV_vdpau_interop.xml \ OES_EGL_image.xml \ GL3x.xml diff --git a/mesalib/src/mapi/glapi/gen/NV_vdpau_interop.xml b/mesalib/src/mapi/glapi/gen/NV_vdpau_interop.xml new file mode 100644 index 000000000..cf5f0eddd --- /dev/null +++ b/mesalib/src/mapi/glapi/gen/NV_vdpau_interop.xml @@ -0,0 +1,69 @@ +<?xml version="1.0"?> +<!DOCTYPE OpenGLAPI SYSTEM "gl_API.dtd"> + +<OpenGLAPI> + +<category name="GL_NV_vdpau_interop" number="396"> + + <function name="VDPAUInitNV" offset="assign"> + <param name="vdpDevice" type="const GLvoid *"/> + <param name="getProcAddress" type="const GLvoid *"/> + </function> + + <function name="VDPAUFiniNV" offset="assign"/> + + <function name="VDPAURegisterVideoSurfaceNV" offset="assign"> + <return type="GLintptr"/> + <param name="vdpSurface" type="const GLvoid *"/> + <param name="target" type="GLenum"/> + <param name="numTextureNames" type="GLsizei"/> + <param name="textureNames" type="const GLuint *"/> + </function> + + <function name="VDPAURegisterOutputSurfaceNV" offset="assign"> + <return type="GLintptr"/> + <param name="vdpSurface" type="const GLvoid *"/> + <param name="target" type="GLenum"/> + <param name="numTextureNames" type="GLsizei"/> + <param name="textureNames" type="const GLuint *"/> + </function> + + <function name="VDPAUIsSurfaceNV" offset="assign"> + <param name="surface" type="GLintptr"/> + </function> + + <function name="VDPAUUnregisterSurfaceNV" offset="assign"> + <param name="surface" type="GLintptr"/> + </function> + + <function name="VDPAUGetSurfaceivNV" offset="assign"> + <param name="surface" type="GLintptr"/> + <param name="pname" type="GLenum"/> + <param name="bufSize" type="GLsizei"/> + <param name="length" type="GLsizei *"/> + <param name="values" type="GLint *"/> + </function> + + <function name="VDPAUSurfaceAccessNV" offset="assign"> + <param name="surface" type="GLintptr"/> + <param name="access" type="GLenum"/> + </function> + + <function name="VDPAUMapSurfacesNV" offset="assign"> + <param name="numSurfaces" type="GLsizei"/> + <param name="surfaces" type="const GLintptr *"/> + </function> + + <function name="VDPAUUnmapSurfacesNV" offset="assign"> + <param name="numSurfaces" type="GLsizei"/> + <param name="surfaces" type="const GLintptr *"/> + </function> + + <enum name="SURFACE_STATE_NV" value="0x86EB"/> + <enum name="SURFACE_REGISTERED_NV" value="0x86FD"/> + <enum name="SURFACE_MAPPED_NV" value="0x8700"/> + <enum name="WRITE_DISCARD_NV" value="0x88BE"/> + +</category> + +</OpenGLAPI> diff --git a/mesalib/src/mapi/glapi/gen/gl_API.xml b/mesalib/src/mapi/glapi/gen/gl_API.xml index 17c322519..eb42258fa 100755 --- a/mesalib/src/mapi/glapi/gen/gl_API.xml +++ b/mesalib/src/mapi/glapi/gen/gl_API.xml @@ -8308,6 +8308,8 @@ <enum name="MIN_MAP_BUFFER_ALIGNMENT" value="0x90BC" /> </category> +<xi:include href="ARB_shader_atomic_counters.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/> + <xi:include href="ARB_texture_storage.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/> <!-- ARB extension #118 --> @@ -13118,4 +13120,6 @@ <xi:include href="EXT_transform_feedback.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/> +<xi:include href="NV_vdpau_interop.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/> + </OpenGLAPI> diff --git a/mesalib/src/mapi/glapi/gen/gl_genexec.py b/mesalib/src/mapi/glapi/gen/gl_genexec.py index a074c2348..3ce190fe3 100644 --- a/mesalib/src/mapi/glapi/gen/gl_genexec.py +++ b/mesalib/src/mapi/glapi/gen/gl_genexec.py @@ -111,6 +111,7 @@ header = """/** #include "main/syncobj.h" #include "main/formatquery.h" #include "main/dispatch.h" +#include "main/vdpau.h" #include "vbo/vbo.h" diff --git a/mesalib/src/mesa/Makefile.sources b/mesalib/src/mesa/Makefile.sources index ff242b4ab..a84f8a788 100644 --- a/mesalib/src/mesa/Makefile.sources +++ b/mesalib/src/mesa/Makefile.sources @@ -108,6 +108,7 @@ MAIN_FILES = \ $(SRCDIR)main/uniforms.c \ $(SRCDIR)main/uniform_query.cpp \ $(SRCDIR)main/varray.c \ + $(SRCDIR)main/vdpau.c \ $(SRCDIR)main/version.c \ $(SRCDIR)main/viewport.c \ $(SRCDIR)main/vtxfmt.c \ @@ -248,7 +249,8 @@ STATETRACKER_FILES = \ $(SRCDIR)state_tracker/st_manager.c \ $(SRCDIR)state_tracker/st_mesa_to_tgsi.c \ $(SRCDIR)state_tracker/st_program.c \ - $(SRCDIR)state_tracker/st_texture.c + $(SRCDIR)state_tracker/st_texture.c \ + $(SRCDIR)state_tracker/st_vdpau.c PROGRAM_FILES = \ $(SRCDIR)program/arbprogparse.c \ diff --git a/mesalib/src/mesa/SConscript b/mesalib/src/mesa/SConscript index 9b7712faf..42134983c 100644 --- a/mesalib/src/mesa/SConscript +++ b/mesalib/src/mesa/SConscript @@ -140,6 +140,7 @@ main_sources = [ 'main/uniform_query.cpp', 'main/uniforms.c', 'main/varray.c', + 'main/vdpau.c', 'main/version.c', 'main/viewport.c', 'main/vtxfmt.c', @@ -287,6 +288,7 @@ statetracker_sources = [ 'state_tracker/st_mesa_to_tgsi.c', 'state_tracker/st_program.c', 'state_tracker/st_texture.c', + 'state_tracker/st_vdpau.c', ] env.Append(YACCFLAGS = '-d -p "_mesa_program_"') diff --git a/mesalib/src/mesa/drivers/dri/common/Makefile.am b/mesalib/src/mesa/drivers/dri/common/Makefile.am index 9f49ff3ae..7f87ed6f5 100644 --- a/mesalib/src/mesa/drivers/dri/common/Makefile.am +++ b/mesalib/src/mesa/drivers/dri/common/Makefile.am @@ -27,6 +27,7 @@ AM_CFLAGS = \ -I$(top_srcdir)/src/mapi \ -I$(top_srcdir)/src/mesa/ \ $(DEFINES) \ + $(EXPAT_CFLAGS) \ $(VISIBILITY_CFLAGS) noinst_LTLIBRARIES = \ diff --git a/mesalib/src/mesa/main/bufferobj.c b/mesalib/src/mesa/main/bufferobj.c index e5814e397..f8312bbb4 100644 --- a/mesalib/src/mesa/main/bufferobj.c +++ b/mesalib/src/mesa/main/bufferobj.c @@ -102,6 +102,11 @@ get_buffer_target(struct gl_context *ctx, GLenum target) return &ctx->UniformBuffer; } break; + case GL_ATOMIC_COUNTER_BUFFER: + if (ctx->Extensions.ARB_shader_atomic_counters) { + return &ctx->AtomicBuffer; + } + break; default: return NULL; } @@ -2119,6 +2124,51 @@ bind_buffer_base_uniform_buffer(struct gl_context *ctx, set_ubo_binding(ctx, index, bufObj, 0, 0, GL_TRUE); } +static void +set_atomic_buffer_binding(struct gl_context *ctx, + unsigned index, + struct gl_buffer_object *bufObj, + GLintptr offset, + GLsizeiptr size, + const char *name) +{ + struct gl_atomic_buffer_binding *binding; + + if (index >= ctx->Const.MaxAtomicBufferBindings) { + _mesa_error(ctx, GL_INVALID_VALUE, "%s(index=%d)", name, index); + return; + } + + if (offset & (ATOMIC_COUNTER_SIZE - 1)) { + _mesa_error(ctx, GL_INVALID_VALUE, + "%s(offset misalgned %d/%d)", name, (int) offset, + ATOMIC_COUNTER_SIZE); + return; + } + + _mesa_reference_buffer_object(ctx, &ctx->AtomicBuffer, bufObj); + + binding = &ctx->AtomicBufferBindings[index]; + if (binding->BufferObject == bufObj && + binding->Offset == offset && + binding->Size == size) { + return; + } + + FLUSH_VERTICES(ctx, 0); + ctx->NewDriverState |= ctx->DriverFlags.NewAtomicBuffer; + + _mesa_reference_buffer_object(ctx, &binding->BufferObject, bufObj); + + if (bufObj == ctx->Shared->NullBufferObj) { + binding->Offset = -1; + binding->Size = -1; + } else { + binding->Offset = offset; + binding->Size = size; + } +} + void GLAPIENTRY _mesa_BindBufferRange(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size) @@ -2156,6 +2206,10 @@ _mesa_BindBufferRange(GLenum target, GLuint index, case GL_UNIFORM_BUFFER: bind_buffer_range_uniform_buffer(ctx, index, bufObj, offset, size); return; + case GL_ATOMIC_COUNTER_BUFFER: + set_atomic_buffer_binding(ctx, index, bufObj, offset, size, + "glBindBufferRange"); + return; default: _mesa_error(ctx, GL_INVALID_ENUM, "glBindBufferRange(target)"); return; @@ -2215,6 +2269,10 @@ _mesa_BindBufferBase(GLenum target, GLuint index, GLuint buffer) case GL_UNIFORM_BUFFER: bind_buffer_base_uniform_buffer(ctx, index, bufObj); return; + case GL_ATOMIC_COUNTER_BUFFER: + set_atomic_buffer_binding(ctx, index, bufObj, 0, 0, + "glBindBufferBase"); + return; default: _mesa_error(ctx, GL_INVALID_ENUM, "glBindBufferBase(target)"); return; diff --git a/mesalib/src/mesa/main/compiler.h b/mesalib/src/mesa/main/compiler.h index 0f27d5a66..d806d5b9d 100644 --- a/mesalib/src/mesa/main/compiler.h +++ b/mesalib/src/mesa/main/compiler.h @@ -444,7 +444,29 @@ do { \ #define Elements(x) (sizeof(x)/sizeof(*(x))) #endif - +#ifdef __cplusplus +/** + * Macro function that evaluates to true if T is a trivially + * destructible type -- that is, if its (non-virtual) destructor + * performs no action and all member variables and base classes are + * trivially destructible themselves. + */ +# if defined(__GNUC__) +# if ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3))) +# define HAS_TRIVIAL_DESTRUCTOR(T) __has_trivial_destructor(T) +# endif +# elif (defined(__clang__) && defined(__has_feature)) +# if __has_feature(has_trivial_destructor) +# define HAS_TRIVIAL_DESTRUCTOR(T) __has_trivial_destructor(T) +# endif +# endif +# ifndef HAS_TRIVIAL_DESTRUCTOR + /* It's always safe (if inefficient) to assume that a + * destructor is non-trivial. + */ +# define HAS_TRIVIAL_DESTRUCTOR(T) (false) +# endif +#endif #ifdef __cplusplus } diff --git a/mesalib/src/mesa/main/config.h b/mesalib/src/mesa/main/config.h index fcb8952ff..ebf99c24b 100644 --- a/mesalib/src/mesa/main/config.h +++ b/mesalib/src/mesa/main/config.h @@ -174,6 +174,11 @@ #define MAX_UNIFORM_BUFFERS 15 /* + 1 default uniform buffer */ /* 6 is for vertex, hull, domain, geometry, fragment, and compute shader. */ #define MAX_COMBINED_UNIFORM_BUFFERS (MAX_UNIFORM_BUFFERS * 6) +#define MAX_ATOMIC_COUNTERS 4096 +/* 6 is for vertex, hull, domain, geometry, fragment, and compute shader. */ +#define MAX_COMBINED_ATOMIC_BUFFERS (MAX_UNIFORM_BUFFERS * 6) +/* Size of an atomic counter in bytes according to ARB_shader_atomic_counters */ +#define ATOMIC_COUNTER_SIZE 4 /*@}*/ /** diff --git a/mesalib/src/mesa/main/context.c b/mesalib/src/mesa/main/context.c index 0d1f71c71..6cdeed19b 100644 --- a/mesalib/src/mesa/main/context.c +++ b/mesalib/src/mesa/main/context.c @@ -537,6 +537,9 @@ init_program_limits(struct gl_context *ctx, GLenum type, prog->MaxCombinedUniformComponents = (prog->MaxUniformComponents + ctx->Const.MaxUniformBlockSize / 4 * prog->MaxUniformBlocks); + + prog->MaxAtomicBuffers = 0; + prog->MaxAtomicCounters = 0; } @@ -669,6 +672,12 @@ _mesa_init_constants(struct gl_context *ctx) ctx->Const.MaxColorTextureSamples = 1; ctx->Const.MaxDepthTextureSamples = 1; ctx->Const.MaxIntegerSamples = 1; + + /* GL_ARB_shader_atomic_counters */ + ctx->Const.MaxAtomicBufferBindings = MAX_COMBINED_ATOMIC_BUFFERS; + ctx->Const.MaxAtomicBufferSize = MAX_ATOMIC_COUNTERS * ATOMIC_COUNTER_SIZE; + ctx->Const.MaxCombinedAtomicBuffers = MAX_COMBINED_ATOMIC_BUFFERS; + ctx->Const.MaxCombinedAtomicCounters = MAX_ATOMIC_COUNTERS; } diff --git a/mesalib/src/mesa/main/dd.h b/mesalib/src/mesa/main/dd.h index 29469ce33..501192199 100644 --- a/mesalib/src/mesa/main/dd.h +++ b/mesalib/src/mesa/main/dd.h @@ -868,6 +868,20 @@ struct dd_function_table { struct gl_framebuffer *fb, GLuint index, GLfloat *outValue); + + /** + * \name NV_vdpau_interop interface + */ + void (*VDPAUMapSurface)(struct gl_context *ctx, GLenum target, + GLenum access, GLboolean output, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage, + const GLvoid *vdpSurface, GLuint index); + void (*VDPAUUnmapSurface)(struct gl_context *ctx, GLenum target, + GLenum access, GLboolean output, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage, + const GLvoid *vdpSurface, GLuint index); }; diff --git a/mesalib/src/mesa/main/extensions.c b/mesalib/src/mesa/main/extensions.c index e8e0a20d8..285ec377c 100644 --- a/mesalib/src/mesa/main/extensions.c +++ b/mesalib/src/mesa/main/extensions.c @@ -120,6 +120,7 @@ static const struct extension extension_table[] = { { "GL_ARB_robustness", o(dummy_true), GL, 2010 }, { "GL_ARB_sampler_objects", o(dummy_true), GL, 2009 }, { "GL_ARB_seamless_cube_map", o(ARB_seamless_cube_map), GL, 2009 }, + { "GL_ARB_shader_atomic_counters", o(ARB_shader_atomic_counters), GL, 2011 }, { "GL_ARB_shader_bit_encoding", o(ARB_shader_bit_encoding), GL, 2010 }, { "GL_ARB_shader_objects", o(dummy_true), GL, 2002 }, { "GL_ARB_shader_stencil_export", o(ARB_shader_stencil_export), GL, 2009 }, @@ -335,6 +336,7 @@ static const struct extension extension_table[] = { { "GL_NV_texture_barrier", o(NV_texture_barrier), GL, 2009 }, { "GL_NV_texture_env_combine4", o(NV_texture_env_combine4), GLL, 1999 }, { "GL_NV_texture_rectangle", o(NV_texture_rectangle), GLL, 2000 }, + { "GL_NV_vdpau_interop", o(NV_vdpau_interop), GL, 2010 }, { "GL_S3_s3tc", o(ANGLE_texture_compression_dxt), GL, 1999 }, { "GL_SGIS_generate_mipmap", o(dummy_true), GLL, 1997 }, { "GL_SGIS_texture_border_clamp", o(ARB_texture_border_clamp), GLL, 1997 }, diff --git a/mesalib/src/mesa/main/get.c b/mesalib/src/mesa/main/get.c index 89b3bf09d..6e72ff5c2 100644 --- a/mesalib/src/mesa/main/get.c +++ b/mesalib/src/mesa/main/get.c @@ -143,6 +143,7 @@ enum value_extra { EXTRA_FLUSH_CURRENT, EXTRA_GLSL_130, EXTRA_EXT_UBO_GS4, + EXTRA_EXT_ATOMICS_GS4, }; #define NO_EXTRA NULL @@ -331,6 +332,11 @@ static const int extra_MESA_texture_array_es3[] = { EXTRA_END }; +static const int extra_ARB_shader_atomic_counters_and_geometry_shader[] = { + EXTRA_EXT_ATOMICS_GS4, + EXTRA_END +}; + EXTRA_EXT(ARB_texture_cube_map); EXTRA_EXT(MESA_texture_array); EXTRA_EXT(NV_fog_distance); @@ -367,6 +373,7 @@ EXTRA_EXT(ARB_texture_cube_map_array); EXTRA_EXT(ARB_texture_buffer_range); EXTRA_EXT(ARB_texture_multisample); EXTRA_EXT(ARB_texture_gather); +EXTRA_EXT(ARB_shader_atomic_counters); static const int extra_ARB_color_buffer_float_or_glcore[] = { @@ -894,6 +901,10 @@ find_custom_value(struct gl_context *ctx, const struct value_desc *d, union valu _mesa_problem(ctx, "driver doesn't implement GetTimestamp"); } break; + /* GL_ARB_shader_atomic_counters */ + case GL_ATOMIC_COUNTER_BUFFER_BINDING: + v->value_int = ctx->AtomicBuffer->Name; + break; } } @@ -999,6 +1010,11 @@ check_extra(struct gl_context *ctx, const char *func, const struct value_desc *d api_found = (ctx->Extensions.ARB_uniform_buffer_object && _mesa_has_geometry_shaders(ctx)); break; + case EXTRA_EXT_ATOMICS_GS4: + api_check = GL_TRUE; + api_found = (ctx->Extensions.ARB_shader_atomic_counters && + _mesa_has_geometry_shaders(ctx)); + break; case EXTRA_END: break; default: /* *e is a offset into the extension struct */ @@ -1692,6 +1708,30 @@ find_value_indexed(const char *func, GLenum pname, GLuint index, union value *v) goto invalid_enum; v->value_int = ctx->Multisample.SampleMaskValue; return TYPE_INT; + + case GL_ATOMIC_COUNTER_BUFFER_BINDING: + if (!ctx->Extensions.ARB_shader_atomic_counters) + goto invalid_enum; + if (index >= ctx->Const.MaxAtomicBufferBindings) + goto invalid_value; + v->value_int = ctx->AtomicBufferBindings[index].BufferObject->Name; + return TYPE_INT; + + case GL_ATOMIC_COUNTER_BUFFER_START: + if (!ctx->Extensions.ARB_shader_atomic_counters) + goto invalid_enum; + if (index >= ctx->Const.MaxAtomicBufferBindings) + goto invalid_value; + v->value_int64 = ctx->AtomicBufferBindings[index].Offset; + return TYPE_INT64; + + case GL_ATOMIC_COUNTER_BUFFER_SIZE: + if (!ctx->Extensions.ARB_shader_atomic_counters) + goto invalid_enum; + if (index >= ctx->Const.MaxAtomicBufferBindings) + goto invalid_value; + v->value_int64 = ctx->AtomicBufferBindings[index].Size; + return TYPE_INT64; } invalid_enum: diff --git a/mesalib/src/mesa/main/get_hash_params.py b/mesalib/src/mesa/main/get_hash_params.py index 9c54af094..9f79f3406 100644 --- a/mesalib/src/mesa/main/get_hash_params.py +++ b/mesalib/src/mesa/main/get_hash_params.py @@ -722,6 +722,18 @@ descriptor=[ [ "MAX_PROGRAM_TEXTURE_GATHER_OFFSET", "CONTEXT_INT(Const.MaxProgramTextureGatherOffset), extra_ARB_texture_gather"], [ "MAX_PROGRAM_TEXTURE_GATHER_COMPONENTS_ARB", "CONTEXT_INT(Const.MaxProgramTextureGatherComponents), extra_ARB_texture_gather"], +# GL_ARB_shader_atomic_counters + [ "ATOMIC_COUNTER_BUFFER_BINDING", "LOC_CUSTOM, TYPE_INT, 0, extra_ARB_shader_atomic_counters" ], + [ "MAX_ATOMIC_COUNTER_BUFFER_BINDINGS", "CONTEXT_INT(Const.MaxAtomicBufferBindings), extra_ARB_shader_atomic_counters" ], + [ "MAX_ATOMIC_COUNTER_BUFFER_SIZE", "CONTEXT_INT(Const.MaxAtomicBufferSize), extra_ARB_shader_atomic_counters" ], + [ "MAX_VERTEX_ATOMIC_COUNTER_BUFFERS", "CONTEXT_INT(Const.VertexProgram.MaxAtomicBuffers), extra_ARB_shader_atomic_counters" ], + [ "MAX_VERTEX_ATOMIC_COUNTERS", "CONTEXT_INT(Const.VertexProgram.MaxAtomicCounters), extra_ARB_shader_atomic_counters" ], + [ "MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS", "CONTEXT_INT(Const.FragmentProgram.MaxAtomicBuffers), extra_ARB_shader_atomic_counters" ], + [ "MAX_FRAGMENT_ATOMIC_COUNTERS", "CONTEXT_INT(Const.FragmentProgram.MaxAtomicCounters), extra_ARB_shader_atomic_counters" ], + [ "MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS", "CONTEXT_INT(Const.GeometryProgram.MaxAtomicBuffers), extra_ARB_shader_atomic_counters_and_geometry_shader" ], + [ "MAX_GEOMETRY_ATOMIC_COUNTERS", "CONTEXT_INT(Const.GeometryProgram.MaxAtomicCounters), extra_ARB_shader_atomic_counters_and_geometry_shader" ], + [ "MAX_COMBINED_ATOMIC_COUNTER_BUFFERS", "CONTEXT_INT(Const.MaxCombinedAtomicBuffers), extra_ARB_shader_atomic_counters" ], + [ "MAX_COMBINED_ATOMIC_COUNTERS", "CONTEXT_INT(Const.MaxCombinedAtomicCounters), extra_ARB_shader_atomic_counters" ], ]}, # Enums restricted to OpenGL Core profile diff --git a/mesalib/src/mesa/main/imports.h b/mesalib/src/mesa/main/imports.h index 53e40b445..d79e2a339 100644 --- a/mesalib/src/mesa/main/imports.h +++ b/mesalib/src/mesa/main/imports.h @@ -141,6 +141,7 @@ static inline float acoshf(float x) { return logf(x + sqrtf(x * x - 1.0f)); } static inline float atanhf(float x) { return (logf(1.0f + x) - logf(1.0f - x)) / 2.0f; } static inline int isblank(int ch) { return ch == ' ' || ch == '\t'; } #define strtoll(p, e, b) _strtoi64(p, e, b) +#define strcasecmp(s1, s2) _stricmp(s1, s2) #endif /*@}*/ diff --git a/mesalib/src/mesa/main/mtypes.h b/mesalib/src/mesa/main/mtypes.h index 97ed1bd6a..a1a5eb4bf 100644 --- a/mesalib/src/mesa/main/mtypes.h +++ b/mesalib/src/mesa/main/mtypes.h @@ -2375,6 +2375,25 @@ struct gl_uniform_block enum gl_uniform_block_packing _Packing; }; +/** + * Structure that represents a reference to an atomic buffer from some + * shader program. + */ +struct gl_active_atomic_buffer +{ + /** Uniform indices of the atomic counters declared within it. */ + GLuint *Uniforms; + GLuint NumUniforms; + + /** Binding point index associated with it. */ + GLuint Binding; + + /** Minimum reasonable size it is expected to have. */ + GLuint MinimumSize; + + /** Shader stages making use of it. */ + GLboolean StageReferences[MESA_SHADER_TYPES]; +}; /** * A GLSL program object. @@ -2523,6 +2542,9 @@ struct gl_shader_program */ struct string_to_uint_map *UniformHash; + struct gl_active_atomic_buffer *AtomicBuffers; + unsigned NumAtomicBuffers; + GLboolean LinkStatus; /**< GL_LINK_STATUS */ GLboolean Validated; GLboolean _Used; /**< Ever used for drawing? */ @@ -2960,6 +2982,9 @@ struct gl_program_constants GLuint MaxUniformBlocks; GLuint MaxCombinedUniformComponents; GLuint MaxTextureImageUnits; + /* GL_ARB_shader_atomic_counters */ + GLuint MaxAtomicBuffers; + GLuint MaxAtomicCounters; }; @@ -3166,6 +3191,12 @@ struct gl_constants GLint MaxColorTextureSamples; GLint MaxDepthTextureSamples; GLint MaxIntegerSamples; + + /** GL_ARB_shader_atomic_counters */ + GLuint MaxAtomicBufferBindings; + GLuint MaxAtomicBufferSize; + GLuint MaxCombinedAtomicBuffers; + GLuint MaxCombinedAtomicCounters; }; @@ -3209,6 +3240,7 @@ struct gl_extensions GLboolean ARB_occlusion_query2; GLboolean ARB_point_sprite; GLboolean ARB_seamless_cube_map; + GLboolean ARB_shader_atomic_counters; GLboolean ARB_shader_bit_encoding; GLboolean ARB_shader_stencil_export; GLboolean ARB_shader_texture_lod; @@ -3302,6 +3334,7 @@ struct gl_extensions GLboolean NV_texture_barrier; GLboolean NV_texture_env_combine4; GLboolean NV_texture_rectangle; + GLboolean NV_vdpau_interop; GLboolean TDFX_texture_compression_FXT1; GLboolean OES_EGL_image; GLboolean OES_draw_texture; @@ -3581,6 +3614,11 @@ struct gl_driver_flags * gl_shader_program::UniformBlocks */ GLbitfield NewUniformBuffer; + + /** + * gl_context::AtomicBufferBindings + */ + GLbitfield NewAtomicBuffer; }; struct gl_uniform_buffer_binding @@ -3598,6 +3636,16 @@ struct gl_uniform_buffer_binding }; /** + * Binding point for an atomic counter buffer object. + */ +struct gl_atomic_buffer_binding +{ + struct gl_buffer_object *BufferObject; + GLintptr Offset; + GLsizeiptr Size; +}; + +/** * Mesa rendering context. * * This is the central context data structure for Mesa. Almost all @@ -3765,6 +3813,18 @@ struct gl_context struct gl_uniform_buffer_binding UniformBufferBindings[MAX_COMBINED_UNIFORM_BUFFERS]; + /** + * Object currently associated with the GL_ATOMIC_COUNTER_BUFFER + * target. + */ + struct gl_buffer_object *AtomicBuffer; + + /** + * Array of atomic counter buffer binding points. + */ + struct gl_atomic_buffer_binding + AtomicBufferBindings[MAX_COMBINED_ATOMIC_BUFFERS]; + /*@}*/ struct gl_meta_state *Meta; /**< for "meta" operations */ @@ -3832,6 +3892,15 @@ struct gl_context struct st_context *st; void *aelt_context; /*@}*/ + + /** + * \name NV_vdpau_interop + */ + /*@{*/ + const void *vdpDevice; + const void *vdpGetProcAddress; + struct set *vdpSurfaces; + /*@}*/ }; diff --git a/mesalib/src/mesa/main/queryobj.c b/mesalib/src/mesa/main/queryobj.c index 414724747..b411eae50 100644 --- a/mesalib/src/mesa/main/queryobj.c +++ b/mesalib/src/mesa/main/queryobj.c @@ -202,13 +202,6 @@ _mesa_GenQueries(GLsizei n, GLuint *ids) return; } - /* No query objects can be active at this time! */ - if (ctx->Query.CurrentOcclusionObject || - ctx->Query.CurrentTimerObject) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glGenQueriesARB"); - return; - } - first = _mesa_HashFindFreeKeyBlock(ctx->Query.QueryObjects, n); if (first) { GLsizei i; @@ -241,18 +234,20 @@ _mesa_DeleteQueries(GLsizei n, const GLuint *ids) return; } - /* No query objects can be active at this time! */ - if (ctx->Query.CurrentOcclusionObject || - ctx->Query.CurrentTimerObject) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glDeleteQueriesARB"); - return; - } - for (i = 0; i < n; i++) { if (ids[i] > 0) { struct gl_query_object *q = _mesa_lookup_query_object(ctx, ids[i]); if (q) { - ASSERT(!q->Active); /* should be caught earlier */ + if (q->Active) { + struct gl_query_object **bindpt; + bindpt = get_query_binding_point(ctx, q->Target); + assert(bindpt); /* Should be non-null for active q. */ + if (bindpt) { + *bindpt = NULL; + } + q->Active = GL_FALSE; + ctx->Driver.EndQuery(ctx, q); + } _mesa_HashRemove(ctx->Query.QueryObjects, ids[i]); ctx->Driver.DeleteQuery(ctx, q); } diff --git a/mesalib/src/mesa/main/shaderapi.c b/mesalib/src/mesa/main/shaderapi.c index f5c04b9f3..7da860ddf 100644 --- a/mesalib/src/mesa/main/shaderapi.c +++ b/mesalib/src/mesa/main/shaderapi.c @@ -648,6 +648,12 @@ get_programiv(struct gl_context *ctx, GLuint program, GLenum pname, GLint *param case GL_PROGRAM_BINARY_LENGTH: *params = 0; return; + case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS: + if (!ctx->Extensions.ARB_shader_atomic_counters) + break; + + *params = shProg->NumAtomicBuffers; + return; default: break; } @@ -926,7 +932,7 @@ _mesa_active_program(struct gl_context *ctx, struct gl_shader_program *shProg, /** */ -static bool +static void use_shader_program(struct gl_context *ctx, GLenum type, struct gl_shader_program *shProg) { @@ -955,7 +961,7 @@ use_shader_program(struct gl_context *ctx, GLenum type, } break; default: - return false; + return; } if (*target != shProg) { @@ -982,10 +988,8 @@ use_shader_program(struct gl_context *ctx, GLenum type, } _mesa_reference_shader_program(ctx, target, shProg); - return true; + return; } - - return false; } /** diff --git a/mesalib/src/mesa/main/texparam.c b/mesalib/src/mesa/main/texparam.c index c9d928f63..d56b7d9d7 100644 --- a/mesalib/src/mesa/main/texparam.c +++ b/mesalib/src/mesa/main/texparam.c @@ -23,7 +23,7 @@ * OTHER DEALINGS IN THE SOFTWARE. */ -/** +/** * \file texparam.c * * glTexParameter-related functions @@ -52,7 +52,7 @@ * Check if a coordinate wrap mode is supported for the texture target. * \return GL_TRUE if legal, GL_FALSE otherwise */ -static GLboolean +static GLboolean validate_texture_wrap_mode(struct gl_context * ctx, GLenum target, GLenum wrap) { const struct gl_extensions * const e = & ctx->Extensions; @@ -91,7 +91,7 @@ validate_texture_wrap_mode(struct gl_context * ctx, GLenum target, GLenum wrap) break; case GL_MIRROR_CLAMP_TO_EDGE_EXT: - supported = is_desktop_gl + supported = is_desktop_gl && (e->ATI_texture_mirror_once || e->EXT_texture_mirror_clamp || e->ARB_texture_mirror_clamp_to_edge) && (target != GL_TEXTURE_RECTANGLE_NV) && (target != GL_TEXTURE_EXTERNAL_OES); @@ -1787,7 +1787,7 @@ _mesa_GetTexParameterIiv(GLenum target, GLenum pname, GLint *params) texObj = get_texobj(ctx, target, GL_TRUE); if (!texObj) return; - + switch (pname) { case GL_TEXTURE_BORDER_COLOR: COPY_4V(params, texObj->Sampler.BorderColor.i); @@ -1808,7 +1808,7 @@ _mesa_GetTexParameterIuiv(GLenum target, GLenum pname, GLuint *params) texObj = get_texobj(ctx, target, GL_TRUE); if (!texObj) return; - + switch (pname) { case GL_TEXTURE_BORDER_COLOR: COPY_4V(params, texObj->Sampler.BorderColor.i); @@ -1818,7 +1818,7 @@ _mesa_GetTexParameterIuiv(GLenum target, GLenum pname, GLuint *params) GLint ip[4]; _mesa_GetTexParameteriv(target, pname, ip); params[0] = ip[0]; - if (pname == GL_TEXTURE_SWIZZLE_RGBA_EXT || + if (pname == GL_TEXTURE_SWIZZLE_RGBA_EXT || pname == GL_TEXTURE_CROP_RECT_OES) { params[1] = ip[1]; params[2] = ip[2]; diff --git a/mesalib/src/mesa/main/uniform_query.cpp b/mesalib/src/mesa/main/uniform_query.cpp index 3c460042e..88ad476ac 100644 --- a/mesalib/src/mesa/main/uniform_query.cpp +++ b/mesalib/src/mesa/main/uniform_query.cpp @@ -154,11 +154,21 @@ _mesa_GetActiveUniformsiv(GLuint program, params[i] = uni->row_major; break; + case GL_UNIFORM_ATOMIC_COUNTER_BUFFER_INDEX: + if (!ctx->Extensions.ARB_shader_atomic_counters) + goto invalid_enum; + params[i] = uni->atomic_buffer_index; + break; + default: - _mesa_error(ctx, GL_INVALID_ENUM, "glGetActiveUniformsiv(pname)"); - return; + goto invalid_enum; } } + + return; + + invalid_enum: + _mesa_error(ctx, GL_INVALID_ENUM, "glGetActiveUniformsiv(pname)"); } static bool diff --git a/mesalib/src/mesa/main/uniforms.c b/mesalib/src/mesa/main/uniforms.c index 1e6f7f483..2e847fe31 100644 --- a/mesalib/src/mesa/main/uniforms.c +++ b/mesalib/src/mesa/main/uniforms.c @@ -535,7 +535,8 @@ _mesa_GetUniformLocation(GLhandleARB programObj, const GLcharARB *name) * with a named uniform block, or if <name> starts with the reserved * prefix "gl_"." */ - if (shProg->UniformStorage[index].block_index != -1) + if (shProg->UniformStorage[index].block_index != -1 || + shProg->UniformStorage[index].atomic_buffer_index != -1) return -1; return _mesa_uniform_merge_location_offset(shProg, index, offset); @@ -844,3 +845,68 @@ _mesa_get_uniform_name(const struct gl_uniform_storage *uni, *length += i; } } + +void GLAPIENTRY +_mesa_GetActiveAtomicCounterBufferiv(GLuint program, GLuint bufferIndex, + GLenum pname, GLint *params) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_shader_program *shProg; + struct gl_active_atomic_buffer *ab; + int i; + + if (!ctx->Extensions.ARB_shader_atomic_counters) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetActiveAtomicCounterBufferiv"); + return; + } + + shProg = _mesa_lookup_shader_program_err(ctx, program, + "glGetActiveAtomicCounterBufferiv"); + if (!shProg) + return; + + if (bufferIndex >= shProg->NumAtomicBuffers) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glGetActiveAtomicCounterBufferiv(bufferIndex)"); + return; + } + + ab = &shProg->AtomicBuffers[bufferIndex]; + + switch (pname) { + case GL_ATOMIC_COUNTER_BUFFER_BINDING: + params[0] = ab->Binding; + return; + case GL_ATOMIC_COUNTER_BUFFER_DATA_SIZE: + params[0] = ab->MinimumSize; + return; + case GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTERS: + params[0] = ab->NumUniforms; + return; + case GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTER_INDICES: + for (i = 0; i < ab->NumUniforms; ++i) + params[i] = ab->Uniforms[i]; + return; + case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_VERTEX_SHADER: + params[0] = ab->StageReferences[MESA_SHADER_VERTEX]; + return; + case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_GEOMETRY_SHADER: + params[0] = ab->StageReferences[MESA_SHADER_GEOMETRY]; + return; + case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_FRAGMENT_SHADER: + params[0] = ab->StageReferences[MESA_SHADER_FRAGMENT]; + return; + case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_CONTROL_SHADER: + params[0] = GL_FALSE; + return; + case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_EVALUATION_SHADER: + params[0] = GL_FALSE; + return; + default: + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetActiveAtomicCounterBufferiv(pname 0x%x (%s))", + pname, _mesa_lookup_enum_by_nr(pname)); + return; + } +} diff --git a/mesalib/src/mesa/main/uniforms.h b/mesalib/src/mesa/main/uniforms.h index 92239176e..f7cac6328 100644 --- a/mesalib/src/mesa/main/uniforms.h +++ b/mesalib/src/mesa/main/uniforms.h @@ -142,6 +142,9 @@ _mesa_UniformBlockBinding(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding); void GLAPIENTRY +_mesa_GetActiveAtomicCounterBufferiv(GLuint program, GLuint bufferIndex, + GLenum pname, GLint *params); +void GLAPIENTRY _mesa_GetActiveUniformBlockiv(GLuint program, GLuint uniformBlockIndex, GLenum pname, diff --git a/mesalib/src/mesa/main/vdpau.c b/mesalib/src/mesa/main/vdpau.c new file mode 100644 index 000000000..e21a26b43 --- /dev/null +++ b/mesalib/src/mesa/main/vdpau.c @@ -0,0 +1,424 @@ +/************************************************************************** + * + * Copyright 2013 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * 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, sub license, 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 (including the + * next paragraph) 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 NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) 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. + * + **************************************************************************/ + +/* + * Authors: + * Christian König <christian.koenig@amd.com> + * + */ + +#include <stdbool.h> +#include "context.h" +#include "glformats.h" +#include "hash_table.h" +#include "set.h" +#include "texobj.h" +#include "teximage.h" +#include "vdpau.h" + +#define MAX_TEXTURES 4 + +struct vdp_surface +{ + GLenum target; + struct gl_texture_object *textures[MAX_TEXTURES]; + GLenum access, state; + GLboolean output; + const GLvoid *vdpSurface; +}; + +void GLAPIENTRY +_mesa_VDPAUInitNV(const GLvoid *vdpDevice, const GLvoid *getProcAddress) +{ + GET_CURRENT_CONTEXT(ctx); + + if (!vdpDevice) { + _mesa_error(ctx, GL_INVALID_VALUE, "vdpDevice"); + return; + } + + if (!getProcAddress) { + _mesa_error(ctx, GL_INVALID_VALUE, "getProcAddress"); + return; + } + + if (ctx->vdpDevice || ctx->vdpGetProcAddress || ctx->vdpSurfaces) { + _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUInitNV"); + return; + } + + ctx->vdpDevice = vdpDevice; + ctx->vdpGetProcAddress = getProcAddress; + ctx->vdpSurfaces = _mesa_set_create(NULL, _mesa_key_pointer_equal); +} + +static void +unregister_surface(struct set_entry *entry) +{ + struct vdp_surface *surf = (struct vdp_surface *)entry->key; + GET_CURRENT_CONTEXT(ctx); + + if (surf->state == GL_SURFACE_MAPPED_NV) { + GLintptr surfaces[] = { (GLintptr)surf }; + _mesa_VDPAUUnmapSurfacesNV(1, surfaces); + } + + _mesa_set_remove(ctx->vdpSurfaces, entry); + FREE(surf); +} + +void GLAPIENTRY +_mesa_VDPAUFiniNV(void) +{ + GET_CURRENT_CONTEXT(ctx); + + if (!ctx->vdpDevice || !ctx->vdpGetProcAddress || !ctx->vdpSurfaces) { + _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUFiniNV"); + return; + } + + _mesa_set_destroy(ctx->vdpSurfaces, unregister_surface); + + ctx->vdpDevice = 0; + ctx->vdpGetProcAddress = 0; + ctx->vdpSurfaces = NULL; +} + +static GLintptr +register_surface(struct gl_context *ctx, GLboolean isOutput, + const GLvoid *vdpSurface, GLenum target, + GLsizei numTextureNames, const GLuint *textureNames) +{ + struct vdp_surface *surf; + int i; + + if (!ctx->vdpDevice || !ctx->vdpGetProcAddress || !ctx->vdpSurfaces) { + _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAURegisterSurfaceNV"); + return (GLintptr)NULL; + } + + if (target != GL_TEXTURE_2D && target != GL_TEXTURE_RECTANGLE) { + _mesa_error(ctx, GL_INVALID_ENUM, "VDPAURegisterSurfaceNV"); + return (GLintptr)NULL; + } + + if (target == GL_TEXTURE_RECTANGLE && !ctx->Extensions.NV_texture_rectangle) { + _mesa_error(ctx, GL_INVALID_ENUM, "VDPAURegisterSurfaceNV"); + return (GLintptr)NULL; + } + + surf = CALLOC_STRUCT( vdp_surface ); + surf->vdpSurface = vdpSurface; + surf->target = target; + surf->access = GL_READ_WRITE; + surf->state = GL_SURFACE_REGISTERED_NV; + surf->output = isOutput; + for (i = 0; i < numTextureNames; ++i) { + struct gl_texture_object *tex; + tex = _mesa_lookup_texture(ctx, textureNames[i]); + + _mesa_lock_texture(ctx, tex); + + if (tex->Immutable) { + _mesa_unlock_texture(ctx, tex); + FREE(surf); + _mesa_error(ctx, GL_INVALID_OPERATION, + "VDPAURegisterSurfaceNV(texture is immutable)"); + return (GLintptr)NULL; + } + + if (tex->Target == 0) + tex->Target = target; + else if (tex->Target != target) { + _mesa_unlock_texture(ctx, tex); + FREE(surf); + _mesa_error(ctx, GL_INVALID_OPERATION, + "VDPAURegisterSurfaceNV(target mismatch)"); + return (GLintptr)NULL; + } + + /* This will disallow respecifying the storage. */ + tex->Immutable = GL_TRUE; + _mesa_unlock_texture(ctx, tex); + + _mesa_reference_texobj(&surf->textures[i], tex); + } + + _mesa_set_add(ctx->vdpSurfaces, _mesa_hash_pointer(surf), surf); + + return (GLintptr)surf; +} + +GLintptr GLAPIENTRY +_mesa_VDPAURegisterVideoSurfaceNV(const GLvoid *vdpSurface, GLenum target, + GLsizei numTextureNames, + const GLuint *textureNames) +{ + GET_CURRENT_CONTEXT(ctx); + + if (numTextureNames != 4) { + _mesa_error(ctx, GL_INVALID_VALUE, "VDPAURegisterVideoSurfaceNV"); + return (GLintptr)NULL; + } + + return register_surface(ctx, false, vdpSurface, target, + numTextureNames, textureNames); +} + +GLintptr GLAPIENTRY +_mesa_VDPAURegisterOutputSurfaceNV(const GLvoid *vdpSurface, GLenum target, + GLsizei numTextureNames, + const GLuint *textureNames) +{ + GET_CURRENT_CONTEXT(ctx); + + if (numTextureNames != 1) { + _mesa_error(ctx, GL_INVALID_VALUE, "VDPAURegisterVideoSurfaceNV"); + return (GLintptr)NULL; + } + + return register_surface(ctx, true, vdpSurface, target, + numTextureNames, textureNames); +} + +void GLAPIENTRY +_mesa_VDPAUIsSurfaceNV(GLintptr surface) +{ + struct vdp_surface *surf = (struct vdp_surface *)surface; + GET_CURRENT_CONTEXT(ctx); + + if (!ctx->vdpDevice || !ctx->vdpGetProcAddress || !ctx->vdpSurfaces) { + _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUIsSurfaceNV"); + return; + } + + if (!_mesa_set_search(ctx->vdpSurfaces, _mesa_hash_pointer(surf), surf)) { + _mesa_error(ctx, GL_INVALID_VALUE, "VDPAUIsSurfaceNV"); + return; + } +} + +void GLAPIENTRY +_mesa_VDPAUUnregisterSurfaceNV(GLintptr surface) +{ + struct vdp_surface *surf = (struct vdp_surface *)surface; + struct set_entry *entry; + int i; + GET_CURRENT_CONTEXT(ctx); + + if (!ctx->vdpDevice || !ctx->vdpGetProcAddress || !ctx->vdpSurfaces) { + _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUUnregisterSurfaceNV"); + return; + } + + /* according to the spec it's ok when this is zero */ + if (surface == 0) + return; + + entry = _mesa_set_search(ctx->vdpSurfaces, _mesa_hash_pointer(surf), surf); + if (!entry) { + _mesa_error(ctx, GL_INVALID_VALUE, "VDPAUUnregisterSurfaceNV"); + return; + } + + for (i = 0; i < MAX_TEXTURES; i++) { + if (surf->textures[i]) { + surf->textures[i]->Immutable = GL_FALSE; + _mesa_reference_texobj(&surf->textures[i], NULL); + } + } + + _mesa_set_remove(ctx->vdpSurfaces, entry); + FREE(surf); +} + +void GLAPIENTRY +_mesa_VDPAUGetSurfaceivNV(GLintptr surface, GLenum pname, GLsizei bufSize, + GLsizei *length, GLint *values) +{ + struct vdp_surface *surf = (struct vdp_surface *)surface; + GET_CURRENT_CONTEXT(ctx); + + if (!ctx->vdpDevice || !ctx->vdpGetProcAddress || !ctx->vdpSurfaces) { + _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUGetSurfaceivNV"); + return; + } + + if (!_mesa_set_search(ctx->vdpSurfaces, _mesa_hash_pointer(surf), surf)) { + _mesa_error(ctx, GL_INVALID_VALUE, "VDPAUGetSurfaceivNV"); + return; + } + + if (pname != GL_SURFACE_STATE_NV) { + _mesa_error(ctx, GL_INVALID_ENUM, "VDPAUGetSurfaceivNV"); + return; + } + + if (bufSize < 1) { + _mesa_error(ctx, GL_INVALID_VALUE, "VDPAUGetSurfaceivNV"); + return; + } + + values[0] = surf->state; + + if (length != NULL) + *length = 1; +} + +void GLAPIENTRY +_mesa_VDPAUSurfaceAccessNV(GLintptr surface, GLenum access) +{ + struct vdp_surface *surf = (struct vdp_surface *)surface; + GET_CURRENT_CONTEXT(ctx); + + if (!ctx->vdpDevice || !ctx->vdpGetProcAddress || !ctx->vdpSurfaces) { + _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUSurfaceAccessNV"); + return; + } + + if (!_mesa_set_search(ctx->vdpSurfaces, _mesa_hash_pointer(surf), surf)) { + _mesa_error(ctx, GL_INVALID_VALUE, "VDPAUSurfaceAccessNV"); + return; + } + + if (access != GL_READ_ONLY && access != GL_WRITE_ONLY && + access != GL_READ_WRITE) { + + _mesa_error(ctx, GL_INVALID_VALUE, "VDPAUSurfaceAccessNV"); + return; + } + + if (surf->state == GL_SURFACE_MAPPED_NV) { + _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUSurfaceAccessNV"); + return; + } + + surf->access = access; +} + +void GLAPIENTRY +_mesa_VDPAUMapSurfacesNV(GLsizei numSurfaces, const GLintptr *surfaces) +{ + GET_CURRENT_CONTEXT(ctx); + int i, j; + + if (!ctx->vdpDevice || !ctx->vdpGetProcAddress || !ctx->vdpSurfaces) { + _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUUnmapSurfacesNV"); + return; + } + + for (i = 0; i < numSurfaces; ++i) { + struct vdp_surface *surf = (struct vdp_surface *)surfaces[i]; + + if (!_mesa_set_search(ctx->vdpSurfaces, _mesa_hash_pointer(surf), surf)) { + _mesa_error(ctx, GL_INVALID_VALUE, "VDPAUSurfaceAccessNV"); + return; + } + + if (surf->state == GL_SURFACE_MAPPED_NV) { + _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUSurfaceAccessNV"); + return; + } + } + + for (i = 0; i < numSurfaces; ++i) { + struct vdp_surface *surf = (struct vdp_surface *)surfaces[i]; + unsigned numTextureNames = surf->output ? 1 : 4; + + for (j = 0; j < numTextureNames; ++j) { + struct gl_texture_object *tex = surf->textures[j]; + struct gl_texture_image *image; + + _mesa_lock_texture(ctx, tex); + image = _mesa_get_tex_image(ctx, tex, surf->target, 0); + if (!image) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "VDPAUMapSurfacesNV"); + _mesa_unlock_texture(ctx, tex); + return; + } + + ctx->Driver.FreeTextureImageBuffer(ctx, image); + + ctx->Driver.VDPAUMapSurface(ctx, surf->target, surf->access, + surf->output, tex, image, + surf->vdpSurface, j); + + _mesa_unlock_texture(ctx, tex); + } + surf->state = GL_SURFACE_MAPPED_NV; + } +} + +void GLAPIENTRY +_mesa_VDPAUUnmapSurfacesNV(GLsizei numSurfaces, const GLintptr *surfaces) +{ + GET_CURRENT_CONTEXT(ctx); + int i, j; + + if (!ctx->vdpDevice || !ctx->vdpGetProcAddress || !ctx->vdpSurfaces) { + _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUUnmapSurfacesNV"); + return; + } + + for (i = 0; i < numSurfaces; ++i) { + struct vdp_surface *surf = (struct vdp_surface *)surfaces[i]; + + if (!_mesa_set_search(ctx->vdpSurfaces, _mesa_hash_pointer(surf), surf)) { + _mesa_error(ctx, GL_INVALID_VALUE, "VDPAUSurfaceAccessNV"); + return; + } + + if (surf->state != GL_SURFACE_MAPPED_NV) { + _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUSurfaceAccessNV"); + return; + } + } + + for (i = 0; i < numSurfaces; ++i) { + struct vdp_surface *surf = (struct vdp_surface *)surfaces[i]; + unsigned numTextureNames = surf->output ? 1 : 4; + + for (j = 0; j < numTextureNames; ++j) { + struct gl_texture_object *tex = surf->textures[j]; + struct gl_texture_image *image; + + _mesa_lock_texture(ctx, tex); + + image = _mesa_select_tex_image(ctx, tex, surf->target, 0); + + ctx->Driver.VDPAUUnmapSurface(ctx, surf->target, surf->access, + surf->output, tex, image, + surf->vdpSurface, j); + + if (image) + ctx->Driver.FreeTextureImageBuffer(ctx, image); + + _mesa_unlock_texture(ctx, tex); + } + surf->state = GL_SURFACE_REGISTERED_NV; + } +} diff --git a/mesalib/src/mesa/main/vdpau.h b/mesalib/src/mesa/main/vdpau.h new file mode 100644 index 000000000..f32d6dacb --- /dev/null +++ b/mesalib/src/mesa/main/vdpau.h @@ -0,0 +1,72 @@ +/************************************************************************** + * + * Copyright 2013 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * 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, sub license, 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 (including the + * next paragraph) 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 NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) 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. + * + **************************************************************************/ + +/* + * Authors: + * Christian König <christian.koenig@amd.com> + * + */ + +#ifndef VDPAU_H +#define VDPAU_H + +extern void GLAPIENTRY +_mesa_VDPAUInitNV(const GLvoid *vdpDevice, const GLvoid *getProcAddress); + +extern void GLAPIENTRY +_mesa_VDPAUFiniNV(void); + +extern GLintptr GLAPIENTRY +_mesa_VDPAURegisterVideoSurfaceNV(const GLvoid *vdpSurface, GLenum target, + GLsizei numTextureNames, + const GLuint *textureNames); + +extern GLintptr GLAPIENTRY +_mesa_VDPAURegisterOutputSurfaceNV(const GLvoid *vdpSurface, GLenum target, + GLsizei numTextureNames, + const GLuint *textureNames); + +extern void GLAPIENTRY +_mesa_VDPAUIsSurfaceNV(GLintptr surface); + +extern void GLAPIENTRY +_mesa_VDPAUUnregisterSurfaceNV(GLintptr surface); + +extern void GLAPIENTRY +_mesa_VDPAUGetSurfaceivNV(GLintptr surface, GLenum pname, GLsizei bufSize, + GLsizei *length, GLint *values); + +extern void GLAPIENTRY +_mesa_VDPAUSurfaceAccessNV(GLintptr surface, GLenum access); + +extern void GLAPIENTRY +_mesa_VDPAUMapSurfacesNV(GLsizei numSurfaces, const GLintptr *surfaces); + +extern void GLAPIENTRY +_mesa_VDPAUUnmapSurfacesNV(GLsizei numSurfaces, const GLintptr *surfaces); + +#endif /* VDPAU_H */ diff --git a/mesalib/src/mesa/program/ir_to_mesa.cpp b/mesalib/src/mesa/program/ir_to_mesa.cpp index cfad91bc4..c833a12f2 100644 --- a/mesalib/src/mesa/program/ir_to_mesa.cpp +++ b/mesalib/src/mesa/program/ir_to_mesa.cpp @@ -622,6 +622,7 @@ type_size(const struct glsl_type *type) * at link time. */ return 1; + case GLSL_TYPE_ATOMIC_UINT: case GLSL_TYPE_VOID: case GLSL_TYPE_ERROR: case GLSL_TYPE_INTERFACE: @@ -2601,6 +2602,7 @@ _mesa_associate_uniform_storage(struct gl_context *ctx, format = uniform_native; columns = 1; break; + case GLSL_TYPE_ATOMIC_UINT: case GLSL_TYPE_ARRAY: case GLSL_TYPE_VOID: case GLSL_TYPE_STRUCT: diff --git a/mesalib/src/mesa/state_tracker/st_context.c b/mesalib/src/mesa/state_tracker/st_context.c index 4e0d98cc3..2cc3567e0 100644 --- a/mesalib/src/mesa/state_tracker/st_context.c +++ b/mesalib/src/mesa/state_tracker/st_context.c @@ -65,6 +65,7 @@ #include "st_extensions.h" #include "st_gen_mipmap.h" #include "st_program.h" +#include "st_vdpau.h" #include "pipe/p_context.h" #include "util/u_inlines.h" #include "util/u_upload_mgr.h" @@ -360,5 +361,7 @@ void st_init_driver_functions(struct dd_function_table *functions) st_init_xformfb_functions(functions); st_init_syncobj_functions(functions); + st_init_vdpau_functions(functions); + functions->UpdateState = st_invalidate_state; } diff --git a/mesalib/src/mesa/state_tracker/st_draw.c b/mesalib/src/mesa/state_tracker/st_draw.c index c35723087..51bb23807 100644 --- a/mesalib/src/mesa/state_tracker/st_draw.c +++ b/mesalib/src/mesa/state_tracker/st_draw.c @@ -210,9 +210,6 @@ st_draw_vbo(struct gl_context *ctx, if (st->dirty.st || ctx->NewDriverState) { st_validate_state(st); - if (st->vertex_array_out_of_memory) - return; - #if 0 if (MESA_VERBOSE & VERBOSE_GLSL) { check_uniforms(ctx); @@ -222,6 +219,10 @@ st_draw_vbo(struct gl_context *ctx, #endif } + if (st->vertex_array_out_of_memory) { + return; + } + util_draw_init_info(&info); if (ib) { diff --git a/mesalib/src/mesa/state_tracker/st_extensions.c b/mesalib/src/mesa/state_tracker/st_extensions.c index 231bb395a..97c5d55e1 100644 --- a/mesalib/src/mesa/state_tracker/st_extensions.c +++ b/mesalib/src/mesa/state_tracker/st_extensions.c @@ -445,8 +445,7 @@ void st_init_extensions(struct st_context *st) { PIPE_FORMAT_Z32_FLOAT, PIPE_FORMAT_Z32_FLOAT_S8X24_UINT } }, - { { o(ARB_framebuffer_object), - o(EXT_packed_depth_stencil) }, + { { o(EXT_packed_depth_stencil) }, { PIPE_FORMAT_S8_UINT_Z24_UNORM, PIPE_FORMAT_Z24_UNORM_S8_UINT }, GL_TRUE }, /* at least one format must be supported */ @@ -565,6 +564,7 @@ void st_init_extensions(struct st_context *st) ctx->Extensions.NV_fog_distance = GL_TRUE; ctx->Extensions.NV_texture_env_combine4 = GL_TRUE; ctx->Extensions.NV_texture_rectangle = GL_TRUE; + ctx->Extensions.NV_vdpau_interop = GL_TRUE; ctx->Extensions.OES_EGL_image = GL_TRUE; ctx->Extensions.OES_EGL_image_external = GL_TRUE; @@ -760,6 +760,10 @@ void st_init_extensions(struct st_context *st) PIPE_BUFFER, PIPE_BIND_SAMPLER_VIEW); } + if (screen->get_param(screen, PIPE_CAP_MIXED_FRAMEBUFFER_SIZES) && + ctx->Extensions.EXT_packed_depth_stencil) { + ctx->Extensions.ARB_framebuffer_object = GL_TRUE; + } /* Unpacking a varying in the fragment shader costs 1 texture indirection. * If the number of available texture indirections is very limited, then we diff --git a/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp index 3e11cce24..0eaf7467b 100644 --- a/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp +++ b/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp @@ -993,6 +993,7 @@ type_size(const struct glsl_type *type) * at link time. */ return 1; + case GLSL_TYPE_ATOMIC_UINT: case GLSL_TYPE_INTERFACE: case GLSL_TYPE_VOID: case GLSL_TYPE_ERROR: diff --git a/mesalib/src/mesa/state_tracker/st_vdpau.c b/mesalib/src/mesa/state_tracker/st_vdpau.c new file mode 100644 index 000000000..9b165ee39 --- /dev/null +++ b/mesalib/src/mesa/state_tracker/st_vdpau.c @@ -0,0 +1,181 @@ +/************************************************************************** + * + * Copyright 2013 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * 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, sub license, 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 (including the + * next paragraph) 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 NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) 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. + * + **************************************************************************/ + +/* + * Authors: + * Christian König <christian.koenig@amd.com> + * + */ + +#include "main/texobj.h" +#include "main/teximage.h" +#include "main/errors.h" +#include "program/prog_instruction.h" + +#include "pipe/p_state.h" +#include "pipe/p_video_codec.h" + +#include "state_tracker/vdpau_interop.h" + +#include "util/u_inlines.h" + +#include "st_vdpau.h" +#include "st_context.h" +#include "st_texture.h" +#include "st_format.h" + +static void +st_vdpau_map_surface(struct gl_context *ctx, GLenum target, GLenum access, + GLboolean output, struct gl_texture_object *texObj, + struct gl_texture_image *texImage, + const GLvoid *vdpSurface, GLuint index) +{ + int (*getProcAddr)(uint32_t device, uint32_t id, void **ptr); + uint32_t device = (uintptr_t)ctx->vdpDevice; + + struct st_context *st = st_context(ctx); + struct st_texture_object *stObj = st_texture_object(texObj); + struct st_texture_image *stImage = st_texture_image(texImage); + + struct pipe_resource *res; + struct pipe_sampler_view *sv, templ; + gl_format texFormat; + + getProcAddr = ctx->vdpGetProcAddress; + if (output) { + VdpOutputSurfaceGallium *f; + + if (getProcAddr(device, VDP_FUNC_ID_OUTPUT_SURFACE_GALLIUM, (void**)&f)) { + _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUMapSurfacesNV"); + return; + } + + res = f((uintptr_t)vdpSurface); + + if (!res) { + _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUMapSurfacesNV"); + return; + } + + } else { + VdpVideoSurfaceGallium *f; + + struct pipe_video_buffer *buffer; + struct pipe_sampler_view **samplers; + + if (getProcAddr(device, VDP_FUNC_ID_VIDEO_SURFACE_GALLIUM, (void**)&f)) { + _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUMapSurfacesNV"); + return; + } + + buffer = f((uintptr_t)vdpSurface); + if (!buffer) { + _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUMapSurfacesNV"); + return; + } + + samplers = buffer->get_sampler_view_planes(buffer); + if (!samplers) { + _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUMapSurfacesNV"); + return; + } + + sv = samplers[index >> 1]; + if (!sv) { + _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUMapSurfacesNV"); + return; + } + + res = sv->texture; + } + + if (!res) { + _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUMapSurfacesNV"); + return; + } + + /* do we have different screen objects ? */ + if (res->screen != st->pipe->screen) { + _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUMapSurfacesNV"); + return; + } + + /* switch to surface based */ + if (!stObj->surface_based) { + _mesa_clear_texture_object(ctx, texObj); + stObj->surface_based = GL_TRUE; + } + + texFormat = st_pipe_format_to_mesa_format(res->format); + + _mesa_init_teximage_fields(ctx, texImage, + res->width0, res->height0, 1, 0, GL_RGBA, + texFormat); + + pipe_resource_reference(&stObj->pt, res); + pipe_sampler_view_reference(&stObj->sampler_view, NULL); + pipe_resource_reference(&stImage->pt, res); + + u_sampler_view_default_template(&templ, res, res->format); + templ.u.tex.first_layer = index & 1; + templ.u.tex.last_layer = index & 1; + templ.swizzle_r = GET_SWZ(stObj->base._Swizzle, 0); + templ.swizzle_g = GET_SWZ(stObj->base._Swizzle, 1); + templ.swizzle_b = GET_SWZ(stObj->base._Swizzle, 2); + templ.swizzle_a = GET_SWZ(stObj->base._Swizzle, 3); + stObj->sampler_view = st->pipe->create_sampler_view(st->pipe, res, &templ); + + stObj->width0 = res->width0; + stObj->height0 = res->height0; + stObj->depth0 = 1; + stObj->surface_format = res->format; + + _mesa_dirty_texobj(ctx, texObj); +} + +static void +st_vdpau_unmap_surface(struct gl_context *ctx, GLenum target, GLenum access, + GLboolean output, struct gl_texture_object *texObj, + struct gl_texture_image *texImage, + const GLvoid *vdpSurface, GLuint index) +{ + struct st_texture_object *stObj = st_texture_object(texObj); + struct st_texture_image *stImage = st_texture_image(texImage); + + pipe_resource_reference(&stObj->pt, NULL); + pipe_sampler_view_reference(&stObj->sampler_view, NULL); + pipe_resource_reference(&stImage->pt, NULL); + + _mesa_dirty_texobj(ctx, texObj); +} + +void +st_init_vdpau_functions(struct dd_function_table *functions) +{ + functions->VDPAUMapSurface = st_vdpau_map_surface; + functions->VDPAUUnmapSurface = st_vdpau_unmap_surface; +} diff --git a/mesalib/src/mesa/state_tracker/st_vdpau.h b/mesalib/src/mesa/state_tracker/st_vdpau.h new file mode 100644 index 000000000..59c744305 --- /dev/null +++ b/mesalib/src/mesa/state_tracker/st_vdpau.h @@ -0,0 +1,42 @@ +/************************************************************************** + * + * Copyright 2013 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * 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, sub license, 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 (including the + * next paragraph) 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 NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) 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. + * + **************************************************************************/ + +/* + * Authors: + * Christian König <christian.koenig@amd.com> + * + */ + +#ifndef ST_VDPAU_H +#define ST_VDPAU_H + +struct dd_function_table; + +extern void +st_init_vdpau_functions(struct dd_function_table *functions); + +#endif /* ST_VDPAU_H */ |