From 4c2247538394a313e1e90bfcd07c1ab9c7d41281 Mon Sep 17 00:00:00 2001 From: Christoph Bumiller Date: Fri, 12 Nov 2010 15:17:40 +0100 Subject: nvc0: import nvc0 gallium driver --- src/gallium/drivers/nvc0/nvc0_state.c | 849 ++++++++++++++++++++++++++++++++++ 1 file changed, 849 insertions(+) create mode 100644 src/gallium/drivers/nvc0/nvc0_state.c (limited to 'src/gallium/drivers/nvc0/nvc0_state.c') diff --git a/src/gallium/drivers/nvc0/nvc0_state.c b/src/gallium/drivers/nvc0/nvc0_state.c new file mode 100644 index 0000000000..afba7ce6a0 --- /dev/null +++ b/src/gallium/drivers/nvc0/nvc0_state.c @@ -0,0 +1,849 @@ +/* + * Copyright 2010 Christoph Bumiller + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "pipe/p_defines.h" +#include "util/u_inlines.h" + +#include "tgsi/tgsi_parse.h" + +#include "nvc0_stateobj.h" +#include "nvc0_context.h" + +#include "nvc0_3d.xml.h" +#include "nv50_texture.xml.h" + +#include "nouveau/nouveau_gldefs.h" + +static INLINE uint32_t +nvc0_colormask(unsigned mask) +{ + uint32_t ret = 0; + + if (mask & PIPE_MASK_R) + ret |= 0x0001; + if (mask & PIPE_MASK_G) + ret |= 0x0010; + if (mask & PIPE_MASK_B) + ret |= 0x0100; + if (mask & PIPE_MASK_A) + ret |= 0x1000; + + return ret; +} + +static INLINE uint32_t +nvc0_blend_fac(unsigned factor) +{ + static const uint16_t bf[] = { + NV50_3D_BLEND_FACTOR_ZERO, /* 0x00 */ + NV50_3D_BLEND_FACTOR_ONE, + NV50_3D_BLEND_FACTOR_SRC_COLOR, + NV50_3D_BLEND_FACTOR_SRC_ALPHA, + NV50_3D_BLEND_FACTOR_DST_ALPHA, + NV50_3D_BLEND_FACTOR_DST_COLOR, + NV50_3D_BLEND_FACTOR_SRC_ALPHA_SATURATE, + NV50_3D_BLEND_FACTOR_CONSTANT_COLOR, + NV50_3D_BLEND_FACTOR_CONSTANT_ALPHA, + NV50_3D_BLEND_FACTOR_SRC1_COLOR, + NV50_3D_BLEND_FACTOR_SRC1_ALPHA, + NV50_3D_BLEND_FACTOR_ZERO, /* 0x0b */ + NV50_3D_BLEND_FACTOR_ZERO, /* 0x0c */ + NV50_3D_BLEND_FACTOR_ZERO, /* 0x0d */ + NV50_3D_BLEND_FACTOR_ZERO, /* 0x0e */ + NV50_3D_BLEND_FACTOR_ZERO, /* 0x0f */ + NV50_3D_BLEND_FACTOR_ZERO, /* 0x10 */ + NV50_3D_BLEND_FACTOR_ZERO, /* 0x11 */ + NV50_3D_BLEND_FACTOR_ONE_MINUS_SRC_COLOR, + NV50_3D_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, + NV50_3D_BLEND_FACTOR_ONE_MINUS_DST_ALPHA, + NV50_3D_BLEND_FACTOR_ONE_MINUS_DST_COLOR, + NV50_3D_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR, + NV50_3D_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA, + NV50_3D_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR, + NV50_3D_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA + }; + + assert(factor < (sizeof(bf) / sizeof(bf[0]))); + return bf[factor]; +} + +static void * +nvc0_blend_state_create(struct pipe_context *pipe, + const struct pipe_blend_state *cso) +{ + struct nvc0_blend_stateobj *so = CALLOC_STRUCT(nvc0_blend_stateobj); + int i; + + so->pipe = *cso; + + SB_OUT_3D(so, BLEND_INDEPENDENT, cso->independent_blend_enable); + + if (!cso->independent_blend_enable) { + SB_BEGIN_3D(so, BLEND_ENABLES, 1); + SB_DATA (so, cso->rt[0].blend_enable ? 0xff : 0); + + if (cso->rt[0].blend_enable) { + SB_BEGIN_3D(so, BLEND_EQUATION_RGB, 5); + SB_DATA (so, nvgl_blend_eqn(cso->rt[0].rgb_func)); + SB_DATA (so, nvc0_blend_fac(cso->rt[0].rgb_src_factor)); + SB_DATA (so, nvc0_blend_fac(cso->rt[0].rgb_dst_factor)); + SB_DATA (so, nvgl_blend_eqn(cso->rt[0].alpha_func)); + SB_DATA (so, nvc0_blend_fac(cso->rt[0].alpha_src_factor)); + SB_BEGIN_3D(so, BLEND_FUNC_DST_ALPHA, 1); + SB_DATA (so, nvc0_blend_fac(cso->rt[0].alpha_dst_factor)); + } + + SB_BEGIN_3D(so, COLOR_MASK_BROADCAST, 1); + SB_DATA (so, nvc0_colormask(cso->rt[0].colormask)); + } else { + uint8_t en = 0; + + for (i = 0; i < 8; ++i) { + if (!cso->rt[i].blend_enable) + continue; + en |= 1 << i; + + SB_BEGIN_3D(so, IBLEND_EQUATION_RGB(i), 6); + SB_DATA (so, nvgl_blend_eqn(cso->rt[i].rgb_func)); + SB_DATA (so, nvc0_blend_fac(cso->rt[i].rgb_src_factor)); + SB_DATA (so, nvc0_blend_fac(cso->rt[i].rgb_dst_factor)); + SB_DATA (so, nvgl_blend_eqn(cso->rt[i].alpha_func)); + SB_DATA (so, nvc0_blend_fac(cso->rt[i].alpha_src_factor)); + SB_DATA (so, nvc0_blend_fac(cso->rt[i].alpha_dst_factor)); + } + SB_BEGIN_3D(so, BLEND_ENABLES, 1); + SB_DATA (so, en); + + SB_BEGIN_3D(so, COLOR_MASK(0), 8); + for (i = 0; i < 8; ++i) + SB_DATA(so, nvc0_colormask(cso->rt[i].colormask)); + } + + if (cso->logicop_enable) { + SB_BEGIN_3D(so, LOGIC_OP_ENABLE, 2); + SB_DATA (so, 1); + SB_DATA (so, nvgl_logicop_func(cso->logicop_func)); + } else { + SB_OUT_3D (so, LOGIC_OP_ENABLE, 0); + } + + assert(so->size < (sizeof(so->state) / sizeof(so->state[0]))); + return so; +} + +static void +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; +} + +static void +nvc0_blend_state_delete(struct pipe_context *pipe, void *hwcso) +{ + FREE(hwcso); +} + +static void * +nvc0_rasterizer_state_create(struct pipe_context *pipe, + const struct pipe_rasterizer_state *cso) +{ + struct nvc0_rasterizer_stateobj *so; + + so = CALLOC_STRUCT(nvc0_rasterizer_stateobj); + if (!so) + return NULL; + so->pipe = *cso; + + SB_BEGIN_3D(so, SHADE_MODEL, 1); + SB_DATA (so, cso->flatshade ? NVC0_3D_SHADE_MODEL_FLAT : + NVC0_3D_SHADE_MODEL_SMOOTH); + SB_OUT_3D (so, PROVOKING_VERTEX_LAST, !cso->flatshade_first); + SB_OUT_3D (so, VERTEX_TWO_SIDE_ENABLE, cso->light_twoside); + + SB_BEGIN_3D(so, LINE_WIDTH, 1); + SB_DATA (so, fui(cso->line_width)); + SB_OUT_3D (so, LINE_SMOOTH_ENABLE, cso->line_smooth); + + SB_BEGIN_3D(so, LINE_STIPPLE_ENABLE, 1); + if (cso->line_stipple_enable) { + SB_DATA (so, 1); + SB_BEGIN_3D(so, LINE_STIPPLE_PATTERN, 1); + SB_DATA (so, (cso->line_stipple_pattern << 8) | + cso->line_stipple_factor); + + } else { + SB_DATA (so, 0); + } + + SB_OUT_3D(so, VP_POINT_SIZE_EN, cso->point_size_per_vertex); + if (!cso->point_size_per_vertex) { + SB_BEGIN_3D(so, POINT_SIZE, 1); + SB_DATA (so, fui(cso->point_size)); + } + SB_OUT_3D(so, POINT_SPRITE_ENABLE, cso->point_quad_rasterization); + + SB_BEGIN_3D(so, POLYGON_MODE_FRONT, 1); + SB_DATA (so, nvgl_polygon_mode(cso->fill_front)); + SB_BEGIN_3D(so, POLYGON_MODE_BACK, 1); + SB_DATA (so, nvgl_polygon_mode(cso->fill_back)); + SB_OUT_3D (so, POLYGON_SMOOTH_ENABLE, cso->poly_smooth); + + if (cso->cull_face != PIPE_FACE_NONE) { + SB_BEGIN_3D(so, CULL_FACE_ENABLE, 3); + SB_DATA (so, 1); + SB_DATA (so, cso->front_ccw ? NVC0_3D_FRONT_FACE_CCW : + NVC0_3D_FRONT_FACE_CW); + switch (cso->cull_face) { + case PIPE_FACE_FRONT_AND_BACK: + SB_DATA(so, NVC0_3D_CULL_FACE_FRONT_AND_BACK); + break; + case PIPE_FACE_FRONT: + SB_DATA(so, NVC0_3D_CULL_FACE_FRONT); + break; + case PIPE_FACE_BACK: + default: + SB_DATA(so, NVC0_3D_CULL_FACE_BACK); + break; + } + } else { + SB_OUT_3D(so, CULL_FACE_ENABLE, 0); + } + + SB_OUT_3D (so, POLYGON_STIPPLE_ENABLE, cso->poly_stipple_enable); + SB_BEGIN_3D(so, POLYGON_OFFSET_POINT_ENABLE, 3); + SB_DATA (so, cso->offset_point); + SB_DATA (so, cso->offset_line); + SB_DATA (so, cso->offset_tri); + + 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)); /* XXX: multiply by 2 ? */ + } + + assert(so->size < (sizeof(so->state) / sizeof(so->state[0]))); + return (void *)so; +} + +static void +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; +} + +static void +nvc0_rasterizer_state_delete(struct pipe_context *pipe, void *hwcso) +{ + FREE(hwcso); +} + +static void * +nvc0_zsa_state_create(struct pipe_context *pipe, + const struct pipe_depth_stencil_alpha_state *cso) +{ + struct nvc0_zsa_stateobj *so = CALLOC_STRUCT(nvc0_zsa_stateobj); + + so->pipe = *cso; + + SB_OUT_3D (so, DEPTH_WRITE_ENABLE, cso->depth.writemask); + SB_BEGIN_3D(so, DEPTH_TEST_ENABLE, 1); + if (cso->depth.enabled) { + SB_DATA (so, 1); + SB_BEGIN_3D(so, DEPTH_TEST_FUNC, 1); + SB_DATA (so, nvgl_comparison_op(cso->depth.func)); + } else { + SB_DATA (so, 0); + } + + if (cso->stencil[0].enabled) { + SB_BEGIN_3D(so, STENCIL_FRONT_ENABLE, 5); + SB_DATA (so, 1); + SB_DATA (so, nvgl_stencil_op(cso->stencil[0].fail_op)); + SB_DATA (so, nvgl_stencil_op(cso->stencil[0].zfail_op)); + SB_DATA (so, nvgl_stencil_op(cso->stencil[0].zpass_op)); + SB_DATA (so, nvgl_comparison_op(cso->stencil[0].func)); + SB_BEGIN_3D(so, STENCIL_FRONT_MASK, 2); + SB_DATA (so, cso->stencil[0].writemask); + SB_DATA (so, cso->stencil[0].valuemask); + } else { + SB_OUT_3D (so, STENCIL_FRONT_ENABLE, 0); + } + + if (cso->stencil[1].enabled) { + SB_BEGIN_3D(so, STENCIL_TWO_SIDE_ENABLE, 5); + SB_DATA (so, 1); + SB_DATA (so, nvgl_stencil_op(cso->stencil[1].fail_op)); + SB_DATA (so, nvgl_stencil_op(cso->stencil[1].zfail_op)); + SB_DATA (so, nvgl_stencil_op(cso->stencil[1].zpass_op)); + SB_DATA (so, nvgl_comparison_op(cso->stencil[1].func)); + SB_BEGIN_3D(so, STENCIL_BACK_MASK, 2); + SB_DATA (so, cso->stencil[1].writemask); + SB_DATA (so, cso->stencil[1].valuemask); + } else { + SB_OUT_3D (so, STENCIL_TWO_SIDE_ENABLE, 0); + } + + SB_BEGIN_3D(so, ALPHA_TEST_ENABLE, 1); + if (cso->alpha.enabled) { + SB_DATA (so, 1); + SB_BEGIN_3D(so, ALPHA_TEST_REF, 2); + SB_DATA (so, fui(cso->alpha.ref_value)); + SB_DATA (so, nvgl_comparison_op(cso->alpha.func)); + } else { + SB_DATA (so, 0); + } + + assert(so->size < (sizeof(so->state) / sizeof(so->state[0]))); + return (void *)so; +} + +static void +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; +} + +static void +nvc0_zsa_state_delete(struct pipe_context *pipe, void *hwcso) +{ + FREE(hwcso); +} + +/* ====================== SAMPLERS AND TEXTURES ================================ + */ + +#define NV50_TSC_WRAP_CASE(n) \ + case PIPE_TEX_WRAP_##n: return NV50_TSC_WRAP_##n + +static INLINE unsigned +nv50_tsc_wrap_mode(unsigned wrap) +{ + switch (wrap) { + NV50_TSC_WRAP_CASE(REPEAT); + NV50_TSC_WRAP_CASE(MIRROR_REPEAT); + NV50_TSC_WRAP_CASE(CLAMP_TO_EDGE); + NV50_TSC_WRAP_CASE(CLAMP_TO_BORDER); + NV50_TSC_WRAP_CASE(CLAMP); + NV50_TSC_WRAP_CASE(MIRROR_CLAMP_TO_EDGE); + NV50_TSC_WRAP_CASE(MIRROR_CLAMP_TO_BORDER); + NV50_TSC_WRAP_CASE(MIRROR_CLAMP); + default: + NOUVEAU_ERR("unknown wrap mode: %d\n", wrap); + return NV50_TSC_WRAP_REPEAT; + } +} + +static void * +nvc0_sampler_state_create(struct pipe_context *pipe, + const struct pipe_sampler_state *cso) +{ + struct nvc0_tsc_entry *so = CALLOC_STRUCT(nvc0_tsc_entry); + float f[2]; + + so->id = -1; + + so->tsc[0] = (0x00026000 | + (nv50_tsc_wrap_mode(cso->wrap_s) << 0) | + (nv50_tsc_wrap_mode(cso->wrap_t) << 3) | + (nv50_tsc_wrap_mode(cso->wrap_r) << 6)); + + switch (cso->mag_img_filter) { + case PIPE_TEX_FILTER_LINEAR: + so->tsc[1] |= NV50_TSC_1_MAGF_LINEAR; + break; + case PIPE_TEX_FILTER_NEAREST: + default: + so->tsc[1] |= NV50_TSC_1_MAGF_NEAREST; + break; + } + + switch (cso->min_img_filter) { + case PIPE_TEX_FILTER_LINEAR: + so->tsc[1] |= NV50_TSC_1_MINF_LINEAR; + break; + case PIPE_TEX_FILTER_NEAREST: + default: + so->tsc[1] |= NV50_TSC_1_MINF_NEAREST; + break; + } + + switch (cso->min_mip_filter) { + case PIPE_TEX_MIPFILTER_LINEAR: + so->tsc[1] |= NV50_TSC_1_MIPF_LINEAR; + break; + case PIPE_TEX_MIPFILTER_NEAREST: + so->tsc[1] |= NV50_TSC_1_MIPF_NEAREST; + break; + case PIPE_TEX_MIPFILTER_NONE: + default: + so->tsc[1] |= NV50_TSC_1_MIPF_NONE; + break; + } + + if (cso->max_anisotropy >= 16) + so->tsc[0] |= (7 << 20); + else + if (cso->max_anisotropy >= 12) + so->tsc[0] |= (6 << 20); + else { + so->tsc[0] |= (cso->max_anisotropy >> 1) << 20; + + if (cso->max_anisotropy >= 4) + so->tsc[1] |= NV50_TSC_1_UNKN_ANISO_35; + else + if (cso->max_anisotropy >= 2) + so->tsc[1] |= NV50_TSC_1_UNKN_ANISO_15; + } + + if (cso->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) { + /* NOTE: must be deactivated for non-shadow textures */ + so->tsc[0] |= (1 << 9); + so->tsc[0] |= (nvgl_comparison_op(cso->compare_func) & 0x7) << 10; + } + + f[0] = CLAMP(cso->lod_bias, -16.0f, 15.0f); + so->tsc[1] |= ((int)(f[0] * 256.0f) & 0x1fff) << 12; + + f[0] = CLAMP(cso->min_lod, 0.0f, 15.0f); + f[1] = CLAMP(cso->max_lod, 0.0f, 15.0f); + so->tsc[2] |= + (((int)(f[1] * 256.0f) & 0xfff) << 12) | ((int)(f[0] * 256.0f) & 0xfff); + + so->tsc[4] = fui(cso->border_color[0]); + so->tsc[5] = fui(cso->border_color[1]); + so->tsc[6] = fui(cso->border_color[2]); + so->tsc[7] = fui(cso->border_color[3]); + + return (void *)so; +} + +static void +nvc0_sampler_state_delete(struct pipe_context *pipe, void *hwcso) +{ + unsigned s, i; + + for (s = 0; s < 5; ++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; + + nvc0_screen_tsc_free(nvc0_context(pipe)->screen, nvc0_tsc_entry(hwcso)); + + FREE(hwcso); +} + +static INLINE void +nvc0_stage_sampler_states_bind(struct nvc0_context *nvc0, int s, + unsigned nr, void **hwcso) +{ + unsigned i; + + for (i = 0; i < nr; ++i) { + struct nvc0_tsc_entry *old = nvc0->samplers[s][i]; + + nvc0->samplers[s][i] = nvc0_tsc_entry(hwcso[i]); + 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->num_samplers[s] = nr; + + nvc0->dirty |= NVC0_NEW_SAMPLERS; +} + +static void +nvc0_vp_sampler_states_bind(struct pipe_context *pipe, unsigned nr, void **s) +{ + nvc0_stage_sampler_states_bind(nvc0_context(pipe), 0, nr, s); +} + +static void +nvc0_fp_sampler_states_bind(struct pipe_context *pipe, unsigned nr, void **s) +{ + nvc0_stage_sampler_states_bind(nvc0_context(pipe), 4, nr, s); +} + +static void +nvc0_gp_sampler_states_bind(struct pipe_context *pipe, unsigned nr, void **s) +{ + nvc0_stage_sampler_states_bind(nvc0_context(pipe), 3, nr, s); +} + +/* NOTE: only called when not referenced anywhere, won't be bound */ +static void +nvc0_sampler_view_destroy(struct pipe_context *pipe, + struct pipe_sampler_view *view) +{ + pipe_resource_reference(&view->texture, NULL); + + nvc0_screen_tic_free(nvc0_context(pipe)->screen, nvc0_tic_entry(view)); + + FREE(nvc0_tic_entry(view)); +} + +static INLINE void +nvc0_stage_set_sampler_views(struct nvc0_context *nvc0, int s, + unsigned nr, + struct pipe_sampler_view **views) +{ + unsigned i; + + for (i = 0; i < nr; ++i) { + struct nvc0_tic_entry *old = nvc0_tic_entry(nvc0->textures[s][i]); + if (old) + nvc0_screen_tic_unlock(nvc0->screen, old); + + pipe_sampler_view_reference(&nvc0->textures[s][i], views[i]); + } + + for (i = nr; i < nvc0->num_textures[s]; ++i) { + struct nvc0_tic_entry *old = nvc0_tic_entry(nvc0->textures[s][i]); + if (!old) + continue; + 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_vp_set_sampler_views(struct pipe_context *pipe, + unsigned nr, + struct pipe_sampler_view **views) +{ + nvc0_stage_set_sampler_views(nvc0_context(pipe), 0, nr, views); +} + +static void +nvc0_fp_set_sampler_views(struct pipe_context *pipe, + unsigned nr, + struct pipe_sampler_view **views) +{ + nvc0_stage_set_sampler_views(nvc0_context(pipe), 4, nr, views); +} + +static void +nvc0_gp_set_sampler_views(struct pipe_context *pipe, + unsigned nr, + struct pipe_sampler_view **views) +{ + nvc0_stage_set_sampler_views(nvc0_context(pipe), 3, nr, views); +} + +/* ============================= SHADERS ======================================= + */ + +static void * +nvc0_sp_state_create(struct pipe_context *pipe, + const struct pipe_shader_state *cso, unsigned type) +{ + struct nvc0_program *prog; + + prog = CALLOC_STRUCT(nvc0_program); + if (!prog) + return NULL; + + prog->type = type; + prog->pipe.tokens = tgsi_dup_tokens(cso->tokens); + + return (void *)prog; +} + +static void +nvc0_sp_state_delete(struct pipe_context *pipe, void *hwcso) +{ + struct nvc0_program *prog = (struct nvc0_program *)hwcso; + + nvc0_program_destroy(nvc0_context(pipe), prog); + + FREE((void *)prog->pipe.tokens); + FREE(prog); +} + +static void * +nvc0_vp_state_create(struct pipe_context *pipe, + const struct pipe_shader_state *cso) +{ + return nvc0_sp_state_create(pipe, cso, PIPE_SHADER_VERTEX); +} + +static void +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; +} + +static void * +nvc0_fp_state_create(struct pipe_context *pipe, + const struct pipe_shader_state *cso) +{ + return nvc0_sp_state_create(pipe, cso, PIPE_SHADER_FRAGMENT); +} + +static void +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; +} + +static void * +nvc0_gp_state_create(struct pipe_context *pipe, + const struct pipe_shader_state *cso) +{ + return nvc0_sp_state_create(pipe, cso, PIPE_SHADER_GEOMETRY); +} + +static void +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; +} + +static void +nvc0_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index, + struct pipe_resource *res) +{ + struct nvc0_context *nvc0 = nvc0_context(pipe); + + switch (shader) { + case PIPE_SHADER_VERTEX: shader = 0; break; + /* + case PIPE_SHADER_TESSELLATION_CONTROL: shader = 1; break; + case PIPE_SHADER_TESSELLATION_EVALUATION: shader = 2; break; + */ + case PIPE_SHADER_GEOMETRY: shader = 3; break; + case PIPE_SHADER_FRAGMENT: shader = 4; break; + default: + assert(0); + break; + } + + if (nvc0->constbuf[shader][index]) + nvc0_bufctx_del_resident(nvc0, NVC0_BUFCTX_CONSTANT, + nvc0_resource( + nvc0->constbuf[shader][index])); + + pipe_resource_reference(&nvc0->constbuf[shader][index], res); + + nvc0->constbuf_dirty[shader] |= 1 << index; + + nvc0->dirty |= NVC0_NEW_CONSTBUF; +} + +/* ============================================================================= + */ + +static void +nvc0_set_blend_color(struct pipe_context *pipe, + const struct pipe_blend_color *bcol) +{ + struct nvc0_context *nvc0 = nvc0_context(pipe); + + nvc0->blend_colour = *bcol; + nvc0->dirty |= NVC0_NEW_BLEND_COLOUR; +} + +static void +nvc0_set_stencil_ref(struct pipe_context *pipe, + const struct pipe_stencil_ref *sr) +{ + struct nvc0_context *nvc0 = nvc0_context(pipe); + + nvc0->stencil_ref = *sr; + nvc0->dirty |= NVC0_NEW_STENCIL_REF; +} + +static void +nvc0_set_clip_state(struct pipe_context *pipe, + const struct pipe_clip_state *clip) +{ + struct nvc0_context *nvc0 = nvc0_context(pipe); + + nvc0->clip.depth_clamp = clip->depth_clamp; + nvc0->dirty |= NVC0_NEW_CLIP; +} + +static void +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; +} + + +static void +nvc0_set_framebuffer_state(struct pipe_context *pipe, + const struct pipe_framebuffer_state *fb) +{ + struct nvc0_context *nvc0 = nvc0_context(pipe); + + nvc0->framebuffer = *fb; + nvc0->dirty |= NVC0_NEW_FRAMEBUFFER; +} + +static void +nvc0_set_polygon_stipple(struct pipe_context *pipe, + const struct pipe_poly_stipple *stipple) +{ + struct nvc0_context *nvc0 = nvc0_context(pipe); + + nvc0->stipple = *stipple; + nvc0->dirty |= NVC0_NEW_STIPPLE; +} + +static void +nvc0_set_scissor_state(struct pipe_context *pipe, + const struct pipe_scissor_state *scissor) +{ + struct nvc0_context *nvc0 = nvc0_context(pipe); + + nvc0->scissor = *scissor; + nvc0->dirty |= NVC0_NEW_SCISSOR; +} + +static void +nvc0_set_viewport_state(struct pipe_context *pipe, + const struct pipe_viewport_state *vpt) +{ + struct nvc0_context *nvc0 = nvc0_context(pipe); + + nvc0->viewport = *vpt; + nvc0->dirty |= NVC0_NEW_VIEWPORT; +} + +static void +nvc0_set_vertex_buffers(struct pipe_context *pipe, + unsigned count, + const struct pipe_vertex_buffer *vb) +{ + struct nvc0_context *nvc0 = nvc0_context(pipe); + + memcpy(nvc0->vtxbuf, vb, sizeof(*vb) * count); + nvc0->num_vtxbufs = count; + + nvc0->dirty |= NVC0_NEW_ARRAYS; +} + +static void +nvc0_set_index_buffer(struct pipe_context *pipe, + const struct pipe_index_buffer *ib) +{ + struct nvc0_context *nvc0 = nvc0_context(pipe); + + if (ib) + memcpy(&nvc0->idxbuf, ib, sizeof(nvc0->idxbuf)); + else + 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; +} + +void +nvc0_init_state_functions(struct nvc0_context *nvc0) +{ + nvc0->pipe.create_blend_state = nvc0_blend_state_create; + nvc0->pipe.bind_blend_state = nvc0_blend_state_bind; + nvc0->pipe.delete_blend_state = nvc0_blend_state_delete; + + nvc0->pipe.create_rasterizer_state = nvc0_rasterizer_state_create; + nvc0->pipe.bind_rasterizer_state = nvc0_rasterizer_state_bind; + nvc0->pipe.delete_rasterizer_state = nvc0_rasterizer_state_delete; + + nvc0->pipe.create_depth_stencil_alpha_state = nvc0_zsa_state_create; + nvc0->pipe.bind_depth_stencil_alpha_state = nvc0_zsa_state_bind; + nvc0->pipe.delete_depth_stencil_alpha_state = nvc0_zsa_state_delete; + + nvc0->pipe.create_sampler_state = nvc0_sampler_state_create; + nvc0->pipe.delete_sampler_state = nvc0_sampler_state_delete; + nvc0->pipe.bind_vertex_sampler_states = nvc0_vp_sampler_states_bind; + nvc0->pipe.bind_fragment_sampler_states = nvc0_fp_sampler_states_bind; + nvc0->pipe.bind_geometry_sampler_states = nvc0_gp_sampler_states_bind; + + nvc0->pipe.create_sampler_view = nvc0_create_sampler_view; + nvc0->pipe.sampler_view_destroy = nvc0_sampler_view_destroy; + nvc0->pipe.set_vertex_sampler_views = nvc0_vp_set_sampler_views; + nvc0->pipe.set_fragment_sampler_views = nvc0_fp_set_sampler_views; + nvc0->pipe.set_geometry_sampler_views = nvc0_gp_set_sampler_views; + + nvc0->pipe.create_vs_state = nvc0_vp_state_create; + nvc0->pipe.create_fs_state = nvc0_fp_state_create; + nvc0->pipe.create_gs_state = nvc0_gp_state_create; + nvc0->pipe.bind_vs_state = nvc0_vp_state_bind; + nvc0->pipe.bind_fs_state = nvc0_fp_state_bind; + nvc0->pipe.bind_gs_state = nvc0_gp_state_bind; + nvc0->pipe.delete_vs_state = nvc0_sp_state_delete; + nvc0->pipe.delete_fs_state = nvc0_sp_state_delete; + nvc0->pipe.delete_gs_state = nvc0_sp_state_delete; + + nvc0->pipe.set_blend_color = nvc0_set_blend_color; + nvc0->pipe.set_stencil_ref = nvc0_set_stencil_ref; + nvc0->pipe.set_clip_state = nvc0_set_clip_state; + nvc0->pipe.set_sample_mask = nvc0_set_sample_mask; + nvc0->pipe.set_constant_buffer = nvc0_set_constant_buffer; + nvc0->pipe.set_framebuffer_state = nvc0_set_framebuffer_state; + nvc0->pipe.set_polygon_stipple = nvc0_set_polygon_stipple; + nvc0->pipe.set_scissor_state = nvc0_set_scissor_state; + nvc0->pipe.set_viewport_state = nvc0_set_viewport_state; + + nvc0->pipe.create_vertex_elements_state = nvc0_vertex_state_create; + nvc0->pipe.delete_vertex_elements_state = nvc0_vertex_state_delete; + nvc0->pipe.bind_vertex_elements_state = nvc0_vertex_state_bind; + + nvc0->pipe.set_vertex_buffers = nvc0_set_vertex_buffers; + nvc0->pipe.set_index_buffer = nvc0_set_index_buffer; +} + -- cgit v1.2.3 From dea9d604005e9aaed2bd6807f1913ac668479443 Mon Sep 17 00:00:00 2001 From: Christoph Bumiller Date: Fri, 10 Dec 2010 20:16:10 +0100 Subject: nvc0: fix FACE state and and handle FACE sysval/varying offset --- src/gallium/drivers/nvc0/nvc0_program.c | 6 ++++++ src/gallium/drivers/nvc0/nvc0_state.c | 34 +++++++++++++----------------- src/gallium/drivers/nvc0/nvc0_tgsi_to_nc.c | 2 ++ 3 files changed, 23 insertions(+), 19 deletions(-) (limited to 'src/gallium/drivers/nvc0/nvc0_state.c') diff --git a/src/gallium/drivers/nvc0/nvc0_program.c b/src/gallium/drivers/nvc0/nvc0_program.c index aeb9213037..7aa6ef02bc 100644 --- a/src/gallium/drivers/nvc0/nvc0_program.c +++ b/src/gallium/drivers/nvc0/nvc0_program.c @@ -23,6 +23,8 @@ #include "pipe/p_shader_tokens.h" #include "pipe/p_defines.h" +#define NOUVEAU_DEBUG + #include "tgsi/tgsi_parse.h" #include "tgsi/tgsi_util.h" #include "tgsi/tgsi_dump.h" @@ -147,6 +149,8 @@ nvc0_system_value_location(unsigned sn, unsigned si) */ case TGSI_SEMANTIC_INSTANCEID: return 0x2f8; + case TGSI_SEMANTIC_FACE: + return 0x3fc; default: assert(0); return 0x000; @@ -178,6 +182,8 @@ nvc0_varying_location(unsigned sn, unsigned si) return 0x360; case TGSI_SEMANTIC_PRIMID: return 0x40; + case TGSI_SEMANTIC_FACE: + return 0x3fc; /* case TGSI_SEMANTIC_CLIP_DISTANCE: return 0x2c0 + (si * 4); diff --git a/src/gallium/drivers/nvc0/nvc0_state.c b/src/gallium/drivers/nvc0/nvc0_state.c index afba7ce6a0..c7a8c4b747 100644 --- a/src/gallium/drivers/nvc0/nvc0_state.c +++ b/src/gallium/drivers/nvc0/nvc0_state.c @@ -210,25 +210,21 @@ nvc0_rasterizer_state_create(struct pipe_context *pipe, SB_DATA (so, nvgl_polygon_mode(cso->fill_back)); SB_OUT_3D (so, POLYGON_SMOOTH_ENABLE, cso->poly_smooth); - if (cso->cull_face != PIPE_FACE_NONE) { - SB_BEGIN_3D(so, CULL_FACE_ENABLE, 3); - SB_DATA (so, 1); - SB_DATA (so, cso->front_ccw ? NVC0_3D_FRONT_FACE_CCW : - NVC0_3D_FRONT_FACE_CW); - switch (cso->cull_face) { - case PIPE_FACE_FRONT_AND_BACK: - SB_DATA(so, NVC0_3D_CULL_FACE_FRONT_AND_BACK); - break; - case PIPE_FACE_FRONT: - SB_DATA(so, NVC0_3D_CULL_FACE_FRONT); - break; - case PIPE_FACE_BACK: - default: - SB_DATA(so, NVC0_3D_CULL_FACE_BACK); - break; - } - } else { - SB_OUT_3D(so, CULL_FACE_ENABLE, 0); + SB_BEGIN_3D(so, CULL_FACE_ENABLE, 3); + SB_DATA (so, cso->cull_face != PIPE_FACE_NONE); + SB_DATA (so, cso->front_ccw ? NVC0_3D_FRONT_FACE_CCW : + NVC0_3D_FRONT_FACE_CW); + switch (cso->cull_face) { + case PIPE_FACE_FRONT_AND_BACK: + SB_DATA(so, NVC0_3D_CULL_FACE_FRONT_AND_BACK); + break; + case PIPE_FACE_FRONT: + SB_DATA(so, NVC0_3D_CULL_FACE_FRONT); + break; + case PIPE_FACE_BACK: + default: + SB_DATA(so, NVC0_3D_CULL_FACE_BACK); + break; } SB_OUT_3D (so, POLYGON_STIPPLE_ENABLE, cso->poly_stipple_enable); diff --git a/src/gallium/drivers/nvc0/nvc0_tgsi_to_nc.c b/src/gallium/drivers/nvc0/nvc0_tgsi_to_nc.c index 26f9e735fb..8a20983a7e 100644 --- a/src/gallium/drivers/nvc0/nvc0_tgsi_to_nc.c +++ b/src/gallium/drivers/nvc0/nvc0_tgsi_to_nc.c @@ -963,8 +963,10 @@ bld_interp(struct bld_context *bld, unsigned mode, struct nv_value *val) if (val->reg.address == 0x3fc) { /* gl_FrontFacing: 0/~0 to -1.0/+1.0 */ val = bld_insn_1(bld, NV_OP_LINTERP, val); + val->insn->flat = 1; val = bld_insn_2(bld, NV_OP_SHL, val, bld_imm_u32(bld, 31)); val = bld_insn_2(bld, NV_OP_XOR, val, bld_imm_f32(bld, -1.0f)); + return val; } else if (mode == NVC0_INTERP_PERSPECTIVE) { val = bld_insn_2(bld, NV_OP_PINTERP, val, bld->frag_coord[3]); -- cgit v1.2.3 From 5138ac033ad3708e2b82f2beebc887f65a77309e Mon Sep 17 00:00:00 2001 From: Christoph Bumiller Date: Sat, 11 Dec 2010 16:23:43 +0100 Subject: nvc0: support user clip planes --- src/gallium/drivers/nvc0/nvc0_program.c | 7 ++++ src/gallium/drivers/nvc0/nvc0_program.h | 2 ++ src/gallium/drivers/nvc0/nvc0_screen.c | 12 ++++++- src/gallium/drivers/nvc0/nvc0_shader_state.c | 8 +++++ src/gallium/drivers/nvc0/nvc0_state.c | 5 +++ src/gallium/drivers/nvc0/nvc0_state_validate.c | 17 +++++++++ src/gallium/drivers/nvc0/nvc0_tgsi_to_nc.c | 48 ++++++++++++++++++++++++-- 7 files changed, 96 insertions(+), 3 deletions(-) (limited to 'src/gallium/drivers/nvc0/nvc0_state.c') diff --git a/src/gallium/drivers/nvc0/nvc0_program.c b/src/gallium/drivers/nvc0/nvc0_program.c index 7aa6ef02bc..e159b7161d 100644 --- a/src/gallium/drivers/nvc0/nvc0_program.c +++ b/src/gallium/drivers/nvc0/nvc0_program.c @@ -418,6 +418,8 @@ nvc0_vp_gen_header(struct nvc0_program *vp, struct nvc0_translation_info *ti) vp->hdr[0] = 0x20461; vp->hdr[4] = 0xff000; + vp->hdr[18] = (1 << vp->vp.num_ucps) - 1; + return nvc0_vp_gp_gen_header(vp, ti); } @@ -605,6 +607,9 @@ nvc0_program_translate(struct nvc0_program *prog) ti->edgeflag_out = PIPE_MAX_SHADER_OUTPUTS; + if (prog->type == PIPE_SHADER_VERTEX && prog->vp.num_ucps) + ti->append_ucp = TRUE; + ret = nvc0_prog_scan(ti); if (ret) { NOUVEAU_ERR("unsupported shader program\n"); @@ -646,5 +651,7 @@ nvc0_program_destroy(struct nvc0_context *nvc0, struct nvc0_program *prog) if (prog->relocs) FREE(prog->relocs); + memset(prog->hdr, 0, sizeof(prog->hdr)); + prog->translated = FALSE; } diff --git a/src/gallium/drivers/nvc0/nvc0_program.h b/src/gallium/drivers/nvc0/nvc0_program.h index 42d9be3830..1271303144 100644 --- a/src/gallium/drivers/nvc0/nvc0_program.h +++ b/src/gallium/drivers/nvc0/nvc0_program.h @@ -27,6 +27,7 @@ struct nvc0_program { struct { uint8_t edgeflag; + uint8_t num_ucps; } vp; void *relocs; @@ -71,6 +72,7 @@ struct nvc0_translation_info { ubyte edgeflag_out; struct nvc0_subroutine *subr; unsigned num_subrs; + boolean append_ucp; struct tgsi_shader_info scan; }; diff --git a/src/gallium/drivers/nvc0/nvc0_screen.c b/src/gallium/drivers/nvc0/nvc0_screen.c index fb100e5233..f0d06be9ce 100644 --- a/src/gallium/drivers/nvc0/nvc0_screen.c +++ b/src/gallium/drivers/nvc0/nvc0_screen.c @@ -457,11 +457,21 @@ nvc0_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev) nouveau_resource_init(&screen->text_heap, 0, 1 << 20); - ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 1 << 12, 5 << 16, + ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 1 << 12, 6 << 16, &screen->uniforms); if (ret) goto fail; + /* auxiliary constants (6 user clip planes, base instance id) */ + BEGIN_RING(chan, RING_3D(CB_SIZE), 3); + OUT_RING (chan, 256); + OUT_RELOCh(chan, screen->uniforms, 5 << 16, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD); + OUT_RELOCl(chan, screen->uniforms, 5 << 16, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD); + for (i = 0; i < 5; ++i) { + BEGIN_RING(chan, RING_3D(CB_BIND(i)), 1); + OUT_RING (chan, (15 << 4) | 1); + } + screen->tls_size = 4 * 4 * 32 * 128 * 4; ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 1 << 17, screen->tls_size, &screen->tls); diff --git a/src/gallium/drivers/nvc0/nvc0_shader_state.c b/src/gallium/drivers/nvc0/nvc0_shader_state.c index a16fa6cf5b..a6595c5610 100644 --- a/src/gallium/drivers/nvc0/nvc0_shader_state.c +++ b/src/gallium/drivers/nvc0/nvc0_shader_state.c @@ -67,6 +67,14 @@ nvc0_vertprog_validate(struct nvc0_context *nvc0) struct nouveau_channel *chan = nvc0->screen->base.channel; struct nvc0_program *vp = nvc0->vertprog; + if (nvc0->clip.nr > vp->vp.num_ucps) { + assert(nvc0->clip.nr <= 6); + vp->vp.num_ucps = 6; + + if (vp->translated) + nvc0_program_destroy(nvc0, vp); + } + if (!nvc0_program_validate(nvc0, vp)) return; diff --git a/src/gallium/drivers/nvc0/nvc0_state.c b/src/gallium/drivers/nvc0/nvc0_state.c index c7a8c4b747..8d293233b1 100644 --- a/src/gallium/drivers/nvc0/nvc0_state.c +++ b/src/gallium/drivers/nvc0/nvc0_state.c @@ -699,8 +699,13 @@ nvc0_set_clip_state(struct pipe_context *pipe, const struct pipe_clip_state *clip) { struct nvc0_context *nvc0 = nvc0_context(pipe); + const unsigned size = clip->nr * sizeof(clip->ucp[0]); + + memcpy(&nvc0->clip.ucp[0][0], &clip->ucp[0][0], size); + nvc0->clip.nr = clip->nr; nvc0->clip.depth_clamp = clip->depth_clamp; + nvc0->dirty |= NVC0_NEW_CLIP; } diff --git a/src/gallium/drivers/nvc0/nvc0_state_validate.c b/src/gallium/drivers/nvc0/nvc0_state_validate.c index 2b38ebc8ba..ded461b9c5 100644 --- a/src/gallium/drivers/nvc0/nvc0_state_validate.c +++ b/src/gallium/drivers/nvc0/nvc0_state_validate.c @@ -193,6 +193,23 @@ nvc0_validate_clip(struct nvc0_context *nvc0) BEGIN_RING(chan, RING_3D(VIEW_VOLUME_CLIP_CTRL), 1); OUT_RING (chan, clip); + + if (nvc0->clip.nr) { + struct nouveau_bo *bo = nvc0->screen->uniforms; + + BEGIN_RING(chan, RING_3D(CB_SIZE), 3); + OUT_RING (chan, 256); + OUT_RELOCh(chan, bo, 5 << 16, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD); + OUT_RELOCl(chan, bo, 5 << 16, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD); + BEGIN_RING_1I(chan, RING_3D(CB_POS), nvc0->clip.nr * 4 + 1); + OUT_RING (chan, 0); + OUT_RINGp (chan, &nvc0->clip.ucp[0][0], nvc0->clip.nr * 4); + + BEGIN_RING(chan, RING_3D(VP_CLIP_DISTANCE_ENABLE), 1); + OUT_RING (chan, (1 << nvc0->clip.nr) - 1); + } else { + INLIN_RING(chan, RING_3D(VP_CLIP_DISTANCE_ENABLE), 0); + } } static void diff --git a/src/gallium/drivers/nvc0/nvc0_tgsi_to_nc.c b/src/gallium/drivers/nvc0/nvc0_tgsi_to_nc.c index 8a20983a7e..d0c8275489 100644 --- a/src/gallium/drivers/nvc0/nvc0_tgsi_to_nc.c +++ b/src/gallium/drivers/nvc0/nvc0_tgsi_to_nc.c @@ -111,6 +111,7 @@ struct bld_context { struct bld_register ovs[BLD_MAX_OUTPS][4]; /* TGSI_FILE_OUTPUT, FP only */ uint32_t outputs_written[(PIPE_MAX_SHADER_OUTPUTS + 7) / 8]; + int hpos_index; struct nv_value *zero; struct nv_value *frag_coord[4]; @@ -903,6 +904,38 @@ bld_is_output_written(struct bld_context *bld, int i, int c) return bld->outputs_written[i / 8] & (1 << ((i * 4 + c) % 32)); } +static void +bld_append_vp_ucp(struct bld_context *bld) +{ + struct nv_value *res[6]; + struct nv_value *ucp, *vtx, *out; + struct nv_instruction *insn; + int i, c; + + assert(bld->ti->prog->vp.num_ucps <= 6); + + for (c = 0; c < 4; ++c) { + vtx = bld_fetch_global(bld, &bld->ovs[bld->hpos_index][c]); + + for (i = 0; i < bld->ti->prog->vp.num_ucps; ++i) { + ucp = new_value(bld->pc, NV_FILE_MEM_C(15), 4); + ucp->reg.address = i * 16 + c * 4; + + if (c == 0) + res[i] = bld_insn_2(bld, NV_OP_MUL_F32, vtx, ucp); + else + res[i] = bld_insn_3(bld, NV_OP_MAD_F32, vtx, ucp, res[i]); + } + } + + for (i = 0; i < bld->ti->prog->vp.num_ucps; ++i) { + (out = new_value(bld->pc, NV_FILE_MEM_V, 4))->reg.address = 0x2c0 + i * 4; + (insn = new_instruction(bld->pc, NV_OP_EXPORT))->fixed = 1; + nv_reference(bld->pc, insn, 0, out); + nv_reference(bld->pc, insn, 1, res[i]); + } +} + static void bld_export_fp_outputs(struct bld_context *bld) { @@ -1755,11 +1788,13 @@ bld_instruction(struct bld_context *bld, /* VP outputs are exported in-place as scalars, optimization later */ if (bld->pc->is_fragprog) bld_export_fp_outputs(bld); - break; + if (bld->ti->append_ucp) + bld_append_vp_ucp(bld); + return; default: NOUVEAU_ERR("unhandled opcode %u\n", insn->Instruction.Opcode); abort(); - break; + return; } if (insn->Dst[0].Register.File == TGSI_FILE_OUTPUT && @@ -1767,6 +1802,15 @@ bld_instruction(struct bld_context *bld, struct nv_instruction *mi = NULL; uint size; + if (bld->ti->append_ucp) { + if (bld->ti->output_loc[insn->Dst[0].Register.Index][0] == 0x70) { + bld->hpos_index = insn->Dst[0].Register.Index; + for (c = 0; c < 4; ++c) + if (mask & (1 << c)) + STORE_OUTP(insn->Dst[0].Register.Index, c, dst0[c]); + } + } + for (c = 0; c < 4; ++c) if ((mask & (1 << c)) && ((dst0[c]->reg.file == NV_FILE_IMM) || -- cgit v1.2.3 From d047168d81cfeb39a98f3ae16416872facc6237c Mon Sep 17 00:00:00 2001 From: Christoph Bumiller Date: Sun, 19 Dec 2010 21:42:00 +0100 Subject: nvc0: fix clipping with scissors/viewport Also setup optional path to use proper primitive clipping instead, which is probably slower. --- src/gallium/drivers/nvc0/nvc0_state.c | 4 ++ src/gallium/drivers/nvc0/nvc0_state_validate.c | 59 +++++++++++++++++++++----- src/gallium/drivers/nvc0/nvc0_stateobj.h | 4 +- 3 files changed, 56 insertions(+), 11 deletions(-) (limited to 'src/gallium/drivers/nvc0/nvc0_state.c') diff --git a/src/gallium/drivers/nvc0/nvc0_state.c b/src/gallium/drivers/nvc0/nvc0_state.c index 8d293233b1..a462b543ad 100644 --- a/src/gallium/drivers/nvc0/nvc0_state.c +++ b/src/gallium/drivers/nvc0/nvc0_state.c @@ -175,6 +175,10 @@ nvc0_rasterizer_state_create(struct pipe_context *pipe, if (!so) return NULL; so->pipe = *cso; + +#ifndef NVC0_SCISSORS_CLIPPING + SB_OUT_3D (so, SCISSOR_ENABLE(0), cso->scissor); +#endif SB_BEGIN_3D(so, SHADE_MODEL, 1); SB_DATA (so, cso->flatshade ? NVC0_3D_SHADE_MODEL_FLAT : diff --git a/src/gallium/drivers/nvc0/nvc0_state_validate.c b/src/gallium/drivers/nvc0/nvc0_state_validate.c index fe40d493d9..a1419bb310 100644 --- a/src/gallium/drivers/nvc0/nvc0_state_validate.c +++ b/src/gallium/drivers/nvc0/nvc0_state_validate.c @@ -107,9 +107,11 @@ nvc0_validate_fb(struct nvc0_context *nvc0) OUT_RING (chan, 0); } +#ifndef NVC0_SCISSORS_CLIPPING BEGIN_RING(chan, RING_3D(VIEWPORT_HORIZ(0)), 2); OUT_RING (chan, fb->width << 16); OUT_RING (chan, fb->height << 16); +#endif } static void @@ -151,21 +153,44 @@ nvc0_validate_scissor(struct nvc0_context *nvc0) { struct nouveau_channel *chan = nvc0->screen->base.channel; struct pipe_scissor_state *s = &nvc0->scissor; +#ifdef NVC0_SCISSORS_CLIPPING + struct pipe_viewport_state *vp = &nvc0->viewport; + int minx, maxx, miny, maxy; - if (!(nvc0->dirty & NVC0_NEW_SCISSOR) && - nvc0->state.scissor == nvc0->rast->pipe.scissor) + if (!(nvc0->dirty & + (NVC0_NEW_SCISSOR | NVC0_NEW_VIEWPORT | NVC0_NEW_FRAMEBUFFER)) && + nvc0->state.scissor == nvc0->rast->pipe.scissor) return; nvc0->state.scissor = nvc0->rast->pipe.scissor; if (nvc0->state.scissor) { - BEGIN_RING(chan, RING_3D(SCISSOR_HORIZ(0)), 2); - OUT_RING (chan, (s->maxx << 16) | s->minx); - OUT_RING (chan, (s->maxy << 16) | s->miny); + minx = s->minx; + maxx = s->maxx; + miny = s->miny; + maxy = s->maxy; } else { - BEGIN_RING(chan, RING_3D(SCISSOR_HORIZ(0)), 2); - OUT_RING (chan, nvc0->framebuffer.width << 16); - OUT_RING (chan, nvc0->framebuffer.height << 16); + minx = 0; + maxx = nvc0->framebuffer.width; + miny = 0; + maxy = nvc0->framebuffer.height; } + + minx = MAX2(minx, (int)(vp->translate[0] - fabsf(vp->scale[0]))); + maxx = MIN2(maxx, (int)(vp->translate[0] + fabsf(vp->scale[0]))); + miny = MAX2(miny, (int)(vp->translate[1] - fabsf(vp->scale[1]))); + maxy = MIN2(maxy, (int)(vp->translate[1] + fabsf(vp->scale[1]))); + + BEGIN_RING(chan, RING_3D(SCISSOR_HORIZ(0)), 2); + OUT_RING (chan, (maxx << 16) | minx); + OUT_RING (chan, (maxy << 16) | miny); + BEGIN_RING(chan, RING_3D(VIEWPORT_HORIZ(0)), 2); + OUT_RING (chan, ((maxx - minx) << 16) | minx); + OUT_RING (chan, ((maxy - miny) << 16) | miny); +#else + BEGIN_RING(chan, RING_3D(SCISSOR_HORIZ(0)), 2); + OUT_RING (chan, (s->maxx << 16) | s->minx); + OUT_RING (chan, (s->maxy << 16) | s->miny); +#endif } static void @@ -181,6 +206,12 @@ nvc0_validate_viewport(struct nvc0_context *nvc0) OUT_RINGf (chan, nvc0->viewport.scale[0]); OUT_RINGf (chan, nvc0->viewport.scale[1]); OUT_RINGf (chan, nvc0->viewport.scale[2]); + +#ifdef NVC0_SCISSORS_CLIPPING + BEGIN_RING(chan, RING_3D(DEPTH_RANGE_NEAR(0)), 2); + OUT_RINGf (chan, nvc0->viewport.translate[2] - nvc0->viewport.scale[2]); + OUT_RINGf (chan, nvc0->viewport.translate[2] + nvc0->viewport.scale[2]); +#endif } static void @@ -190,6 +221,9 @@ nvc0_validate_clip(struct nvc0_context *nvc0) uint32_t clip; clip = nvc0->clip.depth_clamp ? 0x201a : 0x0002; +#ifndef NVC0_SCISSORS_CLIPPING + clip |= 0x1080; +#endif BEGIN_RING(chan, RING_3D(VIEW_VOLUME_CLIP_CTRL), 1); OUT_RING (chan, clip); @@ -342,8 +376,13 @@ static struct state_validate { { nvc0_validate_blend_colour, NVC0_NEW_BLEND_COLOUR }, { nvc0_validate_stencil_ref, NVC0_NEW_STENCIL_REF }, { nvc0_validate_stipple, NVC0_NEW_STIPPLE }, - { nvc0_validate_scissor, NVC0_NEW_SCISSOR | NVC0_NEW_FRAMEBUFFER | - NVC0_NEW_RASTERIZER }, +#ifdef NVC0_SCISSORS_CLIPPING + { nvc0_validate_scissor, NVC0_NEW_SCISSOR | NVC0_NEW_VIEWPORT | + NVC0_NEW_RASTERIZER | + NVC0_NEW_FRAMEBUFFER }, +#else + { nvc0_validate_scissor, NVC0_NEW_SCISSOR }, +#endif { nvc0_validate_viewport, NVC0_NEW_VIEWPORT }, { nvc0_validate_clip, NVC0_NEW_CLIP }, { nvc0_vertprog_validate, NVC0_NEW_VERTPROG }, diff --git a/src/gallium/drivers/nvc0/nvc0_stateobj.h b/src/gallium/drivers/nvc0/nvc0_stateobj.h index 41084f3694..67674d4093 100644 --- a/src/gallium/drivers/nvc0/nvc0_stateobj.h +++ b/src/gallium/drivers/nvc0/nvc0_stateobj.h @@ -4,6 +4,8 @@ #include "pipe/p_state.h" +#define NVC0_SCISSORS_CLIPPING + #define SB_BEGIN_3D(so, m, s) \ (so)->state[(so)->size++] = \ (0x2 << 28) | ((s) << 16) | (NVC0_SUBCH_3D << 13) | ((NVC0_3D_##m) >> 2) @@ -46,7 +48,7 @@ nvc0_tic_entry(struct pipe_sampler_view *view) struct nvc0_rasterizer_stateobj { struct pipe_rasterizer_state pipe; int size; - uint32_t state[42]; + uint32_t state[43]; }; struct nvc0_zsa_stateobj { -- cgit v1.2.3 From 2c20aae23393a3f6899f1775df47697ce65fc6ca Mon Sep 17 00:00:00 2001 From: Christoph Bumiller Date: Wed, 22 Dec 2010 23:36:31 +0100 Subject: nvc0: use most defs/decls from nouveau_pushbuf.h --- src/gallium/drivers/nvc0/nvc0_context.c | 9 ++-- src/gallium/drivers/nvc0/nvc0_context.h | 16 ------- src/gallium/drivers/nvc0/nvc0_screen.c | 10 ++-- src/gallium/drivers/nvc0/nvc0_screen.h | 3 +- src/gallium/drivers/nvc0/nvc0_state.c | 26 +++++------ src/gallium/drivers/nvc0/nvc0_stateobj.h | 2 +- src/gallium/drivers/nvc0/nvc0_transfer.c | 2 +- src/gallium/drivers/nvc0/nvc0_winsys.h | 79 ++------------------------------ 8 files changed, 29 insertions(+), 118 deletions(-) (limited to 'src/gallium/drivers/nvc0/nvc0_state.c') diff --git a/src/gallium/drivers/nvc0/nvc0_context.c b/src/gallium/drivers/nvc0/nvc0_context.c index a05408a678..d41ee297d4 100644 --- a/src/gallium/drivers/nvc0/nvc0_context.c +++ b/src/gallium/drivers/nvc0/nvc0_context.c @@ -153,6 +153,7 @@ nvc0_bufctx_reset(struct nvc0_context *nvc0, int ctx) void nvc0_bufctx_emit_relocs(struct nvc0_context *nvc0) { + struct nouveau_channel *chan = nvc0->screen->base.channel; struct resident *rsd; struct util_dynarray *array; unsigned ctx, i; @@ -163,11 +164,11 @@ nvc0_bufctx_emit_relocs(struct nvc0_context *nvc0) for (i = 0; i < array->size / sizeof(struct resident); ++i) { rsd = util_dynarray_element(array, struct resident, i); - nvc0_make_bo_resident(nvc0, rsd->bo, rsd->flags); + nouveau_bo_validate(chan, rsd->bo, rsd->flags); } } - nvc0_make_bo_resident(nvc0, nvc0->screen->text, NOUVEAU_BO_RD); - nvc0_make_bo_resident(nvc0, nvc0->screen->uniforms, NOUVEAU_BO_RD); - nvc0_make_bo_resident(nvc0, nvc0->screen->txc, NOUVEAU_BO_RD); + nouveau_bo_validate(chan, nvc0->screen->text, NOUVEAU_BO_RD); + nouveau_bo_validate(chan, nvc0->screen->uniforms, NOUVEAU_BO_RD); + nouveau_bo_validate(chan, nvc0->screen->txc, NOUVEAU_BO_RD); } diff --git a/src/gallium/drivers/nvc0/nvc0_context.h b/src/gallium/drivers/nvc0/nvc0_context.h index df8a6da075..962a2c0cf2 100644 --- a/src/gallium/drivers/nvc0/nvc0_context.h +++ b/src/gallium/drivers/nvc0/nvc0_context.h @@ -143,22 +143,6 @@ nvc0_surface(struct pipe_surface *ps) return (struct nvc0_surface *)ps; } -static INLINE void -nvc0_make_bo_resident(struct nvc0_context *nvc0, struct nouveau_bo *bo, - unsigned flags) -{ - nouveau_reloc_emit(nvc0->screen->base.channel, - NULL, 0, NULL, bo, 0, 0, flags, 0, 0); -} - -static INLINE void -nvc0_make_buffer_resident(struct nvc0_context *nvc0, - struct nvc0_resource *res, unsigned flags) -{ - nvc0_resource_validate(res, flags); - nvc0_make_bo_resident(nvc0, res->bo, flags); -} - /* nvc0_context.c */ struct pipe_context *nvc0_create(struct pipe_screen *, void *); diff --git a/src/gallium/drivers/nvc0/nvc0_screen.c b/src/gallium/drivers/nvc0/nvc0_screen.c index 7936ef37d1..de2ddb2fff 100644 --- a/src/gallium/drivers/nvc0/nvc0_screen.c +++ b/src/gallium/drivers/nvc0/nvc0_screen.c @@ -451,7 +451,6 @@ nvc0_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev) ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 1 << 17, 1 << 20, &screen->text); if (ret) goto fail; - /* nouveau_bo_pin(dev, screen->text); */ nouveau_resource_init(&screen->text_heap, 0, 1 << 20); @@ -498,7 +497,6 @@ nvc0_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev) &screen->mp_stack_bo); if (ret) goto fail; - /* nouveau_bo_pin(dev, screen->mp_stack_bo); */ BEGIN_RING(chan, RING_3D_(0x17bc), 3); OUT_RELOCh(chan, screen->mp_stack_bo, 0, NOUVEAU_BO_GART | NOUVEAU_BO_RDWR); @@ -508,7 +506,6 @@ nvc0_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev) ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 1 << 17, 1 << 17, &screen->txc); if (ret) goto fail; - /* nouveau_bo_pin(dev, screen->txc); */ BEGIN_RING(chan, RING_3D(TIC_ADDRESS_HIGH), 3); OUT_RELOCh(chan, screen->txc, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD); @@ -622,9 +619,10 @@ nvc0_screen_make_buffers_resident(struct nvc0_screen *screen) const unsigned flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_RD; - nouveau_reloc_emit(chan, NULL, 0, NULL, screen->text, 0, 0, flags, 0, 0); - nouveau_reloc_emit(chan, NULL, 0, NULL, screen->txc, 0, 0, flags, 0, 0); - nouveau_reloc_emit(chan, NULL, 0, NULL, screen->tls, 0, 0, flags, 0, 0); + nouveau_bo_validate(chan, screen->text, flags); + nouveau_bo_validate(chan, screen->txc, flags); + nouveau_bo_validate(chan, screen->tls, flags); + nouveau_bo_validate(chan, screen->mp_stack_bo, flags); } int diff --git a/src/gallium/drivers/nvc0/nvc0_screen.h b/src/gallium/drivers/nvc0/nvc0_screen.h index 8aa77da2bf..5b1b623356 100644 --- a/src/gallium/drivers/nvc0/nvc0_screen.h +++ b/src/gallium/drivers/nvc0/nvc0_screen.h @@ -112,8 +112,7 @@ nvc0_resource_validate(struct nvc0_resource *res, uint32_t flags) if (flags & NOUVEAU_BO_WR) nvc0_fence_reference(&res->fence_wr, screen->fence.current); - nouveau_reloc_emit(screen->base.channel, - NULL, 0, NULL, res->bo, 0, 0, NOUVEAU_BO_RDWR, 0, 0); + nouveau_bo_validate(screen->base.channel, res->bo, flags); } diff --git a/src/gallium/drivers/nvc0/nvc0_state.c b/src/gallium/drivers/nvc0/nvc0_state.c index a462b543ad..62abaa7577 100644 --- a/src/gallium/drivers/nvc0/nvc0_state.c +++ b/src/gallium/drivers/nvc0/nvc0_state.c @@ -95,7 +95,7 @@ nvc0_blend_state_create(struct pipe_context *pipe, so->pipe = *cso; - SB_OUT_3D(so, BLEND_INDEPENDENT, cso->independent_blend_enable); + SB_IMMED_3D(so, BLEND_INDEPENDENT, cso->independent_blend_enable); if (!cso->independent_blend_enable) { SB_BEGIN_3D(so, BLEND_ENABLES, 1); @@ -143,7 +143,7 @@ nvc0_blend_state_create(struct pipe_context *pipe, SB_DATA (so, 1); SB_DATA (so, nvgl_logicop_func(cso->logicop_func)); } else { - SB_OUT_3D (so, LOGIC_OP_ENABLE, 0); + SB_IMMED_3D(so, LOGIC_OP_ENABLE, 0); } assert(so->size < (sizeof(so->state) / sizeof(so->state[0]))); @@ -177,18 +177,18 @@ nvc0_rasterizer_state_create(struct pipe_context *pipe, so->pipe = *cso; #ifndef NVC0_SCISSORS_CLIPPING - SB_OUT_3D (so, SCISSOR_ENABLE(0), cso->scissor); + SB_IMMED_3D(so, SCISSOR_ENABLE(0), cso->scissor); #endif SB_BEGIN_3D(so, SHADE_MODEL, 1); SB_DATA (so, cso->flatshade ? NVC0_3D_SHADE_MODEL_FLAT : NVC0_3D_SHADE_MODEL_SMOOTH); - SB_OUT_3D (so, PROVOKING_VERTEX_LAST, !cso->flatshade_first); - SB_OUT_3D (so, VERTEX_TWO_SIDE_ENABLE, cso->light_twoside); + SB_IMMED_3D(so, PROVOKING_VERTEX_LAST, !cso->flatshade_first); + SB_IMMED_3D(so, VERTEX_TWO_SIDE_ENABLE, cso->light_twoside); SB_BEGIN_3D(so, LINE_WIDTH, 1); SB_DATA (so, fui(cso->line_width)); - SB_OUT_3D (so, LINE_SMOOTH_ENABLE, cso->line_smooth); + SB_IMMED_3D(so, LINE_SMOOTH_ENABLE, cso->line_smooth); SB_BEGIN_3D(so, LINE_STIPPLE_ENABLE, 1); if (cso->line_stipple_enable) { @@ -201,18 +201,18 @@ nvc0_rasterizer_state_create(struct pipe_context *pipe, SB_DATA (so, 0); } - SB_OUT_3D(so, VP_POINT_SIZE_EN, cso->point_size_per_vertex); + SB_IMMED_3D(so, VP_POINT_SIZE_EN, cso->point_size_per_vertex); if (!cso->point_size_per_vertex) { SB_BEGIN_3D(so, POINT_SIZE, 1); SB_DATA (so, fui(cso->point_size)); } - SB_OUT_3D(so, POINT_SPRITE_ENABLE, cso->point_quad_rasterization); + SB_IMMED_3D(so, POINT_SPRITE_ENABLE, cso->point_quad_rasterization); SB_BEGIN_3D(so, POLYGON_MODE_FRONT, 1); SB_DATA (so, nvgl_polygon_mode(cso->fill_front)); SB_BEGIN_3D(so, POLYGON_MODE_BACK, 1); SB_DATA (so, nvgl_polygon_mode(cso->fill_back)); - SB_OUT_3D (so, POLYGON_SMOOTH_ENABLE, cso->poly_smooth); + SB_IMMED_3D(so, POLYGON_SMOOTH_ENABLE, cso->poly_smooth); SB_BEGIN_3D(so, CULL_FACE_ENABLE, 3); SB_DATA (so, cso->cull_face != PIPE_FACE_NONE); @@ -231,7 +231,7 @@ nvc0_rasterizer_state_create(struct pipe_context *pipe, break; } - SB_OUT_3D (so, POLYGON_STIPPLE_ENABLE, cso->poly_stipple_enable); + SB_IMMED_3D(so, POLYGON_STIPPLE_ENABLE, cso->poly_stipple_enable); SB_BEGIN_3D(so, POLYGON_OFFSET_POINT_ENABLE, 3); SB_DATA (so, cso->offset_point); SB_DATA (so, cso->offset_line); @@ -271,7 +271,7 @@ nvc0_zsa_state_create(struct pipe_context *pipe, so->pipe = *cso; - SB_OUT_3D (so, DEPTH_WRITE_ENABLE, cso->depth.writemask); + SB_IMMED_3D(so, DEPTH_WRITE_ENABLE, cso->depth.writemask); SB_BEGIN_3D(so, DEPTH_TEST_ENABLE, 1); if (cso->depth.enabled) { SB_DATA (so, 1); @@ -292,7 +292,7 @@ nvc0_zsa_state_create(struct pipe_context *pipe, SB_DATA (so, cso->stencil[0].writemask); SB_DATA (so, cso->stencil[0].valuemask); } else { - SB_OUT_3D (so, STENCIL_FRONT_ENABLE, 0); + SB_IMMED_3D(so, STENCIL_FRONT_ENABLE, 0); } if (cso->stencil[1].enabled) { @@ -306,7 +306,7 @@ nvc0_zsa_state_create(struct pipe_context *pipe, SB_DATA (so, cso->stencil[1].writemask); SB_DATA (so, cso->stencil[1].valuemask); } else { - SB_OUT_3D (so, STENCIL_TWO_SIDE_ENABLE, 0); + SB_IMMED_3D(so, STENCIL_TWO_SIDE_ENABLE, 0); } SB_BEGIN_3D(so, ALPHA_TEST_ENABLE, 1); diff --git a/src/gallium/drivers/nvc0/nvc0_stateobj.h b/src/gallium/drivers/nvc0/nvc0_stateobj.h index 67674d4093..e7cd94800d 100644 --- a/src/gallium/drivers/nvc0/nvc0_stateobj.h +++ b/src/gallium/drivers/nvc0/nvc0_stateobj.h @@ -10,7 +10,7 @@ (so)->state[(so)->size++] = \ (0x2 << 28) | ((s) << 16) | (NVC0_SUBCH_3D << 13) | ((NVC0_3D_##m) >> 2) -#define SB_OUT_3D(so, m, d) \ +#define SB_IMMED_3D(so, m, d) \ (so)->state[(so)->size++] = \ (0x8 << 28) | ((d) << 16) | (NVC0_SUBCH_3D << 13) | ((NVC0_3D_##m) >> 2) diff --git a/src/gallium/drivers/nvc0/nvc0_transfer.c b/src/gallium/drivers/nvc0/nvc0_transfer.c index 67f6321cac..138d157652 100644 --- a/src/gallium/drivers/nvc0/nvc0_transfer.c +++ b/src/gallium/drivers/nvc0/nvc0_transfer.c @@ -127,7 +127,7 @@ nvc0_m2mf_push_linear(struct nvc0_context *nvc0, if (nr < 9) { FIRE_RING(chan); - nvc0_make_bo_resident(nvc0, dst, NOUVEAU_BO_WR); + nouveau_bo_validate(chan, dst, NOUVEAU_BO_WR); continue; } nr = MIN2(count, nr - 1); diff --git a/src/gallium/drivers/nvc0/nvc0_winsys.h b/src/gallium/drivers/nvc0/nvc0_winsys.h index 85f8ed4da4..af7711031f 100644 --- a/src/gallium/drivers/nvc0/nvc0_winsys.h +++ b/src/gallium/drivers/nvc0/nvc0_winsys.h @@ -11,6 +11,7 @@ #include "nouveau/nouveau_grobj.h" #include "nouveau/nouveau_device.h" #include "nouveau/nouveau_resource.h" +#include "nouveau/nouveau_pushbuf.h" #include "nouveau/nouveau_reloc.h" #include "nvc0_resource.h" /* OUT_RESRC */ @@ -44,16 +45,10 @@ nouveau_bo_tile_layout(struct nouveau_bo *bo) } static INLINE void -WAIT_RING(struct nouveau_channel *chan, unsigned size) +nouveau_bo_validate(struct nouveau_channel *chan, + struct nouveau_bo *bo, unsigned flags) { - if (chan->cur + size > chan->end) - nouveau_pushbuf_flush(chan, size); -} - -static INLINE void -OUT_RING(struct nouveau_channel *chan, uint32_t data) -{ - *(chan->cur++) = (data); + nouveau_reloc_emit(chan, NULL, 0, NULL, bo, 0, 0, flags, 0, 0); } /* incremental methods */ @@ -88,66 +83,6 @@ IMMED_RING(struct nouveau_channel *chan, uint32_t mthd, unsigned data) OUT_RING (chan, (0x8 << 28) | (data << 16) | mthd); } -int -nouveau_pushbuf_marker_emit(struct nouveau_channel *chan, - unsigned wait_dwords, unsigned wait_relocs); -int -nouveau_pushbuf_emit_reloc(struct nouveau_channel *, void *ptr, - struct nouveau_bo *, uint32_t data, uint32_t data2, - uint32_t flags, uint32_t vor, uint32_t tor); -int -nouveau_pushbuf_submit(struct nouveau_channel *chan, struct nouveau_bo *bo, - unsigned offset, unsigned length); - -static INLINE int -MARK_RING(struct nouveau_channel *chan, unsigned dwords, unsigned relocs) -{ - return nouveau_pushbuf_marker_emit(chan, dwords, relocs); -} - -static INLINE void -OUT_RINGf(struct nouveau_channel *chan, float data) -{ - union { uint32_t i; float f; } u; - u.f = data; - OUT_RING(chan, u.i); -} - -static INLINE unsigned -AVAIL_RING(struct nouveau_channel *chan) -{ - return chan->end - chan->cur; -} - -static INLINE void -OUT_RINGp(struct nouveau_channel *chan, const void *data, unsigned size) -{ - memcpy(chan->cur, data, size * 4); - chan->cur += size; -} - -static INLINE int -OUT_RELOC(struct nouveau_channel *chan, struct nouveau_bo *bo, - unsigned data, unsigned flags, unsigned vor, unsigned tor) -{ - return nouveau_pushbuf_emit_reloc(chan, chan->cur++, bo, - data, 0, flags, vor, tor); -} - -static INLINE int -OUT_RELOCl(struct nouveau_channel *chan, struct nouveau_bo *bo, - unsigned delta, unsigned flags) -{ - return OUT_RELOC(chan, bo, delta, flags | NOUVEAU_BO_LOW, 0, 0); -} - -static INLINE int -OUT_RELOCh(struct nouveau_channel *chan, struct nouveau_bo *bo, - unsigned delta, unsigned flags) -{ - return OUT_RELOC(chan, bo, delta, flags | NOUVEAU_BO_HIGH, 0, 0); -} - static INLINE int OUT_RESRCh(struct nouveau_channel *chan, struct nvc0_resource *res, unsigned delta, unsigned flags) @@ -162,12 +97,6 @@ OUT_RESRCl(struct nouveau_channel *chan, struct nvc0_resource *res, return OUT_RELOCl(chan, res->bo, res->offset + delta, res->domain | flags); } -static INLINE void -FIRE_RING(struct nouveau_channel *chan) -{ - nouveau_pushbuf_flush(chan, 0); -} - static INLINE void BIND_RING(struct nouveau_channel *chan, struct nouveau_grobj *gr, unsigned s) { -- cgit v1.2.3 From e4349027f6842563555992a39add4d0b2283fbbb Mon Sep 17 00:00:00 2001 From: Christoph Bumiller Date: Mon, 27 Dec 2010 13:57:46 +0100 Subject: nvc0: implement VRAM buffer transfers with bounce buffers --- src/gallium/drivers/nvc0/nvc0_buffer.c | 302 ++++++++++++++++++++++++------- src/gallium/drivers/nvc0/nvc0_context.c | 35 ++-- src/gallium/drivers/nvc0/nvc0_context.h | 6 +- src/gallium/drivers/nvc0/nvc0_fence.c | 11 ++ src/gallium/drivers/nvc0/nvc0_fence.h | 1 + src/gallium/drivers/nvc0/nvc0_push.c | 10 +- src/gallium/drivers/nvc0/nvc0_resource.h | 58 ++++-- src/gallium/drivers/nvc0/nvc0_screen.c | 3 +- src/gallium/drivers/nvc0/nvc0_screen.h | 18 +- src/gallium/drivers/nvc0/nvc0_state.c | 4 + src/gallium/drivers/nvc0/nvc0_tex.c | 2 - src/gallium/drivers/nvc0/nvc0_winsys.h | 2 + 12 files changed, 336 insertions(+), 116 deletions(-) (limited to 'src/gallium/drivers/nvc0/nvc0_state.c') diff --git a/src/gallium/drivers/nvc0/nvc0_buffer.c b/src/gallium/drivers/nvc0/nvc0_buffer.c index 93d7f5d303..8021e4348b 100644 --- a/src/gallium/drivers/nvc0/nvc0_buffer.c +++ b/src/gallium/drivers/nvc0/nvc0_buffer.c @@ -11,7 +11,15 @@ #include "nvc0_context.h" #include "nvc0_resource.h" -#define NVC0_BUFFER_STATUS_USER_MEMORY 0xff +struct nvc0_transfer { + struct pipe_transfer base; +}; + +static INLINE struct nvc0_transfer * +nvc0_transfer(struct pipe_transfer *transfer) +{ + return (struct nvc0_transfer *)transfer; +} static INLINE boolean nvc0_buffer_allocate(struct nvc0_screen *screen, struct nvc0_resource *buf, @@ -28,12 +36,13 @@ nvc0_buffer_allocate(struct nvc0_screen *screen, struct nvc0_resource *buf, &buf->offset); if (!buf->bo) return FALSE; - } else { - assert(!domain); - if (!buf->data) + } + if (domain != NOUVEAU_BO_GART) { + if (!buf->data) { buf->data = MALLOC(buf->base.width0); - if (!buf->data) - return FALSE; + if (!buf->data) + return FALSE; + } } buf->domain = domain; return TRUE; @@ -59,68 +68,199 @@ nvc0_buffer_destroy(struct pipe_screen *pscreen, if (res->mm) release_allocation(&res->mm, screen->fence.current); - if (res->status != NVC0_BUFFER_STATUS_USER_MEMORY && res->data) + if (res->data && !(res->status & NVC0_BUFFER_STATUS_USER_MEMORY)) FREE(res->data); FREE(res); } -static INLINE uint32_t -nouveau_buffer_rw_flags(unsigned pipe) +/* Maybe just migrate to GART right away if we actually need to do this. */ +boolean +nvc0_buffer_download(struct nvc0_context *nvc0, struct nvc0_resource *buf, + unsigned start, unsigned size) +{ + struct nvc0_mm_allocation *mm; + struct nouveau_bo *bounce = NULL; + uint32_t offset; + + assert(buf->domain == NOUVEAU_BO_VRAM); + + mm = nvc0_mm_allocate(nvc0->screen->mm_GART, size, &bounce, &offset); + if (!bounce) + return FALSE; + + nvc0_m2mf_copy_linear(nvc0, bounce, offset, NOUVEAU_BO_GART, + buf->bo, buf->offset + start, NOUVEAU_BO_VRAM, + size); + + if (nouveau_bo_map_range(bounce, offset, size, NOUVEAU_BO_RD)) + return FALSE; + memcpy(buf->data + start, bounce->map, size); + nouveau_bo_unmap(bounce); + + buf->status &= ~NVC0_BUFFER_STATUS_DIRTY; + + nouveau_bo_ref(NULL, &bounce); + if (mm) + nvc0_mm_free(mm); + return TRUE; +} + +static boolean +nvc0_buffer_upload(struct nvc0_context *nvc0, struct nvc0_resource *buf, + unsigned start, unsigned size) { - uint32_t flags = 0; + struct nvc0_mm_allocation *mm; + struct nouveau_bo *bounce = NULL; + uint32_t offset; - if (pipe & PIPE_TRANSFER_READ) - flags = NOUVEAU_BO_RD; - if (pipe & PIPE_TRANSFER_WRITE) - flags |= NOUVEAU_BO_WR; + mm = nvc0_mm_allocate(nvc0->screen->mm_GART, size, &bounce, &offset); + if (!bounce) + return FALSE; + + nouveau_bo_map_range(bounce, offset, size, + NOUVEAU_BO_WR | NOUVEAU_BO_NOSYNC); + memcpy(bounce->map, buf->data + start, size); + nouveau_bo_unmap(bounce); + + nvc0_m2mf_copy_linear(nvc0, buf->bo, buf->offset + start, NOUVEAU_BO_VRAM, + bounce, offset, NOUVEAU_BO_GART, size); + + nouveau_bo_ref(NULL, &bounce); + if (mm) + release_allocation(&mm, nvc0->screen->fence.current); + + if (start == 0 && size == buf->base.width0) + buf->status &= ~NVC0_BUFFER_STATUS_DIRTY; + return TRUE; +} + +static struct pipe_transfer * +nvc0_buffer_transfer_get(struct pipe_context *pipe, + struct pipe_resource *resource, + unsigned level, + unsigned usage, + const struct pipe_box *box) +{ + struct nvc0_resource *buf = nvc0_resource(resource); + struct nvc0_transfer *xfr = CALLOC_STRUCT(nvc0_transfer); + if (!xfr) + return NULL; + + xfr->base.resource = resource; + xfr->base.box.x = box->x; + xfr->base.box.width = box->width; + xfr->base.usage = usage; + + if (buf->domain == NOUVEAU_BO_VRAM) { + if (usage & PIPE_TRANSFER_READ) { + if (buf->status & NVC0_BUFFER_STATUS_DIRTY) + nvc0_buffer_download(nvc0_context(pipe), buf, 0, buf->base.width0); + } + } + + return &xfr->base; +} + +static void +nvc0_buffer_transfer_destroy(struct pipe_context *pipe, + struct pipe_transfer *transfer) +{ + struct nvc0_resource *buf = nvc0_resource(transfer->resource); + struct nvc0_transfer *xfr = nvc0_transfer(transfer); + + if (xfr->base.usage & PIPE_TRANSFER_WRITE) { + /* writing is worse */ + nvc0_buffer_adjust_score(nvc0_context(pipe), buf, -5000); + + if (buf->domain == NOUVEAU_BO_VRAM) { + nvc0_buffer_upload(nvc0_context(pipe), buf, + transfer->box.x, transfer->box.width); + } + + if (buf->domain != 0 && (buf->base.bind & (PIPE_BIND_VERTEX_BUFFER | + PIPE_BIND_INDEX_BUFFER))) + nvc0_context(pipe)->vbo_dirty = TRUE; + } - return flags; + FREE(xfr); +} + +static INLINE boolean +nvc0_buffer_sync(struct nvc0_resource *buf, unsigned rw) +{ + if (rw == PIPE_TRANSFER_READ) { + if (!buf->fence_wr) + return TRUE; + if (!nvc0_fence_wait(buf->fence_wr)) + return FALSE; + } else { + if (!buf->fence) + return TRUE; + if (!nvc0_fence_wait(buf->fence)) + return FALSE; + + nvc0_fence_reference(&buf->fence, NULL); + } + nvc0_fence_reference(&buf->fence_wr, NULL); + + return TRUE; +} + +static INLINE boolean +nvc0_buffer_busy(struct nvc0_resource *buf, unsigned rw) +{ + if (rw == PIPE_TRANSFER_READ) + return (buf->fence_wr && !nvc0_fence_signalled(buf->fence_wr)); + else + return (buf->fence && !nvc0_fence_signalled(buf->fence)); } static void * nvc0_buffer_transfer_map(struct pipe_context *pipe, struct pipe_transfer *transfer) { - struct nvc0_resource *res = nvc0_resource(transfer->resource); - struct nvc0_fence *fence; + struct nvc0_transfer *xfr = nvc0_transfer(transfer); + struct nvc0_resource *buf = nvc0_resource(transfer->resource); + struct nouveau_bo *bo = buf->bo; uint8_t *map; int ret; - uint32_t flags = nouveau_buffer_rw_flags(transfer->usage); + uint32_t offset = xfr->base.box.x; + uint32_t flags; - if ((res->base.bind & (PIPE_BIND_VERTEX_BUFFER | PIPE_BIND_INDEX_BUFFER)) && - (flags & NOUVEAU_BO_WR)) - nvc0_context(pipe)->vbo_dirty = TRUE; + nvc0_buffer_adjust_score(nvc0_context(pipe), buf, -250); - if (res->domain == 0) - return res->data + transfer->box.x; + if (buf->domain != NOUVEAU_BO_GART) + return buf->data + offset; - if (res->domain == NOUVEAU_BO_VRAM) { - NOUVEAU_ERR("transfers to/from VRAM buffers are not allowed\n"); - /* if this happens, migrate back to GART */ - return NULL; - } + if (buf->mm) + flags = NOUVEAU_BO_NOSYNC | NOUVEAU_BO_RDWR; + else + flags = nouveau_screen_transfer_flags(xfr->base.usage); - if (res->score > -1024) - --res->score; + offset += buf->offset; - ret = nouveau_bo_map(res->bo, flags | NOUVEAU_BO_NOSYNC); + ret = nouveau_bo_map_range(buf->bo, offset, xfr->base.box.width, flags); if (ret) return NULL; - map = res->bo->map; - nouveau_bo_unmap(res->bo); - - fence = (flags == NOUVEAU_BO_RD) ? res->fence_wr : res->fence; - - if (fence) { - if (nvc0_fence_wait(fence) == FALSE) - NOUVEAU_ERR("failed to fence buffer\n"); - - nvc0_fence_reference(&res->fence, NULL); - nvc0_fence_reference(&res->fence_wr, NULL); + map = bo->map; + + /* Unmap right now. Since multiple buffers can share a single nouveau_bo, + * not doing so might make future maps fail or trigger "reloc while mapped" + * errors. For now, mappings to userspace are guaranteed to be persistent. + */ + nouveau_bo_unmap(bo); + + if (buf->mm) { + if (xfr->base.usage & PIPE_TRANSFER_DONTBLOCK) { + if (nvc0_buffer_busy(buf, xfr->base.usage & PIPE_TRANSFER_READ_WRITE)) + return NULL; + } else + if (!(xfr->base.usage & PIPE_TRANSFER_UNSYNCHRONIZED)) { + nvc0_buffer_sync(buf, xfr->base.usage & PIPE_TRANSFER_READ_WRITE); + } } - - return map + transfer->box.x + res->offset; + return map; } @@ -131,26 +271,23 @@ nvc0_buffer_transfer_flush_region(struct pipe_context *pipe, const struct pipe_box *box) { struct nvc0_resource *res = nvc0_resource(transfer->resource); + struct nouveau_bo *bo = res->bo; + unsigned offset = res->offset + transfer->box.x + box->x; - if (!res->bo) + /* not using non-snoop system memory yet, no need for cflush */ + if (1) return; - nouveau_screen_bo_map_flush_range(pipe->screen, - res->bo, - res->offset + transfer->box.x + box->x, - box->width); + /* XXX: maybe need to upload for VRAM buffers here */ + + nouveau_screen_bo_map_flush_range(pipe->screen, bo, offset, box->width); } static void nvc0_buffer_transfer_unmap(struct pipe_context *pipe, struct pipe_transfer *transfer) { - struct nvc0_resource *res = nvc0_resource(transfer->resource); - - if (res->data) - return; - - /* nouveau_screen_bo_unmap(pipe->screen, res->bo); */ + /* we've called nouveau_bo_unmap right after map */ } const struct u_resource_vtbl nvc0_buffer_vtbl = @@ -158,8 +295,8 @@ const struct u_resource_vtbl nvc0_buffer_vtbl = u_default_resource_get_handle, /* get_handle */ nvc0_buffer_destroy, /* resource_destroy */ NULL, /* is_resource_referenced */ - u_default_get_transfer, /* get_transfer */ - u_default_transfer_destroy, /* transfer_destroy */ + nvc0_buffer_transfer_get, /* get_transfer */ + nvc0_buffer_transfer_destroy, /* transfer_destroy */ nvc0_buffer_transfer_map, /* transfer_map */ nvc0_buffer_transfer_flush_region, /* transfer_flush_region */ nvc0_buffer_transfer_unmap, /* transfer_unmap */ @@ -227,6 +364,23 @@ nvc0_user_buffer_create(struct pipe_screen *pscreen, return &buffer->base; } +static INLINE boolean +nvc0_buffer_fetch_data(struct nvc0_resource *buf, + struct nouveau_bo *bo, unsigned offset, unsigned size) +{ + if (!buf->data) { + buf->data = MALLOC(size); + if (!buf->data) + return FALSE; + } + if (nouveau_bo_map_range(bo, offset, size, NOUVEAU_BO_RD)) + return FALSE; + memcpy(buf->data, bo->map, size); + nouveau_bo_unmap(bo); + + return TRUE; +} + /* Migrate a linear buffer (vertex, index, constants) USER -> GART -> VRAM. */ boolean nvc0_buffer_migrate(struct nvc0_context *nvc0, @@ -235,38 +389,52 @@ nvc0_buffer_migrate(struct nvc0_context *nvc0, struct nvc0_screen *screen = nvc0_screen(buf->base.screen); struct nouveau_bo *bo; unsigned size = buf->base.width0; + unsigned offset; int ret; + assert(domain != buf->domain); + if (domain == NOUVEAU_BO_GART && buf->domain == 0) { if (!nvc0_buffer_allocate(screen, buf, domain)) return FALSE; - ret = nouveau_bo_map(buf->bo, NOUVEAU_BO_WR | NOUVEAU_BO_NOSYNC); + ret = nouveau_bo_map_range(buf->bo, buf->offset, size, NOUVEAU_BO_WR | + NOUVEAU_BO_NOSYNC); if (ret) return ret; - memcpy((uint8_t *)buf->bo->map + buf->offset, buf->data, size); + memcpy(buf->bo->map, buf->data, size); nouveau_bo_unmap(buf->bo); + FREE(buf->data); } else - if (domain == NOUVEAU_BO_VRAM && buf->domain == NOUVEAU_BO_GART) { + if (domain != 0 && buf->domain != 0) { struct nvc0_mm_allocation *mm = buf->mm; + if (domain == NOUVEAU_BO_VRAM) { + /* keep a system memory copy of our data in case we hit a fallback */ + if (!nvc0_buffer_fetch_data(buf, buf->bo, buf->offset, size)) + return FALSE; + debug_printf("migrating %u KiB to VRAM\n", size / 1024); + } + + offset = buf->offset; bo = buf->bo; buf->bo = NULL; buf->mm = NULL; nvc0_buffer_allocate(screen, buf, domain); - nvc0_m2mf_copy_linear(nvc0, buf->bo, 0, NOUVEAU_BO_VRAM, - bo, 0, NOUVEAU_BO_GART, buf->base.width0); + nvc0_m2mf_copy_linear(nvc0, buf->bo, buf->offset, domain, + bo, offset, buf->domain, buf->base.width0); - release_allocation(&mm, screen->fence.current); nouveau_bo_ref(NULL, &bo); + if (mm) + release_allocation(&mm, screen->fence.current); } else if (domain == NOUVEAU_BO_VRAM && buf->domain == 0) { - /* should use a scratch buffer instead here */ - if (!nvc0_buffer_migrate(nvc0, buf, NOUVEAU_BO_GART)) + if (!nvc0_buffer_allocate(screen, buf, NOUVEAU_BO_VRAM)) + return FALSE; + if (!nvc0_buffer_upload(nvc0, buf, 0, buf->base.width0)) return FALSE; - return nvc0_buffer_migrate(nvc0, buf, NOUVEAU_BO_VRAM); } else - return -1; + return FALSE; buf->domain = domain; diff --git a/src/gallium/drivers/nvc0/nvc0_context.c b/src/gallium/drivers/nvc0/nvc0_context.c index d41ee297d4..b2b4fd62ee 100644 --- a/src/gallium/drivers/nvc0/nvc0_context.c +++ b/src/gallium/drivers/nvc0/nvc0_context.c @@ -104,7 +104,7 @@ nvc0_create(struct pipe_screen *pscreen, void *priv) } struct resident { - struct nouveau_bo *bo; + struct nvc0_resource *res; uint32_t flags; }; @@ -112,12 +112,14 @@ void nvc0_bufctx_add_resident(struct nvc0_context *nvc0, int ctx, struct nvc0_resource *resource, uint32_t flags) { - struct resident rsd = { NULL, flags }; + struct resident rsd = { resource, flags }; if (!resource->bo) return; - nouveau_bo_ref(resource->bo, &rsd.bo); + /* We don't need to reference the resource here, it will be referenced + * in the context/state, and bufctx will be reset when state changes. + */ util_dynarray_append(&nvc0->residents[ctx], struct resident, rsd); } @@ -125,35 +127,24 @@ void nvc0_bufctx_del_resident(struct nvc0_context *nvc0, int ctx, struct nvc0_resource *resource) { - struct resident *rsd, rem; + struct resident *rsd, *top; unsigned i; for (i = 0; i < nvc0->residents[ctx].size / sizeof(struct resident); ++i) { rsd = util_dynarray_element(&nvc0->residents[ctx], struct resident, i); - if (rsd->bo == resource->bo) { - rem = util_dynarray_pop(&nvc0->residents[ctx], struct resident); - nouveau_bo_ref(NULL, &rem.bo); + if (rsd->res == resource) { + top = util_dynarray_pop_ptr(&nvc0->residents[ctx], struct resident); + if (rsd != top) + *rsd = *top; break; } } } -void -nvc0_bufctx_reset(struct nvc0_context *nvc0, int ctx) -{ - unsigned i; - - for (i = 0; i < nvc0->residents[ctx].size / sizeof(struct resident); ++i) - nouveau_bo_ref(NULL, &util_dynarray_element(&nvc0->residents[ctx], - struct resident, i)->bo); - util_dynarray_resize(&nvc0->residents[ctx], 0); -} - void nvc0_bufctx_emit_relocs(struct nvc0_context *nvc0) { - struct nouveau_channel *chan = nvc0->screen->base.channel; struct resident *rsd; struct util_dynarray *array; unsigned ctx, i; @@ -164,11 +155,9 @@ nvc0_bufctx_emit_relocs(struct nvc0_context *nvc0) for (i = 0; i < array->size / sizeof(struct resident); ++i) { rsd = util_dynarray_element(array, struct resident, i); - nouveau_bo_validate(chan, rsd->bo, rsd->flags); + nvc0_resource_validate(rsd->res, rsd->flags); } } - nouveau_bo_validate(chan, nvc0->screen->text, NOUVEAU_BO_RD); - nouveau_bo_validate(chan, nvc0->screen->uniforms, NOUVEAU_BO_RD); - nouveau_bo_validate(chan, nvc0->screen->txc, NOUVEAU_BO_RD); + nvc0_screen_make_buffers_resident(nvc0->screen); } diff --git a/src/gallium/drivers/nvc0/nvc0_context.h b/src/gallium/drivers/nvc0/nvc0_context.h index 962a2c0cf2..83aff0a585 100644 --- a/src/gallium/drivers/nvc0/nvc0_context.h +++ b/src/gallium/drivers/nvc0/nvc0_context.h @@ -147,11 +147,15 @@ nvc0_surface(struct pipe_surface *ps) struct pipe_context *nvc0_create(struct pipe_screen *, void *); void nvc0_bufctx_emit_relocs(struct nvc0_context *); -void nvc0_bufctx_reset(struct nvc0_context *, int ctx); void nvc0_bufctx_add_resident(struct nvc0_context *, int ctx, struct nvc0_resource *, uint32_t flags); void nvc0_bufctx_del_resident(struct nvc0_context *, int ctx, struct nvc0_resource *); +static INLINE void +nvc0_bufctx_reset(struct nvc0_context *nvc0, int ctx) +{ + util_dynarray_resize(&nvc0->residents[ctx], 0); +} /* nvc0_draw.c */ extern struct draw_stage *nvc0_draw_render_stage(struct nvc0_context *); diff --git a/src/gallium/drivers/nvc0/nvc0_fence.c b/src/gallium/drivers/nvc0/nvc0_fence.c index dc2abe45bd..0387c5940b 100644 --- a/src/gallium/drivers/nvc0/nvc0_fence.c +++ b/src/gallium/drivers/nvc0/nvc0_fence.c @@ -138,6 +138,17 @@ nvc0_screen_fence_update(struct nvc0_screen *screen) #define NVC0_FENCE_MAX_SPINS (1 << 17) +boolean +nvc0_fence_signalled(struct nvc0_fence *fence) +{ + struct nvc0_screen *screen = fence->screen; + + if (fence->state == NVC0_FENCE_STATE_EMITTED) + nvc0_screen_fence_update(screen); + + return fence->state == NVC0_FENCE_STATE_SIGNALLED; +} + boolean nvc0_fence_wait(struct nvc0_fence *fence) { diff --git a/src/gallium/drivers/nvc0/nvc0_fence.h b/src/gallium/drivers/nvc0/nvc0_fence.h index 7b31f28808..e63c164bda 100644 --- a/src/gallium/drivers/nvc0/nvc0_fence.h +++ b/src/gallium/drivers/nvc0/nvc0_fence.h @@ -24,6 +24,7 @@ void nvc0_fence_emit(struct nvc0_fence *); void nvc0_fence_del(struct nvc0_fence *); boolean nvc0_fence_wait(struct nvc0_fence *); +boolean nvc0_fence_signalled(struct nvc0_fence *); static INLINE void nvc0_fence_reference(struct nvc0_fence **ref, struct nvc0_fence *fence) diff --git a/src/gallium/drivers/nvc0/nvc0_push.c b/src/gallium/drivers/nvc0/nvc0_push.c index 4bf259c646..779a477599 100644 --- a/src/gallium/drivers/nvc0/nvc0_push.c +++ b/src/gallium/drivers/nvc0/nvc0_push.c @@ -215,7 +215,8 @@ nvc0_push_vbo(struct nvc0_context *nvc0, const struct pipe_draw_info *info) struct pipe_vertex_buffer *vb = &nvc0->vtxbuf[i]; struct nvc0_resource *res = nvc0_resource(vb->buffer); - data = nvc0_resource_map_offset(res, vb->buffer_offset, NOUVEAU_BO_RD); + data = nvc0_resource_map_offset(nvc0, res, + vb->buffer_offset, NOUVEAU_BO_RD); if (info->indexed) data += info->index_bias * vb->stride; @@ -223,12 +224,11 @@ nvc0_push_vbo(struct nvc0_context *nvc0, const struct pipe_draw_info *info) } if (info->indexed) { - ctx.idxbuf = pipe_buffer_map(&nvc0->pipe, nvc0->idxbuf.buffer, - PIPE_TRANSFER_READ, &transfer); + ctx.idxbuf = nvc0_resource_map_offset(nvc0, + nvc0_resource(nvc0->idxbuf.buffer), + nvc0->idxbuf.offset, NOUVEAU_BO_RD); if (!ctx.idxbuf) return; - ctx.idxbuf = (uint8_t *)ctx.idxbuf + nvc0->idxbuf.offset; - index_size = nvc0->idxbuf.index_size; ctx.primitive_restart = info->primitive_restart; ctx.restart_index = info->restart_index; diff --git a/src/gallium/drivers/nvc0/nvc0_resource.h b/src/gallium/drivers/nvc0/nvc0_resource.h index 9384f1905d..0ffb9e8fa6 100644 --- a/src/gallium/drivers/nvc0/nvc0_resource.h +++ b/src/gallium/drivers/nvc0/nvc0_resource.h @@ -12,6 +12,14 @@ struct pipe_resource; struct nouveau_bo; +struct nvc0_context; + +#define NVC0_BUFFER_SCORE_MIN -25000 +#define NVC0_BUFFER_SCORE_MAX 25000 +#define NVC0_BUFFER_SCORE_VRAM_THRESHOLD 20000 + +#define NVC0_BUFFER_STATUS_DIRTY (1 << 0) +#define NVC0_BUFFER_STATUS_USER_MEMORY (1 << 7) /* Resources, if mapped into the GPU's address space, are guaranteed to * have constant virtual addresses. @@ -21,7 +29,6 @@ struct nouveau_bo; struct nvc0_resource { struct pipe_resource base; const struct u_resource_vtbl *vtbl; - uint64_t address; uint8_t *data; struct nouveau_bo *bo; @@ -38,22 +45,55 @@ struct nvc0_resource { struct nvc0_mm_allocation *mm; }; +boolean +nvc0_buffer_download(struct nvc0_context *, struct nvc0_resource *, + unsigned start, unsigned size); + +boolean +nvc0_buffer_migrate(struct nvc0_context *, + struct nvc0_resource *, unsigned domain); + +static INLINE void +nvc0_buffer_adjust_score(struct nvc0_context *nvc0, struct nvc0_resource *res, + int16_t score) +{ + if (score < 0) { + if (res->score > NVC0_BUFFER_SCORE_MIN) + res->score += score; + } else + if (score > 0){ + if (res->score < NVC0_BUFFER_SCORE_MAX) + res->score += score; + if (res->domain == NOUVEAU_BO_GART && + res->score > NVC0_BUFFER_SCORE_VRAM_THRESHOLD) + nvc0_buffer_migrate(nvc0, res, NOUVEAU_BO_VRAM); + } +} + /* XXX: wait for fence (atm only using this for vertex push) */ static INLINE void * -nvc0_resource_map_offset(struct nvc0_resource *res, uint32_t offset, +nvc0_resource_map_offset(struct nvc0_context *nvc0, + struct nvc0_resource *res, uint32_t offset, uint32_t flags) { void *map; - if (res->domain == 0) + nvc0_buffer_adjust_score(nvc0, res, -250); + + if ((res->domain == NOUVEAU_BO_VRAM) && + (res->status & NVC0_BUFFER_STATUS_DIRTY)) + nvc0_buffer_download(nvc0, res, 0, res->base.width0); + + if (res->domain != NOUVEAU_BO_GART) return res->data + offset; + if (res->mm) + flags |= NOUVEAU_BO_NOSYNC; + if (nouveau_bo_map_range(res->bo, res->offset + offset, - res->base.width0, flags | NOUVEAU_BO_NOSYNC)) + res->base.width0, flags)) return NULL; - /* With suballocation, the same bo can be mapped several times, so unmap - * immediately. Maps are guaranteed to persist. */ map = res->bo->map; nouveau_bo_unmap(res->bo); return map; @@ -149,12 +189,6 @@ nvc0_miptree_surface_new(struct pipe_context *, void nvc0_miptree_surface_del(struct pipe_context *, struct pipe_surface *); -struct nvc0_context; - -boolean -nvc0_buffer_migrate(struct nvc0_context *, - struct nvc0_resource *, unsigned domain); - boolean nvc0_migrate_vertices(struct nvc0_resource *buf, unsigned base, unsigned size); diff --git a/src/gallium/drivers/nvc0/nvc0_screen.c b/src/gallium/drivers/nvc0/nvc0_screen.c index 4ec73b07aa..0e80e2841a 100644 --- a/src/gallium/drivers/nvc0/nvc0_screen.c +++ b/src/gallium/drivers/nvc0/nvc0_screen.c @@ -248,7 +248,7 @@ nvc0_screen_fence_signalled(struct pipe_screen *pscreen, struct pipe_fence_handle *fence, unsigned flags) { - return !(((struct nvc0_fence *)fence)->state == NVC0_FENCE_STATE_SIGNALLED); + return !(nvc0_fence_signalled(nvc0_fence(fence))); } static int @@ -622,6 +622,7 @@ nvc0_screen_make_buffers_resident(struct nvc0_screen *screen) const unsigned flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_RD; nouveau_bo_validate(chan, screen->text, flags); + nouveau_bo_validate(chan, screen->uniforms, flags); nouveau_bo_validate(chan, screen->txc, flags); nouveau_bo_validate(chan, screen->tls, flags); nouveau_bo_validate(chan, screen->mp_stack_bo, flags); diff --git a/src/gallium/drivers/nvc0/nvc0_screen.h b/src/gallium/drivers/nvc0/nvc0_screen.h index 5b1b623356..efa5ff63f1 100644 --- a/src/gallium/drivers/nvc0/nvc0_screen.h +++ b/src/gallium/drivers/nvc0/nvc0_screen.h @@ -101,18 +101,26 @@ int nvc0_screen_tic_alloc(struct nvc0_screen *, void *); int nvc0_screen_tsc_alloc(struct nvc0_screen *, void *); static INLINE void -nvc0_resource_validate(struct nvc0_resource *res, uint32_t flags) +nvc0_resource_fence(struct nvc0_resource *res, uint32_t flags) { struct nvc0_screen *screen = nvc0_screen(res->base.screen); - assert(res->mm); + if (res->mm) { + nvc0_fence_reference(&res->fence, screen->fence.current); - nvc0_fence_reference(&res->fence, screen->fence.current); + if (flags & NOUVEAU_BO_WR) + nvc0_fence_reference(&res->fence_wr, screen->fence.current); + } +} - if (flags & NOUVEAU_BO_WR) - nvc0_fence_reference(&res->fence_wr, screen->fence.current); +static INLINE void +nvc0_resource_validate(struct nvc0_resource *res, uint32_t flags) +{ + struct nvc0_screen *screen = nvc0_screen(res->base.screen); nouveau_bo_validate(screen->base.channel, res->bo, flags); + + nvc0_resource_fence(res, flags); } diff --git a/src/gallium/drivers/nvc0/nvc0_state.c b/src/gallium/drivers/nvc0/nvc0_state.c index 62abaa7577..e77e95625b 100644 --- a/src/gallium/drivers/nvc0/nvc0_state.c +++ b/src/gallium/drivers/nvc0/nvc0_state.c @@ -539,6 +539,8 @@ nvc0_stage_set_sampler_views(struct nvc0_context *nvc0, int s, nvc0->num_textures[s] = nr; + nvc0_bufctx_reset(nvc0, NVC0_BUFCTX_TEXTURES); + nvc0->dirty |= NVC0_NEW_TEXTURES; } @@ -773,6 +775,8 @@ nvc0_set_vertex_buffers(struct pipe_context *pipe, memcpy(nvc0->vtxbuf, vb, sizeof(*vb) * count); nvc0->num_vtxbufs = count; + nvc0_bufctx_reset(nvc0, NVC0_BUFCTX_VERTEX); + nvc0->dirty |= NVC0_NEW_ARRAYS; } diff --git a/src/gallium/drivers/nvc0/nvc0_tex.c b/src/gallium/drivers/nvc0/nvc0_tex.c index c9f929b942..b219f82c90 100644 --- a/src/gallium/drivers/nvc0/nvc0_tex.c +++ b/src/gallium/drivers/nvc0/nvc0_tex.c @@ -218,8 +218,6 @@ void nvc0_validate_textures(struct nvc0_context *nvc0) { boolean need_flush; - nvc0_bufctx_reset(nvc0, NVC0_BUFCTX_TEXTURES); - need_flush = nvc0_validate_tic(nvc0, 0); need_flush |= nvc0_validate_tic(nvc0, 4); diff --git a/src/gallium/drivers/nvc0/nvc0_winsys.h b/src/gallium/drivers/nvc0/nvc0_winsys.h index af7711031f..1544fb7a1d 100644 --- a/src/gallium/drivers/nvc0/nvc0_winsys.h +++ b/src/gallium/drivers/nvc0/nvc0_winsys.h @@ -94,6 +94,8 @@ static INLINE int OUT_RESRCl(struct nouveau_channel *chan, struct nvc0_resource *res, unsigned delta, unsigned flags) { + if (flags & NOUVEAU_BO_WR) + res->status |= NVC0_BUFFER_STATUS_DIRTY; return OUT_RELOCl(chan, res->bo, res->offset + delta, res->domain | flags); } -- cgit v1.2.3 From 0cb6d1a4eb2dd682b499f54a82505bc3bd318bbc Mon Sep 17 00:00:00 2001 From: Christoph Bumiller Date: Mon, 27 Dec 2010 20:57:54 +0100 Subject: nvc0: reference the vertex buffers --- src/gallium/drivers/nvc0/nvc0_state.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src/gallium/drivers/nvc0/nvc0_state.c') diff --git a/src/gallium/drivers/nvc0/nvc0_state.c b/src/gallium/drivers/nvc0/nvc0_state.c index e77e95625b..5a9b1c2850 100644 --- a/src/gallium/drivers/nvc0/nvc0_state.c +++ b/src/gallium/drivers/nvc0/nvc0_state.c @@ -771,6 +771,12 @@ nvc0_set_vertex_buffers(struct pipe_context *pipe, const struct pipe_vertex_buffer *vb) { struct nvc0_context *nvc0 = nvc0_context(pipe); + unsigned i; + + for (i = 0; i < count; ++i) + pipe_resource_reference(&nvc0->vtxbuf[i].buffer, vb[i].buffer); + for (; i < nvc0->num_vtxbufs; ++i) + pipe_resource_reference(&nvc0->vtxbuf[i].buffer, NULL); memcpy(nvc0->vtxbuf, vb, sizeof(*vb) * count); nvc0->num_vtxbufs = count; -- cgit v1.2.3