+ data_format = si_translate_texformat(&screen->b.b, pipe_format, desc, first_non_void);
+ if (data_format == ~0) {
+ data_format = 0;
+ }
+
+ if (!sampler &&
+ (res->target == PIPE_TEXTURE_CUBE ||
+ res->target == PIPE_TEXTURE_CUBE_ARRAY ||
+ res->target == PIPE_TEXTURE_3D)) {
+ /* For the purpose of shader images, treat cube maps and 3D
+ * textures as 2D arrays. For 3D textures, the address
+ * calculations for mipmaps are different, so we rely on the
+ * caller to effectively disable mipmaps.
+ */
+ type = V_008F1C_SQ_RSRC_IMG_2D_ARRAY;
+
+ assert(res->target != PIPE_TEXTURE_3D || (first_level == 0 && last_level == 0));
+ } else {
+ type = si_tex_dim(res->target, target, res->nr_samples);
+ }
+
+ if (type == V_008F1C_SQ_RSRC_IMG_1D_ARRAY) {
+ height = 1;
+ depth = res->array_size;
+ } else if (type == V_008F1C_SQ_RSRC_IMG_2D_ARRAY ||
+ type == V_008F1C_SQ_RSRC_IMG_2D_MSAA_ARRAY) {
+ if (sampler || res->target != PIPE_TEXTURE_3D)
+ depth = res->array_size;
+ } else if (type == V_008F1C_SQ_RSRC_IMG_CUBE)
+ depth = res->array_size / 6;
+
+ state[0] = 0;
+ state[1] = (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_POW2_PAD(res->last_level > 0) |
+ S_008F1C_TYPE(type));
+ state[4] = S_008F20_DEPTH(depth - 1);
+ state[5] = (S_008F24_BASE_ARRAY(first_layer) |
+ S_008F24_LAST_ARRAY(last_layer));
+ state[6] = 0;
+ state[7] = 0;
+
+ if (tex->dcc_offset) {
+ unsigned swap = r600_translate_colorswap(pipe_format, false);
+
+ state[6] = S_008F28_ALPHA_IS_ON_MSB(swap <= 1);
+ } else {
+ /* The last dword is unused by hw. The shader uses it to clear
+ * bits in the first dword of sampler state.
+ */
+ if (screen->b.chip_class <= CIK && res->nr_samples <= 1) {
+ if (first_level == last_level)
+ state[7] = C_008F30_MAX_ANISO_RATIO;
+ else
+ state[7] = 0xffffffff;
+ }
+ }
+
+ /* Initialize the sampler view for FMASK. */
+ if (tex->fmask.size) {
+ uint32_t fmask_format;
+
+ 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;
+ case 4:
+ fmask_format = V_008F14_IMG_DATA_FORMAT_FMASK8_S4_F4;
+ break;
+ case 8:
+ fmask_format = V_008F14_IMG_DATA_FORMAT_FMASK32_S8_F8;
+ break;
+ default:
+ assert(0);
+ fmask_format = V_008F14_IMG_DATA_FORMAT_INVALID;
+ }
+
+ 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;
+ enum pipe_format pipe_format;
+ const struct radeon_surf_level *surflevel;
+
+ 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;