mesa: add functional FBO changes for AMD_framebuffer_multisample_advanced
authorMarek Olšák <marek.olsak@amd.com>
Mon, 11 Jun 2018 22:30:34 +0000 (18:30 -0400)
committerMarek Olšák <marek.olsak@amd.com>
Sat, 4 Aug 2018 06:46:55 +0000 (02:46 -0400)
- relax FBO completeness rules
- validate sample counts

Reviewed-by: Brian Paul <brianp@vmware.com>
src/mesa/main/fbobject.c
src/mesa/main/multisample.c

index 3ed303b51abf5800da724b8d22cda28dcc79014c..c14c9f4047bb3a8b8a2ad64d90237492e0294bcb 100644 (file)
@@ -969,7 +969,9 @@ _mesa_test_framebuffer_completeness(struct gl_context *ctx,
    GLuint numImages;
    GLenum intFormat = GL_NONE; /* color buffers' internal format */
    GLuint minWidth = ~0, minHeight = ~0, maxWidth = 0, maxHeight = 0;
-   GLint numSamples = -1;
+   GLint numColorSamples = -1;
+   GLint numColorStorageSamples = -1;
+   GLint numDepthSamples = -1;
    GLint fixedSampleLocations = -1;
    GLint i;
    GLuint j;
@@ -1046,6 +1048,8 @@ _mesa_test_framebuffer_completeness(struct gl_context *ctx,
 
       /* get width, height, format of the renderbuffer/texture
        */
+      unsigned attNumSamples, attNumStorageSamples;
+
       if (att->Type == GL_TEXTURE) {
          const struct gl_texture_image *texImg = att->Renderbuffer->TexImage;
          att_tex_target = att->Texture->Target;
@@ -1066,14 +1070,6 @@ _mesa_test_framebuffer_completeness(struct gl_context *ctx,
             return;
          }
 
-         if (numSamples < 0)
-            numSamples = texImg->NumSamples;
-         else if (numSamples != texImg->NumSamples) {
-            fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
-            fbo_incomplete(ctx, "inconsistent sample count", -1);
-            return;
-         }
-
          if (fixedSampleLocations < 0)
             fixedSampleLocations = texImg->FixedSampleLocations;
          else if (fixedSampleLocations != texImg->FixedSampleLocations) {
@@ -1081,6 +1077,9 @@ _mesa_test_framebuffer_completeness(struct gl_context *ctx,
             fbo_incomplete(ctx, "inconsistent fixed sample locations", -1);
             return;
          }
+
+         attNumSamples = texImg->NumSamples;
+         attNumStorageSamples = texImg->NumSamples;
       }
       else if (att->Type == GL_RENDERBUFFER_EXT) {
          minWidth = MIN2(minWidth, att->Renderbuffer->Width);
@@ -1091,14 +1090,6 @@ _mesa_test_framebuffer_completeness(struct gl_context *ctx,
          attFormat = att->Renderbuffer->Format;
          numImages++;
 
-         if (numSamples < 0)
-            numSamples = att->Renderbuffer->NumSamples;
-         else if (numSamples != att->Renderbuffer->NumSamples) {
-            fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
-            fbo_incomplete(ctx, "inconsistent sample count", -1);
-            return;
-         }
-
          /* RENDERBUFFER has fixedSampleLocations implicitly true */
          if (fixedSampleLocations < 0)
             fixedSampleLocations = GL_TRUE;
@@ -1107,12 +1098,38 @@ _mesa_test_framebuffer_completeness(struct gl_context *ctx,
             fbo_incomplete(ctx, "inconsistent fixed sample locations", -1);
             return;
          }
+
+         attNumSamples = att->Renderbuffer->NumSamples;
+         attNumStorageSamples = att->Renderbuffer->NumStorageSamples;
       }
       else {
          assert(att->Type == GL_NONE);
          continue;
       }
 
+      if (i >= 0) {
+         /* Color buffers. */
+         if (numColorSamples < 0) {
+            assert(numColorStorageSamples < 0);
+            numColorSamples = attNumSamples;
+            numColorStorageSamples = attNumStorageSamples;
+         } else if (numColorSamples != attNumSamples ||
+                    numColorStorageSamples != attNumStorageSamples) {
+            fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
+            fbo_incomplete(ctx, "inconsistent sample counts", -1);
+            return;
+         }
+      } else {
+         /* Depth/stencil buffers. */
+         if (numDepthSamples < 0) {
+            numDepthSamples = attNumSamples;
+         } else if (numDepthSamples != attNumSamples) {
+            fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
+            fbo_incomplete(ctx, "inconsistent sample counts", -1);
+            return;
+         }
+      }
+
       /* Update flags describing color buffer datatypes */
       if (i >= 0) {
          GLenum type = _mesa_get_format_datatype(attFormat);
@@ -1218,6 +1235,51 @@ _mesa_test_framebuffer_completeness(struct gl_context *ctx,
        */
    }
 
+   if (ctx->Extensions.AMD_framebuffer_multisample_advanced) {
+      /* See if non-matching sample counts are supported. */
+      if (numColorSamples >= 0 && numDepthSamples >= 0) {
+         bool found = false;
+
+         assert(numColorStorageSamples != -1);
+
+         numColorSamples = MAX2(numColorSamples, 1);
+         numColorStorageSamples = MAX2(numColorStorageSamples, 1);
+         numDepthSamples = MAX2(numDepthSamples, 1);
+
+         if (numColorSamples == 1 && numColorStorageSamples == 1 &&
+             numDepthSamples == 1) {
+            found = true;
+         } else {
+            for (i = 0; i < ctx->Const.NumSupportedMultisampleModes; i++) {
+               GLint *counts =
+                  &ctx->Const.SupportedMultisampleModes[i].NumColorSamples;
+
+               if (counts[0] == numColorSamples &&
+                   counts[1] == numColorStorageSamples &&
+                   counts[2] == numDepthSamples) {
+                  found = true;
+                  break;
+               }
+            }
+         }
+
+         if (!found) {
+            fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
+            fbo_incomplete(ctx, "unsupported sample counts", -1);
+            return;
+         }
+      }
+   } else {
+      /* If the extension is unsupported, all sample counts must be equal. */
+      if (numColorSamples >= 0 &&
+          (numColorSamples != numColorStorageSamples ||
+           (numDepthSamples >= 0 && numColorSamples != numDepthSamples))) {
+         fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
+         fbo_incomplete(ctx, "inconsistent sample counts", -1);
+         return;
+      }
+   }
+
    fb->MaxNumLayers = max_layer_count;
 
    if (numImages == 0) {
index 4341a5918e46f96f3eb7a6cf2f3881cf3d4fea56..8beb1d839ec350f12a23e22169b0e56ab39e0949 100644 (file)
@@ -226,6 +226,58 @@ _mesa_check_sample_count(struct gl_context *ctx, GLenum target,
       return GL_INVALID_OPERATION;
    }
 
+   if (ctx->Extensions.AMD_framebuffer_multisample_advanced &&
+       target == GL_RENDERBUFFER) {
+      if (!_mesa_is_depth_or_stencil_format(internalFormat)) {
+         /* From the AMD_framebuffer_multisample_advanced spec:
+          *
+          *    "An INVALID_OPERATION error is generated if <internalformat>
+          *     is a color format and <storageSamples> is greater than
+          *     the implementation-dependent limit MAX_COLOR_FRAMEBUFFER_-
+          *     STORAGE_SAMPLES_AMD."
+          */
+         if (samples > ctx->Const.MaxColorFramebufferSamples)
+            return GL_INVALID_OPERATION;
+
+         /* From the AMD_framebuffer_multisample_advanced spec:
+          *
+          *    "An INVALID_OPERATION error is generated if <internalformat>
+          *     is a color format and <storageSamples> is greater than
+          *     the implementation-dependent limit MAX_COLOR_FRAMEBUFFER_-
+          *     STORAGE_SAMPLES_AMD."
+          */
+         if (storageSamples > ctx->Const.MaxColorFramebufferStorageSamples)
+            return GL_INVALID_OPERATION;
+
+         /* From the AMD_framebuffer_multisample_advanced spec:
+          *
+          *    "An INVALID_OPERATION error is generated if <storageSamples> is
+          *     greater than <samples>."
+          */
+         if (storageSamples > samples)
+            return GL_INVALID_OPERATION;
+
+         /* Color renderbuffer sample counts are now fully validated
+          * according to AMD_framebuffer_multisample_advanced.
+          */
+         return GL_NO_ERROR;
+      } else {
+         /* From the AMD_framebuffer_multisample_advanced spec:
+          *
+          *    "An INVALID_OPERATION error is generated if <internalformat> is
+          *     a depth or stencil format and <storageSamples> is not equal to
+          *     <samples>."
+          */
+         if (storageSamples != samples)
+            return GL_INVALID_OPERATION;
+      }
+   } else {
+      /* If the extension is unsupported, it's not possible to set
+       * storageSamples differently.
+       */
+      assert(samples == storageSamples);
+   }
+
    /* If ARB_internalformat_query is supported, then treat its highest
     * returned sample count as the absolute maximum for this format; it is
     * allowed to exceed MAX_SAMPLES.