diff --git a/src/compiler/glsl/ast_to_hir.cpp b/src/compiler/glsl/ast_to_hir.cpp index 2a93a7fd401..68eb84eba66 100644 --- a/src/compiler/glsl/ast_to_hir.cpp +++ b/src/compiler/glsl/ast_to_hir.cpp @@ -2066,17 +2066,30 @@ ast_expression::do_hir(exec_list *instructions, this->primary_expression.identifier); } - /* From the EXT_shader_framebuffer_fetch spec: - * - * "Unless the GL_EXT_shader_framebuffer_fetch extension has been - * enabled in addition, it's an error to use gl_LastFragData if it - * hasn't been explicitly redeclared with layout(noncoherent)." - */ - if (var->data.fb_fetch_output && var->data.memory_coherent && - !state->EXT_shader_framebuffer_fetch_enable) { - _mesa_glsl_error(&loc, state, - "invalid use of framebuffer fetch output not " - "qualified with layout(noncoherent)"); + if (var->is_fb_fetch_color_output()) { + /* From the EXT_shader_framebuffer_fetch spec: + * + * "Unless the GL_EXT_shader_framebuffer_fetch extension has been + * enabled in addition, it's an error to use gl_LastFragData if it + * hasn't been explicitly redeclared with layout(noncoherent)." + */ + if (var->data.memory_coherent && !state->EXT_shader_framebuffer_fetch_enable) { + _mesa_glsl_error(&loc, state, + "invalid use of framebuffer fetch output not " + "qualified with layout(noncoherent)"); + } + } else if (var->data.fb_fetch_output) { + /* From the ARM_shader_framebuffer_fetch_depth_stencil spec: + * + * "It is not legal for a fragment shader to read from gl_LastFragDepthARM + * and gl_LastFragStencilARM if the early_fragment_tests layout qualifier + * is specified. This will result in a compile-time error." + */ + if (state->fs_early_fragment_tests) { + _mesa_glsl_error(&loc, state, + "invalid use of depth or stencil fetch " + "with early fragment tests enabled"); + } } } else { @@ -4118,16 +4131,25 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual, else if (qual->flags.q.shared_storage) var->data.mode = ir_var_shader_shared; - if (!is_parameter && state->has_framebuffer_fetch() && - state->stage == MESA_SHADER_FRAGMENT) { - if (state->is_version(130, 300)) - var->data.fb_fetch_output = qual->flags.q.in && qual->flags.q.out; - else - var->data.fb_fetch_output = (strcmp(var->name, "gl_LastFragData") == 0); + if (!is_parameter && state->stage == MESA_SHADER_FRAGMENT) { + if (state->has_framebuffer_fetch()) { + if (state->is_version(130, 300)) + var->data.fb_fetch_output = qual->flags.q.in && qual->flags.q.out; + else + var->data.fb_fetch_output = (strcmp(var->name, "gl_LastFragData") == 0); + } + + if (state->has_framebuffer_fetch_zs() && + (strcmp(var->name, "gl_LastFragDepthARM") == 0 || + strcmp(var->name, "gl_LastFragStencilARM") == 0)) { + var->data.fb_fetch_output = 1; + } } - if (var->data.fb_fetch_output) { + if (var->data.fb_fetch_output) var->data.assigned = true; + + if (var->is_fb_fetch_color_output()) { var->data.memory_coherent = !qual->flags.q.non_coherent; /* From the EXT_shader_framebuffer_fetch spec: diff --git a/src/compiler/glsl/builtin_variables.cpp b/src/compiler/glsl/builtin_variables.cpp index 7afb013b8e3..4aed31d8057 100644 --- a/src/compiler/glsl/builtin_variables.cpp +++ b/src/compiler/glsl/builtin_variables.cpp @@ -1368,6 +1368,22 @@ builtin_variable_generator::generate_fs_special_vars() var->data.memory_coherent = 1; } + if (state->has_framebuffer_fetch_zs()) { + ir_variable *const depth_var = + add_output(FRAG_RESULT_DEPTH, float_t, + GLSL_PRECISION_HIGH, "gl_LastFragDepthARM"); + depth_var->data.read_only = 1; + depth_var->data.fb_fetch_output = 1; + depth_var->data.memory_coherent = 1; + + ir_variable *const stencil_var = + add_output(FRAG_RESULT_STENCIL, int_t, + GLSL_PRECISION_LOW, "gl_LastFragStencilARM"); + stencil_var->data.read_only = 1; + stencil_var->data.fb_fetch_output = 1; + stencil_var->data.memory_coherent = 1; + } + if (state->es_shader && state->language_version == 100 && state->EXT_blend_func_extended_enable) { add_index_output(FRAG_RESULT_COLOR, 1, vec4_t, GLSL_PRECISION_MEDIUM, "gl_SecondaryFragColorEXT"); diff --git a/src/compiler/glsl/glsl_parser_extras.cpp b/src/compiler/glsl/glsl_parser_extras.cpp index e579cf54462..5f8eb70b459 100644 --- a/src/compiler/glsl/glsl_parser_extras.cpp +++ b/src/compiler/glsl/glsl_parser_extras.cpp @@ -744,6 +744,7 @@ static const _mesa_glsl_extension _mesa_glsl_supported_extensions[] = { EXT(AMD_vertex_shader_layer), EXT(AMD_vertex_shader_viewport_index), EXT(ANDROID_extension_pack_es31a), + EXT(ARM_shader_framebuffer_fetch_depth_stencil), EXT(EXT_blend_func_extended), EXT(EXT_demote_to_helper_invocation), EXT(EXT_frag_depth), diff --git a/src/compiler/glsl/glsl_parser_extras.h b/src/compiler/glsl/glsl_parser_extras.h index e35ab6948d7..45ed7ad87bd 100644 --- a/src/compiler/glsl/glsl_parser_extras.h +++ b/src/compiler/glsl/glsl_parser_extras.h @@ -329,6 +329,11 @@ struct _mesa_glsl_parse_state { EXT_shader_framebuffer_fetch_non_coherent_enable; } + bool has_framebuffer_fetch_zs() const + { + return ARM_shader_framebuffer_fetch_depth_stencil_enable; + } + bool has_texture_cube_map_array() const { return ARB_texture_cube_map_array_enable || @@ -827,6 +832,8 @@ struct _mesa_glsl_parse_state { bool AMD_vertex_shader_viewport_index_warn; bool ANDROID_extension_pack_es31a_enable; bool ANDROID_extension_pack_es31a_warn; + bool ARM_shader_framebuffer_fetch_depth_stencil_enable; + bool ARM_shader_framebuffer_fetch_depth_stencil_warn; bool EXT_blend_func_extended_enable; bool EXT_blend_func_extended_warn; bool EXT_clip_cull_distance_enable; diff --git a/src/compiler/glsl/ir.h b/src/compiler/glsl/ir.h index 0b6a773a95f..d6abd843813 100644 --- a/src/compiler/glsl/ir.h +++ b/src/compiler/glsl/ir.h @@ -612,6 +612,13 @@ public: this->name != this->name_storage; } + inline bool is_fb_fetch_color_output() const + { + return this->data.fb_fetch_output && + this->data.location != FRAG_RESULT_DEPTH && + this->data.location != FRAG_RESULT_STENCIL; + } + /** * Enable emitting extension warnings for this variable */