[Mesa-dev] [PATCH 5/8] mesa: add functional FBO changes for AMD_framebuffer_multisample_advanced

Marek Olšák maraeo at gmail.com
Wed Aug 1 23:26:01 UTC 2018


From: Marek Olšák <marek.olsak at amd.com>

- relax FBO completeness rules
- validate sample counts
---
 src/mesa/main/fbobject.c    | 96 ++++++++++++++++++++++++++++++-------
 src/mesa/main/multisample.c | 52 ++++++++++++++++++++
 2 files changed, 131 insertions(+), 17 deletions(-)

diff --git a/src/mesa/main/fbobject.c b/src/mesa/main/fbobject.c
index 3ed303b51ab..c14c9f4047b 100644
--- a/src/mesa/main/fbobject.c
+++ b/src/mesa/main/fbobject.c
@@ -962,21 +962,23 @@ test_attachment_completeness(const struct gl_context *ctx, GLenum format,
  * Also update the framebuffer's Width and Height fields if the
  * framebuffer is complete.
  */
 void
 _mesa_test_framebuffer_completeness(struct gl_context *ctx,
                                     struct gl_framebuffer *fb)
 {
    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;
    /* Covers max_layer_count, is_layered, and layer_tex_target */
    bool layer_info_valid = false;
    GLuint max_layer_count = 0, att_layer_count;
    bool is_layered = false;
    GLenum layer_tex_target = 0;
    bool has_depth_attachment = false;
    bool has_stencil_attachment = false;
@@ -1039,87 +1041,102 @@ _mesa_test_framebuffer_completeness(struct gl_context *ctx,
          test_attachment_completeness(ctx, GL_COLOR, att);
          if (!att->Complete) {
             fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT;
             fbo_incomplete(ctx, "color attachment incomplete", i);
             return;
          }
       }
 
       /* 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;
          minWidth = MIN2(minWidth, texImg->Width);
          maxWidth = MAX2(maxWidth, texImg->Width);
          minHeight = MIN2(minHeight, texImg->Height);
          maxHeight = MAX2(maxHeight, texImg->Height);
          f = texImg->_BaseFormat;
          attFormat = texImg->TexFormat;
          numImages++;
 
          if (!is_format_color_renderable(ctx, attFormat,
                                          texImg->InternalFormat) &&
              !is_legal_depth_format(ctx, f) &&
              f != GL_STENCIL_INDEX) {
             fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
             fbo_incomplete(ctx, "texture attachment incomplete", -1);
             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) {
             fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
             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);
          maxWidth = MAX2(minWidth, att->Renderbuffer->Width);
          minHeight = MIN2(minHeight, att->Renderbuffer->Height);
          maxHeight = MAX2(minHeight, att->Renderbuffer->Height);
          f = att->Renderbuffer->InternalFormat;
          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;
          else if (fixedSampleLocations != GL_TRUE) {
             fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
             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);
 
          /* check if integer color */
          if (_mesa_is_format_integer_color(attFormat))
             fb->_IntegerBuffers |= (1 << i);
 
          fb->_AllColorBuffersFixedPoint =
             fb->_AllColorBuffersFixedPoint &&
@@ -1211,20 +1228,65 @@ _mesa_test_framebuffer_completeness(struct gl_context *ctx,
        *
        * "If image has multiple samples, its sample count is less than or equal
        *  to the value of the implementation-dependent limit
        *  MAX_FRAMEBUFFER_SAMPLES."
        *
        * The same requirements are also in place for GL 4.5,
        * Section 9.4.1 "Framebuffer Attachment Completeness", pg 310-311
        */
    }
 
+   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) {
       fb->_HasAttachments = false;
 
       if (!ctx->Extensions.ARB_framebuffer_no_attachments) {
          fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT;
          fbo_incomplete(ctx, "no attachments", -1);
          return;
       }
diff --git a/src/mesa/main/multisample.c b/src/mesa/main/multisample.c
index 4341a5918e4..8beb1d839ec 100644
--- a/src/mesa/main/multisample.c
+++ b/src/mesa/main/multisample.c
@@ -219,20 +219,72 @@ _mesa_check_sample_count(struct gl_context *ctx, GLenum target,
     *     is greater than zero, then the error INVALID_OPERATION is generated."
     *
     * This restriction is relaxed for OpenGL ES 3.1.
     */
    if ((ctx->API == API_OPENGLES2 && ctx->Version == 30) &&
        _mesa_is_enum_format_integer(internalFormat)
        && samples > 0) {
       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.
     *
     * From the ARB_internalformat_query spec:
     *
     * "If <samples is greater than the maximum number of samples supported
     * for <internalformat> then the error INVALID_OPERATION is generated."
     */
    if (ctx->Extensions.ARB_internalformat_query) {
-- 
2.17.1



More information about the mesa-dev mailing list