[Mesa-dev] [PATCH v2 1/7] radeonsi: Allocate buffers for DCC.

Bas Nieuwenhuizen bas at basnieuwenhuizen.nl
Sun Oct 11 08:38:01 PDT 2015


As the alignment requirements can be 32 KiB or more, also adding
an aligned buffer creation function.

Signed-off-by: Bas Nieuwenhuizen <bas at basnieuwenhuizen.nl>
---
 src/gallium/drivers/radeon/r600_buffer_common.c | 21 +++++++++++
 src/gallium/drivers/radeon/r600_pipe_common.h   |  6 ++++
 src/gallium/drivers/radeon/r600_texture.c       | 18 ++++++++++
 src/gallium/drivers/radeon/radeon_winsys.h      |  5 +++
 src/gallium/winsys/amdgpu/drm/amdgpu_surface.c  | 47 ++++++++++++++++++++++---
 5 files changed, 92 insertions(+), 5 deletions(-)

diff --git a/src/gallium/drivers/radeon/r600_buffer_common.c b/src/gallium/drivers/radeon/r600_buffer_common.c
index f341ecb..0dc6c91 100644
--- a/src/gallium/drivers/radeon/r600_buffer_common.c
+++ b/src/gallium/drivers/radeon/r600_buffer_common.c
@@ -443,6 +443,27 @@ struct pipe_resource *r600_buffer_create(struct pipe_screen *screen,
 	return &rbuffer->b.b;
 }
 
+struct pipe_resource *r600_aligned_buffer_create(struct pipe_screen *screen,
+						 unsigned bind,
+						 unsigned usage,
+						 unsigned size,
+						 unsigned alignment)
+{
+	struct pipe_resource buffer;
+
+	memset(&buffer, 0, sizeof buffer);
+	buffer.target = PIPE_BUFFER;
+	buffer.format = PIPE_FORMAT_R8_UNORM;
+	buffer.bind = bind;
+	buffer.usage = usage;
+	buffer.flags = 0;
+	buffer.width0 = size;
+	buffer.height0 = 1;
+	buffer.depth0 = 1;
+	buffer.array_size = 1;
+	return r600_buffer_create(screen, &buffer, alignment);
+}
+
 struct pipe_resource *
 r600_buffer_from_user_memory(struct pipe_screen *screen,
 			     const struct pipe_resource *templ,
diff --git a/src/gallium/drivers/radeon/r600_pipe_common.h b/src/gallium/drivers/radeon/r600_pipe_common.h
index b58b500..1eec596 100644
--- a/src/gallium/drivers/radeon/r600_pipe_common.h
+++ b/src/gallium/drivers/radeon/r600_pipe_common.h
@@ -214,6 +214,7 @@ struct r600_texture {
 	struct r600_fmask_info		fmask;
 	struct r600_cmask_info		cmask;
 	struct r600_resource		*cmask_buffer;
+	struct r600_resource		*dcc_buffer;
 	unsigned			cb_color_info; /* fast clear enable bit */
 	unsigned			color_clear_value[2];
 
@@ -489,6 +490,11 @@ bool r600_init_resource(struct r600_common_screen *rscreen,
 struct pipe_resource *r600_buffer_create(struct pipe_screen *screen,
 					 const struct pipe_resource *templ,
 					 unsigned alignment);
+struct pipe_resource * r600_aligned_buffer_create(struct pipe_screen *screen,
+						  unsigned bind,
+						  unsigned usage,
+						  unsigned size,
+						  unsigned alignment);
 struct pipe_resource *
 r600_buffer_from_user_memory(struct pipe_screen *screen,
 			     const struct pipe_resource *templ,
diff --git a/src/gallium/drivers/radeon/r600_texture.c b/src/gallium/drivers/radeon/r600_texture.c
index fc69f48..fffb9ef 100644
--- a/src/gallium/drivers/radeon/r600_texture.c
+++ b/src/gallium/drivers/radeon/r600_texture.c
@@ -268,6 +268,7 @@ static void r600_texture_destroy(struct pipe_screen *screen,
 	if (rtex->cmask_buffer != &rtex->resource) {
 	    pipe_resource_reference((struct pipe_resource**)&rtex->cmask_buffer, NULL);
 	}
+	pipe_resource_reference((struct pipe_resource**)&rtex->dcc_buffer, NULL);
 	pb_reference(&resource->buf, NULL);
 	FREE(rtex);
 }
@@ -482,6 +483,20 @@ static void r600_texture_alloc_cmask_separate(struct r600_common_screen *rscreen
 		rtex->cb_color_info |= EG_S_028C70_FAST_CLEAR(1);
 }
 
+static void vi_texture_alloc_dcc_separate(struct r600_common_screen *rscreen,
+					      struct r600_texture *rtex)
+{
+	rtex->dcc_buffer = (struct r600_resource *)
+		r600_aligned_buffer_create(&rscreen->b, PIPE_BIND_CUSTOM,
+				   PIPE_USAGE_DEFAULT, rtex->surface.dcc_size, rtex->surface.dcc_alignment);
+	if (rtex->dcc_buffer == NULL) {
+		return;
+	}
+
+	r600_screen_clear_buffer(rscreen, &rtex->dcc_buffer->b.b, 0, rtex->surface.dcc_size,
+				 0xFFFFFFFF, true);
+}
+
 static unsigned r600_texture_get_htile_size(struct r600_common_screen *rscreen,
 					    struct r600_texture *rtex)
 {
@@ -621,6 +636,9 @@ r600_texture_create_object(struct pipe_screen *screen,
 				return NULL;
 			}
 		}
+		if (rtex->surface.dcc_enabled) {
+			vi_texture_alloc_dcc_separate(rscreen, rtex);
+		}
 	}
 
 	/* Now create the backing buffer. */
diff --git a/src/gallium/drivers/radeon/radeon_winsys.h b/src/gallium/drivers/radeon/radeon_winsys.h
index b91e1ad..a90315c 100644
--- a/src/gallium/drivers/radeon/radeon_winsys.h
+++ b/src/gallium/drivers/radeon/radeon_winsys.h
@@ -331,6 +331,7 @@ struct radeon_surf_level {
     uint32_t                    nblk_z;
     uint32_t                    pitch_bytes;
     uint32_t                    mode;
+    uint64_t                    dcc_offset;
 };
 
 struct radeon_surf {
@@ -366,6 +367,10 @@ struct radeon_surf {
     uint32_t                    stencil_tiling_index[RADEON_SURF_MAX_LEVEL];
     uint32_t                    pipe_config;
     uint32_t                    num_banks;
+
+    uint64_t                    dcc_size;
+    uint64_t                    dcc_alignment;
+    bool                        dcc_enabled;
 };
 
 struct radeon_bo_list_item {
diff --git a/src/gallium/winsys/amdgpu/drm/amdgpu_surface.c b/src/gallium/winsys/amdgpu/drm/amdgpu_surface.c
index 358df38..b442174 100644
--- a/src/gallium/winsys/amdgpu/drm/amdgpu_surface.c
+++ b/src/gallium/winsys/amdgpu/drm/amdgpu_surface.c
@@ -175,7 +175,9 @@ static int compute_level(struct amdgpu_winsys *ws,
                          struct radeon_surf *surf, bool is_stencil,
                          unsigned level, unsigned type, bool compressed,
                          ADDR_COMPUTE_SURFACE_INFO_INPUT *AddrSurfInfoIn,
-                         ADDR_COMPUTE_SURFACE_INFO_OUTPUT *AddrSurfInfoOut)
+                         ADDR_COMPUTE_SURFACE_INFO_OUTPUT *AddrSurfInfoOut,
+                         ADDR_COMPUTE_DCCINFO_INPUT *AddrDccIn,
+                         ADDR_COMPUTE_DCCINFO_OUTPUT *AddrDccOut)
 {
    struct radeon_surf_level *surf_level;
    ADDR_E_RETURNCODE ret;
@@ -248,6 +250,30 @@ static int compute_level(struct amdgpu_winsys *ws,
       surf->tiling_index[level] = AddrSurfInfoOut->tileIndex;
 
    surf->bo_size = surf_level->offset + AddrSurfInfoOut->surfSize;
+
+   if (surf->dcc_enabled) {
+      AddrDccIn->colorSurfSize = AddrSurfInfoOut->surfSize;
+      AddrDccIn->tileMode = AddrSurfInfoOut->tileMode;
+      AddrDccIn->tileInfo = *AddrSurfInfoOut->pTileInfo;
+      AddrDccIn->tileIndex = AddrSurfInfoOut->tileIndex;
+      AddrDccIn->macroModeIndex = AddrSurfInfoOut->macroModeIndex;
+
+      ret = AddrComputeDccInfo(ws->addrlib,
+                               AddrDccIn,
+                               AddrDccOut);
+
+      if (ret == ADDR_OK) {
+         surf_level->dcc_offset = surf->dcc_size;
+         surf->dcc_size = surf_level->dcc_offset + AddrDccOut->dccRamSize;
+         surf->dcc_alignment = MAX2(surf->dcc_alignment, AddrDccOut->dccRamBaseAlign);
+      } else {
+         surf->dcc_enabled = false;
+         surf_level->dcc_offset = 0;
+      }
+   } else {
+      surf_level->dcc_offset = 0;
+   }
+
    return 0;
 }
 
@@ -259,6 +285,8 @@ static int amdgpu_surface_init(struct radeon_winsys *rws,
    bool compressed;
    ADDR_COMPUTE_SURFACE_INFO_INPUT AddrSurfInfoIn = {0};
    ADDR_COMPUTE_SURFACE_INFO_OUTPUT AddrSurfInfoOut = {0};
+   ADDR_COMPUTE_DCCINFO_INPUT AddrDccIn = {0};
+   ADDR_COMPUTE_DCCINFO_OUTPUT AddrDccOut = {0};
    ADDR_TILEINFO AddrTileInfoIn = {0};
    ADDR_TILEINFO AddrTileInfoOut = {0};
    int r;
@@ -269,6 +297,8 @@ static int amdgpu_surface_init(struct radeon_winsys *rws,
 
    AddrSurfInfoIn.size = sizeof(ADDR_COMPUTE_SURFACE_INFO_INPUT);
    AddrSurfInfoOut.size = sizeof(ADDR_COMPUTE_SURFACE_INFO_OUTPUT);
+   AddrDccIn.size = sizeof(ADDR_COMPUTE_DCCINFO_INPUT);
+   AddrDccOut.size = sizeof(ADDR_COMPUTE_DCCINFO_OUTPUT);
    AddrSurfInfoOut.pTileInfo = &AddrTileInfoOut;
 
    type = RADEON_SURF_GET(surf->flags, TYPE);
@@ -318,12 +348,16 @@ static int amdgpu_surface_init(struct radeon_winsys *rws,
       }
    }
    else {
-      AddrSurfInfoIn.bpp = surf->bpe * 8;
+      AddrDccIn.bpp = AddrSurfInfoIn.bpp = surf->bpe * 8;
    }
 
-   AddrSurfInfoIn.numSamples = surf->nsamples;
+   AddrDccIn.numSamples = AddrSurfInfoIn.numSamples = surf->nsamples;
    AddrSurfInfoIn.tileIndex = -1;
 
+   surf->dcc_enabled =  !(surf->flags & RADEON_SURF_Z_OR_SBUFFER) &&
+                        !(surf->flags & RADEON_SURF_SCANOUT) &&
+                        !compressed && AddrDccIn.numSamples <= 1;
+
    /* Set the micro tile type. */
    if (surf->flags & RADEON_SURF_SCANOUT)
       AddrSurfInfoIn.tileType = ADDR_DISPLAYABLE;
@@ -339,6 +373,7 @@ static int amdgpu_surface_init(struct radeon_winsys *rws,
    AddrSurfInfoIn.flags.display = (surf->flags & RADEON_SURF_SCANOUT) != 0;
    AddrSurfInfoIn.flags.pow2Pad = surf->last_level > 0;
    AddrSurfInfoIn.flags.degrade4Space = 1;
+   AddrSurfInfoIn.flags.dccCompatible = surf->dcc_enabled;
 
    /* This disables incorrect calculations (hacks) in addrlib. */
    AddrSurfInfoIn.flags.noStencil = 1;
@@ -375,11 +410,13 @@ static int amdgpu_surface_init(struct radeon_winsys *rws,
    }
 
    surf->bo_size = 0;
+   surf->dcc_size = 0;
+   surf->dcc_alignment = 1;
 
    /* Calculate texture layout information. */
    for (level = 0; level <= surf->last_level; level++) {
       r = compute_level(ws, surf, false, level, type, compressed,
-                        &AddrSurfInfoIn, &AddrSurfInfoOut);
+                        &AddrSurfInfoIn, &AddrSurfInfoOut, &AddrDccIn, &AddrDccOut);
       if (r)
          return r;
 
@@ -406,7 +443,7 @@ static int amdgpu_surface_init(struct radeon_winsys *rws,
 
       for (level = 0; level <= surf->last_level; level++) {
          r = compute_level(ws, surf, true, level, type, compressed,
-                           &AddrSurfInfoIn, &AddrSurfInfoOut);
+                           &AddrSurfInfoIn, &AddrSurfInfoOut, &AddrDccIn, &AddrDccOut);
          if (r)
             return r;
 
-- 
2.5.3



More information about the mesa-dev mailing list