virgl: implement EXT_multisampled_render_to_texture

Signed-off-by: Italo Nicola <italonicola@collabora.com>
Reviewed-by: Gert Wollny <gert.wollny@collabora.com>
macos/master
Italo Nicola 4 years ago committed by Gert Wollny
parent 62cc6ed6e5
commit 4405172812
  1. 1
      src/virgl_hw.h
  2. 5
      src/virgl_protocol.h
  3. 4
      src/vrend_blitter.c
  4. 3
      src/vrend_debug.c
  5. 30
      src/vrend_decode.c
  6. 109
      src/vrend_renderer.c
  7. 12
      src/vrend_renderer.h

@ -441,6 +441,7 @@ enum virgl_formats {
#define VIRGL_CAP_V2_MEMINFO (1 << 3) #define VIRGL_CAP_V2_MEMINFO (1 << 3)
#define VIRGL_CAP_V2_STRING_MARKER (1 << 4) #define VIRGL_CAP_V2_STRING_MARKER (1 << 4)
#define VIRGL_CAP_V2_DIFFERENT_GPU (1 << 5) #define VIRGL_CAP_V2_DIFFERENT_GPU (1 << 5)
#define VIRGL_CAP_V2_IMPLICIT_MSAA (1 << 6)
/* virgl bind flags - these are compatible with mesa 10.5 gallium. /* virgl bind flags - these are compatible with mesa 10.5 gallium.
* but are fixed, no other should be passed to virgl either. * but are fixed, no other should be passed to virgl either.

@ -57,6 +57,7 @@ enum virgl_object_type {
VIRGL_OBJECT_SURFACE, VIRGL_OBJECT_SURFACE,
VIRGL_OBJECT_QUERY, VIRGL_OBJECT_QUERY,
VIRGL_OBJECT_STREAMOUT_TARGET, VIRGL_OBJECT_STREAMOUT_TARGET,
VIRGL_OBJECT_MSAA_SURFACE,
VIRGL_MAX_OBJECTS, VIRGL_MAX_OBJECTS,
}; };
@ -345,6 +346,10 @@ enum virgl_context_cmd {
#define VIRGL_OBJ_SURFACE_TEXTURE_LEVEL 4 #define VIRGL_OBJ_SURFACE_TEXTURE_LEVEL 4
#define VIRGL_OBJ_SURFACE_TEXTURE_LAYERS 5 #define VIRGL_OBJ_SURFACE_TEXTURE_LAYERS 5
/* create surface with implicit MSAA support (for EXT_multisample_render_to_texture) */
#define VIRGL_OBJ_MSAA_SURFACE_SIZE (VIRGL_OBJ_SURFACE_SIZE + 1)
#define VIRGL_OBJ_SURFACE_SAMPLE_COUNT 6
/* create streamout target */ /* create streamout target */
#define VIRGL_OBJ_STREAMOUT_SIZE 4 #define VIRGL_OBJ_STREAMOUT_SIZE 4
#define VIRGL_OBJ_STREAMOUT_HANDLE 1 #define VIRGL_OBJ_STREAMOUT_HANDLE 1

@ -748,7 +748,7 @@ void vrend_renderer_blit_gl(MAYBE_UNUSED struct vrend_context *ctx,
glUseProgram(prog_id); glUseProgram(prog_id);
glBindFramebuffer(GL_FRAMEBUFFER, blit_ctx->fb_id); glBindFramebuffer(GL_FRAMEBUFFER, blit_ctx->fb_id);
vrend_fb_bind_texture_id(dst_res, blit_views[1], 0, info->dst.level, info->dst.box.z); vrend_fb_bind_texture_id(dst_res, blit_views[1], 0, info->dst.level, info->dst.box.z, 0);
buffers = GL_COLOR_ATTACHMENT0; buffers = GL_COLOR_ATTACHMENT0;
glDrawBuffers(1, &buffers); glDrawBuffers(1, &buffers);
@ -783,7 +783,7 @@ void vrend_renderer_blit_gl(MAYBE_UNUSED struct vrend_context *ctx,
uint32_t layer = (dst_res->target == GL_TEXTURE_CUBE_MAP) ? info->dst.box.z : dst_z; uint32_t layer = (dst_res->target == GL_TEXTURE_CUBE_MAP) ? info->dst.box.z : dst_z;
glBindFramebuffer(GL_FRAMEBUFFER, blit_ctx->fb_id); glBindFramebuffer(GL_FRAMEBUFFER, blit_ctx->fb_id);
vrend_fb_bind_texture_id(dst_res, blit_views[1], 0, info->dst.level, layer); vrend_fb_bind_texture_id(dst_res, blit_views[1], 0, info->dst.level, layer, 0);
buffers = GL_COLOR_ATTACHMENT0; buffers = GL_COLOR_ATTACHMENT0;
glDrawBuffers(1, &buffers); glDrawBuffers(1, &buffers);

@ -94,7 +94,8 @@ static const char *object_type_names[VIRGL_MAX_OBJECTS] = {
"SAMPLER_STATE", "SAMPLER_STATE",
"SURFACE", "SURFACE",
"QUERY", "QUERY",
"STREAMOUT_TARGET" "STREAMOUT_TARGET",
"MSAA_SURFACE"
}; };
const char *vrend_get_comand_name(enum virgl_context_cmd cmd) const char *vrend_get_comand_name(enum virgl_context_cmd cmd)

@ -612,21 +612,34 @@ static int vrend_decode_create_rasterizer(struct vrend_context *ctx, const uint3
return 0; return 0;
} }
static int vrend_decode_create_surface(struct vrend_context *ctx, const uint32_t *buf, uint32_t handle, uint16_t length) static int vrend_decode_create_surface_common(struct vrend_context *ctx, const uint32_t *buf, uint32_t handle, uint32_t sample_count)
{ {
uint32_t res_handle, format, val0, val1; uint32_t res_handle, format, val0, val1;
int ret;
if (length != VIRGL_OBJ_SURFACE_SIZE)
return EINVAL;
res_handle = get_buf_entry(buf, VIRGL_OBJ_SURFACE_RES_HANDLE); res_handle = get_buf_entry(buf, VIRGL_OBJ_SURFACE_RES_HANDLE);
format = get_buf_entry(buf, VIRGL_OBJ_SURFACE_FORMAT); format = get_buf_entry(buf, VIRGL_OBJ_SURFACE_FORMAT);
/* decide later if these are texture or buffer */ /* decide later if these are texture or buffer */
val0 = get_buf_entry(buf, VIRGL_OBJ_SURFACE_BUFFER_FIRST_ELEMENT); val0 = get_buf_entry(buf, VIRGL_OBJ_SURFACE_BUFFER_FIRST_ELEMENT);
val1 = get_buf_entry(buf, VIRGL_OBJ_SURFACE_BUFFER_LAST_ELEMENT); val1 = get_buf_entry(buf, VIRGL_OBJ_SURFACE_BUFFER_LAST_ELEMENT);
ret = vrend_create_surface(ctx, handle, res_handle, format, val0, val1);
return ret; return vrend_create_surface(ctx, handle, res_handle, format, val0, val1, sample_count);
}
static int vrend_decode_create_surface(struct vrend_context *ctx, const uint32_t *buf, uint32_t handle, uint16_t length)
{
if (length != VIRGL_OBJ_SURFACE_SIZE)
return EINVAL;
return vrend_decode_create_surface_common(ctx, buf, handle, 0);
}
static int vrend_decode_create_msaa_surface(struct vrend_context *ctx, const uint32_t *buf, uint32_t handle, uint16_t length)
{
if (length != VIRGL_OBJ_MSAA_SURFACE_SIZE)
return EINVAL;
uint32_t sample_count = get_buf_entry(buf, VIRGL_OBJ_SURFACE_SAMPLE_COUNT);
return vrend_decode_create_surface_common(ctx, buf, handle, sample_count);
} }
static int vrend_decode_create_sampler_view(struct vrend_context *ctx, const uint32_t *buf, uint32_t handle, uint16_t length) static int vrend_decode_create_sampler_view(struct vrend_context *ctx, const uint32_t *buf, uint32_t handle, uint16_t length)
@ -789,6 +802,9 @@ static int vrend_decode_create_object(struct vrend_context *ctx, const uint32_t
case VIRGL_OBJECT_STREAMOUT_TARGET: case VIRGL_OBJECT_STREAMOUT_TARGET:
ret = vrend_decode_create_stream_output_target(ctx, buf, handle, length); ret = vrend_decode_create_stream_output_target(ctx, buf, handle, length);
break; break;
case VIRGL_OBJECT_MSAA_SURFACE:
ret = vrend_decode_create_msaa_surface(ctx, buf, handle, length);
break;
default: default:
return EINVAL; return EINVAL;
} }

@ -202,6 +202,7 @@ enum features_id
feat_txqs, feat_txqs,
feat_ubo, feat_ubo,
feat_viewport_array, feat_viewport_array,
feat_implicit_msaa,
feat_last, feat_last,
}; };
@ -302,6 +303,7 @@ static const struct {
FEAT(txqs, 45, UNAVAIL, "GL_ARB_shader_texture_image_samples" ), FEAT(txqs, 45, UNAVAIL, "GL_ARB_shader_texture_image_samples" ),
FEAT(ubo, 31, 30, "GL_ARB_uniform_buffer_object" ), FEAT(ubo, 31, 30, "GL_ARB_uniform_buffer_object" ),
FEAT(viewport_array, 41, UNAVAIL, "GL_ARB_viewport_array", "GL_OES_viewport_array"), FEAT(viewport_array, 41, UNAVAIL, "GL_ARB_viewport_array", "GL_OES_viewport_array"),
FEAT(implicit_msaa, UNAVAIL, UNAVAIL, "GL_EXT_multisampled_render_to_texture"),
}; };
struct global_renderer_state { struct global_renderer_state {
@ -451,6 +453,7 @@ struct vrend_surface {
GLuint res_handle; GLuint res_handle;
GLuint format; GLuint format;
GLuint val0, val1; GLuint val0, val1;
GLuint nr_samples;
struct vrend_resource *texture; struct vrend_resource *texture;
}; };
@ -959,25 +962,27 @@ static void __report_core_warn(const char *fname, struct vrend_context *ctx,
#define GLES_WARN_DEPTH_CLEAR 14 #define GLES_WARN_DEPTH_CLEAR 14
#define GLES_WARN_LOGIC_OP 15 #define GLES_WARN_LOGIC_OP 15
#define GLES_WARN_TIMESTAMP 16 #define GLES_WARN_TIMESTAMP 16
#define GLES_WARN_IMPLICIT_MSAA_SURFACE 17
MAYBE_UNUSED MAYBE_UNUSED
static const char *vrend_gles_warn_strings[] = { static const char *vrend_gles_warn_strings[] = {
[GLES_WARN_NONE] = "None", [GLES_WARN_NONE] = "None",
[GLES_WARN_STIPPLE] = "Stipple", [GLES_WARN_STIPPLE] = "Stipple",
[GLES_WARN_POLYGON_MODE] = "Polygon Mode", [GLES_WARN_POLYGON_MODE] = "Polygon Mode",
[GLES_WARN_DEPTH_RANGE] = "Depth Range", [GLES_WARN_DEPTH_RANGE] = "Depth Range",
[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_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",
[GLES_WARN_LINE_SMOOTH] = "Line Smooth", [GLES_WARN_LINE_SMOOTH] = "Line Smooth",
[GLES_WARN_POLY_SMOOTH] = "Poly Smooth", [GLES_WARN_POLY_SMOOTH] = "Poly Smooth",
[GLES_WARN_DEPTH_CLEAR] = "Depth Clear", [GLES_WARN_DEPTH_CLEAR] = "Depth Clear",
[GLES_WARN_LOGIC_OP] = "LogicOp", [GLES_WARN_LOGIC_OP] = "LogicOp",
[GLES_WARN_TIMESTAMP] = "GL_TIMESTAMP", [GLES_WARN_TIMESTAMP] = "GL_TIMESTAMP",
[GLES_WARN_IMPLICIT_MSAA_SURFACE] = "Implicit MSAA Surface",
}; };
static void __report_gles_warn(MAYBE_UNUSED const char *fname, static void __report_gles_warn(MAYBE_UNUSED const char *fname,
@ -1849,7 +1854,8 @@ void vrend_sync_make_current(virgl_gl_context gl_cxt) {
int vrend_create_surface(struct vrend_context *ctx, int vrend_create_surface(struct vrend_context *ctx,
uint32_t handle, uint32_t handle,
uint32_t res_handle, uint32_t format, uint32_t res_handle, uint32_t format,
uint32_t val0, uint32_t val1) uint32_t val0, uint32_t val1,
uint32_t nr_samples)
{ {
struct vrend_surface *surf; struct vrend_surface *surf;
struct vrend_resource *res; struct vrend_resource *res;
@ -1876,6 +1882,7 @@ int vrend_create_surface(struct vrend_context *ctx,
surf->val0 = val0; surf->val0 = val0;
surf->val1 = val1; surf->val1 = val1;
surf->id = res->id; surf->id = res->id;
surf->nr_samples = nr_samples;
if (!has_bit(res->storage_bits, VREND_STORAGE_GL_BUFFER) && if (!has_bit(res->storage_bits, VREND_STORAGE_GL_BUFFER) &&
has_bit(res->storage_bits, VREND_STORAGE_GL_IMMUTABLE)) { has_bit(res->storage_bits, VREND_STORAGE_GL_IMMUTABLE)) {
@ -2305,6 +2312,41 @@ int vrend_create_sampler_view(struct vrend_context *ctx,
return 0; return 0;
} }
static void vrend_framebuffer_texture_2d(struct vrend_resource *res,
GLenum target, GLenum attachment,
GLenum textarget, uint32_t texture,
int32_t level, uint32_t samples)
{
assert(textarget == GL_TEXTURE_2D);
if (samples == 0) {
glFramebufferTexture2D(target, attachment, textarget, texture, level);
} else if (!has_feature(feat_implicit_msaa)) {
/* fallback to non-msaa */
report_gles_warn(vrend_state.current_ctx, GLES_WARN_IMPLICIT_MSAA_SURFACE);
glFramebufferTexture2D(target, attachment, textarget, texture, level);
} else if (attachment == GL_COLOR_ATTACHMENT0){
glFramebufferTexture2DMultisampleEXT(target, attachment, textarget,
texture, level, samples);
} else if (attachment == GL_STENCIL_ATTACHMENT || attachment == GL_DEPTH_ATTACHMENT) {
GLenum internalformat =
attachment == GL_STENCIL_ATTACHMENT ? GL_STENCIL_INDEX8 : GL_DEPTH_COMPONENT16;
glGenRenderbuffers(1, &res->rbo_id);
glBindRenderbuffer(GL_RENDERBUFFER, res->rbo_id);
glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, samples,
internalformat, res->base.width0,
res->base.height0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachment,
GL_RENDERBUFFER, res->rbo_id);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
} else {
/* unsupported attachment for EXT_multisampled_render_to_texture, fallback to non-msaa */
report_gles_warn(vrend_state.current_ctx, GLES_WARN_IMPLICIT_MSAA_SURFACE);
glFramebufferTexture2D(target, attachment, textarget, texture, level);
}
}
static static
void debug_texture(MAYBE_UNUSED const char *f, const struct vrend_resource *gt) void debug_texture(MAYBE_UNUSED const char *f, const struct vrend_resource *gt)
{ {
@ -2333,9 +2375,8 @@ void debug_texture(MAYBE_UNUSED const char *f, const struct vrend_resource *gt)
} }
void vrend_fb_bind_texture_id(struct vrend_resource *res, void vrend_fb_bind_texture_id(struct vrend_resource *res,
int id, int id, int idx, uint32_t level,
int idx, uint32_t layer, uint32_t samples)
uint32_t level, uint32_t layer)
{ {
const struct util_format_description *desc = util_format_description(res->base.format); const struct util_format_description *desc = util_format_description(res->base.format);
GLenum attachment = GL_COLOR_ATTACHMENT0 + idx; GLenum attachment = GL_COLOR_ATTACHMENT0 + idx;
@ -2380,8 +2421,9 @@ void vrend_fb_bind_texture_id(struct vrend_resource *res,
glFramebufferTexture(GL_FRAMEBUFFER, attachment, glFramebufferTexture(GL_FRAMEBUFFER, attachment,
id, level); id, level);
else else
glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, vrend_framebuffer_texture_2d(res, GL_FRAMEBUFFER, attachment,
GL_TEXTURE_CUBE_MAP_POSITIVE_X + layer, id, level); GL_TEXTURE_CUBE_MAP_POSITIVE_X + layer,
id, level, samples);
break; break;
case GL_TEXTURE_1D: case GL_TEXTURE_1D:
glFramebufferTexture1D(GL_FRAMEBUFFER, attachment, glFramebufferTexture1D(GL_FRAMEBUFFER, attachment,
@ -2389,8 +2431,8 @@ void vrend_fb_bind_texture_id(struct vrend_resource *res,
break; break;
case GL_TEXTURE_2D: case GL_TEXTURE_2D:
default: default:
glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, vrend_framebuffer_texture_2d(res, GL_FRAMEBUFFER, attachment,
res->target, id, level); res->target, id, level, samples);
break; break;
} }
@ -2413,7 +2455,7 @@ void vrend_fb_bind_texture(struct vrend_resource *res,
int idx, int idx,
uint32_t level, uint32_t layer) uint32_t level, uint32_t layer)
{ {
vrend_fb_bind_texture_id(res, res->id, idx, level, layer); vrend_fb_bind_texture_id(res, res->id, idx, level, layer, 0);
} }
static void vrend_hw_set_zsurf_texture(struct vrend_context *ctx) static void vrend_hw_set_zsurf_texture(struct vrend_context *ctx)
@ -2431,7 +2473,8 @@ static void vrend_hw_set_zsurf_texture(struct vrend_context *ctx)
return; return;
vrend_fb_bind_texture_id(surf->texture, surf->id, 0, surf->val0, vrend_fb_bind_texture_id(surf->texture, surf->id, 0, surf->val0,
first_layer != last_layer ? 0xffffffff : first_layer); first_layer != last_layer ? 0xffffffff : first_layer,
surf->nr_samples);
} }
} }
@ -2449,7 +2492,8 @@ static void vrend_hw_set_color_surface(struct vrend_sub_context *sub_ctx, int in
uint32_t last_layer = (sub_ctx->surf[index]->val1 >> 16) & 0xffff; uint32_t last_layer = (sub_ctx->surf[index]->val1 >> 16) & 0xffff;
vrend_fb_bind_texture_id(surf->texture, surf->id, index, surf->val0, vrend_fb_bind_texture_id(surf->texture, surf->id, index, surf->val0,
first_layer != last_layer ? 0xffffffff : first_layer); first_layer != last_layer ? 0xffffffff : first_layer,
surf->nr_samples);
} }
} }
@ -7193,6 +7237,10 @@ void vrend_renderer_resource_destroy(struct vrend_resource *res)
free(res->ptr); free(res->ptr);
} }
if (res->rbo_id) {
glDeleteRenderbuffers(1, &res->rbo_id);
}
if (has_bit(res->storage_bits, VREND_STORAGE_GL_MEMOBJ)) { if (has_bit(res->storage_bits, VREND_STORAGE_GL_MEMOBJ)) {
glDeleteMemoryObjectsEXT(1, &res->memobj); glDeleteMemoryObjectsEXT(1, &res->memobj);
} }
@ -9057,7 +9105,7 @@ static void vrend_renderer_blit_int(struct vrend_context *ctx,
n_layers = info->dst.box.depth; n_layers = info->dst.box.depth;
for (i = 0; i < n_layers; i++) { for (i = 0; i < n_layers; i++) {
glBindFramebuffer(GL_FRAMEBUFFER, ctx->sub->blit_fb_ids[0]); glBindFramebuffer(GL_FRAMEBUFFER, ctx->sub->blit_fb_ids[0]);
vrend_fb_bind_texture_id(src_res, blitter_views[0], 0, info->src.level, info->src.box.z + i); vrend_fb_bind_texture_id(src_res, blitter_views[0], 0, info->src.level, info->src.box.z + i, 0);
if (make_intermediate_copy) { if (make_intermediate_copy) {
int level_width = u_minify(src_res->base.width0, info->src.level); int level_width = u_minify(src_res->base.width0, info->src.level);
@ -9075,7 +9123,7 @@ static void vrend_renderer_blit_int(struct vrend_context *ctx,
} }
glBindFramebuffer(GL_FRAMEBUFFER, ctx->sub->blit_fb_ids[1]); glBindFramebuffer(GL_FRAMEBUFFER, ctx->sub->blit_fb_ids[1]);
vrend_fb_bind_texture_id(dst_res, blitter_views[1], 0, info->dst.level, info->dst.box.z + i); vrend_fb_bind_texture_id(dst_res, blitter_views[1], 0, info->dst.level, info->dst.box.z + i, 0);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, ctx->sub->blit_fb_ids[1]); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, ctx->sub->blit_fb_ids[1]);
if (has_feature(feat_srgb_write_control)) { if (has_feature(feat_srgb_write_control)) {
@ -10483,6 +10531,9 @@ static void vrend_renderer_fill_caps_v2(int gl_ver, int gles_ver, union virgl_c
if (has_feature(feat_khr_debug)) if (has_feature(feat_khr_debug))
caps->v2.capability_bits_v2 |= VIRGL_CAP_V2_STRING_MARKER; caps->v2.capability_bits_v2 |= VIRGL_CAP_V2_STRING_MARKER;
if (has_feature(feat_implicit_msaa))
caps->v2.capability_bits_v2 |= VIRGL_CAP_V2_IMPLICIT_MSAA;
if (vrend_winsys_different_gpu()) if (vrend_winsys_different_gpu())
caps->v2.capability_bits_v2 |= VIRGL_CAP_V2_DIFFERENT_GPU; caps->v2.capability_bits_v2 |= VIRGL_CAP_V2_DIFFERENT_GPU;
} }

@ -74,6 +74,10 @@ struct vrend_resource {
GLuint tbo_tex_id;/* tbos have two ids to track */ GLuint tbo_tex_id;/* tbos have two ids to track */
bool y_0_top; bool y_0_top;
/* used for keeping track of multisampled renderbuffer for
* GL_EXT_multisampled_render_to_texture. */
GLuint rbo_id;
/* Pointer to system memory storage for this resource. Only valid for /* Pointer to system memory storage for this resource. Only valid for
* VREND_RESOURCE_STORAGE_GUEST_ELSE_SYSTEM buffer storage. * VREND_RESOURCE_STORAGE_GUEST_ELSE_SYSTEM buffer storage.
*/ */
@ -204,7 +208,8 @@ vrend_renderer_resource_create(const struct vrend_renderer_resource_create_args
int vrend_create_surface(struct vrend_context *ctx, int vrend_create_surface(struct vrend_context *ctx,
uint32_t handle, uint32_t handle,
uint32_t res_handle, uint32_t format, uint32_t res_handle, uint32_t format,
uint32_t val0, uint32_t val1); uint32_t val0, uint32_t val1,
uint32_t nr_samples);
int vrend_create_sampler_view(struct vrend_context *ctx, int vrend_create_sampler_view(struct vrend_context *ctx,
uint32_t handle, uint32_t handle,
uint32_t res_handle, uint32_t format, uint32_t res_handle, uint32_t format,
@ -347,9 +352,8 @@ void vrend_set_uniform_buffer(struct vrend_context *ctx, uint32_t shader,
uint32_t res_handle); uint32_t res_handle);
void vrend_fb_bind_texture_id(struct vrend_resource *res, void vrend_fb_bind_texture_id(struct vrend_resource *res,
int id, int id, int idx, uint32_t level,
int idx, uint32_t layer, uint32_t samples);
uint32_t level, uint32_t layer);
void vrend_set_tess_state(struct vrend_context *ctx, const float tess_factors[6]); void vrend_set_tess_state(struct vrend_context *ctx, const float tess_factors[6]);

Loading…
Cancel
Save