1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright 2008 Ben Skeggs 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 23bf215546Sopenharmony_ci#include "nv50/nv50_context.h" 24bf215546Sopenharmony_ci#include "nv50/nv50_resource.h" 25bf215546Sopenharmony_ci#include "nv50/g80_texture.xml.h" 26bf215546Sopenharmony_ci#include "nv50/g80_defs.xml.h" 27bf215546Sopenharmony_ci 28bf215546Sopenharmony_ci#include "util/format/u_format.h" 29bf215546Sopenharmony_ci 30bf215546Sopenharmony_cistatic inline uint32_t 31bf215546Sopenharmony_cinv50_tic_swizzle(const struct nv50_format *fmt, unsigned swz, bool tex_int) 32bf215546Sopenharmony_ci{ 33bf215546Sopenharmony_ci switch (swz) { 34bf215546Sopenharmony_ci case PIPE_SWIZZLE_X : return fmt->tic.src_x; 35bf215546Sopenharmony_ci case PIPE_SWIZZLE_Y: return fmt->tic.src_y; 36bf215546Sopenharmony_ci case PIPE_SWIZZLE_Z : return fmt->tic.src_z; 37bf215546Sopenharmony_ci case PIPE_SWIZZLE_W: return fmt->tic.src_w; 38bf215546Sopenharmony_ci case PIPE_SWIZZLE_1: 39bf215546Sopenharmony_ci return tex_int ? G80_TIC_SOURCE_ONE_INT : G80_TIC_SOURCE_ONE_FLOAT; 40bf215546Sopenharmony_ci case PIPE_SWIZZLE_0: 41bf215546Sopenharmony_ci default: 42bf215546Sopenharmony_ci return G80_TIC_SOURCE_ZERO; 43bf215546Sopenharmony_ci } 44bf215546Sopenharmony_ci} 45bf215546Sopenharmony_ci 46bf215546Sopenharmony_cistruct pipe_sampler_view * 47bf215546Sopenharmony_cinv50_create_sampler_view(struct pipe_context *pipe, 48bf215546Sopenharmony_ci struct pipe_resource *res, 49bf215546Sopenharmony_ci const struct pipe_sampler_view *templ) 50bf215546Sopenharmony_ci{ 51bf215546Sopenharmony_ci uint32_t flags = 0; 52bf215546Sopenharmony_ci 53bf215546Sopenharmony_ci if (templ->target == PIPE_TEXTURE_RECT || templ->target == PIPE_BUFFER) 54bf215546Sopenharmony_ci flags |= NV50_TEXVIEW_SCALED_COORDS; 55bf215546Sopenharmony_ci 56bf215546Sopenharmony_ci return nv50_create_texture_view(pipe, res, templ, flags); 57bf215546Sopenharmony_ci} 58bf215546Sopenharmony_ci 59bf215546Sopenharmony_cistruct pipe_sampler_view * 60bf215546Sopenharmony_cinv50_create_texture_view(struct pipe_context *pipe, 61bf215546Sopenharmony_ci struct pipe_resource *texture, 62bf215546Sopenharmony_ci const struct pipe_sampler_view *templ, 63bf215546Sopenharmony_ci uint32_t flags) 64bf215546Sopenharmony_ci{ 65bf215546Sopenharmony_ci const uint32_t class_3d = nouveau_context(pipe)->screen->class_3d; 66bf215546Sopenharmony_ci const struct util_format_description *desc; 67bf215546Sopenharmony_ci const struct nv50_format *fmt; 68bf215546Sopenharmony_ci uint64_t addr; 69bf215546Sopenharmony_ci uint32_t *tic; 70bf215546Sopenharmony_ci uint32_t swz[4]; 71bf215546Sopenharmony_ci uint32_t depth; 72bf215546Sopenharmony_ci struct nv50_tic_entry *view; 73bf215546Sopenharmony_ci struct nv50_miptree *mt = nv50_miptree(texture); 74bf215546Sopenharmony_ci bool tex_int; 75bf215546Sopenharmony_ci 76bf215546Sopenharmony_ci view = MALLOC_STRUCT(nv50_tic_entry); 77bf215546Sopenharmony_ci if (!view) 78bf215546Sopenharmony_ci return NULL; 79bf215546Sopenharmony_ci 80bf215546Sopenharmony_ci view->pipe = *templ; 81bf215546Sopenharmony_ci view->pipe.reference.count = 1; 82bf215546Sopenharmony_ci view->pipe.texture = NULL; 83bf215546Sopenharmony_ci view->pipe.context = pipe; 84bf215546Sopenharmony_ci 85bf215546Sopenharmony_ci view->id = -1; 86bf215546Sopenharmony_ci 87bf215546Sopenharmony_ci pipe_resource_reference(&view->pipe.texture, texture); 88bf215546Sopenharmony_ci 89bf215546Sopenharmony_ci tic = &view->tic[0]; 90bf215546Sopenharmony_ci 91bf215546Sopenharmony_ci desc = util_format_description(view->pipe.format); 92bf215546Sopenharmony_ci 93bf215546Sopenharmony_ci /* TIC[0] */ 94bf215546Sopenharmony_ci 95bf215546Sopenharmony_ci fmt = &nv50_format_table[view->pipe.format]; 96bf215546Sopenharmony_ci 97bf215546Sopenharmony_ci tex_int = util_format_is_pure_integer(view->pipe.format); 98bf215546Sopenharmony_ci 99bf215546Sopenharmony_ci swz[0] = nv50_tic_swizzle(fmt, view->pipe.swizzle_r, tex_int); 100bf215546Sopenharmony_ci swz[1] = nv50_tic_swizzle(fmt, view->pipe.swizzle_g, tex_int); 101bf215546Sopenharmony_ci swz[2] = nv50_tic_swizzle(fmt, view->pipe.swizzle_b, tex_int); 102bf215546Sopenharmony_ci swz[3] = nv50_tic_swizzle(fmt, view->pipe.swizzle_a, tex_int); 103bf215546Sopenharmony_ci tic[0] = (fmt->tic.format << G80_TIC_0_COMPONENTS_SIZES__SHIFT) | 104bf215546Sopenharmony_ci (fmt->tic.type_r << G80_TIC_0_R_DATA_TYPE__SHIFT) | 105bf215546Sopenharmony_ci (fmt->tic.type_g << G80_TIC_0_G_DATA_TYPE__SHIFT) | 106bf215546Sopenharmony_ci (fmt->tic.type_b << G80_TIC_0_B_DATA_TYPE__SHIFT) | 107bf215546Sopenharmony_ci (fmt->tic.type_a << G80_TIC_0_A_DATA_TYPE__SHIFT) | 108bf215546Sopenharmony_ci (swz[0] << G80_TIC_0_X_SOURCE__SHIFT) | 109bf215546Sopenharmony_ci (swz[1] << G80_TIC_0_Y_SOURCE__SHIFT) | 110bf215546Sopenharmony_ci (swz[2] << G80_TIC_0_Z_SOURCE__SHIFT) | 111bf215546Sopenharmony_ci (swz[3] << G80_TIC_0_W_SOURCE__SHIFT); 112bf215546Sopenharmony_ci 113bf215546Sopenharmony_ci addr = mt->base.address; 114bf215546Sopenharmony_ci 115bf215546Sopenharmony_ci depth = MAX2(mt->base.base.array_size, mt->base.base.depth0); 116bf215546Sopenharmony_ci 117bf215546Sopenharmony_ci if (mt->base.base.array_size > 1) { 118bf215546Sopenharmony_ci /* there doesn't seem to be a base layer field in TIC */ 119bf215546Sopenharmony_ci addr += view->pipe.u.tex.first_layer * mt->layer_stride; 120bf215546Sopenharmony_ci depth = view->pipe.u.tex.last_layer - view->pipe.u.tex.first_layer + 1; 121bf215546Sopenharmony_ci } 122bf215546Sopenharmony_ci 123bf215546Sopenharmony_ci tic[2] = 0x10001000 | G80_TIC_2_BORDER_SOURCE_COLOR; 124bf215546Sopenharmony_ci 125bf215546Sopenharmony_ci if (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) 126bf215546Sopenharmony_ci tic[2] |= G80_TIC_2_SRGB_CONVERSION; 127bf215546Sopenharmony_ci 128bf215546Sopenharmony_ci if (!(flags & NV50_TEXVIEW_SCALED_COORDS)) 129bf215546Sopenharmony_ci tic[2] |= G80_TIC_2_NORMALIZED_COORDS; 130bf215546Sopenharmony_ci 131bf215546Sopenharmony_ci if (unlikely(!nouveau_bo_memtype(nv04_resource(texture)->bo))) { 132bf215546Sopenharmony_ci if (templ->target == PIPE_BUFFER) { 133bf215546Sopenharmony_ci addr += view->pipe.u.buf.offset; 134bf215546Sopenharmony_ci tic[2] |= G80_TIC_2_LAYOUT_PITCH | G80_TIC_2_TEXTURE_TYPE_ONE_D_BUFFER; 135bf215546Sopenharmony_ci tic[3] = 0; 136bf215546Sopenharmony_ci tic[4] = /* width */ 137bf215546Sopenharmony_ci view->pipe.u.buf.size / (desc->block.bits / 8); 138bf215546Sopenharmony_ci tic[5] = 0; 139bf215546Sopenharmony_ci } else { 140bf215546Sopenharmony_ci tic[2] |= G80_TIC_2_LAYOUT_PITCH | G80_TIC_2_TEXTURE_TYPE_TWO_D_NO_MIPMAP; 141bf215546Sopenharmony_ci tic[3] = mt->level[0].pitch; 142bf215546Sopenharmony_ci tic[4] = mt->base.base.width0; 143bf215546Sopenharmony_ci tic[5] = (1 << 16) | (mt->base.base.height0); 144bf215546Sopenharmony_ci } 145bf215546Sopenharmony_ci tic[6] = 146bf215546Sopenharmony_ci tic[7] = 0; 147bf215546Sopenharmony_ci tic[1] = addr; 148bf215546Sopenharmony_ci tic[2] |= addr >> 32; 149bf215546Sopenharmony_ci return &view->pipe; 150bf215546Sopenharmony_ci } 151bf215546Sopenharmony_ci 152bf215546Sopenharmony_ci tic[1] = addr; 153bf215546Sopenharmony_ci tic[2] |= (addr >> 32) & 0xff; 154bf215546Sopenharmony_ci 155bf215546Sopenharmony_ci tic[2] |= 156bf215546Sopenharmony_ci ((mt->level[0].tile_mode & 0x0f0) << (22 - 4)) | 157bf215546Sopenharmony_ci ((mt->level[0].tile_mode & 0xf00) << (25 - 8)); 158bf215546Sopenharmony_ci 159bf215546Sopenharmony_ci switch (templ->target) { 160bf215546Sopenharmony_ci case PIPE_TEXTURE_1D: 161bf215546Sopenharmony_ci tic[2] |= G80_TIC_2_TEXTURE_TYPE_ONE_D; 162bf215546Sopenharmony_ci break; 163bf215546Sopenharmony_ci case PIPE_TEXTURE_2D: 164bf215546Sopenharmony_ci if (mt->ms_x) 165bf215546Sopenharmony_ci tic[2] |= G80_TIC_2_TEXTURE_TYPE_TWO_D_NO_MIPMAP; 166bf215546Sopenharmony_ci else 167bf215546Sopenharmony_ci tic[2] |= G80_TIC_2_TEXTURE_TYPE_TWO_D; 168bf215546Sopenharmony_ci break; 169bf215546Sopenharmony_ci case PIPE_TEXTURE_RECT: 170bf215546Sopenharmony_ci tic[2] |= G80_TIC_2_TEXTURE_TYPE_TWO_D_NO_MIPMAP; 171bf215546Sopenharmony_ci break; 172bf215546Sopenharmony_ci case PIPE_TEXTURE_3D: 173bf215546Sopenharmony_ci tic[2] |= G80_TIC_2_TEXTURE_TYPE_THREE_D; 174bf215546Sopenharmony_ci break; 175bf215546Sopenharmony_ci case PIPE_TEXTURE_CUBE: 176bf215546Sopenharmony_ci depth /= 6; 177bf215546Sopenharmony_ci tic[2] |= G80_TIC_2_TEXTURE_TYPE_CUBEMAP; 178bf215546Sopenharmony_ci break; 179bf215546Sopenharmony_ci case PIPE_TEXTURE_1D_ARRAY: 180bf215546Sopenharmony_ci tic[2] |= G80_TIC_2_TEXTURE_TYPE_ONE_D_ARRAY; 181bf215546Sopenharmony_ci break; 182bf215546Sopenharmony_ci case PIPE_TEXTURE_2D_ARRAY: 183bf215546Sopenharmony_ci tic[2] |= G80_TIC_2_TEXTURE_TYPE_TWO_D_ARRAY; 184bf215546Sopenharmony_ci break; 185bf215546Sopenharmony_ci case PIPE_TEXTURE_CUBE_ARRAY: 186bf215546Sopenharmony_ci depth /= 6; 187bf215546Sopenharmony_ci tic[2] |= G80_TIC_2_TEXTURE_TYPE_CUBE_ARRAY; 188bf215546Sopenharmony_ci break; 189bf215546Sopenharmony_ci case PIPE_BUFFER: 190bf215546Sopenharmony_ci assert(0); /* should be linear and handled above ! */ 191bf215546Sopenharmony_ci tic[2] |= G80_TIC_2_TEXTURE_TYPE_ONE_D_BUFFER | G80_TIC_2_LAYOUT_PITCH; 192bf215546Sopenharmony_ci break; 193bf215546Sopenharmony_ci default: 194bf215546Sopenharmony_ci unreachable("unexpected/invalid texture target"); 195bf215546Sopenharmony_ci } 196bf215546Sopenharmony_ci 197bf215546Sopenharmony_ci tic[3] = (flags & NV50_TEXVIEW_FILTER_MSAA8) ? 0x20000000 : 0x00300000; 198bf215546Sopenharmony_ci 199bf215546Sopenharmony_ci tic[4] = (1 << 31) | (mt->base.base.width0 << mt->ms_x); 200bf215546Sopenharmony_ci 201bf215546Sopenharmony_ci tic[5] = (mt->base.base.height0 << mt->ms_y) & 0xffff; 202bf215546Sopenharmony_ci tic[5] |= depth << 16; 203bf215546Sopenharmony_ci if (class_3d > NV50_3D_CLASS) 204bf215546Sopenharmony_ci tic[5] |= mt->base.base.last_level << G80_TIC_5_MAP_MIP_LEVEL__SHIFT; 205bf215546Sopenharmony_ci else 206bf215546Sopenharmony_ci tic[5] |= view->pipe.u.tex.last_level << G80_TIC_5_MAP_MIP_LEVEL__SHIFT; 207bf215546Sopenharmony_ci 208bf215546Sopenharmony_ci tic[6] = (mt->ms_x > 1) ? 0x88000000 : 0x03000000; /* sampling points */ 209bf215546Sopenharmony_ci 210bf215546Sopenharmony_ci if (class_3d > NV50_3D_CLASS) 211bf215546Sopenharmony_ci tic[7] = (view->pipe.u.tex.last_level << 4) | view->pipe.u.tex.first_level; 212bf215546Sopenharmony_ci else 213bf215546Sopenharmony_ci tic[7] = 0; 214bf215546Sopenharmony_ci 215bf215546Sopenharmony_ci if (unlikely(!(tic[2] & G80_TIC_2_NORMALIZED_COORDS))) 216bf215546Sopenharmony_ci if (mt->base.base.last_level) 217bf215546Sopenharmony_ci tic[5] &= ~G80_TIC_5_MAP_MIP_LEVEL__MASK; 218bf215546Sopenharmony_ci 219bf215546Sopenharmony_ci return &view->pipe; 220bf215546Sopenharmony_ci} 221bf215546Sopenharmony_ci 222bf215546Sopenharmony_cistatic void 223bf215546Sopenharmony_cinv50_update_tic(struct nv50_context *nv50, struct nv50_tic_entry *tic, 224bf215546Sopenharmony_ci struct nv04_resource *res) 225bf215546Sopenharmony_ci{ 226bf215546Sopenharmony_ci uint64_t address = res->address; 227bf215546Sopenharmony_ci if (res->base.target != PIPE_BUFFER) 228bf215546Sopenharmony_ci return; 229bf215546Sopenharmony_ci address += tic->pipe.u.buf.offset; 230bf215546Sopenharmony_ci if (tic->tic[1] == (uint32_t)address && 231bf215546Sopenharmony_ci (tic->tic[2] & 0xff) == address >> 32) 232bf215546Sopenharmony_ci return; 233bf215546Sopenharmony_ci 234bf215546Sopenharmony_ci nv50_screen_tic_unlock(nv50->screen, tic); 235bf215546Sopenharmony_ci tic->id = -1; 236bf215546Sopenharmony_ci tic->tic[1] = address; 237bf215546Sopenharmony_ci tic->tic[2] &= 0xffffff00; 238bf215546Sopenharmony_ci tic->tic[2] |= address >> 32; 239bf215546Sopenharmony_ci} 240bf215546Sopenharmony_ci 241bf215546Sopenharmony_cibool 242bf215546Sopenharmony_cinv50_validate_tic(struct nv50_context *nv50, int s) 243bf215546Sopenharmony_ci{ 244bf215546Sopenharmony_ci struct nouveau_pushbuf *push = nv50->base.pushbuf; 245bf215546Sopenharmony_ci struct nouveau_bo *txc = nv50->screen->txc; 246bf215546Sopenharmony_ci unsigned i; 247bf215546Sopenharmony_ci bool need_flush = false; 248bf215546Sopenharmony_ci const bool is_compute_stage = s == NV50_SHADER_STAGE_COMPUTE; 249bf215546Sopenharmony_ci 250bf215546Sopenharmony_ci assert(nv50->num_textures[s] <= PIPE_MAX_SAMPLERS); 251bf215546Sopenharmony_ci for (i = 0; i < nv50->num_textures[s]; ++i) { 252bf215546Sopenharmony_ci struct nv50_tic_entry *tic = nv50_tic_entry(nv50->textures[s][i]); 253bf215546Sopenharmony_ci struct nv04_resource *res; 254bf215546Sopenharmony_ci 255bf215546Sopenharmony_ci if (!tic) { 256bf215546Sopenharmony_ci if (unlikely(is_compute_stage)) 257bf215546Sopenharmony_ci BEGIN_NV04(push, NV50_CP(BIND_TIC), 1); 258bf215546Sopenharmony_ci else 259bf215546Sopenharmony_ci BEGIN_NV04(push, NV50_3D(BIND_TIC(s)), 1); 260bf215546Sopenharmony_ci PUSH_DATA (push, (i << 1) | 0); 261bf215546Sopenharmony_ci continue; 262bf215546Sopenharmony_ci } 263bf215546Sopenharmony_ci res = &nv50_miptree(tic->pipe.texture)->base; 264bf215546Sopenharmony_ci nv50_update_tic(nv50, tic, res); 265bf215546Sopenharmony_ci 266bf215546Sopenharmony_ci if (tic->id < 0) { 267bf215546Sopenharmony_ci tic->id = nv50_screen_tic_alloc(nv50->screen, tic); 268bf215546Sopenharmony_ci 269bf215546Sopenharmony_ci BEGIN_NV04(push, NV50_2D(DST_FORMAT), 2); 270bf215546Sopenharmony_ci PUSH_DATA (push, G80_SURFACE_FORMAT_R8_UNORM); 271bf215546Sopenharmony_ci PUSH_DATA (push, 1); 272bf215546Sopenharmony_ci BEGIN_NV04(push, NV50_2D(DST_PITCH), 5); 273bf215546Sopenharmony_ci PUSH_DATA (push, 262144); 274bf215546Sopenharmony_ci PUSH_DATA (push, 65536); 275bf215546Sopenharmony_ci PUSH_DATA (push, 1); 276bf215546Sopenharmony_ci PUSH_DATAh(push, txc->offset); 277bf215546Sopenharmony_ci PUSH_DATA (push, txc->offset); 278bf215546Sopenharmony_ci BEGIN_NV04(push, NV50_2D(SIFC_BITMAP_ENABLE), 2); 279bf215546Sopenharmony_ci PUSH_DATA (push, 0); 280bf215546Sopenharmony_ci PUSH_DATA (push, G80_SURFACE_FORMAT_R8_UNORM); 281bf215546Sopenharmony_ci BEGIN_NV04(push, NV50_2D(SIFC_WIDTH), 10); 282bf215546Sopenharmony_ci PUSH_DATA (push, 32); 283bf215546Sopenharmony_ci PUSH_DATA (push, 1); 284bf215546Sopenharmony_ci PUSH_DATA (push, 0); 285bf215546Sopenharmony_ci PUSH_DATA (push, 1); 286bf215546Sopenharmony_ci PUSH_DATA (push, 0); 287bf215546Sopenharmony_ci PUSH_DATA (push, 1); 288bf215546Sopenharmony_ci PUSH_DATA (push, 0); 289bf215546Sopenharmony_ci PUSH_DATA (push, tic->id * 32); 290bf215546Sopenharmony_ci PUSH_DATA (push, 0); 291bf215546Sopenharmony_ci PUSH_DATA (push, 0); 292bf215546Sopenharmony_ci BEGIN_NI04(push, NV50_2D(SIFC_DATA), 8); 293bf215546Sopenharmony_ci PUSH_DATAp(push, &tic->tic[0], 8); 294bf215546Sopenharmony_ci 295bf215546Sopenharmony_ci need_flush = true; 296bf215546Sopenharmony_ci } else 297bf215546Sopenharmony_ci if (res->status & NOUVEAU_BUFFER_STATUS_GPU_WRITING) { 298bf215546Sopenharmony_ci if (unlikely(is_compute_stage)) 299bf215546Sopenharmony_ci BEGIN_NV04(push, NV50_CP(TEX_CACHE_CTL), 1); 300bf215546Sopenharmony_ci else 301bf215546Sopenharmony_ci BEGIN_NV04(push, NV50_3D(TEX_CACHE_CTL), 1); 302bf215546Sopenharmony_ci PUSH_DATA (push, 0x20); 303bf215546Sopenharmony_ci } 304bf215546Sopenharmony_ci 305bf215546Sopenharmony_ci nv50->screen->tic.lock[tic->id / 32] |= 1 << (tic->id % 32); 306bf215546Sopenharmony_ci 307bf215546Sopenharmony_ci res->status &= ~NOUVEAU_BUFFER_STATUS_GPU_WRITING; 308bf215546Sopenharmony_ci res->status |= NOUVEAU_BUFFER_STATUS_GPU_READING; 309bf215546Sopenharmony_ci 310bf215546Sopenharmony_ci if (unlikely(is_compute_stage)) { 311bf215546Sopenharmony_ci BCTX_REFN(nv50->bufctx_cp, CP_TEXTURES, res, RD); 312bf215546Sopenharmony_ci BEGIN_NV04(push, NV50_CP(BIND_TIC), 1); 313bf215546Sopenharmony_ci } else { 314bf215546Sopenharmony_ci BCTX_REFN(nv50->bufctx_3d, 3D_TEXTURES, res, RD); 315bf215546Sopenharmony_ci BEGIN_NV04(push, NV50_3D(BIND_TIC(s)), 1); 316bf215546Sopenharmony_ci } 317bf215546Sopenharmony_ci PUSH_DATA (push, (tic->id << 9) | (i << 1) | 1); 318bf215546Sopenharmony_ci } 319bf215546Sopenharmony_ci for (; i < nv50->state.num_textures[s]; ++i) { 320bf215546Sopenharmony_ci if (unlikely(is_compute_stage)) 321bf215546Sopenharmony_ci BEGIN_NV04(push, NV50_CP(BIND_TIC), 1); 322bf215546Sopenharmony_ci else 323bf215546Sopenharmony_ci BEGIN_NV04(push, NV50_3D(BIND_TIC(s)), 1); 324bf215546Sopenharmony_ci PUSH_DATA (push, (i << 1) | 0); 325bf215546Sopenharmony_ci } 326bf215546Sopenharmony_ci if (nv50->num_textures[s]) { 327bf215546Sopenharmony_ci if (unlikely(is_compute_stage)) 328bf215546Sopenharmony_ci BEGIN_NV04(push, NV50_CP(CB_ADDR), 1); 329bf215546Sopenharmony_ci else 330bf215546Sopenharmony_ci BEGIN_NV04(push, NV50_3D(CB_ADDR), 1); 331bf215546Sopenharmony_ci PUSH_DATA (push, ((NV50_CB_AUX_TEX_MS_OFFSET + 16 * s * 2 * 4) << (8 - 2)) | NV50_CB_AUX); 332bf215546Sopenharmony_ci if (unlikely(is_compute_stage)) 333bf215546Sopenharmony_ci BEGIN_NV04(push, NV50_CP(CB_DATA(0)), nv50->num_textures[s] * 2); 334bf215546Sopenharmony_ci else 335bf215546Sopenharmony_ci BEGIN_NI04(push, NV50_3D(CB_DATA(0)), nv50->num_textures[s] * 2); 336bf215546Sopenharmony_ci for (i = 0; i < nv50->num_textures[s]; i++) { 337bf215546Sopenharmony_ci struct nv50_tic_entry *tic = nv50_tic_entry(nv50->textures[s][i]); 338bf215546Sopenharmony_ci struct nv50_miptree *res; 339bf215546Sopenharmony_ci 340bf215546Sopenharmony_ci if (!tic || tic->pipe.target == PIPE_BUFFER) { 341bf215546Sopenharmony_ci PUSH_DATA (push, 0); 342bf215546Sopenharmony_ci PUSH_DATA (push, 0); 343bf215546Sopenharmony_ci continue; 344bf215546Sopenharmony_ci } 345bf215546Sopenharmony_ci res = nv50_miptree(tic->pipe.texture); 346bf215546Sopenharmony_ci PUSH_DATA (push, res->ms_x); 347bf215546Sopenharmony_ci PUSH_DATA (push, res->ms_y); 348bf215546Sopenharmony_ci } 349bf215546Sopenharmony_ci } 350bf215546Sopenharmony_ci nv50->state.num_textures[s] = nv50->num_textures[s]; 351bf215546Sopenharmony_ci 352bf215546Sopenharmony_ci return need_flush; 353bf215546Sopenharmony_ci} 354bf215546Sopenharmony_ci 355bf215546Sopenharmony_civoid nv50_validate_textures(struct nv50_context *nv50) 356bf215546Sopenharmony_ci{ 357bf215546Sopenharmony_ci unsigned s; 358bf215546Sopenharmony_ci bool need_flush = false; 359bf215546Sopenharmony_ci 360bf215546Sopenharmony_ci for (s = 0; s < NV50_MAX_3D_SHADER_STAGES; ++s) 361bf215546Sopenharmony_ci need_flush |= nv50_validate_tic(nv50, s); 362bf215546Sopenharmony_ci 363bf215546Sopenharmony_ci if (need_flush) { 364bf215546Sopenharmony_ci BEGIN_NV04(nv50->base.pushbuf, NV50_3D(TIC_FLUSH), 1); 365bf215546Sopenharmony_ci PUSH_DATA (nv50->base.pushbuf, 0); 366bf215546Sopenharmony_ci } 367bf215546Sopenharmony_ci 368bf215546Sopenharmony_ci /* Invalidate all CP textures because they are aliased. */ 369bf215546Sopenharmony_ci nouveau_bufctx_reset(nv50->bufctx_cp, NV50_BIND_CP_TEXTURES); 370bf215546Sopenharmony_ci nv50->dirty_cp |= NV50_NEW_CP_TEXTURES; 371bf215546Sopenharmony_ci} 372bf215546Sopenharmony_ci 373bf215546Sopenharmony_cibool 374bf215546Sopenharmony_cinv50_validate_tsc(struct nv50_context *nv50, int s) 375bf215546Sopenharmony_ci{ 376bf215546Sopenharmony_ci struct nouveau_pushbuf *push = nv50->base.pushbuf; 377bf215546Sopenharmony_ci unsigned i; 378bf215546Sopenharmony_ci bool need_flush = false; 379bf215546Sopenharmony_ci const bool is_compute_stage = s == NV50_SHADER_STAGE_COMPUTE; 380bf215546Sopenharmony_ci 381bf215546Sopenharmony_ci assert(nv50->num_samplers[s] <= PIPE_MAX_SAMPLERS); 382bf215546Sopenharmony_ci for (i = 0; i < nv50->num_samplers[s]; ++i) { 383bf215546Sopenharmony_ci struct nv50_tsc_entry *tsc = nv50_tsc_entry(nv50->samplers[s][i]); 384bf215546Sopenharmony_ci 385bf215546Sopenharmony_ci if (!tsc) { 386bf215546Sopenharmony_ci if (is_compute_stage) 387bf215546Sopenharmony_ci BEGIN_NV04(push, NV50_CP(BIND_TSC), 1); 388bf215546Sopenharmony_ci else 389bf215546Sopenharmony_ci BEGIN_NV04(push, NV50_3D(BIND_TSC(s)), 1); 390bf215546Sopenharmony_ci PUSH_DATA (push, (i << 4) | 0); 391bf215546Sopenharmony_ci continue; 392bf215546Sopenharmony_ci } 393bf215546Sopenharmony_ci nv50->seamless_cube_map = tsc->seamless_cube_map; 394bf215546Sopenharmony_ci if (tsc->id < 0) { 395bf215546Sopenharmony_ci tsc->id = nv50_screen_tsc_alloc(nv50->screen, tsc); 396bf215546Sopenharmony_ci 397bf215546Sopenharmony_ci nv50_sifc_linear_u8(&nv50->base, nv50->screen->txc, 398bf215546Sopenharmony_ci 65536 + tsc->id * 32, 399bf215546Sopenharmony_ci NOUVEAU_BO_VRAM, 32, tsc->tsc); 400bf215546Sopenharmony_ci need_flush = true; 401bf215546Sopenharmony_ci } 402bf215546Sopenharmony_ci nv50->screen->tsc.lock[tsc->id / 32] |= 1 << (tsc->id % 32); 403bf215546Sopenharmony_ci 404bf215546Sopenharmony_ci if (is_compute_stage) 405bf215546Sopenharmony_ci BEGIN_NV04(push, NV50_CP(BIND_TSC), 1); 406bf215546Sopenharmony_ci else 407bf215546Sopenharmony_ci BEGIN_NV04(push, NV50_3D(BIND_TSC(s)), 1); 408bf215546Sopenharmony_ci PUSH_DATA (push, (tsc->id << 12) | (i << 4) | 1); 409bf215546Sopenharmony_ci } 410bf215546Sopenharmony_ci for (; i < nv50->state.num_samplers[s]; ++i) { 411bf215546Sopenharmony_ci if (is_compute_stage) 412bf215546Sopenharmony_ci BEGIN_NV04(push, NV50_CP(BIND_TSC), 1); 413bf215546Sopenharmony_ci else 414bf215546Sopenharmony_ci BEGIN_NV04(push, NV50_3D(BIND_TSC(s)), 1); 415bf215546Sopenharmony_ci PUSH_DATA (push, (i << 4) | 0); 416bf215546Sopenharmony_ci } 417bf215546Sopenharmony_ci nv50->state.num_samplers[s] = nv50->num_samplers[s]; 418bf215546Sopenharmony_ci 419bf215546Sopenharmony_ci // TXF, in unlinked tsc mode, will always use sampler 0. So we have to 420bf215546Sopenharmony_ci // ensure that it remains bound. Its contents don't matter, all samplers we 421bf215546Sopenharmony_ci // ever create have the SRGB_CONVERSION bit set, so as long as the first 422bf215546Sopenharmony_ci // entry is initialized, we're good to go. This is the only bit that has 423bf215546Sopenharmony_ci // any effect on what TXF does. 424bf215546Sopenharmony_ci if (!nv50->samplers[s][0]) { 425bf215546Sopenharmony_ci if (is_compute_stage) 426bf215546Sopenharmony_ci BEGIN_NV04(push, NV50_CP(BIND_TSC), 1); 427bf215546Sopenharmony_ci else 428bf215546Sopenharmony_ci BEGIN_NV04(push, NV50_3D(BIND_TSC(s)), 1); 429bf215546Sopenharmony_ci PUSH_DATA (push, 1); 430bf215546Sopenharmony_ci } 431bf215546Sopenharmony_ci 432bf215546Sopenharmony_ci return need_flush; 433bf215546Sopenharmony_ci} 434bf215546Sopenharmony_ci 435bf215546Sopenharmony_civoid nv50_validate_samplers(struct nv50_context *nv50) 436bf215546Sopenharmony_ci{ 437bf215546Sopenharmony_ci unsigned s; 438bf215546Sopenharmony_ci bool need_flush = false; 439bf215546Sopenharmony_ci 440bf215546Sopenharmony_ci for (s = 0; s < NV50_MAX_3D_SHADER_STAGES; ++s) 441bf215546Sopenharmony_ci need_flush |= nv50_validate_tsc(nv50, s); 442bf215546Sopenharmony_ci 443bf215546Sopenharmony_ci if (need_flush) { 444bf215546Sopenharmony_ci BEGIN_NV04(nv50->base.pushbuf, NV50_3D(TSC_FLUSH), 1); 445bf215546Sopenharmony_ci PUSH_DATA (nv50->base.pushbuf, 0); 446bf215546Sopenharmony_ci } 447bf215546Sopenharmony_ci 448bf215546Sopenharmony_ci /* Invalidate all CP samplers because they are aliased. */ 449bf215546Sopenharmony_ci nv50->dirty_cp |= NV50_NEW_CP_SAMPLERS; 450bf215546Sopenharmony_ci} 451bf215546Sopenharmony_ci 452bf215546Sopenharmony_ci/* There can be up to 4 different MS levels (1, 2, 4, 8). To simplify the 453bf215546Sopenharmony_ci * shader logic, allow each one to take up 8 offsets. 454bf215546Sopenharmony_ci */ 455bf215546Sopenharmony_ci#define COMBINE(x, y) x, y 456bf215546Sopenharmony_ci#define DUMMY 0, 0 457bf215546Sopenharmony_cistatic const uint32_t msaa_sample_xy_offsets[] = { 458bf215546Sopenharmony_ci /* MS1 */ 459bf215546Sopenharmony_ci COMBINE(0, 0), 460bf215546Sopenharmony_ci DUMMY, 461bf215546Sopenharmony_ci DUMMY, 462bf215546Sopenharmony_ci DUMMY, 463bf215546Sopenharmony_ci DUMMY, 464bf215546Sopenharmony_ci DUMMY, 465bf215546Sopenharmony_ci DUMMY, 466bf215546Sopenharmony_ci DUMMY, 467bf215546Sopenharmony_ci 468bf215546Sopenharmony_ci /* MS2 */ 469bf215546Sopenharmony_ci COMBINE(0, 0), 470bf215546Sopenharmony_ci COMBINE(1, 0), 471bf215546Sopenharmony_ci DUMMY, 472bf215546Sopenharmony_ci DUMMY, 473bf215546Sopenharmony_ci DUMMY, 474bf215546Sopenharmony_ci DUMMY, 475bf215546Sopenharmony_ci DUMMY, 476bf215546Sopenharmony_ci DUMMY, 477bf215546Sopenharmony_ci 478bf215546Sopenharmony_ci /* MS4 */ 479bf215546Sopenharmony_ci COMBINE(0, 0), 480bf215546Sopenharmony_ci COMBINE(1, 0), 481bf215546Sopenharmony_ci COMBINE(0, 1), 482bf215546Sopenharmony_ci COMBINE(1, 1), 483bf215546Sopenharmony_ci DUMMY, 484bf215546Sopenharmony_ci DUMMY, 485bf215546Sopenharmony_ci DUMMY, 486bf215546Sopenharmony_ci DUMMY, 487bf215546Sopenharmony_ci 488bf215546Sopenharmony_ci /* MS8 */ 489bf215546Sopenharmony_ci COMBINE(0, 0), 490bf215546Sopenharmony_ci COMBINE(1, 0), 491bf215546Sopenharmony_ci COMBINE(0, 1), 492bf215546Sopenharmony_ci COMBINE(1, 1), 493bf215546Sopenharmony_ci COMBINE(2, 0), 494bf215546Sopenharmony_ci COMBINE(3, 0), 495bf215546Sopenharmony_ci COMBINE(2, 1), 496bf215546Sopenharmony_ci COMBINE(3, 1), 497bf215546Sopenharmony_ci}; 498bf215546Sopenharmony_ci 499bf215546Sopenharmony_civoid nv50_upload_ms_info(struct nouveau_pushbuf *push) 500bf215546Sopenharmony_ci{ 501bf215546Sopenharmony_ci BEGIN_NV04(push, NV50_3D(CB_ADDR), 1); 502bf215546Sopenharmony_ci PUSH_DATA (push, (NV50_CB_AUX_MS_OFFSET << (8 - 2)) | NV50_CB_AUX); 503bf215546Sopenharmony_ci BEGIN_NI04(push, NV50_3D(CB_DATA(0)), ARRAY_SIZE(msaa_sample_xy_offsets)); 504bf215546Sopenharmony_ci PUSH_DATAp(push, msaa_sample_xy_offsets, ARRAY_SIZE(msaa_sample_xy_offsets)); 505bf215546Sopenharmony_ci} 506bf215546Sopenharmony_ci 507bf215546Sopenharmony_civoid nv50_upload_tsc0(struct nv50_context *nv50) 508bf215546Sopenharmony_ci{ 509bf215546Sopenharmony_ci struct nouveau_pushbuf *push = nv50->base.pushbuf; 510bf215546Sopenharmony_ci u32 data[8] = { G80_TSC_0_SRGB_CONVERSION }; 511bf215546Sopenharmony_ci nv50_sifc_linear_u8(&nv50->base, nv50->screen->txc, 512bf215546Sopenharmony_ci 65536 /* + tsc->id * 32 */, 513bf215546Sopenharmony_ci NOUVEAU_BO_VRAM, 32, data); 514bf215546Sopenharmony_ci BEGIN_NV04(push, NV50_3D(TSC_FLUSH), 1); 515bf215546Sopenharmony_ci PUSH_DATA (push, 0); 516bf215546Sopenharmony_ci} 517