Path: blob/21.2-virgl/src/gallium/drivers/nouveau/nv50/nv50_state_validate.c
4574 views
1#include "util/u_viewport.h"23#include "nv50/nv50_context.h"45static inline void6nv50_fb_set_null_rt(struct nouveau_pushbuf *push, unsigned i)7{8BEGIN_NV04(push, NV50_3D(RT_ADDRESS_HIGH(i)), 4);9PUSH_DATA (push, 0);10PUSH_DATA (push, 0);11PUSH_DATA (push, 0);12PUSH_DATA (push, 0);13BEGIN_NV04(push, NV50_3D(RT_HORIZ(i)), 2);14PUSH_DATA (push, 64);15PUSH_DATA (push, 0);16}1718static void19nv50_validate_fb(struct nv50_context *nv50)20{21struct nouveau_pushbuf *push = nv50->base.pushbuf;22struct pipe_framebuffer_state *fb = &nv50->framebuffer;23unsigned i;24unsigned ms_mode = NV50_3D_MULTISAMPLE_MODE_MS1;25uint32_t array_size = 0xffff, array_mode = 0;2627nouveau_bufctx_reset(nv50->bufctx_3d, NV50_BIND_3D_FB);2829BEGIN_NV04(push, NV50_3D(RT_CONTROL), 1);30PUSH_DATA (push, (076543210 << 4) | fb->nr_cbufs);31BEGIN_NV04(push, NV50_3D(SCREEN_SCISSOR_HORIZ), 2);32PUSH_DATA (push, fb->width << 16);33PUSH_DATA (push, fb->height << 16);3435for (i = 0; i < fb->nr_cbufs; ++i) {36struct nv50_miptree *mt;37struct nv50_surface *sf;38struct nouveau_bo *bo;3940if (!fb->cbufs[i]) {41nv50_fb_set_null_rt(push, i);42continue;43}4445mt = nv50_miptree(fb->cbufs[i]->texture);46sf = nv50_surface(fb->cbufs[i]);47bo = mt->base.bo;4849array_size = MIN2(array_size, sf->depth);50if (mt->layout_3d)51array_mode = NV50_3D_RT_ARRAY_MODE_MODE_3D; /* 1 << 16 */5253/* can't mix 3D with ARRAY or have RTs of different depth/array_size */54assert(mt->layout_3d || !array_mode || array_size == 1);5556BEGIN_NV04(push, NV50_3D(RT_ADDRESS_HIGH(i)), 5);57PUSH_DATAh(push, mt->base.address + sf->offset);58PUSH_DATA (push, mt->base.address + sf->offset);59PUSH_DATA (push, nv50_format_table[sf->base.format].rt);60if (likely(nouveau_bo_memtype(bo))) {61assert(sf->base.texture->target != PIPE_BUFFER);6263PUSH_DATA (push, mt->level[sf->base.u.tex.level].tile_mode);64PUSH_DATA (push, mt->layer_stride >> 2);65BEGIN_NV04(push, NV50_3D(RT_HORIZ(i)), 2);66PUSH_DATA (push, sf->width);67PUSH_DATA (push, sf->height);68BEGIN_NV04(push, NV50_3D(RT_ARRAY_MODE), 1);69PUSH_DATA (push, array_mode | array_size);70nv50->rt_array_mode = array_mode | array_size;71} else {72PUSH_DATA (push, 0);73PUSH_DATA (push, 0);74BEGIN_NV04(push, NV50_3D(RT_HORIZ(i)), 2);75PUSH_DATA (push, NV50_3D_RT_HORIZ_LINEAR | mt->level[0].pitch);76PUSH_DATA (push, sf->height);77BEGIN_NV04(push, NV50_3D(RT_ARRAY_MODE), 1);78PUSH_DATA (push, 0);7980assert(!fb->zsbuf);81assert(!mt->ms_mode);82}8384ms_mode = mt->ms_mode;8586if (mt->base.status & NOUVEAU_BUFFER_STATUS_GPU_READING)87nv50->state.rt_serialize = true;88mt->base.status |= NOUVEAU_BUFFER_STATUS_GPU_WRITING;89mt->base.status &= ~NOUVEAU_BUFFER_STATUS_GPU_READING;9091/* only register for writing, otherwise we'd always serialize here */92BCTX_REFN(nv50->bufctx_3d, 3D_FB, &mt->base, WR);93}9495if (fb->zsbuf) {96struct nv50_miptree *mt = nv50_miptree(fb->zsbuf->texture);97struct nv50_surface *sf = nv50_surface(fb->zsbuf);98int unk = mt->base.base.target == PIPE_TEXTURE_3D || sf->depth == 1;99100BEGIN_NV04(push, NV50_3D(ZETA_ADDRESS_HIGH), 5);101PUSH_DATAh(push, mt->base.address + sf->offset);102PUSH_DATA (push, mt->base.address + sf->offset);103PUSH_DATA (push, nv50_format_table[fb->zsbuf->format].rt);104PUSH_DATA (push, mt->level[sf->base.u.tex.level].tile_mode);105PUSH_DATA (push, mt->layer_stride >> 2);106BEGIN_NV04(push, NV50_3D(ZETA_ENABLE), 1);107PUSH_DATA (push, 1);108BEGIN_NV04(push, NV50_3D(ZETA_HORIZ), 3);109PUSH_DATA (push, sf->width);110PUSH_DATA (push, sf->height);111PUSH_DATA (push, (unk << 16) | sf->depth);112113ms_mode = mt->ms_mode;114115if (mt->base.status & NOUVEAU_BUFFER_STATUS_GPU_READING)116nv50->state.rt_serialize = true;117mt->base.status |= NOUVEAU_BUFFER_STATUS_GPU_WRITING;118mt->base.status &= ~NOUVEAU_BUFFER_STATUS_GPU_READING;119120BCTX_REFN(nv50->bufctx_3d, 3D_FB, &mt->base, WR);121} else {122BEGIN_NV04(push, NV50_3D(ZETA_ENABLE), 1);123PUSH_DATA (push, 0);124}125126BEGIN_NV04(push, NV50_3D(MULTISAMPLE_MODE), 1);127PUSH_DATA (push, ms_mode);128129/* Only need to initialize the first viewport, which is used for clears */130BEGIN_NV04(push, NV50_3D(VIEWPORT_HORIZ(0)), 2);131PUSH_DATA (push, fb->width << 16);132PUSH_DATA (push, fb->height << 16);133134if (nv50->screen->tesla->oclass >= NVA3_3D_CLASS) {135unsigned ms = 1 << ms_mode;136BEGIN_NV04(push, NV50_3D(CB_ADDR), 1);137PUSH_DATA (push, (NV50_CB_AUX_SAMPLE_OFFSET << (8 - 2)) | NV50_CB_AUX);138BEGIN_NI04(push, NV50_3D(CB_DATA(0)), 2 * ms);139for (i = 0; i < ms; i++) {140float xy[2];141nv50->base.pipe.get_sample_position(&nv50->base.pipe, ms, i, xy);142PUSH_DATAf(push, xy[0]);143PUSH_DATAf(push, xy[1]);144}145}146}147148static void149nv50_validate_blend_colour(struct nv50_context *nv50)150{151struct nouveau_pushbuf *push = nv50->base.pushbuf;152153BEGIN_NV04(push, NV50_3D(BLEND_COLOR(0)), 4);154PUSH_DATAf(push, nv50->blend_colour.color[0]);155PUSH_DATAf(push, nv50->blend_colour.color[1]);156PUSH_DATAf(push, nv50->blend_colour.color[2]);157PUSH_DATAf(push, nv50->blend_colour.color[3]);158}159160static void161nv50_validate_stencil_ref(struct nv50_context *nv50)162{163struct nouveau_pushbuf *push = nv50->base.pushbuf;164165BEGIN_NV04(push, NV50_3D(STENCIL_FRONT_FUNC_REF), 1);166PUSH_DATA (push, nv50->stencil_ref.ref_value[0]);167BEGIN_NV04(push, NV50_3D(STENCIL_BACK_FUNC_REF), 1);168PUSH_DATA (push, nv50->stencil_ref.ref_value[1]);169}170171static void172nv50_validate_stipple(struct nv50_context *nv50)173{174struct nouveau_pushbuf *push = nv50->base.pushbuf;175unsigned i;176177BEGIN_NV04(push, NV50_3D(POLYGON_STIPPLE_PATTERN(0)), 32);178for (i = 0; i < 32; ++i)179PUSH_DATA(push, util_bswap32(nv50->stipple.stipple[i]));180}181182static void183nv50_validate_scissor(struct nv50_context *nv50)184{185struct nouveau_pushbuf *push = nv50->base.pushbuf;186#ifdef NV50_SCISSORS_CLIPPING187int minx, maxx, miny, maxy, i;188bool rast_scissor = nv50->rast ? nv50->rast->pipe.scissor : false;189190if (!(nv50->dirty_3d &191(NV50_NEW_3D_SCISSOR | NV50_NEW_3D_VIEWPORT | NV50_NEW_3D_FRAMEBUFFER)) &&192nv50->state.scissor == rast_scissor)193return;194195if (nv50->state.scissor != rast_scissor)196nv50->scissors_dirty = (1 << NV50_MAX_VIEWPORTS) - 1;197198nv50->state.scissor = rast_scissor;199200if ((nv50->dirty_3d & NV50_NEW_3D_FRAMEBUFFER) && !nv50->state.scissor)201nv50->scissors_dirty = (1 << NV50_MAX_VIEWPORTS) - 1;202203for (i = 0; i < NV50_MAX_VIEWPORTS; i++) {204struct pipe_scissor_state *s = &nv50->scissors[i];205struct pipe_viewport_state *vp = &nv50->viewports[i];206207if (!(nv50->scissors_dirty & (1 << i)) &&208!(nv50->viewports_dirty & (1 << i)))209continue;210211if (nv50->state.scissor) {212minx = s->minx;213maxx = s->maxx;214miny = s->miny;215maxy = s->maxy;216} else {217minx = 0;218maxx = nv50->framebuffer.width;219miny = 0;220maxy = nv50->framebuffer.height;221}222223minx = MAX2(minx, (int)(vp->translate[0] - fabsf(vp->scale[0])));224maxx = MIN2(maxx, (int)(vp->translate[0] + fabsf(vp->scale[0])));225miny = MAX2(miny, (int)(vp->translate[1] - fabsf(vp->scale[1])));226maxy = MIN2(maxy, (int)(vp->translate[1] + fabsf(vp->scale[1])));227228minx = MIN2(minx, 8192);229maxx = MAX2(maxx, 0);230miny = MIN2(miny, 8192);231maxy = MAX2(maxy, 0);232233BEGIN_NV04(push, NV50_3D(SCISSOR_HORIZ(i)), 2);234PUSH_DATA (push, (maxx << 16) | minx);235PUSH_DATA (push, (maxy << 16) | miny);236#else237BEGIN_NV04(push, NV50_3D(SCISSOR_HORIZ(i)), 2);238PUSH_DATA (push, (s->maxx << 16) | s->minx);239PUSH_DATA (push, (s->maxy << 16) | s->miny);240#endif241}242243nv50->scissors_dirty = 0;244}245246static void247nv50_validate_viewport(struct nv50_context *nv50)248{249struct nouveau_pushbuf *push = nv50->base.pushbuf;250float zmin, zmax;251int i;252253for (i = 0; i < NV50_MAX_VIEWPORTS; i++) {254struct pipe_viewport_state *vpt = &nv50->viewports[i];255256if (!(nv50->viewports_dirty & (1 << i)))257continue;258259BEGIN_NV04(push, NV50_3D(VIEWPORT_TRANSLATE_X(i)), 3);260PUSH_DATAf(push, vpt->translate[0]);261PUSH_DATAf(push, vpt->translate[1]);262PUSH_DATAf(push, vpt->translate[2]);263BEGIN_NV04(push, NV50_3D(VIEWPORT_SCALE_X(i)), 3);264PUSH_DATAf(push, vpt->scale[0]);265PUSH_DATAf(push, vpt->scale[1]);266PUSH_DATAf(push, vpt->scale[2]);267268/* If the halfz setting ever changes, the viewports will also get269* updated. The rast will get updated before the validate function has a270* chance to hit, so we can just use it directly without an atom271* dependency.272*/273util_viewport_zmin_zmax(vpt, nv50->rast->pipe.clip_halfz, &zmin, &zmax);274275#ifdef NV50_SCISSORS_CLIPPING276BEGIN_NV04(push, NV50_3D(DEPTH_RANGE_NEAR(i)), 2);277PUSH_DATAf(push, zmin);278PUSH_DATAf(push, zmax);279#endif280}281282nv50->viewports_dirty = 0;283}284285static void286nv50_validate_window_rects(struct nv50_context *nv50)287{288struct nouveau_pushbuf *push = nv50->base.pushbuf;289bool enable = nv50->window_rect.rects > 0 || nv50->window_rect.inclusive;290int i;291292BEGIN_NV04(push, NV50_3D(CLIP_RECTS_EN), 1);293PUSH_DATA (push, enable);294if (!enable)295return;296297BEGIN_NV04(push, NV50_3D(CLIP_RECTS_MODE), 1);298PUSH_DATA (push, !nv50->window_rect.inclusive);299BEGIN_NV04(push, NV50_3D(CLIP_RECT_HORIZ(0)), NV50_MAX_WINDOW_RECTANGLES * 2);300for (i = 0; i < nv50->window_rect.rects; i++) {301struct pipe_scissor_state *s = &nv50->window_rect.rect[i];302PUSH_DATA(push, (s->maxx << 16) | s->minx);303PUSH_DATA(push, (s->maxy << 16) | s->miny);304}305for (; i < NV50_MAX_WINDOW_RECTANGLES; i++) {306PUSH_DATA(push, 0);307PUSH_DATA(push, 0);308}309}310311static inline void312nv50_check_program_ucps(struct nv50_context *nv50,313struct nv50_program *vp, uint8_t mask)314{315const unsigned n = util_logbase2(mask) + 1;316317if (vp->vp.clpd_nr >= n)318return;319nv50_program_destroy(nv50, vp);320321vp->vp.clpd_nr = n;322if (likely(vp == nv50->vertprog)) {323nv50->dirty_3d |= NV50_NEW_3D_VERTPROG;324nv50_vertprog_validate(nv50);325} else {326nv50->dirty_3d |= NV50_NEW_3D_GMTYPROG;327nv50_gmtyprog_validate(nv50);328}329nv50_fp_linkage_validate(nv50);330}331332/* alpha test is disabled if there are no color RTs, so make sure we have at333* least one if alpha test is enabled. Note that this must run after334* nv50_validate_fb, otherwise that will override the RT count setting.335*/336static void337nv50_validate_derived_2(struct nv50_context *nv50)338{339struct nouveau_pushbuf *push = nv50->base.pushbuf;340341if (nv50->zsa && nv50->zsa->pipe.alpha_enabled &&342nv50->framebuffer.nr_cbufs == 0) {343nv50_fb_set_null_rt(push, 0);344BEGIN_NV04(push, NV50_3D(RT_CONTROL), 1);345PUSH_DATA (push, (076543210 << 4) | 1);346}347}348349static void350nv50_validate_clip(struct nv50_context *nv50)351{352struct nouveau_pushbuf *push = nv50->base.pushbuf;353struct nv50_program *vp;354uint8_t clip_enable = nv50->rast->pipe.clip_plane_enable;355356if (nv50->dirty_3d & NV50_NEW_3D_CLIP) {357BEGIN_NV04(push, NV50_3D(CB_ADDR), 1);358PUSH_DATA (push, NV50_CB_AUX_UCP_OFFSET << (8 - 2) | NV50_CB_AUX);359BEGIN_NI04(push, NV50_3D(CB_DATA(0)), PIPE_MAX_CLIP_PLANES * 4);360PUSH_DATAp(push, &nv50->clip.ucp[0][0], PIPE_MAX_CLIP_PLANES * 4);361}362363vp = nv50->gmtyprog;364if (likely(!vp))365vp = nv50->vertprog;366367if (clip_enable)368nv50_check_program_ucps(nv50, vp, clip_enable);369370clip_enable &= vp->vp.clip_enable;371clip_enable |= vp->vp.cull_enable;372373BEGIN_NV04(push, NV50_3D(CLIP_DISTANCE_ENABLE), 1);374PUSH_DATA (push, clip_enable);375376if (nv50->state.clip_mode != vp->vp.clip_mode) {377nv50->state.clip_mode = vp->vp.clip_mode;378BEGIN_NV04(push, NV50_3D(CLIP_DISTANCE_MODE), 1);379PUSH_DATA (push, vp->vp.clip_mode);380}381}382383static void384nv50_validate_blend(struct nv50_context *nv50)385{386struct nouveau_pushbuf *push = nv50->base.pushbuf;387388PUSH_SPACE(push, nv50->blend->size);389PUSH_DATAp(push, nv50->blend->state, nv50->blend->size);390}391392static void393nv50_validate_zsa(struct nv50_context *nv50)394{395struct nouveau_pushbuf *push = nv50->base.pushbuf;396397PUSH_SPACE(push, nv50->zsa->size);398PUSH_DATAp(push, nv50->zsa->state, nv50->zsa->size);399}400401static void402nv50_validate_rasterizer(struct nv50_context *nv50)403{404struct nouveau_pushbuf *push = nv50->base.pushbuf;405406PUSH_SPACE(push, nv50->rast->size);407PUSH_DATAp(push, nv50->rast->state, nv50->rast->size);408}409410static void411nv50_validate_sample_mask(struct nv50_context *nv50)412{413struct nouveau_pushbuf *push = nv50->base.pushbuf;414415unsigned mask[4] =416{417nv50->sample_mask & 0xffff,418nv50->sample_mask & 0xffff,419nv50->sample_mask & 0xffff,420nv50->sample_mask & 0xffff421};422423BEGIN_NV04(push, NV50_3D(MSAA_MASK(0)), 4);424PUSH_DATA (push, mask[0]);425PUSH_DATA (push, mask[1]);426PUSH_DATA (push, mask[2]);427PUSH_DATA (push, mask[3]);428}429430static void431nv50_validate_min_samples(struct nv50_context *nv50)432{433struct nouveau_pushbuf *push = nv50->base.pushbuf;434int samples;435436if (nv50->screen->tesla->oclass < NVA3_3D_CLASS)437return;438439samples = util_next_power_of_two(nv50->min_samples);440if (samples > 1)441samples |= NVA3_3D_SAMPLE_SHADING_ENABLE;442443BEGIN_NV04(push, SUBC_3D(NVA3_3D_SAMPLE_SHADING), 1);444PUSH_DATA (push, samples);445}446447static void448nv50_switch_pipe_context(struct nv50_context *ctx_to)449{450struct nv50_context *ctx_from = ctx_to->screen->cur_ctx;451452if (ctx_from)453ctx_to->state = ctx_from->state;454else455ctx_to->state = ctx_to->screen->save_state;456457ctx_to->dirty_3d = ~0;458ctx_to->dirty_cp = ~0;459ctx_to->viewports_dirty = ~0;460ctx_to->scissors_dirty = ~0;461462ctx_to->constbuf_dirty[NV50_SHADER_STAGE_VERTEX] =463ctx_to->constbuf_dirty[NV50_SHADER_STAGE_GEOMETRY] =464ctx_to->constbuf_dirty[NV50_SHADER_STAGE_FRAGMENT] = (1 << NV50_MAX_PIPE_CONSTBUFS) - 1;465466if (!ctx_to->vertex)467ctx_to->dirty_3d &= ~(NV50_NEW_3D_VERTEX | NV50_NEW_3D_ARRAYS);468469if (!ctx_to->vertprog)470ctx_to->dirty_3d &= ~NV50_NEW_3D_VERTPROG;471if (!ctx_to->fragprog)472ctx_to->dirty_3d &= ~NV50_NEW_3D_FRAGPROG;473474if (!ctx_to->blend)475ctx_to->dirty_3d &= ~NV50_NEW_3D_BLEND;476if (!ctx_to->rast)477#ifdef NV50_SCISSORS_CLIPPING478ctx_to->dirty_3d &= ~(NV50_NEW_3D_RASTERIZER | NV50_NEW_3D_SCISSOR);479#else480ctx_to->dirty_3d &= ~NV50_NEW_3D_RASTERIZER;481#endif482if (!ctx_to->zsa)483ctx_to->dirty_3d &= ~NV50_NEW_3D_ZSA;484485ctx_to->screen->cur_ctx = ctx_to;486}487488static struct nv50_state_validate489validate_list_3d[] = {490{ nv50_validate_fb, NV50_NEW_3D_FRAMEBUFFER },491{ nv50_validate_blend, NV50_NEW_3D_BLEND },492{ nv50_validate_zsa, NV50_NEW_3D_ZSA },493{ nv50_validate_sample_mask, NV50_NEW_3D_SAMPLE_MASK },494{ nv50_validate_rasterizer, NV50_NEW_3D_RASTERIZER },495{ nv50_validate_blend_colour, NV50_NEW_3D_BLEND_COLOUR },496{ nv50_validate_stencil_ref, NV50_NEW_3D_STENCIL_REF },497{ nv50_validate_stipple, NV50_NEW_3D_STIPPLE },498#ifdef NV50_SCISSORS_CLIPPING499{ nv50_validate_scissor, NV50_NEW_3D_SCISSOR | NV50_NEW_3D_VIEWPORT |500NV50_NEW_3D_RASTERIZER |501NV50_NEW_3D_FRAMEBUFFER },502#else503{ nv50_validate_scissor, NV50_NEW_3D_SCISSOR },504#endif505{ nv50_validate_viewport, NV50_NEW_3D_VIEWPORT },506{ nv50_validate_window_rects, NV50_NEW_3D_WINDOW_RECTS },507{ nv50_vertprog_validate, NV50_NEW_3D_VERTPROG },508{ nv50_gmtyprog_validate, NV50_NEW_3D_GMTYPROG },509{ nv50_fragprog_validate, NV50_NEW_3D_FRAGPROG | NV50_NEW_3D_RASTERIZER |510NV50_NEW_3D_MIN_SAMPLES | NV50_NEW_3D_ZSA |511NV50_NEW_3D_FRAMEBUFFER},512{ nv50_fp_linkage_validate, NV50_NEW_3D_FRAGPROG | NV50_NEW_3D_VERTPROG |513NV50_NEW_3D_GMTYPROG | NV50_NEW_3D_RASTERIZER },514{ nv50_gp_linkage_validate, NV50_NEW_3D_GMTYPROG | NV50_NEW_3D_VERTPROG },515{ nv50_validate_derived_rs, NV50_NEW_3D_FRAGPROG | NV50_NEW_3D_RASTERIZER |516NV50_NEW_3D_VERTPROG | NV50_NEW_3D_GMTYPROG },517{ nv50_validate_derived_2, NV50_NEW_3D_ZSA | NV50_NEW_3D_FRAMEBUFFER },518{ nv50_validate_clip, NV50_NEW_3D_CLIP | NV50_NEW_3D_RASTERIZER |519NV50_NEW_3D_VERTPROG | NV50_NEW_3D_GMTYPROG },520{ nv50_constbufs_validate, NV50_NEW_3D_CONSTBUF },521{ nv50_validate_textures, NV50_NEW_3D_TEXTURES },522{ nv50_validate_samplers, NV50_NEW_3D_SAMPLERS },523{ nv50_stream_output_validate, NV50_NEW_3D_STRMOUT |524NV50_NEW_3D_VERTPROG | NV50_NEW_3D_GMTYPROG },525{ nv50_vertex_arrays_validate, NV50_NEW_3D_VERTEX | NV50_NEW_3D_ARRAYS },526{ nv50_validate_min_samples, NV50_NEW_3D_MIN_SAMPLES },527};528529bool530nv50_state_validate(struct nv50_context *nv50, uint32_t mask,531struct nv50_state_validate *validate_list, int size,532uint32_t *dirty, struct nouveau_bufctx *bufctx)533{534uint32_t state_mask;535int ret;536unsigned i;537538if (nv50->screen->cur_ctx != nv50)539nv50_switch_pipe_context(nv50);540541state_mask = *dirty & mask;542543if (state_mask) {544for (i = 0; i < size; i++) {545struct nv50_state_validate *validate = &validate_list[i];546547if (state_mask & validate->states)548validate->func(nv50);549}550*dirty &= ~state_mask;551552if (nv50->state.rt_serialize) {553nv50->state.rt_serialize = false;554BEGIN_NV04(nv50->base.pushbuf, SUBC_3D(NV50_GRAPH_SERIALIZE), 1);555PUSH_DATA (nv50->base.pushbuf, 0);556}557558nv50_bufctx_fence(bufctx, false);559}560nouveau_pushbuf_bufctx(nv50->base.pushbuf, bufctx);561ret = nouveau_pushbuf_validate(nv50->base.pushbuf);562563return !ret;564}565566bool567nv50_state_validate_3d(struct nv50_context *nv50, uint32_t mask)568{569bool ret;570571ret = nv50_state_validate(nv50, mask, validate_list_3d,572ARRAY_SIZE(validate_list_3d), &nv50->dirty_3d,573nv50->bufctx_3d);574575if (unlikely(nv50->state.flushed)) {576nv50->state.flushed = false;577nv50_bufctx_fence(nv50->bufctx_3d, true);578}579return ret;580}581582583