From 459f05c7ec4b885450acd7e4b64eb4ad8c955c03 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Marek=20Ol=C5=A1=C3=A1k?= Date: Mon, 11 Jun 2018 18:30:34 -0400 Subject: [PATCH] mesa: add functional FBO changes for AMD_framebuffer_multisample_advanced - relax FBO completeness rules - validate sample counts Reviewed-by: Brian Paul --- 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 @@ -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) { 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 @@ -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 + * is a color format and 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 + * is a color format and 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 is + * greater than ." + */ + 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 is + * a depth or stencil format and is not equal to + * ." + */ + 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. -- 2.30.2