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 <akihiko.odaki@gmail.com>
macos/master
Akihiko Odaki 3 years ago
parent 1822e84319
commit b3d1a654cd
  1. 1
      .gitlab-ci/expectations/host/piglit-virgl-gles-fails.txt
  2. 1
      .gitlab-ci/expectations/virt/piglit-virgl-gles-fails.txt
  3. 8
      src/vrend_formats.c
  4. 64
      src/vrend_renderer.c
  5. 1
      src/vrend_renderer.h
  6. 13
      src/vrend_shader.c
  7. 15
      src/vrend_shader.h

@ -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_imageLoad,ExpectedFail
spec@oes_egl_image_external_essl3@oes_egl_image_external_essl3@oes_egl_image_external_essl3_imageStore,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@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-drawbuffer-modes,ExpectedFail
spec@!opengl 1.0@gl-1.0-edgeflag-const,Fail spec@!opengl 1.0@gl-1.0-edgeflag-const,Fail
spec@!opengl 1.0@gl-1.0-edgeflag,Fail spec@!opengl 1.0@gl-1.0-edgeflag,Fail

@ -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_imageLoad,ExpectedFail
spec@oes_egl_image_external_essl3@oes_egl_image_external_essl3@oes_egl_image_external_essl3_imageStore,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@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-drawbuffer-modes,ExpectedFail
spec@!opengl 1.0@gl-1.0-edgeflag-const,Fail spec@!opengl 1.0@gl-1.0-edgeflag-const,Fail
spec@!opengl 1.0@gl-1.0-edgeflag,Fail spec@!opengl 1.0@gl-1.0-edgeflag,Fail

@ -504,6 +504,14 @@ static void vrend_add_formats(struct vrend_format_table *table, int num_entries)
continue; 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)) { if (table[i].format < VIRGL_FORMAT_MAX && util_format_is_depth_or_stencil(table[i].format)) {
GLenum attachment; GLenum attachment;

@ -507,6 +507,7 @@ struct vrend_sampler_view {
GLenum depth_texture_mode; GLenum depth_texture_mode;
GLuint srgb_decode; GLuint srgb_decode;
GLuint levels; GLuint levels;
bool emulated_rect;
struct vrend_resource *texture; 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_POINT_SIZE 4
#define GLES_WARN_SEAMLESS_CUBE_MAP 5 #define GLES_WARN_SEAMLESS_CUBE_MAP 5
#define GLES_WARN_LOD_BIAS 6 #define GLES_WARN_LOD_BIAS 6
#define GLES_WARN_TEXTURE_RECT 7
#define GLES_WARN_OFFSET_LINE 8 #define GLES_WARN_OFFSET_LINE 8
#define GLES_WARN_OFFSET_POINT 9 #define GLES_WARN_OFFSET_POINT 9
//#define GLES_WARN_ free slot 10 //#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_POINT_SIZE] = "Point Size",
[GLES_WARN_SEAMLESS_CUBE_MAP] = "Seamless Cube Map", [GLES_WARN_SEAMLESS_CUBE_MAP] = "Seamless Cube Map",
[GLES_WARN_LOD_BIAS] = "Lod Bias", [GLES_WARN_LOD_BIAS] = "Lod Bias",
[GLES_WARN_TEXTURE_RECT] = "Texture Rect",
[GLES_WARN_OFFSET_LINE] = "Offset Line", [GLES_WARN_OFFSET_LINE] = "Offset Line",
[GLES_WARN_OFFSET_POINT] = "Offset Point", [GLES_WARN_OFFSET_POINT] = "Offset Point",
[GLES_WARN_FLATSHADE_FIRST] = "Flatshade First", [GLES_WARN_FLATSHADE_FIRST] = "Flatshade First",
@ -1956,13 +1955,17 @@ int vrend_create_surface(struct vrend_context *ctx,
glGenTextures(1, &surf->id); glGenTextures(1, &surf->id);
if (vrend_state.use_gles) { if (vrend_state.use_gles) {
if (target == GL_TEXTURE_RECTANGLE_NV || if (target == GL_TEXTURE_1D)
target == GL_TEXTURE_1D)
target = GL_TEXTURE_2D; target = GL_TEXTURE_2D;
else if (target == GL_TEXTURE_1D_ARRAY) else if (target == GL_TEXTURE_1D_ARRAY)
target = GL_TEXTURE_2D_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, glTextureView(surf->id, target, res->id, internalformat,
0, res->base.last_level + 1, 0, res->base.last_level + 1,
first_layer, last_layer - first_layer + 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); 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 (vrend_state.use_gles) {
if (view->target == GL_TEXTURE_RECTANGLE_NV || if (view->target == GL_TEXTURE_1D)
view->target == GL_TEXTURE_1D)
view->target = GL_TEXTURE_2D; view->target = GL_TEXTURE_2D;
else if (view->target == GL_TEXTURE_1D_ARRAY) else if (view->target == GL_TEXTURE_1D_ARRAY)
view->target = GL_TEXTURE_2D_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->val0 = val0;
view->val1 = val1; 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++) { for (int i = 0; i < sub_ctx->views[type].num_views; i++) {
struct vrend_sampler_view *view = sub_ctx->views[type].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) { 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]) | 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[1]) << 3 |
to_pipe_swizzle(view->gl_swizzle[2]) << 6 | 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->target = tgsitargettogltarget(pr->target, pr->nr_samples);
gr->storage_bits |= VREND_STORAGE_GL_TEXTURE; gr->storage_bits |= VREND_STORAGE_GL_TEXTURE;
/* ugly workaround for texture rectangle missing on GLES */ /* ugly workaround for texture rectangle incompatibility */
if (vrend_state.use_gles && gr->target == GL_TEXTURE_RECTANGLE_NV) { 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 */ /* for some guests this is the only usage of rect */
if (pr->width0 != 1 || pr->height0 != 1) { 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; gr->target = GL_TEXTURE_2D;
} }
@ -9051,34 +9067,14 @@ static void vrend_resource_copy_fallback(struct vrend_resource *src_res,
glBindTexture(GL_TEXTURE_2D, 0); 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 static inline void
vrend_copy_sub_image(struct vrend_resource* src_res, struct vrend_resource * dst_res, 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 src_level, const struct pipe_box *src_box,
uint32_t dst_level, uint32_t dstx, uint32_t dsty, uint32_t dstz) uint32_t dst_level, uint32_t dstx, uint32_t dsty, uint32_t dstz)
{ {
glCopyImageSubData(src_res->id, src_res->target, src_level,
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,
src_box->x, src_box->y, src_box->z, 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, dstx, dsty, dstz,
src_box->width, src_box->height,src_box->depth); src_box->width, src_box->height,src_box->depth);
} }

@ -100,6 +100,7 @@ struct vrend_resource {
#define VIRGL_TEXTURE_NEED_SWIZZLE (1 << 0) #define VIRGL_TEXTURE_NEED_SWIZZLE (1 << 0)
#define VIRGL_TEXTURE_CAN_TEXTURE_STORAGE (1 << 1) #define VIRGL_TEXTURE_CAN_TEXTURE_STORAGE (1 << 1)
#define VIRGL_TEXTURE_CAN_READBACK (1 << 2) #define VIRGL_TEXTURE_CAN_READBACK (1 << 2)
#define VIRGL_TEXTURE_CAN_TARGET_RECTANGLE (1 << 3)
struct vrend_format_table { struct vrend_format_table {
enum virgl_formats format; enum virgl_formats format;

@ -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 */ /* We have to unnormalize the coordinate for all but the texel fetch instruction */
if (ctx->cfg->use_gles && if (inst->Instruction.Opcode != TGSI_OPCODE_TXF &&
inst->Instruction.Opcode != TGSI_OPCODE_TXF && vrend_shader_sampler_views_mask_get(ctx->key->sampler_views_emulated_rect_mask, sinfo->sreg_index)) {
(inst->Texture.Texture == TGSI_TEXTURE_RECT ||
inst->Texture.Texture == TGSI_TEXTURE_SHADOWRECT)) {
char buf[255]; char buf[255];
const char *new_srcs[4] = { buf, srcs[1], srcs[2], srcs[3] }; 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], tex_ext, srcs[sampler_index], get_string(txfi), srcs[0],
get_wm_string(twm), bias, offset); 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]; int16_t packed_swizzles = ctx->key->tex_swizzle[sinfo->sreg_index];
emit_buff(&ctx->glsl_strbufs, " val = vec4("); 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", emit_buff(&ctx->glsl_strbufs, " %s = val%s;\n}\n",
dst, dinfo->dst_override_no_wm[0] ? "" : writemask); 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 */ /* rect is special in GLSL 1.30 */
if (inst->Texture.Texture == TGSI_TEXTURE_RECT) if (inst->Texture.Texture == TGSI_TEXTURE_RECT)
emit_buff(&ctx->glsl_strbufs, "%s = texture2DRect(%s, %s.xy)%s;\n", emit_buff(&ctx->glsl_strbufs, "%s = texture2DRect(%s, %s.xy)%s;\n",

@ -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_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]; uint16_t tex_swizzle[PIPE_MAX_SHADER_SAMPLER_VIEWS];
uint8_t num_in_cull : 4; 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); 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 #endif

Loading…
Cancel
Save