diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_driver.h b/src/gallium/drivers/nouveau/codegen/nv50_ir_driver.h index 391130e67af..c0cab3299b5 100644 --- a/src/gallium/drivers/nouveau/codegen/nv50_ir_driver.h +++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_driver.h @@ -144,6 +144,7 @@ struct nv50_ir_prog_info bool earlyFragTests; bool separateFragData; bool usesDiscard; + bool sampleInterp; /* perform sample interp on all fp inputs */ } fp; struct { uint32_t inputOffset; /* base address for user args */ @@ -168,7 +169,6 @@ struct nv50_ir_prog_info int8_t viewportId; /* output index of ViewportIndex */ uint8_t fragDepth; /* output index of FragDepth */ uint8_t sampleMask; /* output index of SampleMask */ - bool sampleInterp; /* perform sample interp on all fp inputs */ uint8_t backFaceColor[2]; /* input/output indices of back face colour */ uint8_t globalAccess; /* 1 for read, 2 for wr, 3 for rw */ bool fp64; /* program uses fp64 math */ diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_nv50.cpp b/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_nv50.cpp index 90147668c91..e9b1cef2aa0 100644 --- a/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_nv50.cpp +++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_nv50.cpp @@ -876,6 +876,30 @@ CodeEmitterNV50::emitPFETCH(const Instruction *i) emitFlagsRd(i); } +static void +interpApply(const InterpEntry *entry, uint32_t *code, + bool force_persample_interp, bool flatshade) +{ + int ipa = entry->ipa; + int encSize = entry->reg; + int loc = entry->loc; + + if ((ipa & NV50_IR_INTERP_SAMPLE_MASK) == NV50_IR_INTERP_DEFAULT && + (ipa & NV50_IR_INTERP_MODE_MASK) != NV50_IR_INTERP_FLAT) { + if (force_persample_interp) { + if (encSize == 8) + code[loc + 1] |= 1 << 16; + else + code[loc + 0] |= 1 << 24; + } else { + if (encSize == 8) + code[loc + 1] &= ~(1 << 16); + else + code[loc + 0] &= ~(1 << 24); + } + } +} + void CodeEmitterNV50::emitINTERP(const Instruction *i) { @@ -904,6 +928,8 @@ CodeEmitterNV50::emitINTERP(const Instruction *i) code[0] |= 1; emitFlagsRd(i); } + + addInterp(i->ipa, i->encSize, interpApply); } void diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_from_tgsi.cpp b/src/gallium/drivers/nouveau/codegen/nv50_ir_from_tgsi.cpp index eb28622eb59..0031b5e15e8 100644 --- a/src/gallium/drivers/nouveau/codegen/nv50_ir_from_tgsi.cpp +++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_from_tgsi.cpp @@ -1125,7 +1125,7 @@ bool Source::scanDeclaration(const struct tgsi_full_declaration *decl) break; case TGSI_SEMANTIC_SAMPLEID: case TGSI_SEMANTIC_SAMPLEPOS: - info->io.sampleInterp = 1; + info->prop.fp.sampleInterp = 1; break; default: break; @@ -1478,7 +1478,7 @@ Converter::translateInterpMode(const struct nv50_ir_varying *var, operation& op) op = (mode == NV50_IR_INTERP_PERSPECTIVE || mode == NV50_IR_INTERP_SC) ? OP_PINTERP : OP_LINTERP; - if (var->centroid || info->io.sampleInterp) + if (var->centroid || info->prop.fp.sampleInterp) mode |= NV50_IR_INTERP_CENTROID; return mode; diff --git a/src/gallium/drivers/nouveau/nv50/nv50_program.c b/src/gallium/drivers/nouveau/nv50/nv50_program.c index eff4477472c..26ba2c2c380 100644 --- a/src/gallium/drivers/nouveau/nv50/nv50_program.c +++ b/src/gallium/drivers/nouveau/nv50/nv50_program.c @@ -336,7 +336,6 @@ nv50_program_translate(struct nv50_program *prog, uint16_t chipset) info->io.ucpCBSlot = 15; info->io.ucpBase = NV50_CB_AUX_UCP_OFFSET; info->io.genUserClip = prog->vp.clpd_nr; - info->io.sampleInterp = prog->fp.sample_interp; info->io.resInfoCBSlot = 15; info->io.suInfoBase = NV50_CB_AUX_TEX_MS_OFFSET; @@ -374,6 +373,7 @@ nv50_program_translate(struct nv50_program *prog, uint16_t chipset) prog->code = info->bin.code; prog->code_size = info->bin.codeSize; prog->fixups = info->bin.relocData; + prog->interps = info->bin.interpData; prog->max_gpr = MAX2(4, (info->bin.maxGPR >> 1) + 1); prog->tls_space = info->bin.tlsSpace; @@ -456,6 +456,10 @@ nv50_program_upload_code(struct nv50_context *nv50, struct nv50_program *prog) if (prog->fixups) nv50_ir_relocate_code(prog->fixups, prog->code, prog->code_base, 0, 0); + if (prog->interps) + nv50_ir_change_interp(prog->interps, prog->code, + prog->fp.force_persample_interp, + false /* flatshade */); nv50_sifc_linear_u8(&nv50->base, nv50->screen->code, (prog->type << NV50_CODE_BO_SIZE_LOG2) + prog->code_base, diff --git a/src/gallium/drivers/nouveau/nv50/nv50_program.h b/src/gallium/drivers/nouveau/nv50/nv50_program.h index f4e8e9402ca..24cc96567d7 100644 --- a/src/gallium/drivers/nouveau/nv50/nv50_program.h +++ b/src/gallium/drivers/nouveau/nv50/nv50_program.h @@ -86,7 +86,7 @@ struct nv50_program { uint32_t interp; /* 0x1988 */ uint32_t colors; /* 0x1904 */ uint8_t has_samplemask; - uint8_t sample_interp; + uint8_t force_persample_interp; } fp; struct { @@ -99,6 +99,7 @@ struct nv50_program { } gp; void *fixups; /* relocation records */ + void *interps; /* interpolation records */ struct nouveau_heap *mem; diff --git a/src/gallium/drivers/nouveau/nv50/nv50_screen.c b/src/gallium/drivers/nouveau/nv50/nv50_screen.c index bcad90128d2..398abfb97ba 100644 --- a/src/gallium/drivers/nouveau/nv50/nv50_screen.c +++ b/src/gallium/drivers/nouveau/nv50/nv50_screen.c @@ -192,6 +192,7 @@ nv50_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) case PIPE_CAP_INDEP_BLEND_FUNC: case PIPE_CAP_TEXTURE_QUERY_LOD: case PIPE_CAP_SAMPLE_SHADING: + case PIPE_CAP_FORCE_PERSAMPLE_INTERP: return class_3d >= NVA3_3D_CLASS; /* unsupported caps */ @@ -216,7 +217,6 @@ nv50_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) case PIPE_CAP_RESOURCE_FROM_USER_MEMORY: case PIPE_CAP_DEVICE_RESET_STATUS_QUERY: case PIPE_CAP_MAX_SHADER_PATCH_VARYINGS: - case PIPE_CAP_FORCE_PERSAMPLE_INTERP: case PIPE_CAP_SHAREABLE_SHADERS: return 0; diff --git a/src/gallium/drivers/nouveau/nv50/nv50_shader_state.c b/src/gallium/drivers/nouveau/nv50/nv50_shader_state.c index 941555ffbf8..b3fece07c3f 100644 --- a/src/gallium/drivers/nouveau/nv50/nv50_shader_state.c +++ b/src/gallium/drivers/nouveau/nv50/nv50_shader_state.c @@ -168,11 +168,23 @@ nv50_fragprog_validate(struct nv50_context *nv50) { struct nouveau_pushbuf *push = nv50->base.pushbuf; struct nv50_program *fp = nv50->fragprog; + struct pipe_rasterizer_state *rast = &nv50->rast->pipe; - fp->fp.sample_interp = nv50->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; + } + + if (fp->mem && !(nv50->dirty & (NV50_NEW_FRAGPROG | NV50_NEW_MIN_SAMPLES))) + return; if (!nv50_program_validate(nv50, fp)) - return; + return; nv50_program_update_context_state(nv50, fp, 1); BEGIN_NV04(push, NV50_3D(FP_REG_ALLOC_TEMP), 1); diff --git a/src/gallium/drivers/nouveau/nv50/nv50_state_validate.c b/src/gallium/drivers/nouveau/nv50/nv50_state_validate.c index 66dcf43533b..b6181edf24f 100644 --- a/src/gallium/drivers/nouveau/nv50/nv50_state_validate.c +++ b/src/gallium/drivers/nouveau/nv50/nv50_state_validate.c @@ -487,7 +487,7 @@ static struct state_validate { { nv50_validate_viewport, NV50_NEW_VIEWPORT }, { nv50_vertprog_validate, NV50_NEW_VERTPROG }, { nv50_gmtyprog_validate, NV50_NEW_GMTYPROG }, - { nv50_fragprog_validate, NV50_NEW_FRAGPROG | + { nv50_fragprog_validate, NV50_NEW_FRAGPROG | NV50_NEW_RASTERIZER | NV50_NEW_MIN_SAMPLES }, { nv50_fp_linkage_validate, NV50_NEW_FRAGPROG | NV50_NEW_VERTPROG | NV50_NEW_GMTYPROG | NV50_NEW_RASTERIZER },