From 75207aaac9b1e31beef0663ee780fe8821f78eae Mon Sep 17 00:00:00 2001 From: Akihiko Odaki Date: Fri, 18 Feb 2022 16:55:54 +0900 Subject: [PATCH] vrend: Check GL_TEXTURE_RECTANGLE compatibility The compressed formats are incompatible with GL_TEXTURE_RECTANGLE on Mesa 21.3.6. This also fixes spec@!opengl 1.0@gl-1.0-dlist-bitmap, which makes the guest to have GL_TEXTURE_RECTANGLE but TGSI specifies TGSI_TEXTURE_2D, on OpenGL ES by always looking at the target of given texture. v2: Use the result of compatibility check in shader transformation. (Gert Wollny) Signed-off-by: Akihiko Odaki Part-of: --- .../host/piglit-virgl-gles-fails.txt | 1 - .../virt/piglit-virgl-gles-fails.txt | 1 - src/vrend_formats.c | 8 +++ src/vrend_renderer.c | 64 +++++++++---------- src/vrend_renderer.h | 1 + src/vrend_shader.c | 13 ++-- src/vrend_shader.h | 15 +++++ 7 files changed, 60 insertions(+), 43 deletions(-) diff --git a/.gitlab-ci/expectations/host/piglit-virgl-gles-fails.txt b/.gitlab-ci/expectations/host/piglit-virgl-gles-fails.txt index 33c3d59..85c2af2 100644 --- a/.gitlab-ci/expectations/host/piglit-virgl-gles-fails.txt +++ b/.gitlab-ci/expectations/host/piglit-virgl-gles-fails.txt @@ -2590,7 +2590,6 @@ spec@oes_egl_image_external_essl3@oes_egl_image_external_essl3,ExpectedFail spec@oes_egl_image_external_essl3@oes_egl_image_external_essl3@oes_egl_image_external_essl3_imageLoad,ExpectedFail spec@oes_egl_image_external_essl3@oes_egl_image_external_essl3@oes_egl_image_external_essl3_imageStore,ExpectedFail spec@oes_point_sprite@arb_point_sprite-checkerboard_gles1,Fail -spec@!opengl 1.0@gl-1.0-dlist-bitmap,Fail spec@!opengl 1.0@gl-1.0-drawbuffer-modes,ExpectedFail spec@!opengl 1.0@gl-1.0-edgeflag-const,Fail spec@!opengl 1.0@gl-1.0-edgeflag,Fail diff --git a/.gitlab-ci/expectations/virt/piglit-virgl-gles-fails.txt b/.gitlab-ci/expectations/virt/piglit-virgl-gles-fails.txt index 126ed2a..f290ba4 100644 --- a/.gitlab-ci/expectations/virt/piglit-virgl-gles-fails.txt +++ b/.gitlab-ci/expectations/virt/piglit-virgl-gles-fails.txt @@ -2616,7 +2616,6 @@ spec@oes_egl_image_external_essl3@oes_egl_image_external_essl3,ExpectedFail spec@oes_egl_image_external_essl3@oes_egl_image_external_essl3@oes_egl_image_external_essl3_imageLoad,ExpectedFail spec@oes_egl_image_external_essl3@oes_egl_image_external_essl3@oes_egl_image_external_essl3_imageStore,ExpectedFail spec@oes_point_sprite@arb_point_sprite-checkerboard_gles1,Fail -spec@!opengl 1.0@gl-1.0-dlist-bitmap,Fail spec@!opengl 1.0@gl-1.0-drawbuffer-modes,ExpectedFail spec@!opengl 1.0@gl-1.0-edgeflag-const,Fail spec@!opengl 1.0@gl-1.0-edgeflag,Fail diff --git a/src/vrend_formats.c b/src/vrend_formats.c index 987e610..7190bce 100644 --- a/src/vrend_formats.c +++ b/src/vrend_formats.c @@ -504,6 +504,14 @@ static void vrend_add_formats(struct vrend_format_table *table, int num_entries) continue; } + if (is_desktop_gl) { + glTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0, table[i].internalformat, 32, 32, 0, table[i].glformat, table[i].gltype, NULL); + status = glGetError(); + if (status == GL_NO_ERROR) { + flags |= VIRGL_TEXTURE_CAN_TARGET_RECTANGLE; + } + } + if (table[i].format < VIRGL_FORMAT_MAX && util_format_is_depth_or_stencil(table[i].format)) { GLenum attachment; diff --git a/src/vrend_renderer.c b/src/vrend_renderer.c index 8d563e8..cd1fea0 100644 --- a/src/vrend_renderer.c +++ b/src/vrend_renderer.c @@ -507,6 +507,7 @@ struct vrend_sampler_view { GLenum depth_texture_mode; GLuint srgb_decode; GLuint levels; + bool emulated_rect; struct vrend_resource *texture; }; @@ -1021,7 +1022,6 @@ static void __report_core_warn(const char *fname, struct vrend_context *ctx, #define GLES_WARN_POINT_SIZE 4 #define GLES_WARN_SEAMLESS_CUBE_MAP 5 #define GLES_WARN_LOD_BIAS 6 -#define GLES_WARN_TEXTURE_RECT 7 #define GLES_WARN_OFFSET_LINE 8 #define GLES_WARN_OFFSET_POINT 9 //#define GLES_WARN_ free slot 10 @@ -1042,7 +1042,6 @@ static const char *vrend_gles_warn_strings[] = { [GLES_WARN_POINT_SIZE] = "Point Size", [GLES_WARN_SEAMLESS_CUBE_MAP] = "Seamless Cube Map", [GLES_WARN_LOD_BIAS] = "Lod Bias", - [GLES_WARN_TEXTURE_RECT] = "Texture Rect", [GLES_WARN_OFFSET_LINE] = "Offset Line", [GLES_WARN_OFFSET_POINT] = "Offset Point", [GLES_WARN_FLATSHADE_FIRST] = "Flatshade First", @@ -1956,13 +1955,17 @@ int vrend_create_surface(struct vrend_context *ctx, glGenTextures(1, &surf->id); if (vrend_state.use_gles) { - if (target == GL_TEXTURE_RECTANGLE_NV || - target == GL_TEXTURE_1D) + if (target == GL_TEXTURE_1D) target = GL_TEXTURE_2D; else if (target == GL_TEXTURE_1D_ARRAY) target = GL_TEXTURE_2D_ARRAY; } + if (target == GL_TEXTURE_RECTANGLE_NV && + !(tex_conv_table[format].flags & VIRGL_TEXTURE_CAN_TARGET_RECTANGLE)) { + target = GL_TEXTURE_2D; + } + glTextureView(surf->id, target, res->id, internalformat, 0, res->base.last_level + 1, first_layer, last_layer - first_layer + 1); @@ -2229,15 +2232,20 @@ int vrend_create_sampler_view(struct vrend_context *ctx, view->target = tgsitargettogltarget(pipe_target, res->base.nr_samples); - /* Work around TEXTURE_RECTANGLE and TEXTURE_1D missing on GLES */ + /* Work around TEXTURE_1D missing on GLES */ if (vrend_state.use_gles) { - if (view->target == GL_TEXTURE_RECTANGLE_NV || - view->target == GL_TEXTURE_1D) + if (view->target == GL_TEXTURE_1D) view->target = GL_TEXTURE_2D; else if (view->target == GL_TEXTURE_1D_ARRAY) view->target = GL_TEXTURE_2D_ARRAY; } + if (view->target == GL_TEXTURE_RECTANGLE_NV && + !(tex_conv_table[view->format].flags & VIRGL_TEXTURE_CAN_TARGET_RECTANGLE)) { + view->emulated_rect = true; + view->target = GL_TEXTURE_2D; + } + view->val0 = val0; view->val1 = val1; @@ -3594,10 +3602,17 @@ static inline void vrend_fill_shader_key(struct vrend_sub_context *sub_ctx, for (int i = 0; i < sub_ctx->views[type].num_views; i++) { struct vrend_sampler_view *view = sub_ctx->views[type].views[i]; - if (view && view->texture->target == GL_TEXTURE_BUFFER && + if (!view) + continue; + + if (view->emulated_rect) { + vrend_shader_sampler_views_mask_set(key->sampler_views_emulated_rect_mask, i); + } + + if (view->texture->target == GL_TEXTURE_BUFFER && tex_conv_table[view->format].flags & VIRGL_TEXTURE_NEED_SWIZZLE) { - key->sampler_views_lower_swizzle_mask[i / 64] |= 1ull << (i % 64); + vrend_shader_sampler_views_mask_set(key->sampler_views_lower_swizzle_mask, i); key->tex_swizzle[i] = to_pipe_swizzle(view->gl_swizzle[0]) | to_pipe_swizzle(view->gl_swizzle[1]) << 3 | to_pipe_swizzle(view->gl_swizzle[2]) << 6 | @@ -7253,11 +7268,12 @@ static int vrend_resource_alloc_texture(struct vrend_resource *gr, gr->target = tgsitargettogltarget(pr->target, pr->nr_samples); gr->storage_bits |= VREND_STORAGE_GL_TEXTURE; - /* ugly workaround for texture rectangle missing on GLES */ - if (vrend_state.use_gles && gr->target == GL_TEXTURE_RECTANGLE_NV) { + /* ugly workaround for texture rectangle incompatibility */ + if (gr->target == GL_TEXTURE_RECTANGLE_NV && + !(tex_conv_table[format].flags & VIRGL_TEXTURE_CAN_TARGET_RECTANGLE)) { /* for some guests this is the only usage of rect */ if (pr->width0 != 1 || pr->height0 != 1) { - report_gles_warn(NULL, GLES_WARN_TEXTURE_RECT); + vrend_printf("Warning: specifying format incompatible with GL_TEXTURE_RECTANGLE_NV\n"); } gr->target = GL_TEXTURE_2D; } @@ -9089,34 +9105,14 @@ static void vrend_resource_copy_fallback(struct vrend_resource *src_res, glBindTexture(GL_TEXTURE_2D, 0); } -static inline -GLenum translate_gles_emulation_texture_target(GLenum target) -{ - switch (target) { - case GL_TEXTURE_1D: - case GL_TEXTURE_RECTANGLE: return GL_TEXTURE_2D; - case GL_TEXTURE_1D_ARRAY: return GL_TEXTURE_2D_ARRAY; - default: return target; - } -} - static inline void vrend_copy_sub_image(struct vrend_resource* src_res, struct vrend_resource * dst_res, uint32_t src_level, const struct pipe_box *src_box, uint32_t dst_level, uint32_t dstx, uint32_t dsty, uint32_t dstz) { - - GLenum src_target = tgsitargettogltarget(src_res->base.target, src_res->base.nr_samples); - GLenum dst_target = tgsitargettogltarget(dst_res->base.target, dst_res->base.nr_samples); - - if (vrend_state.use_gles) { - src_target = translate_gles_emulation_texture_target(src_target); - dst_target = translate_gles_emulation_texture_target(dst_target); - } - - glCopyImageSubData(src_res->id, src_target, src_level, + glCopyImageSubData(src_res->id, src_res->target, src_level, src_box->x, src_box->y, src_box->z, - dst_res->id, dst_target, dst_level, + dst_res->id, dst_res->target, dst_level, dstx, dsty, dstz, src_box->width, src_box->height,src_box->depth); } diff --git a/src/vrend_renderer.h b/src/vrend_renderer.h index 73cb0d9..0a9050e 100644 --- a/src/vrend_renderer.h +++ b/src/vrend_renderer.h @@ -100,6 +100,7 @@ struct vrend_resource { #define VIRGL_TEXTURE_NEED_SWIZZLE (1 << 0) #define VIRGL_TEXTURE_CAN_TEXTURE_STORAGE (1 << 1) #define VIRGL_TEXTURE_CAN_READBACK (1 << 2) +#define VIRGL_TEXTURE_CAN_TARGET_RECTANGLE (1 << 3) struct vrend_format_table { enum virgl_formats format; diff --git a/src/vrend_shader.c b/src/vrend_shader.c index f355798..2a2005c 100644 --- a/src/vrend_shader.c +++ b/src/vrend_shader.c @@ -2879,11 +2879,9 @@ static void translate_tex(struct dump_ctx *ctx, } } - /* On GLES we have to normalized the coordinate for all but the texel fetch instruction */ - if (ctx->cfg->use_gles && - inst->Instruction.Opcode != TGSI_OPCODE_TXF && - (inst->Texture.Texture == TGSI_TEXTURE_RECT || - inst->Texture.Texture == TGSI_TEXTURE_SHADOWRECT)) { + /* We have to unnormalize the coordinate for all but the texel fetch instruction */ + if (inst->Instruction.Opcode != TGSI_OPCODE_TXF && + vrend_shader_sampler_views_mask_get(ctx->key->sampler_views_emulated_rect_mask, sinfo->sreg_index)) { char buf[255]; const char *new_srcs[4] = { buf, srcs[1], srcs[2], srcs[3] }; @@ -2948,7 +2946,7 @@ static void translate_tex(struct dump_ctx *ctx, tex_ext, srcs[sampler_index], get_string(txfi), srcs[0], get_wm_string(twm), bias, offset); - if (ctx->key->sampler_views_lower_swizzle_mask[sinfo->sreg_index / 64] & (1ull << (sinfo->sreg_index % 64))) { + if (vrend_shader_sampler_views_mask_get(ctx->key->sampler_views_lower_swizzle_mask, sinfo->sreg_index)) { int16_t packed_swizzles = ctx->key->tex_swizzle[sinfo->sreg_index]; emit_buff(&ctx->glsl_strbufs, " val = vec4("); @@ -2971,7 +2969,8 @@ static void translate_tex(struct dump_ctx *ctx, emit_buff(&ctx->glsl_strbufs, " %s = val%s;\n}\n", dst, dinfo->dst_override_no_wm[0] ? "" : writemask); } - } else if (ctx->cfg->glsl_version < 140 && (ctx->shader_req_bits & SHADER_REQ_SAMPLER_RECT)) { + } else if ((ctx->cfg->glsl_version < 140 && (ctx->shader_req_bits & SHADER_REQ_SAMPLER_RECT)) && + !vrend_shader_sampler_views_mask_get(ctx->key->sampler_views_emulated_rect_mask, sinfo->sreg_index)) { /* rect is special in GLSL 1.30 */ if (inst->Texture.Texture == TGSI_TEXTURE_RECT) emit_buff(&ctx->glsl_strbufs, "%s = texture2DRect(%s, %s.xy)%s;\n", diff --git a/src/vrend_shader.h b/src/vrend_shader.h index 31cdcf0..14757d9 100644 --- a/src/vrend_shader.h +++ b/src/vrend_shader.h @@ -184,6 +184,7 @@ struct vrend_shader_key { }; uint64_t sampler_views_lower_swizzle_mask[VREND_SHADER_SAMPLER_VIEWS_MASK_LENGTH]; + uint64_t sampler_views_emulated_rect_mask[VREND_SHADER_SAMPLER_VIEWS_MASK_LENGTH]; uint16_t tex_swizzle[PIPE_MAX_SHADER_SAMPLER_VIEWS]; uint8_t num_in_cull : 4; @@ -247,4 +248,18 @@ bool vrend_shader_create_passthrough_tcs(const struct vrend_context *ctx, bool vrend_shader_needs_alpha_func(const struct vrend_shader_key *key); +static inline bool vrend_shader_sampler_views_mask_get( + const uint64_t mask[static VREND_SHADER_SAMPLER_VIEWS_MASK_LENGTH], + int index) +{ + return (mask[index / 64] >> (index % 64)) & 1; +} + +static inline void vrend_shader_sampler_views_mask_set( + uint64_t mask[static VREND_SHADER_SAMPLER_VIEWS_MASK_LENGTH], + int index) +{ + mask[index / 64] |= 1ull << (index % 64); +} + #endif