From b75fff70d82474a571c59c2a3a01e4f9f02286a7 Mon Sep 17 00:00:00 2001 From: Ilia Mirkin Date: Tue, 20 Oct 2015 18:03:40 -0400 Subject: nvc0: do upload-time fixups for interpolation parameters Unfortunately flatshading is an all-or-nothing proposition on nvc0, while GL 3.0 calls for the ability to selectively specify explicit interpolation parameters on gl_Color/gl_SecondaryColor which would override the flatshading setting. This allows us to fix up the interpolation settings after shader generation based on rasterizer settings. While we're at it, we can add support for dynamically forcing all (non-flat) shader inputs to be interpolated per-sample, which allows st/mesa to not generate variants for these. Fixes the remaining failing glsl-1.30/execution/interpolation piglits. Signed-off-by: Ilia Mirkin --- src/gallium/drivers/nouveau/nvc0/nvc0_program.c | 25 ++++++++++- src/gallium/drivers/nouveau/nvc0/nvc0_program.h | 7 +++- src/gallium/drivers/nouveau/nvc0/nvc0_screen.c | 4 +- src/gallium/drivers/nouveau/nvc0/nvc0_screen.h | 1 + .../drivers/nouveau/nvc0/nvc0_shader_state.c | 48 +++++++++++++++++++++- src/gallium/drivers/nouveau/nvc0/nvc0_state.c | 3 -- .../drivers/nouveau/nvc0/nvc0_state_validate.c | 2 +- src/gallium/drivers/nouveau/nvc0/nvc0_stateobj.h | 2 +- 8 files changed, 82 insertions(+), 10 deletions(-) (limited to 'src/gallium/drivers/nouveau/nvc0') diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_program.c b/src/gallium/drivers/nouveau/nvc0/nvc0_program.c index a168dd684ab..b70b08a4a1e 100644 --- a/src/gallium/drivers/nouveau/nvc0/nvc0_program.c +++ b/src/gallium/drivers/nouveau/nvc0/nvc0_program.c @@ -424,6 +424,11 @@ nvc0_fp_gen_header(struct nvc0_program *fp, struct nv50_ir_prog_info *info) for (i = 0; i < info->numInputs; ++i) { m = nvc0_hdr_interp_mode(&info->in[i]); + if (info->in[i].sn == TGSI_SEMANTIC_COLOR) { + fp->fp.colors |= 1 << info->in[i].si; + if (info->in[i].sc) + fp->fp.color_interp[info->in[i].si] = m | (info->in[i].mask << 4); + } for (c = 0; c < 4; ++c) { if (!(info->in[i].mask & (1 << c))) continue; @@ -531,7 +536,6 @@ nvc0_program_translate(struct nvc0_program *prog, uint16_t chipset) info->io.genUserClip = prog->vp.num_ucps; info->io.ucpBase = 256; info->io.ucpCBSlot = 15; - info->io.sampleInterp = prog->fp.sample_interp; if (prog->type == PIPE_SHADER_COMPUTE) { if (chipset >= NVISA_GK104_CHIPSET) { @@ -575,6 +579,7 @@ nvc0_program_translate(struct nvc0_program *prog, uint16_t chipset) prog->immd_data = info->immd.buf; prog->immd_size = info->immd.bufSize; prog->relocs = info->bin.relocData; + prog->interps = info->bin.interpData; prog->num_gprs = MAX2(4, (info->bin.maxGPR + 1)); prog->num_barriers = info->numBarriers; @@ -713,6 +718,23 @@ nvc0_program_upload_code(struct nvc0_context *nvc0, struct nvc0_program *prog) if (prog->relocs) nv50_ir_relocate_code(prog->relocs, prog->code, code_pos, lib_pos, 0); + if (prog->interps) { + nv50_ir_change_interp(prog->interps, prog->code, + prog->fp.force_persample_interp, + prog->fp.flatshade); + for (int i = 0; i < 2; i++) { + unsigned mask = prog->fp.color_interp[i] >> 4; + unsigned interp = prog->fp.color_interp[i] & 3; + if (!mask) + continue; + prog->hdr[14] &= ~(0xff << (8 * i)); + if (prog->fp.flatshade) + interp = NVC0_INTERP_FLAT; + for (int c = 0; c < 4; c++) + if (mask & (1 << c)) + prog->hdr[14] |= interp << (2 * (4 * i + c)); + } + } #ifdef DEBUG if (debug_get_bool_option("NV50_PROG_DEBUG", false)) @@ -773,6 +795,7 @@ nvc0_program_destroy(struct nvc0_context *nvc0, struct nvc0_program *prog) FREE(prog->code); /* may be 0 for hardcoded shaders */ FREE(prog->immd_data); FREE(prog->relocs); + FREE(prog->interps); if (prog->type == PIPE_SHADER_COMPUTE && prog->cp.syms) FREE(prog->cp.syms); if (prog->tfb) { diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_program.h b/src/gallium/drivers/nouveau/nvc0/nvc0_program.h index 390e0c7a4f0..9c45e7b3e31 100644 --- a/src/gallium/drivers/nouveau/nvc0/nvc0_program.h +++ b/src/gallium/drivers/nouveau/nvc0/nvc0_program.h @@ -45,8 +45,10 @@ struct nvc0_program { } vp; struct { uint8_t early_z; - uint8_t in_pos[PIPE_MAX_SHADER_INPUTS]; - uint8_t sample_interp; + uint8_t colors; + uint8_t color_interp[2]; + bool force_persample_interp; + bool flatshade; } fp; struct { uint32_t tess_mode; /* ~0 if defined by the other stage */ @@ -61,6 +63,7 @@ struct nvc0_program { uint8_t num_barriers; void *relocs; + void *interps; struct nvc0_transform_feedback_state *tfb; diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c b/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c index 422d6d45369..d48c32d2b93 100644 --- a/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c +++ b/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c @@ -180,6 +180,7 @@ nvc0_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) case PIPE_CAP_DEPTH_BOUNDS_TEST: case PIPE_CAP_TGSI_TXQS: case PIPE_CAP_COPY_BETWEEN_COMPRESSED_AND_PLAIN_FORMATS: + case PIPE_CAP_FORCE_PERSAMPLE_INTERP: return 1; case PIPE_CAP_SEAMLESS_CUBE_MAP_PER_TEXTURE: return (class_3d >= NVE4_3D_CLASS) ? 1 : 0; @@ -202,7 +203,6 @@ nvc0_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) case PIPE_CAP_VERTEXID_NOBASE: case PIPE_CAP_RESOURCE_FROM_USER_MEMORY: case PIPE_CAP_DEVICE_RESET_STATUS_QUERY: - case PIPE_CAP_FORCE_PERSAMPLE_INTERP: case PIPE_CAP_SHAREABLE_SHADERS: return 0; @@ -828,6 +828,8 @@ nvc0_screen_create(struct nouveau_device *dev) PUSH_DATA (push, 1); BEGIN_NVC0(push, NVC0_3D(BLEND_ENABLE_COMMON), 1); PUSH_DATA (push, 0); + BEGIN_NVC0(push, NVC0_3D(SHADE_MODEL), 1); + PUSH_DATA (push, NVC0_3D_SHADE_MODEL_SMOOTH); if (screen->eng3d->oclass < NVE4_3D_CLASS) { BEGIN_NVC0(push, NVC0_3D(TEX_MISC), 1); PUSH_DATA (push, NVC0_3D_TEX_MISC_SEAMLESS_CUBE_MAP); diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_screen.h b/src/gallium/drivers/nouveau/nvc0/nvc0_screen.h index 857eb0316c7..8b73102b98b 100644 --- a/src/gallium/drivers/nouveau/nvc0/nvc0_screen.h +++ b/src/gallium/drivers/nouveau/nvc0/nvc0_screen.h @@ -38,6 +38,7 @@ struct nvc0_graph_state { uint32_t constant_elts; int32_t index_bias; uint16_t scissor; + bool flatshade; uint8_t patch_vertices; uint8_t vbo_mode; /* 0 = normal, 1 = translate, 3 = translate, forced */ uint8_t num_vtxbufs; diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_shader_state.c b/src/gallium/drivers/nouveau/nvc0/nvc0_shader_state.c index af837fc4a33..8595800592c 100644 --- a/src/gallium/drivers/nouveau/nvc0/nvc0_shader_state.c +++ b/src/gallium/drivers/nouveau/nvc0/nvc0_shader_state.c @@ -107,8 +107,54 @@ nvc0_fragprog_validate(struct nvc0_context *nvc0) { struct nouveau_pushbuf *push = nvc0->base.pushbuf; struct nvc0_program *fp = nvc0->fragprog; + struct pipe_rasterizer_state *rast = &nvc0->rast->pipe; - fp->fp.sample_interp = nvc0->min_samples > 1; + if (fp->fp.force_persample_interp != rast->force_persample_interp) { + /* Force the program to be reuploaded, which will trigger interp fixups + * to get applied + */ + if (fp->mem) + nouveau_heap_free(&fp->mem); + + fp->fp.force_persample_interp = rast->force_persample_interp; + } + + /* Shade model works well enough when both colors follow it. However if one + * (or both) is explicitly set, then we have to go the patching route. + */ + bool has_explicit_color = fp->fp.colors && + (((fp->fp.colors & 1) && !fp->fp.color_interp[0]) || + ((fp->fp.colors & 2) && !fp->fp.color_interp[1])); + bool hwflatshade = false; + if (has_explicit_color && fp->fp.flatshade != rast->flatshade) { + /* Force re-upload */ + if (fp->mem) + nouveau_heap_free(&fp->mem); + + fp->fp.flatshade = rast->flatshade; + + /* Always smooth-shade in this mode, the shader will decide on its own + * when to flat-shade. + */ + } else if (!has_explicit_color) { + hwflatshade = rast->flatshade; + + /* No need to binary-patch the shader each time, make sure that it's set + * up for the default behaviour. + */ + fp->fp.flatshade = 0; + } + + if (hwflatshade != nvc0->state.flatshade) { + nvc0->state.flatshade = hwflatshade; + BEGIN_NVC0(push, NVC0_3D(SHADE_MODEL), 1); + PUSH_DATA (push, hwflatshade ? NVC0_3D_SHADE_MODEL_FLAT : + NVC0_3D_SHADE_MODEL_SMOOTH); + } + + if (fp->mem && !(nvc0->dirty & NVC0_NEW_FRAGPROG)) { + return; + } if (!nvc0_program_validate(nvc0, fp)) return; diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_state.c b/src/gallium/drivers/nouveau/nvc0/nvc0_state.c index 742bef39247..e95554df12e 100644 --- a/src/gallium/drivers/nouveau/nvc0/nvc0_state.c +++ b/src/gallium/drivers/nouveau/nvc0/nvc0_state.c @@ -212,9 +212,6 @@ nvc0_rasterizer_state_create(struct pipe_context *pipe, * always emit 16 commands, one for each scissor rectangle, here. */ - SB_BEGIN_3D(so, SHADE_MODEL, 1); - SB_DATA (so, cso->flatshade ? NVC0_3D_SHADE_MODEL_FLAT : - NVC0_3D_SHADE_MODEL_SMOOTH); SB_IMMED_3D(so, PROVOKING_VERTEX_LAST, !cso->flatshade_first); SB_IMMED_3D(so, VERTEX_TWO_SIDE_ENABLE, cso->light_twoside); diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_state_validate.c b/src/gallium/drivers/nouveau/nvc0/nvc0_state_validate.c index aec06097bbd..f86de31c889 100644 --- a/src/gallium/drivers/nouveau/nvc0/nvc0_state_validate.c +++ b/src/gallium/drivers/nouveau/nvc0/nvc0_state_validate.c @@ -645,7 +645,7 @@ static struct state_validate { { nvc0_tevlprog_validate, NVC0_NEW_TEVLPROG }, { nvc0_validate_tess_state, NVC0_NEW_TESSFACTOR }, { nvc0_gmtyprog_validate, NVC0_NEW_GMTYPROG }, - { nvc0_fragprog_validate, NVC0_NEW_FRAGPROG }, + { nvc0_fragprog_validate, NVC0_NEW_FRAGPROG | NVC0_NEW_RASTERIZER }, { nvc0_validate_derived_1, NVC0_NEW_FRAGPROG | NVC0_NEW_ZSA | NVC0_NEW_RASTERIZER }, { nvc0_validate_derived_2, NVC0_NEW_ZSA | NVC0_NEW_FRAMEBUFFER }, diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_stateobj.h b/src/gallium/drivers/nouveau/nvc0/nvc0_stateobj.h index 8bc33c6a0e0..f9680f5a90f 100644 --- a/src/gallium/drivers/nouveau/nvc0/nvc0_stateobj.h +++ b/src/gallium/drivers/nouveau/nvc0/nvc0_stateobj.h @@ -23,7 +23,7 @@ struct nvc0_blend_stateobj { struct nvc0_rasterizer_stateobj { struct pipe_rasterizer_state pipe; int size; - uint32_t state[44]; + uint32_t state[42]; }; struct nvc0_zsa_stateobj { -- cgit v1.2.3