diff --git a/src/gallium/include/pipe/p_state.h b/src/gallium/include/pipe/p_state.h index a99b386..2b4d9e4 100644 --- a/src/gallium/include/pipe/p_state.h +++ b/src/gallium/include/pipe/p_state.h @@ -102,6 +102,7 @@ struct pipe_rasterizer_state unsigned point_tri_clip:1; /** large points clipped as tris or points */ unsigned point_size_per_vertex:1; /**< size computed in vertex shader */ unsigned multisample:1; /* XXX maybe more ms state in future */ + unsigned force_persample_interp:1; unsigned line_smooth:1; unsigned line_stipple_enable:1; unsigned line_last_pixel:1; diff --git a/src/virgl_protocol.h b/src/virgl_protocol.h index 1430422..7688ac5 100644 --- a/src/virgl_protocol.h +++ b/src/virgl_protocol.h @@ -181,6 +181,7 @@ enum virgl_context_cmd { #define VIRGL_OBJ_RS_S0_LINE_LAST_PIXEL(x) (((x) & 0x1) << 28) #define VIRGL_OBJ_RS_S0_HALF_PIXEL_CENTER(x) (((x) & 0x1) << 29) #define VIRGL_OBJ_RS_S0_BOTTOM_EDGE_RULE(x) (((x) & 0x1) << 30) +#define VIRGL_OBJ_RS_S0_FORCE_PERSAMPLE_INTERP(x) (((x) & 0x1) << 31) #define VIRGL_OBJ_RS_POINT_SIZE 3 #define VIRGL_OBJ_RS_SPRITE_COORD_ENABLE 4 diff --git a/src/vrend_decode.c b/src/vrend_decode.c index 3b18596..6112bd8 100644 --- a/src/vrend_decode.c +++ b/src/vrend_decode.c @@ -523,6 +523,7 @@ static int vrend_decode_create_rasterizer(struct vrend_decode_ctx *ctx, uint32_t ebit(line_last_pixel, 28); ebit(half_pixel_center, 29); ebit(bottom_edge_rule, 30); + ebit(force_persample_interp, 31); rs_state->point_size = uif(get_buf_entry(ctx, VIRGL_OBJ_RS_POINT_SIZE)); rs_state->sprite_coord_enable = get_buf_entry(ctx, VIRGL_OBJ_RS_SPRITE_COORD_ENABLE); tmp = get_buf_entry(ctx, VIRGL_OBJ_RS_S3); diff --git a/src/vrend_renderer.c b/src/vrend_renderer.c index 087139e..36ded80 100644 --- a/src/vrend_renderer.c +++ b/src/vrend_renderer.c @@ -115,6 +115,7 @@ struct global_renderer_state { bool have_vertex_attrib_binding; bool have_tf2; bool have_stencil_texturing; + bool have_sample_shading; /* these appeared broken on at least one driver */ bool use_explicit_locations; @@ -3646,6 +3647,12 @@ static void vrend_hw_emit_rs(struct vrend_context *ctx) glDisable(GL_MULTISAMPLE); glDisable(GL_SAMPLE_MASK); } + if (vrend_state.have_sample_shading) { + if (state->force_persample_interp) + glEnable(GL_SAMPLE_SHADING); + else + glDisable(GL_SAMPLE_SHADING); + } } } @@ -4048,6 +4055,9 @@ int vrend_renderer_init(struct vrend_if_cbs *cbs, uint32_t flags) vrend_state.have_ms_scaled_blit = true; } + if (gl_ver >= 40 || epoxy_has_gl_extension("GL_ARB_sample_shading")) + vrend_state.have_sample_shading = true; + /* callbacks for when we are cleaning up the object table */ vrend_resource_set_destroy_callback(vrend_destroy_resource_object); vrend_object_set_destroy_callback(VIRGL_OBJECT_QUERY, vrend_destroy_query_object); @@ -6337,6 +6347,7 @@ void vrend_renderer_fill_caps(uint32_t set, uint32_t version, caps->v1.bset.cube_map_array = 1; caps->v1.bset.texture_query_lod = 1; caps->v1.bset.has_indirect_draw = 1; + caps->v1.bset.has_sample_shading = 1; } else { if (epoxy_has_gl_extension("GL_ARB_draw_buffers_blend")) caps->v1.bset.indep_blend_func = 1; @@ -6346,6 +6357,8 @@ void vrend_renderer_fill_caps(uint32_t set, uint32_t version, caps->v1.bset.texture_query_lod = 1; if (epoxy_has_gl_extension("GL_ARB_indirect_draw")) caps->v1.bset.has_indirect_draw = 1; + if (epoxy_has_gl_extension("GL_ARB_sample_shading")) + caps->v1.bset.has_sample_shading = 1; } if (gl_ver >= 42) { diff --git a/src/vrend_shader.c b/src/vrend_shader.c index 8e925d3..420bc83 100644 --- a/src/vrend_shader.c +++ b/src/vrend_shader.c @@ -141,6 +141,7 @@ struct dump_ctx { bool has_viewport_idx; bool has_frag_viewport_idx; bool vs_has_pervertex; + bool uses_sample_shading; }; static inline const char *tgsi_proc_to_prefix(int shader_type) @@ -506,7 +507,18 @@ iter_declaration(struct tgsi_iterate_context *iter, if (ctx->glsl_ver_required >= 140) ctx->has_clipvertex = true; break; - + case TGSI_SEMANTIC_SAMPLEMASK: + if (iter->processor.Processor == TGSI_PROCESSOR_FRAGMENT) { + ctx->outputs[i].glsl_predefined_no_emit = true; + ctx->outputs[i].glsl_no_index = true; + ctx->outputs[i].override_no_wm = true; + ctx->outputs[i].is_int = true; + ctx->has_ints = true; + name_prefix = "gl_SampleMask"; + ctx->uses_sample_shading = true; + break; + } + break; case TGSI_SEMANTIC_COLOR: if (iter->processor.Processor == TGSI_PROCESSOR_VERTEX) { if (ctx->glsl_ver_required < 140) { @@ -660,6 +672,13 @@ iter_declaration(struct tgsi_iterate_context *iter, } else if (decl->Semantic.Name == TGSI_SEMANTIC_VERTEXID) { name_prefix = "gl_VertexID"; ctx->has_ints = true; + } else if (decl->Semantic.Name == TGSI_SEMANTIC_SAMPLEID) { + name_prefix = "gl_SampleID"; + ctx->uses_sample_shading = true; + ctx->has_ints = true; + } else if (decl->Semantic.Name == TGSI_SEMANTIC_SAMPLEPOS) { + name_prefix = "gl_SamplePosition"; + ctx->uses_sample_shading = true; } else { fprintf(stderr, "unsupported system value %d\n", decl->Semantic.Name); name_prefix = "unknown"; @@ -1446,6 +1465,22 @@ iter_instruction(struct tgsi_iterate_context *iter, snprintf(dsts[i], 255, "clipv_tmp"); } else if (ctx->outputs[j].name == TGSI_SEMANTIC_CLIPDIST) { snprintf(dsts[i], 255, "clip_dist_temp[%d]", ctx->outputs[j].sid); + } else if (ctx->outputs[j].name == TGSI_SEMANTIC_SAMPLEMASK) { + int idx; + switch (dst->Register.WriteMask) { + case 0x1: idx = 0; break; + case 0x2: idx = 1; break; + case 0x4: idx = 2; break; + case 0x8: idx = 3; break; + default: + idx = 0; + break; + } + snprintf(dsts[i], 255, "%s[%d]", ctx->outputs[j].glsl_name, idx); + if (ctx->outputs[j].is_int) { + dtypeprefix = "floatBitsToInt"; + snprintf(dstconv, 6, "int"); + } } else { snprintf(dsts[i], 255, "%s%s", ctx->outputs[j].glsl_name, ctx->outputs[j].override_no_wm ? "" : writemask); dst_override_no_wm[i] = ctx->outputs[j].override_no_wm; @@ -1646,9 +1681,17 @@ iter_instruction(struct tgsi_iterate_context *iter, } else if (src->Register.File == TGSI_FILE_SYSTEM_VALUE) { for (j = 0; j < ctx->num_system_values; j++) if (ctx->system_values[j].first == src->Register.Index) { - if (ctx->system_values[j].name == TGSI_SEMANTIC_VERTEXID || ctx->system_values[j].name == TGSI_SEMANTIC_INSTANCEID) + if (ctx->system_values[j].name == TGSI_SEMANTIC_VERTEXID || + ctx->system_values[j].name == TGSI_SEMANTIC_INSTANCEID || + ctx->system_values[j].name == TGSI_SEMANTIC_SAMPLEID) snprintf(srcs[i], 255, "%s(vec4(intBitsToFloat(%s)))", stypeprefix, ctx->system_values[j].glsl_name); - else + else if (ctx->system_values[j].name == TGSI_SEMANTIC_SAMPLEPOS) { + snprintf(srcs[i], 255, "vec4(%s.%c, %s.%c, %s.%c, %s.%c)", + ctx->system_values[j].glsl_name, get_swiz_char(src->Register.SwizzleX), + ctx->system_values[j].glsl_name, get_swiz_char(src->Register.SwizzleY), + ctx->system_values[j].glsl_name, get_swiz_char(src->Register.SwizzleZ), + ctx->system_values[j].glsl_name, get_swiz_char(src->Register.SwizzleW)); + } else snprintf(srcs[i], 255, "%s%s", prefix, ctx->system_values[j].glsl_name); override_no_wm[i] = ctx->system_values[j].override_no_wm; break; @@ -2128,6 +2171,8 @@ static char *emit_header(struct dump_ctx *ctx, char *glsl_hdr) STRCAT_WITH_RET(glsl_hdr, "#extension GL_ARB_shader_stencil_export : require\n"); if (ctx->uses_layer) STRCAT_WITH_RET(glsl_hdr, "#extension GL_ARB_fragment_layer_viewport : require\n"); + if (ctx->uses_sample_shading) + STRCAT_WITH_RET(glsl_hdr, "#extension GL_ARB_sample_shading : require\n"); return glsl_hdr; }