Commit 950b4a2e authored by Louis-Francis Ratté-Boulianne's avatar Louis-Francis Ratté-Boulianne Committed by Erik Faye-Lund
Browse files

d3d12: Fix face culling when lowering polygon mode

parent 849551cf
......@@ -222,6 +222,7 @@ struct d3d12_selection_context {
unsigned provoking_vertex;
bool alternate_tri;
unsigned fill_mode_lowered;
unsigned cull_mode_lowered;
bool manual_depth_range;
unsigned missing_dual_src_outputs;
unsigned frag_result_color_lowering;
......@@ -362,6 +363,18 @@ fill_mode_lowered(struct d3d12_context *ctx, const struct pipe_draw_info *dinfo)
return PIPE_POLYGON_MODE_FILL;
}
static unsigned
cull_mode_lowered(struct d3d12_context *ctx, unsigned fill_mode)
{
if ((ctx->gfx_stages[PIPE_SHADER_GEOMETRY] != NULL &&
!ctx->gfx_stages[PIPE_SHADER_GEOMETRY]->is_gs_variant) ||
ctx->gfx_pipeline_state.rast == NULL ||
ctx->gfx_pipeline_state.rast->base.cull_face == PIPE_FACE_NONE)
return PIPE_FACE_NONE;
return ctx->gfx_pipeline_state.rast->base.cull_face;
}
static unsigned
get_provoking_vertex(struct d3d12_selection_context *sel_ctx, bool *alternate)
{
......@@ -500,6 +513,9 @@ validate_geometry_shader_variant(struct d3d12_selection_context *sel_ctx)
variant_needed = true;
} else if (sel_ctx->fill_mode_lowered != PIPE_POLYGON_MODE_FILL) {
key.fill_mode = sel_ctx->fill_mode_lowered;
key.cull_mode = sel_ctx->cull_mode_lowered;
if (key.cull_mode != PIPE_FACE_NONE)
key.front_ccw = ctx->gfx_pipeline_state.rast->base.front_ccw ^ (ctx->flip_y < 0);
key.edge_flag_fix = needs_edge_flag_fix(ctx->initial_api_prim);
fill_flat_varyings(&key, fs);
if (key.flat_varyings != 0)
......@@ -1012,6 +1028,7 @@ d3d12_select_shader_variants(struct d3d12_context *ctx, const struct pipe_draw_i
sel_ctx.dinfo = dinfo;
sel_ctx.needs_point_sprite_lowering = needs_point_sprite_lowering(ctx, dinfo);
sel_ctx.fill_mode_lowered = fill_mode_lowered(ctx, dinfo);
sel_ctx.cull_mode_lowered = cull_mode_lowered(ctx, sel_ctx.fill_mode_lowered);
sel_ctx.provoking_vertex = get_provoking_vertex(&sel_ctx, &sel_ctx.alternate_tri);
sel_ctx.needs_vertex_reordering = needs_vertex_reordering(&sel_ctx);
sel_ctx.missing_dual_src_outputs = missing_dual_src_outputs(ctx);
......
......@@ -139,6 +139,8 @@ struct d3d12_gs_variant_key
unsigned provoking_vertex:3;
unsigned alternate_tri:1;
unsigned fill_mode:2;
unsigned cull_mode:2;
unsigned front_ccw:1;
unsigned edge_flag_fix:1;
unsigned flatshade_first:1;
uint64_t flat_varyings;
......
......@@ -486,6 +486,7 @@ d3d12_create_rasterizer_state(struct pipe_context *pctx,
switch (rs_state->cull_face) {
case PIPE_FACE_NONE:
if (rs_state->fill_front != rs_state->fill_back) {
cso->base.cull_face = PIPE_FACE_BACK;
cso->desc.CullMode = D3D12_CULL_MODE_BACK;
cso->desc.FillMode = fill_mode(rs_state->fill_front);
......
......@@ -29,6 +29,7 @@
#include "nir.h"
#include "compiler/nir/nir_builder.h"
#include "compiler/nir/nir_builtin_builder.h"
#include "util/u_memory.h"
#include "util/u_simple_shaders.h"
......@@ -53,6 +54,25 @@ nir_end_primitve(nir_builder *b, unsigned stream_id)
nir_builder_instr_insert(b, &instr->instr);
}
static nir_ssa_def *
nir_cull_face(nir_builder *b, nir_variable *vertices, bool ccw)
{
nir_ssa_def *v0 =
nir_load_deref(b, nir_build_deref_array(b, nir_build_deref_var(b, vertices), nir_imm_int(b, 0)));
nir_ssa_def *v1 =
nir_load_deref(b, nir_build_deref_array(b, nir_build_deref_var(b, vertices), nir_imm_int(b, 1)));
nir_ssa_def *v2 =
nir_load_deref(b, nir_build_deref_array(b, nir_build_deref_var(b, vertices), nir_imm_int(b, 2)));
nir_ssa_def *dir = nir_fdot(b, nir_cross4(b, nir_fsub(b, v1, v0),
nir_fsub(b, v2, v0)),
nir_imm_vec4(b, 0.0, 0.0, -1.0, 0.0));
if (ccw)
return nir_fge(b, nir_imm_int(b, 0), dir);
else
return nir_flt(b, nir_imm_int(b, 0), dir);
}
static d3d12_shader_selector*
d3d12_make_passthrough_gs(struct d3d12_context *ctx, struct d3d12_gs_variant_key *key)
{
......@@ -146,6 +166,7 @@ d3d12_begin_emit_primitives_gs(struct emit_primitives_context *emit_ctx,
nir_builder *b = &emit_ctx->b;
nir_intrinsic_instr *instr;
nir_variable *edgeflag_var = NULL;
nir_variable *pos_var = NULL;
uint64_t varyings = key->varyings.mask;
emit_ctx->ctx = ctx;
......@@ -182,6 +203,8 @@ d3d12_begin_emit_primitives_gs(struct emit_primitives_context *emit_ctx,
if (i == VARYING_SLOT_EDGE) {
edgeflag_var = emit_ctx->in[emit_ctx->num_vars];
continue;
} else if (i == VARYING_SLOT_POS) {
pos_var = emit_ctx->in[emit_ctx->num_vars];
}
snprintf(tmp, ARRAY_SIZE(tmp), "out_%d", emit_ctx->num_vars);
......@@ -215,6 +238,13 @@ d3d12_begin_emit_primitives_gs(struct emit_primitives_context *emit_ctx,
nir_imm_int(b, 1));
}
if (key->cull_mode != PIPE_FACE_NONE) {
if (key->cull_mode == PIPE_FACE_BACK)
emit_ctx->edgeflag_cmp = nir_cull_face(b, pos_var, key->front_ccw);
else if (key->cull_mode == PIPE_FACE_FRONT)
emit_ctx->edgeflag_cmp = nir_cull_face(b, pos_var, !key->front_ccw);
}
/**
* while {
* if (loop_index >= 3)
......@@ -232,7 +262,11 @@ d3d12_begin_emit_primitives_gs(struct emit_primitives_context *emit_ctx,
if (edgeflag_var) {
nir_ssa_def *edge_flag =
nir_load_deref(b, nir_build_deref_array(b, nir_build_deref_var(b, edgeflag_var), emit_ctx->loop_index));
emit_ctx->edgeflag_cmp = nir_feq(b, nir_channel(b, edge_flag, 0), nir_imm_float(b, 1.0));
nir_ssa_def *is_edge = nir_feq(b, nir_channel(b, edge_flag, 0), nir_imm_float(b, 1.0));
if (emit_ctx->edgeflag_cmp)
emit_ctx->edgeflag_cmp = nir_iand(b, emit_ctx->edgeflag_cmp, is_edge);
else
emit_ctx->edgeflag_cmp = is_edge;
}
if (key->edge_flag_fix) {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment