nvc0_vtgp_gen_header(tcp, info);
+ if (info->target >= NVISA_GM107_CHIPSET) {
+ /* On GM107+, the number of output patch components has moved in the TCP
+ * header, but it seems like blob still also uses the old position.
+ * Also, the high 8-bits are located inbetween the min/max parallel
+ * field and has to be set after updating the outputs. */
+ tcp->hdr[3] = (opcs & 0x0f) << 28;
+ tcp->hdr[4] |= (opcs & 0xf0) << 16;
+ }
+
nvc0_tp_get_tess_mode(tcp, info);
return 0;
if (chipset >= NVISA_GK104_CHIPSET) {
info->io.auxCBSlot = 7;
info->io.msInfoCBSlot = 7;
- info->prop.cp.gridInfoBase = NVC0_CB_AUX_GRID_INFO;
info->io.uboInfoBase = NVC0_CB_AUX_UBO_INFO(0);
}
+ info->prop.cp.gridInfoBase = NVC0_CB_AUX_GRID_INFO(0);
} else {
info->io.sampleInfoBase = NVC0_CB_AUX_SAMPLE_INFO;
}
prog->code = info->bin.code;
prog->code_size = info->bin.codeSize;
- prog->immd_data = info->immd.buf;
- prog->immd_size = info->immd.bufSize;
prog->relocs = info->bin.relocData;
prog->fixups = info->bin.fixupData;
prog->num_gprs = MAX2(4, (info->bin.maxGPR + 1));
return !ret;
}
-bool
-nvc0_program_upload_code(struct nvc0_context *nvc0, struct nvc0_program *prog)
+static inline int
+nvc0_program_alloc_code(struct nvc0_context *nvc0, struct nvc0_program *prog)
{
struct nvc0_screen *screen = nvc0->screen;
const bool is_cp = prog->type == PIPE_SHADER_COMPUTE;
int ret;
uint32_t size = prog->code_size + (is_cp ? 0 : NVC0_SHADER_HEADER_SIZE);
- uint32_t lib_pos = screen->lib_code->start;
- uint32_t code_pos;
-
- /* c[] bindings need to be aligned to 0x100, but we could use relocations
- * to save space. */
- if (prog->immd_size) {
- prog->immd_base = size;
- size = align(size, 0x40);
- size += prog->immd_size + 0xc0; /* add 0xc0 for align 0x40 -> 0x100 */
- }
+
/* On Fermi, SP_START_ID must be aligned to 0x40.
* On Kepler, the first instruction must be aligned to 0x80 because
* latency information is expected only at certain positions.
size = align(size, 0x40);
ret = nouveau_heap_alloc(screen->text_heap, size, prog, &prog->mem);
- if (ret) {
- struct nouveau_heap *heap = screen->text_heap;
- /* Note that the code library, which is allocated before anything else,
- * does not have a priv pointer. We can stop once we hit it.
- */
- while (heap->next && heap->next->priv) {
- struct nvc0_program *evict = heap->next->priv;
- nouveau_heap_free(&evict->mem);
- }
- debug_printf("WARNING: out of code space, evicting all shaders.\n");
- ret = nouveau_heap_alloc(heap, size, prog, &prog->mem);
- if (ret) {
- NOUVEAU_ERR("shader too large (0x%x) to fit in code space ?\n", size);
- return false;
- }
- IMMED_NVC0(nvc0->base.pushbuf, NVC0_3D(SERIALIZE), 0);
- }
+ if (ret)
+ return ret;
prog->code_base = prog->mem->start;
- prog->immd_base = align(prog->mem->start + prog->immd_base, 0x100);
- assert((prog->immd_size == 0) || (prog->immd_base + prog->immd_size <=
- prog->mem->start + prog->mem->size));
if (!is_cp) {
if (screen->base.class_3d >= NVE4_3D_CLASS) {
break;
}
}
- code_pos = prog->code_base + NVC0_SHADER_HEADER_SIZE;
} else {
if (screen->base.class_3d >= NVE4_3D_CLASS) {
if (prog->mem->start & 0x40)
prog->code_base += 0x40;
assert((prog->code_base & 0x7f) == 0x00);
}
- code_pos = prog->code_base;
}
+ return 0;
+}
+
+static inline void
+nvc0_program_upload_code(struct nvc0_context *nvc0, struct nvc0_program *prog)
+{
+ struct nvc0_screen *screen = nvc0->screen;
+ const bool is_cp = prog->type == PIPE_SHADER_COMPUTE;
+ uint32_t code_pos = prog->code_base + (is_cp ? 0 : NVC0_SHADER_HEADER_SIZE);
+
if (prog->relocs)
- nv50_ir_relocate_code(prog->relocs, prog->code, code_pos, lib_pos, 0);
+ nv50_ir_relocate_code(prog->relocs, prog->code, code_pos,
+ screen->lib_code->start, 0);
if (prog->fixups) {
nv50_ir_apply_fixups(prog->fixups, prog->code,
prog->fp.force_persample_interp,
- prog->fp.flatshade);
+ prog->fp.flatshade,
+ 0 /* alphatest */);
for (int i = 0; i < 2; i++) {
unsigned mask = prog->fp.color_interp[i] >> 4;
unsigned interp = prog->fp.color_interp[i] & 3;
}
}
+ if (!is_cp)
+ nvc0->base.push_data(&nvc0->base, screen->text, prog->code_base,
+ NV_VRAM_DOMAIN(&screen->base),
+ NVC0_SHADER_HEADER_SIZE, prog->hdr);
+
+ nvc0->base.push_data(&nvc0->base, screen->text, code_pos,
+ NV_VRAM_DOMAIN(&screen->base), prog->code_size,
+ prog->code);
+}
+
+bool
+nvc0_program_upload(struct nvc0_context *nvc0, struct nvc0_program *prog)
+{
+ struct nvc0_screen *screen = nvc0->screen;
+ const bool is_cp = prog->type == PIPE_SHADER_COMPUTE;
+ int ret;
+ uint32_t size = prog->code_size + (is_cp ? 0 : NVC0_SHADER_HEADER_SIZE);
+
+ ret = nvc0_program_alloc_code(nvc0, prog);
+ if (ret) {
+ struct nouveau_heap *heap = screen->text_heap;
+ struct nvc0_program *progs[] = { /* Sorted accordingly to SP_START_ID */
+ nvc0->compprog, nvc0->vertprog, nvc0->tctlprog,
+ nvc0->tevlprog, nvc0->gmtyprog, nvc0->fragprog
+ };
+
+ /* Note that the code library, which is allocated before anything else,
+ * does not have a priv pointer. We can stop once we hit it.
+ */
+ while (heap->next && heap->next->priv) {
+ struct nvc0_program *evict = heap->next->priv;
+ nouveau_heap_free(&evict->mem);
+ }
+ debug_printf("WARNING: out of code space, evicting all shaders.\n");
+
+ ret = nvc0_program_alloc_code(nvc0, prog);
+ if (ret) {
+ NOUVEAU_ERR("shader too large (0x%x) to fit in code space ?\n", size);
+ return false;
+ }
+ IMMED_NVC0(nvc0->base.pushbuf, NVC0_3D(SERIALIZE), 0);
+
+ /* All currently bound shaders have to be reuploaded. */
+ for (int i = 0; i < ARRAY_SIZE(progs); i++) {
+ if (!progs[i] || progs[i] == prog)
+ continue;
+
+ ret = nvc0_program_alloc_code(nvc0, progs[i]);
+ if (ret) {
+ NOUVEAU_ERR("failed to re-upload a shader after code eviction.\n");
+ return false;
+ }
+ nvc0_program_upload_code(nvc0, progs[i]);
+
+ if (progs[i]->type == PIPE_SHADER_COMPUTE) {
+ /* Caches have to be invalidated but the CP_START_ID will be
+ * updated in the launch_grid functions. */
+ BEGIN_NVC0(nvc0->base.pushbuf, NVC0_CP(FLUSH), 1);
+ PUSH_DATA (nvc0->base.pushbuf, NVC0_COMPUTE_FLUSH_CODE);
+ } else {
+ BEGIN_NVC0(nvc0->base.pushbuf, NVC0_3D(SP_START_ID(i)), 1);
+ PUSH_DATA (nvc0->base.pushbuf, progs[i]->code_base);
+ }
+ }
+ }
+
+ nvc0_program_upload_code(nvc0, prog);
+
#ifdef DEBUG
if (debug_get_bool_option("NV50_PROG_DEBUG", false))
nvc0_program_dump(prog);
#endif
- if (!is_cp)
- nvc0->base.push_data(&nvc0->base, screen->text, prog->code_base,
- NV_VRAM_DOMAIN(&screen->base), NVC0_SHADER_HEADER_SIZE, prog->hdr);
- nvc0->base.push_data(&nvc0->base, screen->text, code_pos,
- NV_VRAM_DOMAIN(&screen->base), prog->code_size, prog->code);
- if (prog->immd_size)
- nvc0->base.push_data(&nvc0->base,
- screen->text, prog->immd_base, NV_VRAM_DOMAIN(&screen->base),
- prog->immd_size, prog->immd_data);
-
BEGIN_NVC0(nvc0->base.pushbuf, NVC0_3D(MEM_BARRIER), 1);
PUSH_DATA (nvc0->base.pushbuf, 0x1011);
if (prog->mem)
nouveau_heap_free(&prog->mem);
FREE(prog->code); /* may be 0 for hardcoded shaders */
- FREE(prog->immd_data);
FREE(prog->relocs);
FREE(prog->fixups);
if (prog->type == PIPE_SHADER_COMPUTE && prog->cp.syms)