From: Marek Olšák Date: Sat, 10 Apr 2010 23:13:11 +0000 (+0200) Subject: r300g: cleanup handling of sampler views X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=1c356ac95b6df0962dbd15311ff7e0ea172e1aea;p=mesa.git r300g: cleanup handling of sampler views The evolution of TX_FORMAT bits is as follows: * When a texture is created, set bits independent of pipe_format. * When a sampler view is created, add format-specific bits. * When sampler states and views are getting merged, add min/max LOD. --- diff --git a/src/gallium/drivers/r300/r300_blit.c b/src/gallium/drivers/r300/r300_blit.c index b99879afdd3..f26330ef1da 100644 --- a/src/gallium/drivers/r300/r300_blit.c +++ b/src/gallium/drivers/r300/r300_blit.c @@ -111,11 +111,12 @@ static void r300_hw_copy(struct pipe_context* pipe, util_blitter_save_framebuffer(r300->blitter, r300->fb_state.state); util_blitter_save_fragment_sampler_states( - r300->blitter, state->sampler_count, (void**)state->sampler_states); + r300->blitter, state->sampler_state_count, + (void**)state->sampler_states); util_blitter_save_fragment_sampler_views( - r300->blitter, state->texture_count, - state->fragment_sampler_views); + r300->blitter, state->sampler_view_count, + (struct pipe_sampler_view**)state->sampler_views); /* Do a copy */ util_blitter_copy(r300->blitter, diff --git a/src/gallium/drivers/r300/r300_context.h b/src/gallium/drivers/r300/r300_context.h index 8d770853a46..fc186df640e 100644 --- a/src/gallium/drivers/r300/r300_context.h +++ b/src/gallium/drivers/r300/r300_context.h @@ -130,6 +130,15 @@ struct r300_texture_format_state { uint32_t format0; /* R300_TX_FORMAT0: 0x4480 */ uint32_t format1; /* R300_TX_FORMAT1: 0x44c0 */ uint32_t format2; /* R300_TX_FORMAT2: 0x4500 */ + uint32_t tile_config; /* R300_TX_OFFSET (subset thereof) */ +}; + +struct r300_sampler_view { + struct pipe_sampler_view base; + + /* Copy of r300_texture::texture_format_state with format-specific bits + * added. */ + struct r300_texture_format_state format; }; struct r300_texture_fb_state { @@ -144,20 +153,20 @@ struct r300_texture_fb_state { struct r300_textures_state { /* Textures. */ - struct pipe_sampler_view *fragment_sampler_views[16]; - int texture_count; + struct r300_sampler_view *sampler_views[16]; + int sampler_view_count; /* Sampler states. */ struct r300_sampler_state *sampler_states[16]; - int sampler_count; + int sampler_state_count; - /* These is the merge of the texture and sampler states. */ + /* This is the merge of the texture and sampler states. */ unsigned count; uint32_t tx_enable; /* R300_TX_ENABLE: 0x4101 */ struct r300_texture_sampler_state { - uint32_t format[3]; /* R300_TX_FORMAT[0-2] */ - uint32_t filter[2]; /* R300_TX_FILTER[0-1] */ + struct r300_texture_format_state format; + uint32_t filter0; /* R300_TX_FILTER0: 0x4400 */ + uint32_t filter1; /* R300_TX_FILTER1: 0x4440 */ uint32_t border_color; /* R300_TX_BORDER_COLOR: 0x45c0 */ - uint32_t tile_config; /* R300_TX_OFFSET (subset thereof) */ } regs[16]; }; @@ -266,7 +275,9 @@ struct r300_texture { struct r300_winsys_buffer *buffer; /* Registers carrying texture format data. */ - struct r300_texture_format_state state; + /* Only format-independent bits should be filled in. */ + struct r300_texture_format_state tx_format; + /* All bits should be filled in. */ struct r300_texture_fb_state fb_state; /* Buffer tiling */ diff --git a/src/gallium/drivers/r300/r300_emit.c b/src/gallium/drivers/r300/r300_emit.c index 350c538ebc5..771aaf8d224 100644 --- a/src/gallium/drivers/r300/r300_emit.c +++ b/src/gallium/drivers/r300/r300_emit.c @@ -159,7 +159,7 @@ static const float * get_shader_constant( /* Factor for converting rectangle coords to * normalized coords. Should only show up on non-r500. */ case RC_STATE_R300_TEXRECT_FACTOR: - tex = texstate->fragment_sampler_views[constant->u.State[1]]->texture; + tex = texstate->sampler_views[constant->u.State[1]]->base.texture; vec[0] = 1.0 / tex->width0; vec[1] = 1.0 / tex->height0; break; @@ -729,18 +729,18 @@ void r300_emit_textures_state(struct r300_context *r300, if ((1 << i) & allstate->tx_enable) { texstate = &allstate->regs[i]; - OUT_CS_REG(R300_TX_FILTER0_0 + (i * 4), texstate->filter[0]); - OUT_CS_REG(R300_TX_FILTER1_0 + (i * 4), texstate->filter[1]); + OUT_CS_REG(R300_TX_FILTER0_0 + (i * 4), texstate->filter0); + OUT_CS_REG(R300_TX_FILTER1_0 + (i * 4), texstate->filter1); OUT_CS_REG(R300_TX_BORDER_COLOR_0 + (i * 4), texstate->border_color); - OUT_CS_REG(R300_TX_FORMAT0_0 + (i * 4), texstate->format[0]); - OUT_CS_REG(R300_TX_FORMAT1_0 + (i * 4), texstate->format[1]); - OUT_CS_REG(R300_TX_FORMAT2_0 + (i * 4), texstate->format[2]); + OUT_CS_REG(R300_TX_FORMAT0_0 + (i * 4), texstate->format.format0); + OUT_CS_REG(R300_TX_FORMAT1_0 + (i * 4), texstate->format.format1); + OUT_CS_REG(R300_TX_FORMAT2_0 + (i * 4), texstate->format.format2); OUT_CS_REG_SEQ(R300_TX_OFFSET_0 + (i * 4), 1); - OUT_CS_TEX_RELOC(r300_texture(allstate->fragment_sampler_views[i]->texture), - texstate->tile_config, + OUT_CS_TEX_RELOC(r300_texture(allstate->sampler_views[i]->base.texture), + texstate->format.tile_config, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0, 0); } } @@ -1022,7 +1022,7 @@ validate: continue; } - tex = r300_texture(texstate->fragment_sampler_views[i]->texture); + tex = r300_texture(texstate->sampler_views[i]->base.texture); if (!r300_add_texture(r300->rws, tex, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0)) { r300->context.flush(&r300->context, 0, NULL); diff --git a/src/gallium/drivers/r300/r300_fs.c b/src/gallium/drivers/r300/r300_fs.c index b70bb51ba2d..0444e58f0dd 100644 --- a/src/gallium/drivers/r300/r300_fs.c +++ b/src/gallium/drivers/r300/r300_fs.c @@ -138,7 +138,7 @@ static void get_compare_state( memset(state, 0, sizeof(*state)); - for (int i = 0; i < texstate->sampler_count; i++) { + for (int i = 0; i < texstate->sampler_state_count; i++) { struct r300_sampler_state* s = texstate->sampler_states[i]; if (s && s->state.compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) { diff --git a/src/gallium/drivers/r300/r300_state.c b/src/gallium/drivers/r300/r300_state.c index 30f1df7bf66..f549b453ee5 100644 --- a/src/gallium/drivers/r300/r300_state.c +++ b/src/gallium/drivers/r300/r300_state.c @@ -37,6 +37,7 @@ #include "r300_screen_buffer.h" #include "r300_state_inlines.h" #include "r300_fs.h" +#include "r300_texture.h" #include "r300_vs.h" #include "r300_winsys.h" @@ -938,7 +939,7 @@ static void r300_bind_sampler_states(struct pipe_context* pipe, } memcpy(state->sampler_states, states, sizeof(void*) * count); - state->sampler_count = count; + state->sampler_state_count = count; r300->textures_state.dirty = TRUE; @@ -980,9 +981,10 @@ static void r300_set_fragment_sampler_views(struct pipe_context* pipe, } for (i = 0; i < count; i++) { - if (state->fragment_sampler_views[i] != views[i]) { - pipe_sampler_view_reference(&state->fragment_sampler_views[i], - views[i]); + if (&state->sampler_views[i]->base != views[i]) { + pipe_sampler_view_reference( + (struct pipe_sampler_view**)&state->sampler_views[i], + views[i]); if (!views[i]) { continue; @@ -1002,13 +1004,14 @@ static void r300_set_fragment_sampler_views(struct pipe_context* pipe, } for (i = count; i < tex_units; i++) { - if (state->fragment_sampler_views[i]) { - pipe_sampler_view_reference(&state->fragment_sampler_views[i], - NULL); + if (state->sampler_views[i]) { + pipe_sampler_view_reference( + (struct pipe_sampler_view**)&state->sampler_views[i], + NULL); } } - state->texture_count = count; + state->sampler_view_count = count; r300->textures_state.dirty = TRUE; @@ -1022,17 +1025,33 @@ r300_create_sampler_view(struct pipe_context *pipe, struct pipe_resource *texture, const struct pipe_sampler_view *templ) { - struct pipe_sampler_view *view = CALLOC_STRUCT(pipe_sampler_view); - - if (view) { - *view = *templ; - view->reference.count = 1; - view->texture = NULL; - pipe_resource_reference(&view->texture, texture); - view->context = pipe; - } + struct r300_sampler_view *view = CALLOC_STRUCT(r300_sampler_view); + struct r300_texture *tex = r300_texture(texture); + unsigned char swizzle[4]; + + if (view) { + view->base = *templ; + view->base.reference.count = 1; + view->base.context = pipe; + view->base.texture = NULL; + pipe_resource_reference(&view->base.texture, texture); + + swizzle[0] = templ->swizzle_r; + swizzle[1] = templ->swizzle_g; + swizzle[2] = templ->swizzle_b; + swizzle[3] = templ->swizzle_a; + + /* XXX Enable swizzles when they become supported. Now we get RGBA + * everywhere. And do testing! */ + view->format = tex->tx_format; + view->format.format1 |= r300_translate_texformat(templ->format, + 0); /*swizzle);*/ + if (r300_screen(pipe->screen)->caps.is_r500) { + view->format.format2 |= r500_tx_format_msb_bit(templ->format); + } + } - return view; + return (struct pipe_sampler_view*)view; } static void diff --git a/src/gallium/drivers/r300/r300_state_derived.c b/src/gallium/drivers/r300/r300_state_derived.c index ade603a47cf..94968153836 100644 --- a/src/gallium/drivers/r300/r300_state_derived.c +++ b/src/gallium/drivers/r300/r300_state_derived.c @@ -456,74 +456,71 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300) (struct r300_textures_state*)r300->textures_state.state; struct r300_texture_sampler_state *texstate; struct r300_sampler_state *sampler; - struct pipe_sampler_view *view; + struct r300_sampler_view *view; struct r300_texture *tex; unsigned min_level, max_level, i, size; - unsigned count = MIN2(state->texture_count, state->sampler_count); + unsigned count = MIN2(state->sampler_view_count, + state->sampler_state_count); state->tx_enable = 0; state->count = 0; size = 2; for (i = 0; i < count; i++) { - if (state->fragment_sampler_views[i] && state->sampler_states[i]) { + if (state->sampler_views[i] && state->sampler_states[i]) { state->tx_enable |= 1 << i; - view = state->fragment_sampler_views[i]; - tex = r300_texture(view->texture); + view = state->sampler_views[i]; + tex = r300_texture(view->base.texture); sampler = state->sampler_states[i]; - assert(view->format == tex->b.b.format); - texstate = &state->regs[i]; - memcpy(texstate->format, &tex->state, sizeof(uint32_t)*3); - texstate->filter[0] = sampler->filter0; - texstate->filter[1] = sampler->filter1; + texstate->format = view->format; + texstate->filter0 = sampler->filter0; + texstate->filter1 = sampler->filter1; texstate->border_color = sampler->border_color; - texstate->tile_config = R300_TXO_MACRO_TILE(tex->macrotile) | - R300_TXO_MICRO_TILE(tex->microtile); /* to emulate 1D textures through 2D ones correctly */ if (tex->b.b.target == PIPE_TEXTURE_1D) { - texstate->filter[0] &= ~R300_TX_WRAP_T_MASK; - texstate->filter[0] |= R300_TX_WRAP_T(R300_TX_CLAMP_TO_EDGE); + texstate->filter0 &= ~R300_TX_WRAP_T_MASK; + texstate->filter0 |= R300_TX_WRAP_T(R300_TX_CLAMP_TO_EDGE); } if (tex->uses_pitch) { /* NPOT textures don't support mip filter, unfortunately. * This prevents incorrect rendering. */ - texstate->filter[0] &= ~R300_TX_MIN_FILTER_MIP_MASK; + texstate->filter0 &= ~R300_TX_MIN_FILTER_MIP_MASK; /* Set repeat or mirrored-repeat to clamp-to-edge. */ /* Wrap S. */ - if ((texstate->filter[0] & R300_TX_WRAP_S_MASK) == + if ((texstate->filter0 & R300_TX_WRAP_S_MASK) == R300_TX_WRAP_S(R300_TX_REPEAT) || - (texstate->filter[0] & R300_TX_WRAP_S_MASK) == + (texstate->filter0 & R300_TX_WRAP_S_MASK) == R300_TX_WRAP_S(R300_TX_MIRRORED)) { - texstate->filter[0] &= ~R300_TX_WRAP_S_MASK; - texstate->filter[0] |= R300_TX_WRAP_S(R300_TX_CLAMP_TO_EDGE); + texstate->filter0 &= ~R300_TX_WRAP_S_MASK; + texstate->filter0 |= R300_TX_WRAP_S(R300_TX_CLAMP_TO_EDGE); } /* Wrap T. */ - if ((texstate->filter[0] & R300_TX_WRAP_T_MASK) == + if ((texstate->filter0 & R300_TX_WRAP_T_MASK) == R300_TX_WRAP_T(R300_TX_REPEAT) || - (texstate->filter[0] & R300_TX_WRAP_T_MASK) == + (texstate->filter0 & R300_TX_WRAP_T_MASK) == R300_TX_WRAP_T(R300_TX_MIRRORED)) { - texstate->filter[0] &= ~R300_TX_WRAP_T_MASK; - texstate->filter[0] |= R300_TX_WRAP_T(R300_TX_CLAMP_TO_EDGE); + texstate->filter0 &= ~R300_TX_WRAP_T_MASK; + texstate->filter0 |= R300_TX_WRAP_T(R300_TX_CLAMP_TO_EDGE); } } else { /* determine min/max levels */ /* the MAX_MIP level is the largest (finest) one */ - max_level = MIN3(sampler->max_lod + view->first_level, - tex->b.b.last_level, view->last_level); - min_level = MIN2(sampler->min_lod + view->first_level, + max_level = MIN3(sampler->max_lod + view->base.first_level, + tex->b.b.last_level, view->base.last_level); + min_level = MIN2(sampler->min_lod + view->base.first_level, max_level); - texstate->format[0] |= R300_TX_NUM_LEVELS(max_level); - texstate->filter[0] |= R300_TX_MAX_MIP_LEVEL(min_level); + texstate->format.format0 |= R300_TX_NUM_LEVELS(max_level); + texstate->filter0 |= R300_TX_MAX_MIP_LEVEL(min_level); } - texstate->filter[0] |= i << 28; + texstate->filter0 |= i << 28; size += 16; state->count = i+1; diff --git a/src/gallium/drivers/r300/r300_texture.c b/src/gallium/drivers/r300/r300_texture.c index 59e9517fd2c..4f1562ddc73 100644 --- a/src/gallium/drivers/r300/r300_texture.c +++ b/src/gallium/drivers/r300/r300_texture.c @@ -28,6 +28,7 @@ #include "util/u_memory.h" #include "r300_context.h" +#include "r300_reg.h" #include "r300_texture.h" #include "r300_transfer.h" #include "r300_screen.h" @@ -72,7 +73,8 @@ static boolean r300_format_is_plain(enum pipe_format format) * * The FORMAT specifies how the texture sampler will treat the texture, and * makes available X, Y, Z, W, ZERO, and ONE for swizzling. */ -static uint32_t r300_translate_texformat(enum pipe_format format) +uint32_t r300_translate_texformat(enum pipe_format format, + const unsigned char *swizzle) { uint32_t result = 0; const struct util_format_description *desc; @@ -84,7 +86,7 @@ static uint32_t r300_translate_texformat(enum pipe_format format) R300_TX_FORMAT_B_SHIFT, R300_TX_FORMAT_A_SHIFT }; - const uint32_t swizzle[4] = { + const uint32_t swizzle_bit[4] = { R300_TX_FORMAT_X, R300_TX_FORMAT_Y, R300_TX_FORMAT_Z, @@ -141,20 +143,38 @@ static uint32_t r300_translate_texformat(enum pipe_format format) } /* Add swizzle. */ + if (!swizzle) { + swizzle = desc->swizzle; + } /*else { + if (swizzle[0] != desc->swizzle[0] || + swizzle[1] != desc->swizzle[1] || + swizzle[2] != desc->swizzle[2] || + swizzle[3] != desc->swizzle[3]) + { + const char n[6] = "RGBA01"; + fprintf(stderr, "Got different swizzling! Format: %c%c%c%c, " + "View: %c%c%c%c\n", + n[desc->swizzle[0]], n[desc->swizzle[1]], + n[desc->swizzle[2]], n[desc->swizzle[3]], + n[swizzle[0]], n[swizzle[1]], n[swizzle[2]], + n[swizzle[3]]); + } + }*/ + for (i = 0; i < 4; i++) { - switch (desc->swizzle[i]) { + switch (swizzle[i]) { case UTIL_FORMAT_SWIZZLE_X: case UTIL_FORMAT_SWIZZLE_NONE: - result |= swizzle[0] << swizzle_shift[i]; + result |= swizzle_bit[0] << swizzle_shift[i]; break; case UTIL_FORMAT_SWIZZLE_Y: - result |= swizzle[1] << swizzle_shift[i]; + result |= swizzle_bit[1] << swizzle_shift[i]; break; case UTIL_FORMAT_SWIZZLE_Z: - result |= swizzle[2] << swizzle_shift[i]; + result |= swizzle_bit[2] << swizzle_shift[i]; break; case UTIL_FORMAT_SWIZZLE_W: - result |= swizzle[3] << swizzle_shift[i]; + result |= swizzle_bit[3] << swizzle_shift[i]; break; case UTIL_FORMAT_SWIZZLE_0: result |= R300_TX_FORMAT_ZERO << swizzle_shift[i]; @@ -317,7 +337,7 @@ static uint32_t r300_translate_texformat(enum pipe_format format) return ~0; /* Unsupported/unknown. */ } -static uint32_t r500_tx_format_msb_bit(enum pipe_format format) +uint32_t r500_tx_format_msb_bit(enum pipe_format format) { switch (format) { case PIPE_FORMAT_RGTC1_UNORM: @@ -527,51 +547,59 @@ boolean r300_is_zs_format_supported(enum pipe_format format) boolean r300_is_sampler_format_supported(enum pipe_format format) { - return r300_translate_texformat(format) != ~0; + return r300_translate_texformat(format, 0) != ~0; } -static void r300_setup_texture_state(struct r300_screen* screen, struct r300_texture* tex) +static void r300_texture_setup_immutable_state(struct r300_screen* screen, + struct r300_texture* tex) { - struct r300_texture_format_state* state = &tex->state; + struct r300_texture_format_state* f = &tex->tx_format; struct pipe_resource *pt = &tex->b.b; - unsigned i; boolean is_r500 = screen->caps.is_r500; /* Set sampler state. */ - state->format0 = R300_TX_WIDTH((pt->width0 - 1) & 0x7ff) | - R300_TX_HEIGHT((pt->height0 - 1) & 0x7ff); + f->format0 = R300_TX_WIDTH((pt->width0 - 1) & 0x7ff) | + R300_TX_HEIGHT((pt->height0 - 1) & 0x7ff); if (tex->uses_pitch) { /* rectangles love this */ - state->format0 |= R300_TX_PITCH_EN; - state->format2 = (tex->pitch[0] - 1) & 0x1fff; + f->format0 |= R300_TX_PITCH_EN; + f->format2 = (tex->pitch[0] - 1) & 0x1fff; } else { /* power of two textures (3D, mipmaps, and no pitch) */ - state->format0 |= R300_TX_DEPTH(util_logbase2(pt->depth0) & 0xf); + f->format0 |= R300_TX_DEPTH(util_logbase2(pt->depth0) & 0xf); } - state->format1 = r300_translate_texformat(pt->format); + f->format1 = 0; if (pt->target == PIPE_TEXTURE_CUBE) { - state->format1 |= R300_TX_FORMAT_CUBIC_MAP; + f->format1 |= R300_TX_FORMAT_CUBIC_MAP; } if (pt->target == PIPE_TEXTURE_3D) { - state->format1 |= R300_TX_FORMAT_3D; + f->format1 |= R300_TX_FORMAT_3D; } /* large textures on r500 */ if (is_r500) { if (pt->width0 > 2048) { - state->format2 |= R500_TXWIDTH_BIT11; + f->format2 |= R500_TXWIDTH_BIT11; } if (pt->height0 > 2048) { - state->format2 |= R500_TXHEIGHT_BIT11; + f->format2 |= R500_TXHEIGHT_BIT11; } - state->format2 |= r500_tx_format_msb_bit(pt->format); } + f->tile_config = R300_TXO_MACRO_TILE(tex->macrotile) | + R300_TXO_MICRO_TILE(tex->microtile); + SCREEN_DBG(screen, DBG_TEX, "r300: Set texture state (%dx%d, %d levels)\n", pt->width0, pt->height0, pt->last_level); +} + +static void r300_texture_setup_fb_state(struct r300_screen* screen, + struct r300_texture* tex) +{ + unsigned i; /* Set framebuffer state. */ if (util_format_is_depth_or_stencil(tex->b.b.format)) { @@ -605,7 +633,7 @@ void r300_texture_reinterpret_format(struct pipe_screen *screen, tex->format = new_format; - r300_setup_texture_state(r300_screen(screen), r300_texture(tex)); + r300_texture_setup_fb_state(r300_screen(screen), r300_texture(tex)); } unsigned r300_texture_get_offset(struct r300_texture* tex, unsigned level, @@ -807,7 +835,6 @@ static void r300_setup_tiling(struct pipe_screen *screen, } } - static unsigned r300_texture_is_referenced(struct pipe_context *context, struct pipe_resource *texture, unsigned face, unsigned level) @@ -894,7 +921,8 @@ struct pipe_resource* r300_texture_create(struct pipe_screen* screen, r300_setup_tiling(screen, tex); } r300_setup_miptree(rscreen, tex); - r300_setup_texture_state(rscreen, tex); + r300_texture_setup_immutable_state(rscreen, tex); + r300_texture_setup_fb_state(rscreen, tex); tex->buffer = rws->buffer_create(rws, 2048, PIPE_BIND_SAMPLER_VIEW, /* XXX */ @@ -1019,7 +1047,8 @@ r300_texture_from_handle(struct pipe_screen* screen, } r300_setup_miptree(rscreen, tex); - r300_setup_texture_state(rscreen, tex); + r300_texture_setup_immutable_state(rscreen, tex); + r300_texture_setup_fb_state(rscreen, tex); if (override_zb_flags) { rws->buffer_set_tiling(rws, tex->buffer, diff --git a/src/gallium/drivers/r300/r300_texture.h b/src/gallium/drivers/r300/r300_texture.h index a545a0f2212..7b8b40551da 100644 --- a/src/gallium/drivers/r300/r300_texture.h +++ b/src/gallium/drivers/r300/r300_texture.h @@ -25,10 +25,13 @@ #include "util/u_format.h" -#include "r300_reg.h" - struct r300_texture; +uint32_t r300_translate_texformat(enum pipe_format format, + const unsigned char *swizzle); + +uint32_t r500_tx_format_msb_bit(enum pipe_format format); + unsigned r300_texture_get_stride(struct r300_screen* screen, struct r300_texture* tex, unsigned level);