[v2] virgl: Add method to query supported MSAA samples and positions

Submitted by Gert Wollny on June 28, 2018, 1:08 p.m.

Details

Message ID 20180628130801.12546-1-gert.wollny@collabora.com
State New
Headers show
Series "virgl: Add method to query supported MSAA samples and positions" ( rev: 2 ) in Virgil 3D

Not browsing as part of any series.

Commit Message

Gert Wollny June 28, 2018, 1:08 p.m.
Query the number of supported samples and the sample position and
store these to the caps.v2 structure. We support only up to 16 samples.
This implementation requires a GL host backend.

v2: - glTexImage2Dmultisample is not available on a gles 3.1 host
      and trying to call it crashed qemu (Jakob Bornecrantz) 
      Use glTexStorage2DMultisample instead and delete texture each 
      round because the texture becomes immutable.
    - move call to get sample positions only when caps v2 needs to be
      filled.

Signed-off-by: Gert Wollny <gert.wollny@collabora.com>
---
 src/virgl_hw.h       |  1 +
 src/vrend_formats.c  | 45 +++++++++++++++++++++++++++++++++++++++++++++
 src/vrend_renderer.c |  5 ++++-
 src/vrend_renderer.h |  3 +++
 4 files changed, 53 insertions(+), 1 deletion(-)

Patch hide | download patch | download mbox

diff --git a/src/virgl_hw.h b/src/virgl_hw.h
index 33ee0a1..65ff138 100644
--- a/src/virgl_hw.h
+++ b/src/virgl_hw.h
@@ -313,6 +313,7 @@  struct virgl_caps_v2 {
         uint32_t uniform_buffer_offset_alignment;
         uint32_t shader_buffer_offset_alignment;
         uint32_t capability_bits;
+        uint32_t sample_locations[8];
 };
 
 union virgl_caps {
diff --git a/src/vrend_formats.c b/src/vrend_formats.c
index 0a5dd69..cd4f86f 100644
--- a/src/vrend_formats.c
+++ b/src/vrend_formats.c
@@ -468,3 +468,48 @@  bool vrend_is_canonical_format(enum pipe_format format)
       return false;
    }
 }
+
+
+unsigned vrend_renderer_query_multisample_caps(unsigned max_samples, struct virgl_caps_v2 *caps)
+{
+   GLuint tex;
+   GLuint fbo;
+   GLenum status;
+
+   uint max_samples_confirmed = 1;
+   uint test_num_samples[4] = {2,4,8,16};
+   int out_buf_offsets[4] = {0,1,2,4};
+
+   glGenFramebuffers( 1, &fbo );
+   memset(caps->sample_locations, 0, 8 * sizeof(uint32_t));
+
+   for (int i = 0; i < 4 && test_num_samples[i] <= max_samples; ++i) {
+      glGenTextures(1, &tex);
+      glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, tex);
+      glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, test_num_samples[i], GL_RGBA32F, 16, 16, GL_TRUE);
+      status = glGetError();
+      if (status == GL_NO_ERROR) {
+         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, tex, 0);
+         status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+         if (status == GL_FRAMEBUFFER_COMPLETE) {
+            max_samples_confirmed = test_num_samples[i];
+
+            for (uint k = 0; k < test_num_samples[i]; ++k) {
+               float msp[2];
+               uint32_t compressed;
+               glGetMultisamplefv(GL_SAMPLE_POSITION, k, msp);
+               debug_printf("VIRGL: sample postion [%2d/%2d] = (%f, %f)\n",
+                            k, test_num_samples[i], msp[0], msp[1]);
+               compressed = ((unsigned)(floor(msp[0] * 16.0f)) & 0xf) << 4;
+               compressed |= ((unsigned)(floor(msp[1] * 16.0f)) & 0xf);
+               caps->sample_locations[out_buf_offsets[i] + (k >> 2)] |= compressed  << (8 * (k & 3));
+            }
+         }
+      }
+      glBindFramebuffer(GL_FRAMEBUFFER, 0);
+      glDeleteTextures(1, &tex);
+   }
+   glDeleteFramebuffers(1, &fbo);
+   return max_samples_confirmed;
+}
diff --git a/src/vrend_renderer.c b/src/vrend_renderer.c
index 17c10db..52f1c44 100644
--- a/src/vrend_renderer.c
+++ b/src/vrend_renderer.c
@@ -7213,7 +7213,6 @@  static bool vrend_renderer_fill_caps_common(uint32_t set, UNUSED uint32_t versio
    glGetIntegerv(GL_MAX_SAMPLES, &max);
    caps->v1.max_samples = max;
 
-
    /* All of the formats are common. */
    for (i = 0; i < VIRGL_FORMAT_MAX; i++) {
       uint32_t offset = i / 32;
@@ -7367,6 +7366,8 @@  static void vrend_renderer_fill_caps_gles(uint32_t set, UNUSED uint32_t version,
 
    /* Not available on GLES */
    caps->v2.texture_buffer_offset_alignment = 0;
+
+   caps->v1.max_samples = vrend_renderer_query_multisample_caps(max, &caps->v2);
 }
 
 void vrend_renderer_fill_caps(uint32_t set, uint32_t version,
@@ -7593,6 +7594,8 @@  void vrend_renderer_fill_caps(uint32_t set, uint32_t version,
       glGetIntegerv(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, (GLint*)&caps->v2.shader_buffer_offset_alignment);
    }
 
+   caps->v1.max_samples = vrend_renderer_query_multisample_caps(max, &caps->v2);
+
    caps->v2.capability_bits |= VIRGL_CAP_TGSI_INVARIANT;
 
    if (gl_ver >= 43 || epoxy_has_gl_extension("GL_ARB_texture_view"))
diff --git a/src/vrend_renderer.h b/src/vrend_renderer.h
index e73a0dd..718d779 100644
--- a/src/vrend_renderer.h
+++ b/src/vrend_renderer.h
@@ -392,6 +392,9 @@  void vrend_renderer_reset(void);
 int vrend_renderer_get_poll_fd(void);
 void vrend_decode_reset(bool ctx_0_only);
 
+unsigned vrend_renderer_query_multisample_caps(unsigned max_samples,
+                                               struct virgl_caps_v2 *caps);
+
 struct gl_version {
    uint32_t major;
    uint32_t minor;

Comments

On 28 June 2018 at 23:08, Gert Wollny <gert.wollny@collabora.com> wrote:
> Query the number of supported samples and the sample position and
> store these to the caps.v2 structure. We support only up to 16 samples.
> This implementation requires a GL host backend.
>
> v2: - glTexImage2Dmultisample is not available on a gles 3.1 host
>       and trying to call it crashed qemu (Jakob Bornecrantz)
>       Use glTexStorage2DMultisample instead and delete texture each
>       round because the texture becomes immutable.
>     - move call to get sample positions only when caps v2 needs to be
>       filled.
>

I haven't tested this yet, but there are a couple of whitespace nits.
>
>  union virgl_caps {
> diff --git a/src/vrend_formats.c b/src/vrend_formats.c
> index 0a5dd69..cd4f86f 100644
> --- a/src/vrend_formats.c
> +++ b/src/vrend_formats.c
> @@ -468,3 +468,48 @@ bool vrend_is_canonical_format(enum pipe_format format)
>        return false;
>     }
>  }
> +
> +

^ only one line please.

> +unsigned vrend_renderer_query_multisample_caps(unsigned max_samples, struct virgl_caps_v2 *caps)
> +{
> +   GLuint tex;
> +   GLuint fbo;
> +   GLenum status;
> +
> +   uint max_samples_confirmed = 1;
> +   uint test_num_samples[4] = {2,4,8,16};
> +   int out_buf_offsets[4] = {0,1,2,4};
> +
> +   glGenFramebuffers( 1, &fbo );
> +   memset(caps->sample_locations, 0, 8 * sizeof(uint32_t));
> +
> +   for (int i = 0; i < 4 && test_num_samples[i] <= max_samples; ++i) {
> +      glGenTextures(1, &tex);
> +      glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, tex);
> +      glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, test_num_samples[i], GL_RGBA32F, 16, 16, GL_TRUE);
> +      status = glGetError();
> +      if (status == GL_NO_ERROR) {
> +         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
> +         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, tex, 0);
> +         status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
> +         if (status == GL_FRAMEBUFFER_COMPLETE) {
> +            max_samples_confirmed = test_num_samples[i];
> +
> +            for (uint k = 0; k < test_num_samples[i]; ++k) {
> +               float msp[2];
> +               uint32_t compressed;
> +               glGetMultisamplefv(GL_SAMPLE_POSITION, k, msp);
> +               debug_printf("VIRGL: sample postion [%2d/%2d] = (%f, %f)\n",
> +                            k, test_num_samples[i], msp[0], msp[1]);
> +               compressed = ((unsigned)(floor(msp[0] * 16.0f)) & 0xf) << 4;
> +               compressed |= ((unsigned)(floor(msp[1] * 16.0f)) & 0xf);
> +               caps->sample_locations[out_buf_offsets[i] + (k >> 2)] |= compressed  << (8 * (k & 3));
> +            }
> +         }
> +      }
> +      glBindFramebuffer(GL_FRAMEBUFFER, 0);
> +      glDeleteTextures(1, &tex);
> +   }
> +   glDeleteFramebuffers(1, &fbo);
> +   return max_samples_confirmed;
> +}
> diff --git a/src/vrend_renderer.c b/src/vrend_renderer.c
> index 17c10db..52f1c44 100644
> --- a/src/vrend_renderer.c
> +++ b/src/vrend_renderer.c
> @@ -7213,7 +7213,6 @@ static bool vrend_renderer_fill_caps_common(uint32_t set, UNUSED uint32_t versio
>     glGetIntegerv(GL_MAX_SAMPLES, &max);
>     caps->v1.max_samples = max;
>
> -
>     /* All of the formats are common. */

Don't remove a line here.


Dave.