diff --git a/src/virgl_hw.h b/src/virgl_hw.h index 589cd73..44c7108 100644 --- a/src/virgl_hw.h +++ b/src/virgl_hw.h @@ -305,6 +305,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 eb9f217..82a1b5c 100644 --- a/src/vrend_formats.c +++ b/src/vrend_formats.c @@ -443,3 +443,47 @@ void vrend_build_format_list_gles(void) */ add_formats(gles_z32_format); } + +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 23494a8..0e21b10 100644 --- a/src/vrend_renderer.c +++ b/src/vrend_renderer.c @@ -7314,6 +7314,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, @@ -7540,6 +7542,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 d07d11c..f59d45f 100644 --- a/src/vrend_renderer.h +++ b/src/vrend_renderer.h @@ -390,6 +390,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;