1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright 2012 Red Hat Inc. 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice shall be included in 12bf215546Sopenharmony_ci * all copies or substantial portions of the Software. 13bf215546Sopenharmony_ci * 14bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 18bf215546Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19bf215546Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20bf215546Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE. 21bf215546Sopenharmony_ci * 22bf215546Sopenharmony_ci * Authors: Ben Skeggs 23bf215546Sopenharmony_ci * 24bf215546Sopenharmony_ci */ 25bf215546Sopenharmony_ci 26bf215546Sopenharmony_ci#include "draw/draw_context.h" 27bf215546Sopenharmony_ci#include "tgsi/tgsi_parse.h" 28bf215546Sopenharmony_ci#include "nir/nir_to_tgsi.h" 29bf215546Sopenharmony_ci 30bf215546Sopenharmony_ci#include "nv_object.xml.h" 31bf215546Sopenharmony_ci#include "nv30/nv30-40_3d.xml.h" 32bf215546Sopenharmony_ci#include "nv30/nv30_context.h" 33bf215546Sopenharmony_ci#include "nv30/nvfx_shader.h" 34bf215546Sopenharmony_ci 35bf215546Sopenharmony_cistatic void 36bf215546Sopenharmony_cinv30_fragprog_upload(struct nv30_context *nv30) 37bf215546Sopenharmony_ci{ 38bf215546Sopenharmony_ci struct nouveau_context *nv = &nv30->base; 39bf215546Sopenharmony_ci struct nv30_fragprog *fp = nv30->fragprog.program; 40bf215546Sopenharmony_ci struct pipe_context *pipe = &nv30->base.pipe; 41bf215546Sopenharmony_ci 42bf215546Sopenharmony_ci if (unlikely(!fp->buffer)) 43bf215546Sopenharmony_ci fp->buffer = pipe_buffer_create(pipe->screen, 0, 0, fp->insn_len * 4); 44bf215546Sopenharmony_ci 45bf215546Sopenharmony_ci#if !UTIL_ARCH_BIG_ENDIAN 46bf215546Sopenharmony_ci pipe_buffer_write(pipe, fp->buffer, 0, fp->insn_len * 4, fp->insn); 47bf215546Sopenharmony_ci#else 48bf215546Sopenharmony_ci { 49bf215546Sopenharmony_ci struct pipe_transfer *transfer; 50bf215546Sopenharmony_ci uint32_t *map; 51bf215546Sopenharmony_ci int i; 52bf215546Sopenharmony_ci 53bf215546Sopenharmony_ci map = pipe_buffer_map(pipe, fp->buffer, 54bf215546Sopenharmony_ci PIPE_MAP_WRITE | PIPE_MAP_DISCARD_WHOLE_RESOURCE, 55bf215546Sopenharmony_ci &transfer); 56bf215546Sopenharmony_ci for (i = 0; i < fp->insn_len; i++) 57bf215546Sopenharmony_ci *map++ = (fp->insn[i] >> 16) | (fp->insn[i] << 16); 58bf215546Sopenharmony_ci pipe_buffer_unmap(pipe, transfer); 59bf215546Sopenharmony_ci } 60bf215546Sopenharmony_ci#endif 61bf215546Sopenharmony_ci 62bf215546Sopenharmony_ci if (nv04_resource(fp->buffer)->domain != NOUVEAU_BO_VRAM) 63bf215546Sopenharmony_ci nouveau_buffer_migrate(nv, nv04_resource(fp->buffer), NOUVEAU_BO_VRAM); 64bf215546Sopenharmony_ci} 65bf215546Sopenharmony_ci 66bf215546Sopenharmony_civoid 67bf215546Sopenharmony_cinv30_fragprog_validate(struct nv30_context *nv30) 68bf215546Sopenharmony_ci{ 69bf215546Sopenharmony_ci struct nouveau_pushbuf *push = nv30->base.pushbuf; 70bf215546Sopenharmony_ci struct nouveau_object *eng3d = nv30->screen->eng3d; 71bf215546Sopenharmony_ci struct nv30_fragprog *fp = nv30->fragprog.program; 72bf215546Sopenharmony_ci bool upload = false; 73bf215546Sopenharmony_ci int i; 74bf215546Sopenharmony_ci 75bf215546Sopenharmony_ci if (!fp->translated) { 76bf215546Sopenharmony_ci _nvfx_fragprog_translate(eng3d->oclass, fp); 77bf215546Sopenharmony_ci if (!fp->translated) 78bf215546Sopenharmony_ci return; 79bf215546Sopenharmony_ci 80bf215546Sopenharmony_ci upload = true; 81bf215546Sopenharmony_ci } 82bf215546Sopenharmony_ci 83bf215546Sopenharmony_ci /* update constants, also needs to be done on every fp switch as we 84bf215546Sopenharmony_ci * have no idea whether the constbuf changed in the meantime 85bf215546Sopenharmony_ci */ 86bf215546Sopenharmony_ci if (nv30->fragprog.constbuf) { 87bf215546Sopenharmony_ci struct pipe_resource *constbuf = nv30->fragprog.constbuf; 88bf215546Sopenharmony_ci uint32_t *cbuf = (uint32_t *)nv04_resource(constbuf)->data; 89bf215546Sopenharmony_ci 90bf215546Sopenharmony_ci for (i = 0; i < fp->nr_consts; i++) { 91bf215546Sopenharmony_ci unsigned off = fp->consts[i].offset; 92bf215546Sopenharmony_ci unsigned idx = fp->consts[i].index * 4; 93bf215546Sopenharmony_ci 94bf215546Sopenharmony_ci if (!memcmp(&fp->insn[off], &cbuf[idx], 4 * 4)) 95bf215546Sopenharmony_ci continue; 96bf215546Sopenharmony_ci memcpy(&fp->insn[off], &cbuf[idx], 4 * 4); 97bf215546Sopenharmony_ci upload = true; 98bf215546Sopenharmony_ci } 99bf215546Sopenharmony_ci } 100bf215546Sopenharmony_ci 101bf215546Sopenharmony_ci if (upload) 102bf215546Sopenharmony_ci nv30_fragprog_upload(nv30); 103bf215546Sopenharmony_ci 104bf215546Sopenharmony_ci /* FP_ACTIVE_PROGRAM needs to be done again even if only the consts 105bf215546Sopenharmony_ci * were updated. TEX_CACHE_CTL magic is not enough to convince the 106bf215546Sopenharmony_ci * GPU that it should re-read the fragprog from VRAM... sigh. 107bf215546Sopenharmony_ci */ 108bf215546Sopenharmony_ci if (nv30->state.fragprog != fp || upload) { 109bf215546Sopenharmony_ci struct nv04_resource *r = nv04_resource(fp->buffer); 110bf215546Sopenharmony_ci 111bf215546Sopenharmony_ci if (!PUSH_SPACE(push, 8)) 112bf215546Sopenharmony_ci return; 113bf215546Sopenharmony_ci PUSH_RESET(push, BUFCTX_FRAGPROG); 114bf215546Sopenharmony_ci 115bf215546Sopenharmony_ci BEGIN_NV04(push, NV30_3D(FP_ACTIVE_PROGRAM), 1); 116bf215546Sopenharmony_ci PUSH_RESRC(push, NV30_3D(FP_ACTIVE_PROGRAM), BUFCTX_FRAGPROG, r, 0, 117bf215546Sopenharmony_ci NOUVEAU_BO_LOW | NOUVEAU_BO_RD | NOUVEAU_BO_OR, 118bf215546Sopenharmony_ci NV30_3D_FP_ACTIVE_PROGRAM_DMA0, 119bf215546Sopenharmony_ci NV30_3D_FP_ACTIVE_PROGRAM_DMA1); 120bf215546Sopenharmony_ci BEGIN_NV04(push, NV30_3D(FP_CONTROL), 1); 121bf215546Sopenharmony_ci PUSH_DATA (push, fp->fp_control); 122bf215546Sopenharmony_ci if (eng3d->oclass < NV40_3D_CLASS) { 123bf215546Sopenharmony_ci BEGIN_NV04(push, NV30_3D(FP_REG_CONTROL), 1); 124bf215546Sopenharmony_ci PUSH_DATA (push, 0x00010004); 125bf215546Sopenharmony_ci BEGIN_NV04(push, NV30_3D(TEX_UNITS_ENABLE), 1); 126bf215546Sopenharmony_ci PUSH_DATA (push, fp->texcoords); 127bf215546Sopenharmony_ci } else { 128bf215546Sopenharmony_ci BEGIN_NV04(push, SUBC_3D(0x0b40), 1); 129bf215546Sopenharmony_ci PUSH_DATA (push, 0x00000000); 130bf215546Sopenharmony_ci } 131bf215546Sopenharmony_ci 132bf215546Sopenharmony_ci nv30->state.fragprog = fp; 133bf215546Sopenharmony_ci } 134bf215546Sopenharmony_ci} 135bf215546Sopenharmony_ci 136bf215546Sopenharmony_cistatic void * 137bf215546Sopenharmony_cinv30_fp_state_create(struct pipe_context *pipe, 138bf215546Sopenharmony_ci const struct pipe_shader_state *cso) 139bf215546Sopenharmony_ci{ 140bf215546Sopenharmony_ci struct nv30_fragprog *fp = CALLOC_STRUCT(nv30_fragprog); 141bf215546Sopenharmony_ci if (!fp) 142bf215546Sopenharmony_ci return NULL; 143bf215546Sopenharmony_ci 144bf215546Sopenharmony_ci if (cso->type == PIPE_SHADER_IR_NIR) { 145bf215546Sopenharmony_ci fp->pipe.tokens = nir_to_tgsi(cso->ir.nir, pipe->screen); 146bf215546Sopenharmony_ci } else { 147bf215546Sopenharmony_ci assert(cso->type == PIPE_SHADER_IR_TGSI); 148bf215546Sopenharmony_ci /* we need to keep a local copy of the tokens */ 149bf215546Sopenharmony_ci fp->pipe.tokens = tgsi_dup_tokens(cso->tokens); 150bf215546Sopenharmony_ci } 151bf215546Sopenharmony_ci 152bf215546Sopenharmony_ci tgsi_scan_shader(fp->pipe.tokens, &fp->info); 153bf215546Sopenharmony_ci return fp; 154bf215546Sopenharmony_ci} 155bf215546Sopenharmony_ci 156bf215546Sopenharmony_cistatic void 157bf215546Sopenharmony_cinv30_fp_state_delete(struct pipe_context *pipe, void *hwcso) 158bf215546Sopenharmony_ci{ 159bf215546Sopenharmony_ci struct nv30_fragprog *fp = hwcso; 160bf215546Sopenharmony_ci 161bf215546Sopenharmony_ci pipe_resource_reference(&fp->buffer, NULL); 162bf215546Sopenharmony_ci 163bf215546Sopenharmony_ci if (fp->draw) 164bf215546Sopenharmony_ci draw_delete_fragment_shader(nv30_context(pipe)->draw, fp->draw); 165bf215546Sopenharmony_ci 166bf215546Sopenharmony_ci FREE((void *)fp->pipe.tokens); 167bf215546Sopenharmony_ci FREE(fp->insn); 168bf215546Sopenharmony_ci FREE(fp->consts); 169bf215546Sopenharmony_ci FREE(fp); 170bf215546Sopenharmony_ci} 171bf215546Sopenharmony_ci 172bf215546Sopenharmony_cistatic void 173bf215546Sopenharmony_cinv30_fp_state_bind(struct pipe_context *pipe, void *hwcso) 174bf215546Sopenharmony_ci{ 175bf215546Sopenharmony_ci struct nv30_context *nv30 = nv30_context(pipe); 176bf215546Sopenharmony_ci struct nv30_fragprog *fp = hwcso; 177bf215546Sopenharmony_ci 178bf215546Sopenharmony_ci /* reset the bucftx so that we don't keep a dangling reference to the fp 179bf215546Sopenharmony_ci * code 180bf215546Sopenharmony_ci */ 181bf215546Sopenharmony_ci if (fp != nv30->state.fragprog) 182bf215546Sopenharmony_ci nouveau_bufctx_reset(nv30->bufctx, BUFCTX_FRAGPROG); 183bf215546Sopenharmony_ci 184bf215546Sopenharmony_ci nv30->fragprog.program = fp; 185bf215546Sopenharmony_ci nv30->dirty |= NV30_NEW_FRAGPROG; 186bf215546Sopenharmony_ci} 187bf215546Sopenharmony_ci 188bf215546Sopenharmony_civoid 189bf215546Sopenharmony_cinv30_fragprog_init(struct pipe_context *pipe) 190bf215546Sopenharmony_ci{ 191bf215546Sopenharmony_ci pipe->create_fs_state = nv30_fp_state_create; 192bf215546Sopenharmony_ci pipe->bind_fs_state = nv30_fp_state_bind; 193bf215546Sopenharmony_ci pipe->delete_fs_state = nv30_fp_state_delete; 194bf215546Sopenharmony_ci} 195