X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fdrivers%2Fnouveau%2Fnvc0%2Fnvc0_state.c;h=2f00bd1c9377811bad326323a521903f03d7e40e;hb=6e52c6dfcc93aa801d1ac86796492fc325d997d2;hp=24a6c222dd5ba926d49f1a642fd8ca9e848bc375;hpb=83c86e09a8d7610022eae49731ac1ed03ee4f67b;p=mesa.git diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_state.c b/src/gallium/drivers/nouveau/nvc0/nvc0_state.c index 24a6c222dd5..2f00bd1c937 100644 --- a/src/gallium/drivers/nouveau/nvc0/nvc0_state.c +++ b/src/gallium/drivers/nouveau/nvc0/nvc0_state.c @@ -21,18 +21,20 @@ */ #include "pipe/p_defines.h" +#include "util/u_framebuffer.h" #include "util/u_helpers.h" #include "util/u_inlines.h" #include "util/u_transfer.h" #include "tgsi/tgsi_parse.h" +#include "compiler/nir/nir.h" +#include "compiler/nir/nir_serialize.h" #include "nvc0/nvc0_stateobj.h" #include "nvc0/nvc0_context.h" #include "nvc0/nvc0_query_hw.h" #include "nvc0/nvc0_3d.xml.h" -#include "nv50/nv50_texture.xml.h" #include "nouveau_gldefs.h" @@ -91,6 +93,7 @@ nvc0_blend_state_create(struct pipe_context *pipe, struct nvc0_blend_stateobj *so = CALLOC_STRUCT(nvc0_blend_stateobj); int i; int r; /* reference */ + uint32_t ms; uint8_t blend_en = 0; bool indep_masks = false; bool indep_funcs = false; @@ -176,6 +179,15 @@ nvc0_blend_state_create(struct pipe_context *pipe, } } + ms = 0; + if (cso->alpha_to_coverage) + ms |= NVC0_3D_MULTISAMPLE_CTRL_ALPHA_TO_COVERAGE; + if (cso->alpha_to_one) + ms |= NVC0_3D_MULTISAMPLE_CTRL_ALPHA_TO_ONE; + + SB_BEGIN_3D(so, MULTISAMPLE_CTRL, 1); + SB_DATA (so, ms); + assert(so->size <= ARRAY_SIZE(so->state)); return so; } @@ -186,7 +198,7 @@ nvc0_blend_state_bind(struct pipe_context *pipe, void *hwcso) struct nvc0_context *nvc0 = nvc0_context(pipe); nvc0->blend = hwcso; - nvc0->dirty |= NVC0_NEW_BLEND; + nvc0->dirty_3d |= NVC0_NEW_3D_BLEND; } static void @@ -201,6 +213,7 @@ nvc0_rasterizer_state_create(struct pipe_context *pipe, const struct pipe_rasterizer_state *cso) { struct nvc0_rasterizer_stateobj *so; + uint16_t class_3d = nouveau_screen(pipe->screen)->class_3d; uint32_t reg; so = CALLOC_STRUCT(nvc0_rasterizer_stateobj); @@ -251,6 +264,12 @@ nvc0_rasterizer_state_create(struct pipe_context *pipe, SB_IMMED_3D(so, POINT_SPRITE_ENABLE, cso->point_quad_rasterization); SB_IMMED_3D(so, POINT_SMOOTH_ENABLE, cso->point_smooth); + if (class_3d >= GM200_3D_CLASS) { + SB_IMMED_3D(so, FILL_RECTANGLE, + cso->fill_front == PIPE_POLYGON_MODE_FILL_RECTANGLE ? + NVC0_3D_FILL_RECTANGLE_ENABLE : 0); + } + SB_BEGIN_3D(so, MACRO_POLYGON_MODE_FRONT, 1); SB_DATA (so, nvgl_polygon_mode(cso->fill_front)); SB_BEGIN_3D(so, MACRO_POLYGON_MODE_BACK, 1); @@ -283,13 +302,15 @@ nvc0_rasterizer_state_create(struct pipe_context *pipe, if (cso->offset_point || cso->offset_line || cso->offset_tri) { SB_BEGIN_3D(so, POLYGON_OFFSET_FACTOR, 1); SB_DATA (so, fui(cso->offset_scale)); - SB_BEGIN_3D(so, POLYGON_OFFSET_UNITS, 1); - SB_DATA (so, fui(cso->offset_units * 2.0f)); + if (!cso->offset_units_unscaled) { + SB_BEGIN_3D(so, POLYGON_OFFSET_UNITS, 1); + SB_DATA (so, fui(cso->offset_units * 2.0f)); + } SB_BEGIN_3D(so, POLYGON_OFFSET_CLAMP, 1); SB_DATA (so, fui(cso->offset_clamp)); } - if (cso->depth_clip) + if (cso->depth_clip_near) reg = NVC0_3D_VIEW_VOLUME_CLIP_CTRL_UNK1_UNK1; else reg = @@ -305,6 +326,20 @@ nvc0_rasterizer_state_create(struct pipe_context *pipe, SB_IMMED_3D(so, PIXEL_CENTER_INTEGER, !cso->half_pixel_center); + if (class_3d >= GM200_3D_CLASS) { + if (cso->conservative_raster_mode != PIPE_CONSERVATIVE_RASTER_OFF) { + bool post_snap = cso->conservative_raster_mode == + PIPE_CONSERVATIVE_RASTER_POST_SNAP; + uint32_t state = cso->subpixel_precision_x; + state |= cso->subpixel_precision_y << 4; + state |= (uint32_t)(cso->conservative_raster_dilate * 4) << 8; + state |= (post_snap || class_3d < GP100_3D_CLASS) ? 1 << 10 : 0; + SB_IMMED_3D(so, MACRO_CONSERVATIVE_RASTER_STATE, state); + } else { + SB_IMMED_3D(so, CONSERVATIVE_RASTER, 0); + } + } + assert(so->size <= ARRAY_SIZE(so->state)); return (void *)so; } @@ -315,7 +350,7 @@ nvc0_rasterizer_state_bind(struct pipe_context *pipe, void *hwcso) struct nvc0_context *nvc0 = nvc0_context(pipe); nvc0->rast = hwcso; - nvc0->dirty |= NVC0_NEW_RASTERIZER; + nvc0->dirty_3d |= NVC0_NEW_3D_RASTERIZER; } static void @@ -393,7 +428,7 @@ nvc0_zsa_state_bind(struct pipe_context *pipe, void *hwcso) struct nvc0_context *nvc0 = nvc0_context(pipe); nvc0->zsa = hwcso; - nvc0->dirty |= NVC0_NEW_ZSA; + nvc0->dirty_3d |= NVC0_NEW_3D_ZSA; } static void @@ -413,7 +448,7 @@ nvc0_sampler_state_delete(struct pipe_context *pipe, void *hwcso) { unsigned s, i; - for (s = 0; s < 5; ++s) + for (s = 0; s < 6; ++s) for (i = 0; i < nvc0_context(pipe)->num_samplers[s]; ++i) if (nvc0_context(pipe)->samplers[s][i] == hwcso) nvc0_context(pipe)->samplers[s][i] = NULL; @@ -424,107 +459,46 @@ nvc0_sampler_state_delete(struct pipe_context *pipe, void *hwcso) } static inline void -nvc0_stage_sampler_states_bind(struct nvc0_context *nvc0, int s, - unsigned nr, void **hwcso) +nvc0_stage_sampler_states_bind(struct nvc0_context *nvc0, + unsigned s, + unsigned nr, void **hwcsos) { + unsigned highest_found = 0; unsigned i; for (i = 0; i < nr; ++i) { + struct nv50_tsc_entry *hwcso = hwcsos ? nv50_tsc_entry(hwcsos[i]) : NULL; struct nv50_tsc_entry *old = nvc0->samplers[s][i]; - if (hwcso[i] == old) + if (hwcso) + highest_found = i; + + if (hwcso == old) continue; nvc0->samplers_dirty[s] |= 1 << i; - nvc0->samplers[s][i] = nv50_tsc_entry(hwcso[i]); + nvc0->samplers[s][i] = hwcso; if (old) nvc0_screen_tsc_unlock(nvc0->screen, old); } - for (; i < nvc0->num_samplers[s]; ++i) { - if (nvc0->samplers[s][i]) { - nvc0_screen_tsc_unlock(nvc0->screen, nvc0->samplers[s][i]); - nvc0->samplers[s][i] = NULL; - } - } - - nvc0->num_samplers[s] = nr; - - nvc0->dirty |= NVC0_NEW_SAMPLERS; + if (nr >= nvc0->num_samplers[s]) + nvc0->num_samplers[s] = highest_found + 1; } static void -nvc0_stage_sampler_states_bind_range(struct nvc0_context *nvc0, - const unsigned s, - unsigned start, unsigned nr, void **cso) +nvc0_bind_sampler_states(struct pipe_context *pipe, + enum pipe_shader_type shader, + unsigned start, unsigned nr, void **samplers) { - const unsigned end = start + nr; - int last_valid = -1; - unsigned i; - - if (cso) { - for (i = start; i < end; ++i) { - const unsigned p = i - start; - if (cso[p]) - last_valid = i; - if (cso[p] == nvc0->samplers[s][i]) - continue; - nvc0->samplers_dirty[s] |= 1 << i; - - if (nvc0->samplers[s][i]) - nvc0_screen_tsc_unlock(nvc0->screen, nvc0->samplers[s][i]); - nvc0->samplers[s][i] = cso[p]; - } - } else { - for (i = start; i < end; ++i) { - if (nvc0->samplers[s][i]) { - nvc0_screen_tsc_unlock(nvc0->screen, nvc0->samplers[s][i]); - nvc0->samplers[s][i] = NULL; - nvc0->samplers_dirty[s] |= 1 << i; - } - } - } + const unsigned s = nvc0_shader_stage(shader); - if (nvc0->num_samplers[s] <= end) { - if (last_valid < 0) { - for (i = start; i && !nvc0->samplers[s][i - 1]; --i); - nvc0->num_samplers[s] = i; - } else { - nvc0->num_samplers[s] = last_valid + 1; - } - } -} + assert(start == 0); + nvc0_stage_sampler_states_bind(nvc0_context(pipe), s, nr, samplers); -static void -nvc0_bind_sampler_states(struct pipe_context *pipe, unsigned shader, - unsigned start, unsigned nr, void **s) -{ - switch (shader) { - case PIPE_SHADER_VERTEX: - assert(start == 0); - nvc0_stage_sampler_states_bind(nvc0_context(pipe), 0, nr, s); - break; - case PIPE_SHADER_TESS_CTRL: - assert(start == 0); - nvc0_stage_sampler_states_bind(nvc0_context(pipe), 1, nr, s); - break; - case PIPE_SHADER_TESS_EVAL: - assert(start == 0); - nvc0_stage_sampler_states_bind(nvc0_context(pipe), 2, nr, s); - break; - case PIPE_SHADER_GEOMETRY: - assert(start == 0); - nvc0_stage_sampler_states_bind(nvc0_context(pipe), 3, nr, s); - break; - case PIPE_SHADER_FRAGMENT: - assert(start == 0); - nvc0_stage_sampler_states_bind(nvc0_context(pipe), 4, nr, s); - break; - case PIPE_SHADER_COMPUTE: - nvc0_stage_sampler_states_bind_range(nvc0_context(pipe), 5, - start, nr, s); + if (s == 5) nvc0_context(pipe)->dirty_cp |= NVC0_NEW_CP_SAMPLERS; - break; - } + else + nvc0_context(pipe)->dirty_3d |= NVC0_NEW_3D_SAMPLERS; } @@ -548,14 +522,15 @@ nvc0_stage_set_sampler_views(struct nvc0_context *nvc0, int s, unsigned i; for (i = 0; i < nr; ++i) { + struct pipe_sampler_view *view = views ? views[i] : NULL; struct nv50_tic_entry *old = nv50_tic_entry(nvc0->textures[s][i]); - if (views[i] == nvc0->textures[s][i]) + if (view == nvc0->textures[s][i]) continue; nvc0->textures_dirty[s] |= 1 << i; - if (views[i] && views[i]->texture) { - struct pipe_resource *res = views[i]->texture; + if (view && view->texture) { + struct pipe_resource *res = view->texture; if (res->target == PIPE_BUFFER && (res->flags & PIPE_RESOURCE_FLAG_MAP_COHERENT)) nvc0->textures_coherent[s] |= 1 << i; @@ -566,121 +541,47 @@ nvc0_stage_set_sampler_views(struct nvc0_context *nvc0, int s, } if (old) { - nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_TEX(s, i)); + if (s == 5) + nouveau_bufctx_reset(nvc0->bufctx_cp, NVC0_BIND_CP_TEX(i)); + else + nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_3D_TEX(s, i)); nvc0_screen_tic_unlock(nvc0->screen, old); } - pipe_sampler_view_reference(&nvc0->textures[s][i], views[i]); + pipe_sampler_view_reference(&nvc0->textures[s][i], view); } for (i = nr; i < nvc0->num_textures[s]; ++i) { struct nv50_tic_entry *old = nv50_tic_entry(nvc0->textures[s][i]); if (old) { - nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_TEX(s, i)); + if (s == 5) + nouveau_bufctx_reset(nvc0->bufctx_cp, NVC0_BIND_CP_TEX(i)); + else + nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_3D_TEX(s, i)); nvc0_screen_tic_unlock(nvc0->screen, old); pipe_sampler_view_reference(&nvc0->textures[s][i], NULL); } } nvc0->num_textures[s] = nr; - - nvc0->dirty |= NVC0_NEW_TEXTURES; -} - -static void -nvc0_stage_set_sampler_views_range(struct nvc0_context *nvc0, const unsigned s, - unsigned start, unsigned nr, - struct pipe_sampler_view **views) -{ - struct nouveau_bufctx *bctx = (s == 5) ? nvc0->bufctx_cp : nvc0->bufctx_3d; - const unsigned end = start + nr; - const unsigned bin = (s == 5) ? NVC0_BIND_CP_TEX(0) : NVC0_BIND_TEX(s, 0); - int last_valid = -1; - unsigned i; - - if (views) { - for (i = start; i < end; ++i) { - const unsigned p = i - start; - if (views[p]) - last_valid = i; - if (views[p] == nvc0->textures[s][i]) - continue; - nvc0->textures_dirty[s] |= 1 << i; - - if (views[p] && views[p]->texture) { - struct pipe_resource *res = views[p]->texture; - if (res->target == PIPE_BUFFER && - (res->flags & PIPE_RESOURCE_FLAG_MAP_COHERENT)) - nvc0->textures_coherent[s] |= 1 << i; - else - nvc0->textures_coherent[s] &= ~(1 << i); - } else { - nvc0->textures_coherent[s] &= ~(1 << i); - } - - if (nvc0->textures[s][i]) { - struct nv50_tic_entry *old = nv50_tic_entry(nvc0->textures[s][i]); - nouveau_bufctx_reset(bctx, bin + i); - nvc0_screen_tic_unlock(nvc0->screen, old); - } - pipe_sampler_view_reference(&nvc0->textures[s][i], views[p]); - } - } else { - for (i = start; i < end; ++i) { - struct nv50_tic_entry *old = nv50_tic_entry(nvc0->textures[s][i]); - if (!old) - continue; - nvc0->textures_dirty[s] |= 1 << i; - - nvc0_screen_tic_unlock(nvc0->screen, old); - pipe_sampler_view_reference(&nvc0->textures[s][i], NULL); - nouveau_bufctx_reset(bctx, bin + i); - } - } - - if (nvc0->num_textures[s] <= end) { - if (last_valid < 0) { - for (i = start; i && !nvc0->textures[s][i - 1]; --i); - nvc0->num_textures[s] = i; - } else { - nvc0->num_textures[s] = last_valid + 1; - } - } } static void -nvc0_set_sampler_views(struct pipe_context *pipe, unsigned shader, +nvc0_set_sampler_views(struct pipe_context *pipe, enum pipe_shader_type shader, unsigned start, unsigned nr, struct pipe_sampler_view **views) { + const unsigned s = nvc0_shader_stage(shader); + assert(start == 0); - switch (shader) { - case PIPE_SHADER_VERTEX: - nvc0_stage_set_sampler_views(nvc0_context(pipe), 0, nr, views); - break; - case PIPE_SHADER_TESS_CTRL: - nvc0_stage_set_sampler_views(nvc0_context(pipe), 1, nr, views); - break; - case PIPE_SHADER_TESS_EVAL: - nvc0_stage_set_sampler_views(nvc0_context(pipe), 2, nr, views); - break; - case PIPE_SHADER_GEOMETRY: - nvc0_stage_set_sampler_views(nvc0_context(pipe), 3, nr, views); - break; - case PIPE_SHADER_FRAGMENT: - nvc0_stage_set_sampler_views(nvc0_context(pipe), 4, nr, views); - break; - case PIPE_SHADER_COMPUTE: - nvc0_stage_set_sampler_views_range(nvc0_context(pipe), 5, - start, nr, views); + nvc0_stage_set_sampler_views(nvc0_context(pipe), s, nr, views); + + if (s == 5) nvc0_context(pipe)->dirty_cp |= NVC0_NEW_CP_TEXTURES; - break; - default: - ; - } + else + nvc0_context(pipe)->dirty_3d |= NVC0_NEW_3D_TEXTURES; } - /* ============================= SHADERS ======================================= */ @@ -695,15 +596,27 @@ nvc0_sp_state_create(struct pipe_context *pipe, return NULL; prog->type = type; + prog->pipe.type = cso->type; - if (cso->tokens) + switch(cso->type) { + case PIPE_SHADER_IR_TGSI: prog->pipe.tokens = tgsi_dup_tokens(cso->tokens); + break; + case PIPE_SHADER_IR_NIR: + prog->pipe.ir.nir = cso->ir.nir; + break; + default: + assert(!"unsupported IR!"); + free(prog); + return NULL; + } if (cso->stream_output.num_outputs) prog->pipe.stream_output = cso->stream_output; prog->translated = nvc0_program_translate( prog, nvc0_context(pipe)->screen->base.device->chipset, + nvc0_context(pipe)->screen->base.disk_shader_cache, &nouveau_context(pipe)->debug); return (void *)prog; @@ -716,7 +629,10 @@ nvc0_sp_state_delete(struct pipe_context *pipe, void *hwcso) nvc0_program_destroy(nvc0_context(pipe), prog); - FREE((void *)prog->pipe.tokens); + if (prog->pipe.type == PIPE_SHADER_IR_TGSI) + FREE((void *)prog->pipe.tokens); + else if (prog->pipe.type == PIPE_SHADER_IR_NIR) + ralloc_free(prog->pipe.ir.nir); FREE(prog); } @@ -733,7 +649,7 @@ nvc0_vp_state_bind(struct pipe_context *pipe, void *hwcso) struct nvc0_context *nvc0 = nvc0_context(pipe); nvc0->vertprog = hwcso; - nvc0->dirty |= NVC0_NEW_VERTPROG; + nvc0->dirty_3d |= NVC0_NEW_3D_VERTPROG; } static void * @@ -749,7 +665,7 @@ nvc0_fp_state_bind(struct pipe_context *pipe, void *hwcso) struct nvc0_context *nvc0 = nvc0_context(pipe); nvc0->fragprog = hwcso; - nvc0->dirty |= NVC0_NEW_FRAGPROG; + nvc0->dirty_3d |= NVC0_NEW_3D_FRAGPROG; } static void * @@ -765,7 +681,7 @@ nvc0_gp_state_bind(struct pipe_context *pipe, void *hwcso) struct nvc0_context *nvc0 = nvc0_context(pipe); nvc0->gmtyprog = hwcso; - nvc0->dirty |= NVC0_NEW_GMTYPROG; + nvc0->dirty_3d |= NVC0_NEW_3D_GMTYPROG; } static void * @@ -781,7 +697,7 @@ nvc0_tcp_state_bind(struct pipe_context *pipe, void *hwcso) struct nvc0_context *nvc0 = nvc0_context(pipe); nvc0->tctlprog = hwcso; - nvc0->dirty |= NVC0_NEW_TCTLPROG; + nvc0->dirty_3d |= NVC0_NEW_3D_TCTLPROG; } static void * @@ -797,7 +713,7 @@ nvc0_tep_state_bind(struct pipe_context *pipe, void *hwcso) struct nvc0_context *nvc0 = nvc0_context(pipe); nvc0->tevlprog = hwcso; - nvc0->dirty |= NVC0_NEW_TEVLPROG; + nvc0->dirty_3d |= NVC0_NEW_3D_TEVLPROG; } static void * @@ -810,12 +726,38 @@ nvc0_cp_state_create(struct pipe_context *pipe, if (!prog) return NULL; prog->type = PIPE_SHADER_COMPUTE; + prog->pipe.type = cso->ir_type; prog->cp.smem_size = cso->req_local_mem; prog->cp.lmem_size = cso->req_private_mem; prog->parm_size = cso->req_input_mem; - prog->pipe.tokens = tgsi_dup_tokens((const struct tgsi_token *)cso->prog); + switch(cso->ir_type) { + case PIPE_SHADER_IR_TGSI: + prog->pipe.tokens = tgsi_dup_tokens((const struct tgsi_token *)cso->prog); + break; + case PIPE_SHADER_IR_NIR: + prog->pipe.ir.nir = (nir_shader *)cso->prog; + break; + case PIPE_SHADER_IR_NIR_SERIALIZED: { + struct blob_reader reader; + const struct pipe_binary_program_header *hdr = cso->prog; + + blob_reader_init(&reader, hdr->blob, hdr->num_bytes); + prog->pipe.ir.nir = nir_deserialize(NULL, pipe->screen->get_compiler_options(pipe->screen, PIPE_SHADER_IR_NIR, PIPE_SHADER_COMPUTE), &reader); + prog->pipe.type = PIPE_SHADER_IR_NIR; + break; + } + default: + assert(!"unsupported IR!"); + free(prog); + return NULL; + } + + prog->translated = nvc0_program_translate( + prog, nvc0_context(pipe)->screen->base.device->chipset, + nvc0_context(pipe)->screen->base.disk_shader_cache, + &nouveau_context(pipe)->debug); return (void *)prog; } @@ -830,8 +772,9 @@ nvc0_cp_state_bind(struct pipe_context *pipe, void *hwcso) } static void -nvc0_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index, - struct pipe_constant_buffer *cb) +nvc0_set_constant_buffer(struct pipe_context *pipe, + enum pipe_shader_type shader, uint index, + const struct pipe_constant_buffer *cb) { struct nvc0_context *nvc0 = nvc0_context(pipe); struct pipe_resource *res = cb ? cb->buffer : NULL; @@ -839,7 +782,9 @@ nvc0_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index, const unsigned i = index; if (unlikely(shader == PIPE_SHADER_COMPUTE)) { - assert(!cb || !cb->user_buffer); + if (nvc0->constbuf[s][i].user) + nvc0->constbuf[s][i].u.buf = NULL; + else if (nvc0->constbuf[s][i].u.buf) nouveau_bufctx_reset(nvc0->bufctx_cp, NVC0_BIND_CP_CB(i)); @@ -849,9 +794,9 @@ nvc0_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index, nvc0->constbuf[s][i].u.buf = NULL; else if (nvc0->constbuf[s][i].u.buf) - nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_CB(s, i)); + nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_3D_CB(s, i)); - nvc0->dirty |= NVC0_NEW_CONSTBUF; + nvc0->dirty_3d |= NVC0_NEW_3D_CONSTBUF; } nvc0->constbuf_dirty[s] |= 1 << i; @@ -891,7 +836,7 @@ nvc0_set_blend_color(struct pipe_context *pipe, struct nvc0_context *nvc0 = nvc0_context(pipe); nvc0->blend_colour = *bcol; - nvc0->dirty |= NVC0_NEW_BLEND_COLOUR; + nvc0->dirty_3d |= NVC0_NEW_3D_BLEND_COLOUR; } static void @@ -901,7 +846,7 @@ nvc0_set_stencil_ref(struct pipe_context *pipe, struct nvc0_context *nvc0 = nvc0_context(pipe); nvc0->stencil_ref = *sr; - nvc0->dirty |= NVC0_NEW_STENCIL_REF; + nvc0->dirty_3d |= NVC0_NEW_3D_STENCIL_REF; } static void @@ -912,7 +857,7 @@ nvc0_set_clip_state(struct pipe_context *pipe, memcpy(nvc0->clip.ucp, clip->ucp, sizeof(clip->ucp)); - nvc0->dirty |= NVC0_NEW_CLIP; + nvc0->dirty_3d |= NVC0_NEW_3D_CLIP; } static void @@ -921,7 +866,7 @@ nvc0_set_sample_mask(struct pipe_context *pipe, unsigned sample_mask) struct nvc0_context *nvc0 = nvc0_context(pipe); nvc0->sample_mask = sample_mask; - nvc0->dirty |= NVC0_NEW_SAMPLE_MASK; + nvc0->dirty_3d |= NVC0_NEW_3D_SAMPLE_MASK; } static void @@ -931,7 +876,7 @@ nvc0_set_min_samples(struct pipe_context *pipe, unsigned min_samples) if (nvc0->min_samples != min_samples) { nvc0->min_samples = min_samples; - nvc0->dirty |= NVC0_NEW_MIN_SAMPLES; + nvc0->dirty_3d |= NVC0_NEW_3D_MIN_SAMPLES; } } @@ -940,23 +885,28 @@ nvc0_set_framebuffer_state(struct pipe_context *pipe, const struct pipe_framebuffer_state *fb) { struct nvc0_context *nvc0 = nvc0_context(pipe); - unsigned i; - nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_FB); + nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_3D_FB); - for (i = 0; i < fb->nr_cbufs; ++i) - pipe_surface_reference(&nvc0->framebuffer.cbufs[i], fb->cbufs[i]); - for (; i < nvc0->framebuffer.nr_cbufs; ++i) - pipe_surface_reference(&nvc0->framebuffer.cbufs[i], NULL); + util_copy_framebuffer_state(&nvc0->framebuffer, fb); - nvc0->framebuffer.nr_cbufs = fb->nr_cbufs; + nvc0->dirty_3d |= NVC0_NEW_3D_FRAMEBUFFER | NVC0_NEW_3D_SAMPLE_LOCATIONS | + NVC0_NEW_3D_TEXTURES; + nvc0->dirty_cp |= NVC0_NEW_CP_TEXTURES; +} - nvc0->framebuffer.width = fb->width; - nvc0->framebuffer.height = fb->height; +static void +nvc0_set_sample_locations(struct pipe_context *pipe, + size_t size, const uint8_t *locations) +{ + struct nvc0_context *nvc0 = nvc0_context(pipe); - pipe_surface_reference(&nvc0->framebuffer.zsbuf, fb->zsbuf); + nvc0->sample_locations_enabled = size && locations; + if (size > sizeof(nvc0->sample_locations)) + size = sizeof(nvc0->sample_locations); + memcpy(nvc0->sample_locations, locations, size); - nvc0->dirty |= NVC0_NEW_FRAMEBUFFER; + nvc0->dirty_3d |= NVC0_NEW_3D_SAMPLE_LOCATIONS; } static void @@ -966,7 +916,7 @@ nvc0_set_polygon_stipple(struct pipe_context *pipe, struct nvc0_context *nvc0 = nvc0_context(pipe); nvc0->stipple = *stipple; - nvc0->dirty |= NVC0_NEW_STIPPLE; + nvc0->dirty_3d |= NVC0_NEW_3D_STIPPLE; } static void @@ -984,7 +934,7 @@ nvc0_set_scissor_states(struct pipe_context *pipe, continue; nvc0->scissors[start_slot + i] = scissor[i]; nvc0->scissors_dirty |= 1 << (start_slot + i); - nvc0->dirty |= NVC0_NEW_SCISSOR; + nvc0->dirty_3d |= NVC0_NEW_3D_SCISSOR; } } @@ -1003,11 +953,27 @@ nvc0_set_viewport_states(struct pipe_context *pipe, continue; nvc0->viewports[start_slot + i] = vpt[i]; nvc0->viewports_dirty |= 1 << (start_slot + i); - nvc0->dirty |= NVC0_NEW_VIEWPORT; + nvc0->dirty_3d |= NVC0_NEW_3D_VIEWPORT; } } +static void +nvc0_set_window_rectangles(struct pipe_context *pipe, + bool include, + unsigned num_rectangles, + const struct pipe_scissor_state *rectangles) +{ + struct nvc0_context *nvc0 = nvc0_context(pipe); + + nvc0->window_rect.inclusive = include; + nvc0->window_rect.rects = MIN2(num_rectangles, NVC0_MAX_WINDOW_RECTANGLES); + memcpy(nvc0->window_rect.rect, rectangles, + sizeof(struct pipe_scissor_state) * nvc0->window_rect.rects); + + nvc0->dirty_3d |= NVC0_NEW_3D_WINDOW_RECTS; +} + static void nvc0_set_tess_state(struct pipe_context *pipe, const float default_tess_outer[4], @@ -1017,7 +983,7 @@ nvc0_set_tess_state(struct pipe_context *pipe, memcpy(nvc0->default_tess_outer, default_tess_outer, 4 * sizeof(float)); memcpy(nvc0->default_tess_inner, default_tess_inner, 2 * sizeof(float)); - nvc0->dirty |= NVC0_NEW_TESSFACTOR; + nvc0->dirty_3d |= NVC0_NEW_3D_TESSFACTOR; } static void @@ -1028,8 +994,8 @@ nvc0_set_vertex_buffers(struct pipe_context *pipe, struct nvc0_context *nvc0 = nvc0_context(pipe); unsigned i; - nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_VTX); - nvc0->dirty |= NVC0_NEW_ARRAYS; + nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_3D_VTX); + nvc0->dirty_3d |= NVC0_NEW_3D_ARRAYS; util_set_vertex_buffers_count(nvc0->vtxbuf, &nvc0->num_vtxbufs, vb, start_slot, count); @@ -1044,7 +1010,7 @@ nvc0_set_vertex_buffers(struct pipe_context *pipe, for (i = 0; i < count; ++i) { unsigned dst_index = start_slot + i; - if (vb[i].user_buffer) { + if (vb[i].is_user_buffer) { nvc0->vbo_user |= 1 << dst_index; if (!vb[i].stride && nvc0->screen->eng3d->oclass < GM107_3D_CLASS) nvc0->constant_vbos |= 1 << dst_index; @@ -1055,8 +1021,8 @@ nvc0_set_vertex_buffers(struct pipe_context *pipe, nvc0->vbo_user &= ~(1 << dst_index); nvc0->constant_vbos &= ~(1 << dst_index); - if (vb[i].buffer && - vb[i].buffer->flags & PIPE_RESOURCE_FLAG_MAP_COHERENT) + if (vb[i].buffer.resource && + vb[i].buffer.resource->flags & PIPE_RESOURCE_FLAG_MAP_COHERENT) nvc0->vtxbufs_coherent |= (1 << dst_index); else nvc0->vtxbufs_coherent &= ~(1 << dst_index); @@ -1064,38 +1030,13 @@ nvc0_set_vertex_buffers(struct pipe_context *pipe, } } -static void -nvc0_set_index_buffer(struct pipe_context *pipe, - const struct pipe_index_buffer *ib) -{ - struct nvc0_context *nvc0 = nvc0_context(pipe); - - if (nvc0->idxbuf.buffer) - nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_IDX); - - if (ib) { - pipe_resource_reference(&nvc0->idxbuf.buffer, ib->buffer); - nvc0->idxbuf.index_size = ib->index_size; - if (ib->buffer) { - nvc0->idxbuf.offset = ib->offset; - nvc0->dirty |= NVC0_NEW_IDXBUF; - } else { - nvc0->idxbuf.user_buffer = ib->user_buffer; - nvc0->dirty &= ~NVC0_NEW_IDXBUF; - } - } else { - nvc0->dirty &= ~NVC0_NEW_IDXBUF; - pipe_resource_reference(&nvc0->idxbuf.buffer, NULL); - } -} - static void nvc0_vertex_state_bind(struct pipe_context *pipe, void *hwcso) { struct nvc0_context *nvc0 = nvc0_context(pipe); nvc0->vertex = hwcso; - nvc0->dirty |= NVC0_NEW_VERTEX; + nvc0->dirty_3d |= NVC0_NEW_3D_VERTEX; } static struct pipe_stream_output_target * @@ -1123,7 +1064,7 @@ nvc0_so_target_create(struct pipe_context *pipe, pipe_reference_init(&targ->pipe.reference, 1); assert(buf->base.target == PIPE_BUFFER); - util_range_add(&buf->valid_buffer_range, offset, offset + size); + util_range_add(&buf->base, &buf->valid_buffer_range, offset, offset + size); return &targ->pipe; } @@ -1193,8 +1134,10 @@ nvc0_set_transform_feedback_targets(struct pipe_context *pipe, } nvc0->num_tfbbufs = num_targets; - if (nvc0->tfbbuf_dirty) - nvc0->dirty |= NVC0_NEW_TFB_TARGETS; + if (nvc0->tfbbuf_dirty) { + nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_3D_TFB); + nvc0->dirty_3d |= NVC0_NEW_3D_TFB_TARGETS; + } } static void @@ -1223,7 +1166,7 @@ nvc0_bind_surfaces_range(struct nvc0_context *nvc0, const unsigned t, nvc0->surfaces_dirty[t] |= mask; if (t == 0) - nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_SUF); + nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_3D_SUF); else nouveau_bufctx_reset(nvc0->bufctx_cp, NVC0_BIND_CP_SUF); } @@ -1238,16 +1181,175 @@ nvc0_set_compute_resources(struct pipe_context *pipe, nvc0_context(pipe)->dirty_cp |= NVC0_NEW_CP_SURFACES; } +static bool +nvc0_bind_images_range(struct nvc0_context *nvc0, const unsigned s, + unsigned start, unsigned nr, + const struct pipe_image_view *pimages) +{ + const unsigned end = start + nr; + unsigned mask = 0; + unsigned i; + + assert(s < 6); + + if (pimages) { + for (i = start; i < end; ++i) { + struct pipe_image_view *img = &nvc0->images[s][i]; + const unsigned p = i - start; + + if (img->resource == pimages[p].resource && + img->format == pimages[p].format && + img->access == pimages[p].access) { + if (img->resource == NULL) + continue; + if (img->resource->target == PIPE_BUFFER && + img->u.buf.offset == pimages[p].u.buf.offset && + img->u.buf.size == pimages[p].u.buf.size) + continue; + if (img->resource->target != PIPE_BUFFER && + img->u.tex.first_layer == pimages[p].u.tex.first_layer && + img->u.tex.last_layer == pimages[p].u.tex.last_layer && + img->u.tex.level == pimages[p].u.tex.level) + continue; + } + + mask |= (1 << i); + if (pimages[p].resource) + nvc0->images_valid[s] |= (1 << i); + else + nvc0->images_valid[s] &= ~(1 << i); + + img->format = pimages[p].format; + img->access = pimages[p].access; + if (pimages[p].resource && pimages[p].resource->target == PIPE_BUFFER) + img->u.buf = pimages[p].u.buf; + else + img->u.tex = pimages[p].u.tex; + + pipe_resource_reference( + &img->resource, pimages[p].resource); + + if (nvc0->screen->base.class_3d >= GM107_3D_CLASS) { + if (nvc0->images_tic[s][i]) { + struct nv50_tic_entry *old = + nv50_tic_entry(nvc0->images_tic[s][i]); + nvc0_screen_tic_unlock(nvc0->screen, old); + pipe_sampler_view_reference(&nvc0->images_tic[s][i], NULL); + } + + nvc0->images_tic[s][i] = + gm107_create_texture_view_from_image(&nvc0->base.pipe, + &pimages[p]); + } + } + if (!mask) + return false; + } else { + mask = ((1 << nr) - 1) << start; + if (!(nvc0->images_valid[s] & mask)) + return false; + for (i = start; i < end; ++i) { + pipe_resource_reference(&nvc0->images[s][i].resource, NULL); + if (nvc0->screen->base.class_3d >= GM107_3D_CLASS) { + struct nv50_tic_entry *old = nv50_tic_entry(nvc0->images_tic[s][i]); + if (old) { + nvc0_screen_tic_unlock(nvc0->screen, old); + pipe_sampler_view_reference(&nvc0->images_tic[s][i], NULL); + } + } + } + nvc0->images_valid[s] &= ~mask; + } + nvc0->images_dirty[s] |= mask; + + if (s == 5) + nouveau_bufctx_reset(nvc0->bufctx_cp, NVC0_BIND_CP_SUF); + else + nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_3D_SUF); + + return true; +} + +static void +nvc0_set_shader_images(struct pipe_context *pipe, + enum pipe_shader_type shader, + unsigned start, unsigned nr, + const struct pipe_image_view *images) +{ + const unsigned s = nvc0_shader_stage(shader); + if (!nvc0_bind_images_range(nvc0_context(pipe), s, start, nr, images)) + return; + + if (s == 5) + nvc0_context(pipe)->dirty_cp |= NVC0_NEW_CP_SURFACES; + else + nvc0_context(pipe)->dirty_3d |= NVC0_NEW_3D_SURFACES; +} + +static bool +nvc0_bind_buffers_range(struct nvc0_context *nvc0, const unsigned t, + unsigned start, unsigned nr, + const struct pipe_shader_buffer *pbuffers) +{ + const unsigned end = start + nr; + unsigned mask = 0; + unsigned i; + + assert(t < 6); + + if (pbuffers) { + for (i = start; i < end; ++i) { + struct pipe_shader_buffer *buf = &nvc0->buffers[t][i]; + const unsigned p = i - start; + if (buf->buffer == pbuffers[p].buffer && + buf->buffer_offset == pbuffers[p].buffer_offset && + buf->buffer_size == pbuffers[p].buffer_size) + continue; + + mask |= (1 << i); + if (pbuffers[p].buffer) + nvc0->buffers_valid[t] |= (1 << i); + else + nvc0->buffers_valid[t] &= ~(1 << i); + buf->buffer_offset = pbuffers[p].buffer_offset; + buf->buffer_size = pbuffers[p].buffer_size; + pipe_resource_reference(&buf->buffer, pbuffers[p].buffer); + } + if (!mask) + return false; + } else { + mask = ((1 << nr) - 1) << start; + if (!(nvc0->buffers_valid[t] & mask)) + return false; + for (i = start; i < end; ++i) + pipe_resource_reference(&nvc0->buffers[t][i].buffer, NULL); + nvc0->buffers_valid[t] &= ~mask; + } + nvc0->buffers_dirty[t] |= mask; + + if (t == 5) + nouveau_bufctx_reset(nvc0->bufctx_cp, NVC0_BIND_CP_BUF); + else + nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_3D_BUF); + + return true; +} + static void -nvc0_set_shader_images(struct pipe_context *pipe, unsigned shader, - unsigned start_slot, unsigned count, - struct pipe_image_view **views) +nvc0_set_shader_buffers(struct pipe_context *pipe, + enum pipe_shader_type shader, + unsigned start, unsigned nr, + const struct pipe_shader_buffer *buffers, + unsigned writable_bitmask) { -#if 0 - nvc0_bind_surfaces_range(nvc0_context(pipe), 0, start, nr, views); + const unsigned s = nvc0_shader_stage(shader); + if (!nvc0_bind_buffers_range(nvc0_context(pipe), s, start, nr, buffers)) + return; - nvc0_context(pipe)->dirty |= NVC0_NEW_SURFACES; -#endif + if (s == 5) + nvc0_context(pipe)->dirty_cp |= NVC0_NEW_CP_BUFFERS; + else + nvc0_context(pipe)->dirty_3d |= NVC0_NEW_3D_BUFFERS; } static inline void @@ -1255,14 +1357,9 @@ nvc0_set_global_handle(uint32_t *phandle, struct pipe_resource *res) { struct nv04_resource *buf = nv04_resource(res); if (buf) { - uint64_t limit = (buf->address + buf->base.width0) - 1; - if (limit < (1ULL << 32)) { - *phandle = (uint32_t)buf->address; - } else { - NOUVEAU_ERR("Cannot map into TGSI_RESOURCE_GLOBAL: " - "resource not contained within 32-bit address space !\n"); - *phandle = 0; - } + uint64_t address = buf->address + *phandle; + /* even though it's a pointer to uint32_t that's fine */ + memcpy(phandle, &address, 8); } else { *phandle = 0; } @@ -1279,12 +1376,18 @@ nvc0_set_global_bindings(struct pipe_context *pipe, unsigned i; const unsigned end = start + nr; + if (!nr) + return; + if (nvc0->global_residents.size <= (end * sizeof(struct pipe_resource *))) { const unsigned old_size = nvc0->global_residents.size; - const unsigned req_size = end * sizeof(struct pipe_resource *); - util_dynarray_resize(&nvc0->global_residents, req_size); - memset((uint8_t *)nvc0->global_residents.data + old_size, 0, - req_size - old_size); + if (util_dynarray_resize(&nvc0->global_residents, struct pipe_resource *, end)) { + memset((uint8_t *)nvc0->global_residents.data + old_size, 0, + nvc0->global_residents.size - old_size); + } else { + NOUVEAU_ERR("Could not resize global residents array\n"); + return; + } } if (resources) { @@ -1303,7 +1406,7 @@ nvc0_set_global_bindings(struct pipe_context *pipe, nouveau_bufctx_reset(nvc0->bufctx_cp, NVC0_BIND_CP_GLOBAL); - nvc0->dirty_cp = NVC0_NEW_CP_GLOBALS; + nvc0->dirty_cp |= NVC0_NEW_CP_GLOBALS; } void @@ -1358,9 +1461,11 @@ nvc0_init_state_functions(struct nvc0_context *nvc0) pipe->set_min_samples = nvc0_set_min_samples; pipe->set_constant_buffer = nvc0_set_constant_buffer; pipe->set_framebuffer_state = nvc0_set_framebuffer_state; + pipe->set_sample_locations = nvc0_set_sample_locations; pipe->set_polygon_stipple = nvc0_set_polygon_stipple; pipe->set_scissor_states = nvc0_set_scissor_states; pipe->set_viewport_states = nvc0_set_viewport_states; + pipe->set_window_rectangles = nvc0_set_window_rectangles; pipe->set_tess_state = nvc0_set_tess_state; pipe->create_vertex_elements_state = nvc0_vertex_state_create; @@ -1368,7 +1473,6 @@ nvc0_init_state_functions(struct nvc0_context *nvc0) pipe->bind_vertex_elements_state = nvc0_vertex_state_bind; pipe->set_vertex_buffers = nvc0_set_vertex_buffers; - pipe->set_index_buffer = nvc0_set_index_buffer; pipe->create_stream_output_target = nvc0_so_target_create; pipe->stream_output_target_destroy = nvc0_so_target_destroy; @@ -1377,6 +1481,7 @@ nvc0_init_state_functions(struct nvc0_context *nvc0) pipe->set_global_binding = nvc0_set_global_bindings; pipe->set_compute_resources = nvc0_set_compute_resources; pipe->set_shader_images = nvc0_set_shader_images; + pipe->set_shader_buffers = nvc0_set_shader_buffers; nvc0->sample_mask = ~0; nvc0->min_samples = 1;