#include "util/u_format_s3tc.h"
#include "util/u_memory.h"
#include "util/u_pstipple.h"
+#include "util/u_resource.h"
/* Initialize an external atom (owned by ../radeon). */
static void
* Build the sampler view descriptor for a buffer texture.
* @param state 256-bit descriptor; only the high 128 bits are filled in
*/
-static void
+void
si_make_buffer_descriptor(struct si_screen *screen, struct r600_resource *buf,
enum pipe_format format,
unsigned first_element, unsigned last_element,
/**
* Build the sampler view descriptor for a texture.
*/
-static void
+void
si_make_texture_descriptor(struct si_screen *screen,
struct r600_texture *tex,
+ bool sampler,
enum pipe_texture_target target,
enum pipe_format pipe_format,
const unsigned char state_swizzle[4],
const struct util_format_description *desc;
unsigned char swizzle[4];
int first_non_void;
- unsigned num_format, data_format;
+ unsigned num_format, data_format, type;
uint32_t pitch;
uint64_t va;
data_format = 0;
}
- if (res->target == PIPE_TEXTURE_1D_ARRAY) {
+ 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 (res->target == PIPE_TEXTURE_2D_ARRAY) {
- depth = res->array_size;
- } else if (res->target == PIPE_TEXTURE_CUBE_ARRAY)
+ } else if (type == V_008F1C_SQ_RSRC_IMG_2D_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;
pitch = surflevel[base_level].nblk_x * util_format_get_blockwidth(pipe_format);
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)));
+ S_008F1C_TYPE(type));
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));
state->target == PIPE_TEXTURE_CUBE)
last_layer = state->u.tex.first_layer;
- si_make_texture_descriptor(sctx->screen, tmp, state->target,
+ si_make_texture_descriptor(sctx->screen, tmp, true, state->target,
state->format, state_swizzle,
base_level, first_level, last_level,
state->u.tex.first_layer, last_layer,
SI_CONTEXT_FLUSH_AND_INV_CB;
}
+static void si_memory_barrier(struct pipe_context *ctx, unsigned flags)
+{
+ struct si_context *sctx = (struct si_context *)ctx;
+
+ /* Subsequent commands must wait for all shader invocations to
+ * complete. */
+ sctx->b.flags |= SI_CONTEXT_PS_PARTIAL_FLUSH;
+
+ if (flags & PIPE_BARRIER_CONSTANT_BUFFER)
+ sctx->b.flags |= SI_CONTEXT_INV_SMEM_L1 |
+ SI_CONTEXT_INV_VMEM_L1;
+
+ if (flags & (PIPE_BARRIER_VERTEX_BUFFER |
+ PIPE_BARRIER_SHADER_BUFFER |
+ PIPE_BARRIER_TEXTURE |
+ PIPE_BARRIER_IMAGE)) {
+ /* As far as I can tell, L1 contents are written back to L2
+ * automatically at end of shader, but the contents of other
+ * L1 caches might still be stale. */
+ sctx->b.flags |= SI_CONTEXT_INV_VMEM_L1;
+ }
+
+ if (flags & PIPE_BARRIER_FRAMEBUFFER)
+ sctx->b.flags |= SI_CONTEXT_FLUSH_AND_INV_FRAMEBUFFER;
+
+ if (flags & (PIPE_BARRIER_MAPPED_BUFFER |
+ PIPE_BARRIER_FRAMEBUFFER)) {
+ /* Not sure if INV_GLOBAL_L2 is the best thing here.
+ *
+ * We need to make sure that TC L1 & L2 are written back to
+ * memory, because neither CPU accesses nor CB fetches consider
+ * TC, but there's no need to invalidate any TC cache lines. */
+ sctx->b.flags |= SI_CONTEXT_INV_GLOBAL_L2;
+ }
+}
+
static void *si_create_blend_custom(struct si_context *sctx, unsigned mode)
{
struct pipe_blend_state blend;
sctx->b.b.set_index_buffer = si_set_index_buffer;
sctx->b.b.texture_barrier = si_texture_barrier;
+ sctx->b.b.memory_barrier = si_memory_barrier;
sctx->b.b.set_polygon_stipple = si_set_polygon_stipple;
sctx->b.b.set_min_samples = si_set_min_samples;
sctx->b.b.set_tess_state = si_set_tess_state;
si_init_config(sctx);
}
+static void si_query_opaque_metadata(struct r600_common_screen *rscreen,
+ struct r600_texture *rtex,
+ struct radeon_bo_metadata *md)
+{
+ struct si_screen *sscreen = (struct si_screen*)rscreen;
+ struct pipe_resource *res = &rtex->resource.b.b;
+ static const unsigned char swizzle[] = {
+ PIPE_SWIZZLE_RED,
+ PIPE_SWIZZLE_GREEN,
+ PIPE_SWIZZLE_BLUE,
+ PIPE_SWIZZLE_ALPHA
+ };
+ uint32_t desc[8], i;
+ bool is_array = util_resource_is_array_texture(res);
+
+ /* DRM 2.x.x doesn't support this. */
+ if (rscreen->info.drm_major != 3)
+ return;
+
+ assert(rtex->fmask.size == 0);
+
+ /* Metadata image format format version 1:
+ * [0] = 1 (metadata format identifier)
+ * [1] = (VENDOR_ID << 16) | PCI_ID
+ * [2:9] = image descriptor for the whole resource
+ * [2] is always 0, because the base address is cleared
+ * [9] is the DCC offset bits [39:8] from the beginning of
+ * the buffer
+ * [10:10+LAST_LEVEL] = mipmap level offset bits [39:8] for each level
+ */
+
+ md->metadata[0] = 1; /* metadata image format version 1 */
+
+ /* TILE_MODE_INDEX is ambiguous without a PCI ID. */
+ md->metadata[1] = (ATI_VENDOR_ID << 16) | rscreen->info.pci_id;
+
+ si_make_texture_descriptor(sscreen, rtex, true,
+ res->target, res->format,
+ swizzle, 0, 0, res->last_level, 0,
+ is_array ? res->array_size - 1 : 0,
+ res->width0, res->height0, res->depth0,
+ desc, NULL);
+
+ /* Clear the base address and set the relative DCC offset. */
+ desc[0] = 0;
+ desc[1] &= C_008F14_BASE_ADDRESS_HI;
+ desc[7] = rtex->dcc_offset >> 8;
+
+ /* Dwords [2:9] contain the image descriptor. */
+ memcpy(&md->metadata[2], desc, sizeof(desc));
+
+ /* Dwords [10:..] contain the mipmap level offsets. */
+ for (i = 0; i <= res->last_level; i++)
+ md->metadata[10+i] = rtex->surface.level[i].offset >> 8;
+
+ md->size_metadata = (11 + res->last_level) * 4;
+}
+
+void si_init_screen_state_functions(struct si_screen *sscreen)
+{
+ sscreen->b.query_opaque_metadata = si_query_opaque_metadata;
+}
+
static void
si_write_harvested_raster_configs(struct si_context *sctx,
struct si_pm4_state *pm4,