aboutsummaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/nouveau/nvc0
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/drivers/nouveau/nvc0')
-rw-r--r--src/gallium/drivers/nouveau/nvc0/nvc0_program.c25
-rw-r--r--src/gallium/drivers/nouveau/nvc0/nvc0_program.h7
-rw-r--r--src/gallium/drivers/nouveau/nvc0/nvc0_screen.c4
-rw-r--r--src/gallium/drivers/nouveau/nvc0/nvc0_screen.h1
-rw-r--r--src/gallium/drivers/nouveau/nvc0/nvc0_shader_state.c48
-rw-r--r--src/gallium/drivers/nouveau/nvc0/nvc0_state.c3
-rw-r--r--src/gallium/drivers/nouveau/nvc0/nvc0_state_validate.c2
-rw-r--r--src/gallium/drivers/nouveau/nvc0/nvc0_stateobj.h2
8 files changed, 82 insertions, 10 deletions
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 {