}
/**
- * Create a sampler view.
- *
- * @param ctx context
- * @param texture texture
- * @param state sampler view template
- * @param width0 width0 override (for compressed textures as int)
- * @param height0 height0 override (for compressed textures as int)
- * @param force_level set the base address to the level (for compressed textures)
+ * Build the sampler view descriptor for a texture.
*/
-struct pipe_sampler_view *
-si_create_sampler_view_custom(struct pipe_context *ctx,
- struct pipe_resource *texture,
- const struct pipe_sampler_view *state,
- unsigned width0, unsigned height0,
- unsigned force_level)
-{
- struct si_context *sctx = (struct si_context*)ctx;
- struct si_sampler_view *view = CALLOC_STRUCT(si_sampler_view);
- struct r600_texture *tmp = (struct r600_texture*)texture;
+static void
+si_make_texture_descriptor(struct si_screen *screen,
+ struct r600_texture *tex,
+ enum pipe_texture_target target,
+ enum pipe_format pipe_format,
+ const unsigned char state_swizzle[4],
+ unsigned base_level, unsigned first_level, unsigned last_level,
+ unsigned first_layer, unsigned last_layer,
+ unsigned width, unsigned height, unsigned depth,
+ uint32_t *state,
+ uint32_t *fmask_state)
+{
+ struct pipe_resource *res = &tex->resource.b.b;
+ const struct radeon_surf_level *surflevel = tex->surface.level;
const struct util_format_description *desc;
- unsigned format, num_format, base_level, first_level, last_level;
- uint32_t pitch = 0;
- unsigned char state_swizzle[4], swizzle[4];
- unsigned height, depth, width;
- enum pipe_format pipe_format = state->format;
- struct radeon_surf_level *surflevel;
+ unsigned char swizzle[4];
int first_non_void;
+ unsigned num_format, data_format;
+ uint32_t pitch;
uint64_t va;
- unsigned last_layer = state->u.tex.last_layer;
-
- if (!view)
- return NULL;
-
- /* initialize base object */
- view->base = *state;
- view->base.texture = NULL;
- view->base.reference.count = 1;
- view->base.context = ctx;
-
- /* NULL resource, obey swizzle (only ZERO and ONE make sense). */
- if (!texture) {
- view->state[3] = S_008F1C_DST_SEL_X(si_map_swizzle(state->swizzle_r)) |
- S_008F1C_DST_SEL_Y(si_map_swizzle(state->swizzle_g)) |
- S_008F1C_DST_SEL_Z(si_map_swizzle(state->swizzle_b)) |
- S_008F1C_DST_SEL_W(si_map_swizzle(state->swizzle_a)) |
- S_008F1C_TYPE(V_008F1C_SQ_RSRC_IMG_1D);
- return &view->base;
- }
-
- pipe_resource_reference(&view->base.texture, texture);
-
- if (state->format == PIPE_FORMAT_X24S8_UINT ||
- state->format == PIPE_FORMAT_S8X24_UINT ||
- state->format == PIPE_FORMAT_X32_S8X24_UINT ||
- state->format == PIPE_FORMAT_S8_UINT)
- view->is_stencil_sampler = true;
-
- /* Buffer resource. */
- if (texture->target == PIPE_BUFFER) {
- si_make_buffer_descriptor(sctx->screen,
- (struct r600_resource *)texture,
- state->format,
- state->u.buf.first_element,
- state->u.buf.last_element,
- view->state);
-
- LIST_ADDTAIL(&view->list, &sctx->b.texture_buffers);
- return &view->base;
- }
-
- state_swizzle[0] = state->swizzle_r;
- state_swizzle[1] = state->swizzle_g;
- state_swizzle[2] = state->swizzle_b;
- state_swizzle[3] = state->swizzle_a;
-
- surflevel = tmp->surface.level;
/* Texturing with separate depth and stencil. */
- if (tmp->is_depth && !tmp->is_flushing_texture) {
+ if (tex->is_depth && !tex->is_flushing_texture) {
switch (pipe_format) {
case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
pipe_format = PIPE_FORMAT_Z32_FLOAT;
case PIPE_FORMAT_S8X24_UINT:
case PIPE_FORMAT_X32_S8X24_UINT:
pipe_format = PIPE_FORMAT_S8_UINT;
- surflevel = tmp->surface.stencil_level;
+ surflevel = tex->surface.stencil_level;
break;
default:;
}
}
}
- format = si_translate_texformat(ctx->screen, pipe_format, desc, first_non_void);
- if (format == ~0) {
- format = 0;
- }
-
- base_level = 0;
- first_level = state->u.tex.first_level;
- last_level = state->u.tex.last_level;
- width = width0;
- height = height0;
- depth = texture->depth0;
-
- if (force_level) {
- assert(force_level == first_level &&
- force_level == last_level);
- base_level = force_level;
- first_level = 0;
- last_level = 0;
- width = u_minify(width, force_level);
- height = u_minify(height, force_level);
- depth = u_minify(depth, force_level);
+ data_format = si_translate_texformat(&screen->b.b, pipe_format, desc, first_non_void);
+ if (data_format == ~0) {
+ data_format = 0;
}
- pitch = surflevel[base_level].nblk_x * util_format_get_blockwidth(pipe_format);
-
- if (texture->target == PIPE_TEXTURE_1D_ARRAY) {
+ if (res->target == PIPE_TEXTURE_1D_ARRAY) {
height = 1;
- depth = texture->array_size;
- } else if (texture->target == PIPE_TEXTURE_2D_ARRAY) {
- depth = texture->array_size;
- } else if (texture->target == PIPE_TEXTURE_CUBE_ARRAY)
- depth = texture->array_size / 6;
-
- /* This is not needed if state trackers set last_layer correctly. */
- if (state->target == PIPE_TEXTURE_1D ||
- state->target == PIPE_TEXTURE_2D ||
- state->target == PIPE_TEXTURE_RECT ||
- state->target == PIPE_TEXTURE_CUBE)
- last_layer = state->u.tex.first_layer;
+ depth = res->array_size;
+ } else if (res->target == PIPE_TEXTURE_2D_ARRAY) {
+ depth = res->array_size;
+ } else if (res->target == PIPE_TEXTURE_CUBE_ARRAY)
+ depth = res->array_size / 6;
- va = tmp->resource.gpu_address + surflevel[base_level].offset;
-
- view->state[0] = va >> 8;
- view->state[1] = (S_008F14_BASE_ADDRESS_HI(va >> 40) |
- S_008F14_DATA_FORMAT(format) |
- S_008F14_NUM_FORMAT(num_format));
- view->state[2] = (S_008F18_WIDTH(width - 1) |
- S_008F18_HEIGHT(height - 1));
- view->state[3] = (S_008F1C_DST_SEL_X(si_map_swizzle(swizzle[0])) |
- S_008F1C_DST_SEL_Y(si_map_swizzle(swizzle[1])) |
- S_008F1C_DST_SEL_Z(si_map_swizzle(swizzle[2])) |
- S_008F1C_DST_SEL_W(si_map_swizzle(swizzle[3])) |
- S_008F1C_BASE_LEVEL(texture->nr_samples > 1 ?
- 0 : first_level) |
- S_008F1C_LAST_LEVEL(texture->nr_samples > 1 ?
- util_logbase2(texture->nr_samples) :
- last_level) |
- S_008F1C_TILING_INDEX(si_tile_mode_index(tmp, base_level, false)) |
- S_008F1C_POW2_PAD(texture->last_level > 0) |
- S_008F1C_TYPE(si_tex_dim(texture->target, state->target,
- texture->nr_samples)));
- view->state[4] = (S_008F20_DEPTH(depth - 1) | S_008F20_PITCH(pitch - 1));
- view->state[5] = (S_008F24_BASE_ARRAY(state->u.tex.first_layer) |
- S_008F24_LAST_ARRAY(last_layer));
-
- if (tmp->dcc_offset) {
+ pitch = surflevel[base_level].nblk_x * util_format_get_blockwidth(pipe_format);
+ va = tex->resource.gpu_address + surflevel[base_level].offset;
+
+ state[0] = va >> 8;
+ state[1] = (S_008F14_BASE_ADDRESS_HI(va >> 40) |
+ S_008F14_DATA_FORMAT(data_format) |
+ S_008F14_NUM_FORMAT(num_format));
+ state[2] = (S_008F18_WIDTH(width - 1) |
+ S_008F18_HEIGHT(height - 1));
+ state[3] = (S_008F1C_DST_SEL_X(si_map_swizzle(swizzle[0])) |
+ S_008F1C_DST_SEL_Y(si_map_swizzle(swizzle[1])) |
+ S_008F1C_DST_SEL_Z(si_map_swizzle(swizzle[2])) |
+ S_008F1C_DST_SEL_W(si_map_swizzle(swizzle[3])) |
+ S_008F1C_BASE_LEVEL(res->nr_samples > 1 ?
+ 0 : first_level) |
+ S_008F1C_LAST_LEVEL(res->nr_samples > 1 ?
+ util_logbase2(res->nr_samples) :
+ last_level) |
+ S_008F1C_TILING_INDEX(si_tile_mode_index(tex, base_level, false)) |
+ S_008F1C_POW2_PAD(res->last_level > 0) |
+ S_008F1C_TYPE(si_tex_dim(res->target, target, res->nr_samples)));
+ state[4] = (S_008F20_DEPTH(depth - 1) | S_008F20_PITCH(pitch - 1));
+ state[5] = (S_008F24_BASE_ARRAY(first_layer) |
+ S_008F24_LAST_ARRAY(last_layer));
+
+ if (tex->dcc_offset) {
unsigned swap = r600_translate_colorswap(pipe_format);
- view->state[6] = S_008F28_COMPRESSION_EN(1) | S_008F28_ALPHA_IS_ON_MSB(swap <= 1);
- view->state[7] = (tmp->resource.gpu_address +
- tmp->dcc_offset +
- surflevel[base_level].dcc_offset) >> 8;
+ state[6] = S_008F28_COMPRESSION_EN(1) | S_008F28_ALPHA_IS_ON_MSB(swap <= 1);
+ state[7] = (tex->resource.gpu_address +
+ tex->dcc_offset +
+ surflevel[base_level].dcc_offset) >> 8;
} else {
- view->state[6] = 0;
- view->state[7] = 0;
+ state[6] = 0;
+ state[7] = 0;
}
/* Initialize the sampler view for FMASK. */
- if (tmp->fmask.size) {
- uint64_t va = tmp->resource.gpu_address + tmp->fmask.offset;
+ if (tex->fmask.size) {
uint32_t fmask_format;
- switch (texture->nr_samples) {
+ va = tex->resource.gpu_address + tex->fmask.offset;
+
+ switch (res->nr_samples) {
case 2:
fmask_format = V_008F14_IMG_DATA_FORMAT_FMASK8_S2_F2;
break;
fmask_format = V_008F14_IMG_DATA_FORMAT_INVALID;
}
- view->fmask_state[0] = va >> 8;
- view->fmask_state[1] = S_008F14_BASE_ADDRESS_HI(va >> 40) |
- S_008F14_DATA_FORMAT(fmask_format) |
- S_008F14_NUM_FORMAT(V_008F14_IMG_NUM_FORMAT_UINT);
- view->fmask_state[2] = S_008F18_WIDTH(width - 1) |
- S_008F18_HEIGHT(height - 1);
- view->fmask_state[3] = S_008F1C_DST_SEL_X(V_008F1C_SQ_SEL_X) |
- S_008F1C_DST_SEL_Y(V_008F1C_SQ_SEL_X) |
- S_008F1C_DST_SEL_Z(V_008F1C_SQ_SEL_X) |
- S_008F1C_DST_SEL_W(V_008F1C_SQ_SEL_X) |
- S_008F1C_TILING_INDEX(tmp->fmask.tile_mode_index) |
- S_008F1C_TYPE(si_tex_dim(texture->target,
- state->target, 0));
- view->fmask_state[4] = S_008F20_DEPTH(depth - 1) |
- S_008F20_PITCH(tmp->fmask.pitch_in_pixels - 1);
- view->fmask_state[5] = S_008F24_BASE_ARRAY(state->u.tex.first_layer) |
- S_008F24_LAST_ARRAY(last_layer);
- view->fmask_state[6] = 0;
- view->fmask_state[7] = 0;
+ fmask_state[0] = va >> 8;
+ fmask_state[1] = S_008F14_BASE_ADDRESS_HI(va >> 40) |
+ S_008F14_DATA_FORMAT(fmask_format) |
+ S_008F14_NUM_FORMAT(V_008F14_IMG_NUM_FORMAT_UINT);
+ fmask_state[2] = S_008F18_WIDTH(width - 1) |
+ S_008F18_HEIGHT(height - 1);
+ fmask_state[3] = S_008F1C_DST_SEL_X(V_008F1C_SQ_SEL_X) |
+ S_008F1C_DST_SEL_Y(V_008F1C_SQ_SEL_X) |
+ S_008F1C_DST_SEL_Z(V_008F1C_SQ_SEL_X) |
+ S_008F1C_DST_SEL_W(V_008F1C_SQ_SEL_X) |
+ S_008F1C_TILING_INDEX(tex->fmask.tile_mode_index) |
+ S_008F1C_TYPE(si_tex_dim(res->target, target, 0));
+ fmask_state[4] = S_008F20_DEPTH(depth - 1) |
+ S_008F20_PITCH(tex->fmask.pitch_in_pixels - 1);
+ fmask_state[5] = S_008F24_BASE_ARRAY(first_layer) |
+ S_008F24_LAST_ARRAY(last_layer);
+ fmask_state[6] = 0;
+ fmask_state[7] = 0;
+ }
+}
+
+/**
+ * Create a sampler view.
+ *
+ * @param ctx context
+ * @param texture texture
+ * @param state sampler view template
+ * @param width0 width0 override (for compressed textures as int)
+ * @param height0 height0 override (for compressed textures as int)
+ * @param force_level set the base address to the level (for compressed textures)
+ */
+struct pipe_sampler_view *
+si_create_sampler_view_custom(struct pipe_context *ctx,
+ struct pipe_resource *texture,
+ const struct pipe_sampler_view *state,
+ unsigned width0, unsigned height0,
+ unsigned force_level)
+{
+ struct si_context *sctx = (struct si_context*)ctx;
+ struct si_sampler_view *view = CALLOC_STRUCT(si_sampler_view);
+ struct r600_texture *tmp = (struct r600_texture*)texture;
+ unsigned base_level, first_level, last_level;
+ unsigned char state_swizzle[4];
+ unsigned height, depth, width;
+ unsigned last_layer = state->u.tex.last_layer;
+
+ if (!view)
+ return NULL;
+
+ /* initialize base object */
+ view->base = *state;
+ view->base.texture = NULL;
+ view->base.reference.count = 1;
+ view->base.context = ctx;
+
+ /* NULL resource, obey swizzle (only ZERO and ONE make sense). */
+ if (!texture) {
+ view->state[3] = S_008F1C_DST_SEL_X(si_map_swizzle(state->swizzle_r)) |
+ S_008F1C_DST_SEL_Y(si_map_swizzle(state->swizzle_g)) |
+ S_008F1C_DST_SEL_Z(si_map_swizzle(state->swizzle_b)) |
+ S_008F1C_DST_SEL_W(si_map_swizzle(state->swizzle_a)) |
+ S_008F1C_TYPE(V_008F1C_SQ_RSRC_IMG_1D);
+ return &view->base;
+ }
+
+ pipe_resource_reference(&view->base.texture, texture);
+
+ if (state->format == PIPE_FORMAT_X24S8_UINT ||
+ state->format == PIPE_FORMAT_S8X24_UINT ||
+ state->format == PIPE_FORMAT_X32_S8X24_UINT ||
+ state->format == PIPE_FORMAT_S8_UINT)
+ view->is_stencil_sampler = true;
+
+ /* Buffer resource. */
+ if (texture->target == PIPE_BUFFER) {
+ si_make_buffer_descriptor(sctx->screen,
+ (struct r600_resource *)texture,
+ state->format,
+ state->u.buf.first_element,
+ state->u.buf.last_element,
+ view->state);
+
+ LIST_ADDTAIL(&view->list, &sctx->b.texture_buffers);
+ return &view->base;
+ }
+
+ state_swizzle[0] = state->swizzle_r;
+ state_swizzle[1] = state->swizzle_g;
+ state_swizzle[2] = state->swizzle_b;
+ state_swizzle[3] = state->swizzle_a;
+
+ base_level = 0;
+ first_level = state->u.tex.first_level;
+ last_level = state->u.tex.last_level;
+ width = width0;
+ height = height0;
+ depth = texture->depth0;
+
+ if (force_level) {
+ assert(force_level == first_level &&
+ force_level == last_level);
+ base_level = force_level;
+ first_level = 0;
+ last_level = 0;
+ width = u_minify(width, force_level);
+ height = u_minify(height, force_level);
+ depth = u_minify(depth, force_level);
}
+ /* This is not needed if state trackers set last_layer correctly. */
+ if (state->target == PIPE_TEXTURE_1D ||
+ state->target == PIPE_TEXTURE_2D ||
+ state->target == PIPE_TEXTURE_RECT ||
+ state->target == PIPE_TEXTURE_CUBE)
+ last_layer = state->u.tex.first_layer;
+
+ si_make_texture_descriptor(sctx->screen, tmp, state->target,
+ state->format, state_swizzle,
+ base_level, first_level, last_level,
+ state->u.tex.first_layer, last_layer,
+ width, height, depth,
+ view->state, view->fmask_state);
+
return &view->base;
}