gallium/radeon: allow multiple exports of the same texture with different usage
authorMarek Olšák <marek.olsak@amd.com>
Mon, 28 Mar 2016 23:36:40 +0000 (01:36 +0200)
committerMarek Olšák <marek.olsak@amd.com>
Tue, 5 Apr 2016 13:32:40 +0000 (15:32 +0200)
Instead of failing an assertion, disable DCC and CMASK on the first export
that needs it, and merge the external usage flags.

v2: clear the EXPLICIT_FLUSH flag if it's not set; whitespace fixes

Reviewed-by: Michel Dänzer <michel.daenzer@amd.com>
src/gallium/drivers/radeon/r600_texture.c

index 83fc002122775376f67c6724c67509bb5570f7ab..4850b73f2915577c918797a1bffb0a3d7077214f 100644 (file)
@@ -329,6 +329,7 @@ static boolean r600_texture_get_handle(struct pipe_screen* screen,
        struct r600_resource *res = (struct r600_resource*)resource;
        struct r600_texture *rtex = (struct r600_texture*)resource;
        struct radeon_bo_metadata metadata;
+       bool update_metadata = false;
 
        /* This is not supported now, but it might be required for OpenCL
         * interop in the future.
@@ -337,29 +338,30 @@ static boolean r600_texture_get_handle(struct pipe_screen* screen,
            (resource->nr_samples > 1 || rtex->is_depth))
                return false;
 
-       if (!res->is_shared) {
-               res->is_shared = true;
-               res->external_usage = usage;
-
-               if (resource->target != PIPE_BUFFER) {
-                       /* Since shader image stores don't support DCC on VI,
-                        * disable it for external clients that want write
-                        * access.
-                        */
-                       if (usage & PIPE_HANDLE_USAGE_WRITE)
-                               r600_texture_disable_dcc(rscreen, rtex);
+       if (resource->target != PIPE_BUFFER) {
+               /* Since shader image stores don't support DCC on VI,
+                * disable it for external clients that want write
+                * access.
+                */
+               if (usage & PIPE_HANDLE_USAGE_WRITE && rtex->dcc_offset) {
+                       r600_texture_disable_dcc(rscreen, rtex);
+                       update_metadata = true;
+               }
 
-                       if (!(usage & PIPE_HANDLE_USAGE_EXPLICIT_FLUSH)) {
-                               /* Eliminate fast clear (both CMASK and DCC) */
-                               r600_eliminate_fast_color_clear(rscreen, rtex);
+               if (!(usage & PIPE_HANDLE_USAGE_EXPLICIT_FLUSH) &&
+                   rtex->cmask.size) {
+                       /* Eliminate fast clear (both CMASK and DCC) */
+                       r600_eliminate_fast_color_clear(rscreen, rtex);
 
-                               /* Disable CMASK if flush_resource isn't going
-                                * to be called.
-                                */
-                               r600_texture_disable_cmask(rscreen, rtex);
-                       }
+                       /* Disable CMASK if flush_resource isn't going
+                        * to be called.
+                        */
+                       r600_texture_disable_cmask(rscreen, rtex);
+                       update_metadata = true;
+               }
 
-                       /* Set metadata. */
+               /* Set metadata. */
+               if (!res->is_shared || update_metadata) {
                        r600_texture_init_metadata(rtex, &metadata);
                        if (rscreen->query_opaque_metadata)
                                rscreen->query_opaque_metadata(rscreen, rtex,
@@ -367,8 +369,18 @@ static boolean r600_texture_get_handle(struct pipe_screen* screen,
 
                        rscreen->ws->buffer_set_metadata(res->buf, &metadata);
                }
+       }
+
+       if (res->is_shared) {
+               /* USAGE_EXPLICIT_FLUSH must be cleared if at least one user
+                * doesn't set it.
+                */
+               res->external_usage |= usage & ~PIPE_HANDLE_USAGE_EXPLICIT_FLUSH;
+               if (!(usage & PIPE_HANDLE_USAGE_EXPLICIT_FLUSH))
+                       res->external_usage &= ~PIPE_HANDLE_USAGE_EXPLICIT_FLUSH;
        } else {
-               assert(res->external_usage == usage);
+               res->is_shared = true;
+               res->external_usage = usage;
        }
 
        return rscreen->ws->buffer_get_handle(res->buf,