diff --git a/src/vrend_renderer.c b/src/vrend_renderer.c index 285be7ac1a89384953578634124455f7c8890a6f..cdeec2524a98dab89aacb000c6506e494a6393d9 100644 --- a/src/vrend_renderer.c +++ b/src/vrend_renderer.c @@ -143,6 +143,7 @@ enum features_id feat_cull_distance, feat_debug_cb, feat_depth_clamp, + feat_direct_state_access, feat_draw_instance, feat_dual_src_blend, feat_egl_image_external, @@ -247,6 +248,7 @@ static const struct { FEAT(draw_instance, 31, 30, "GL_ARB_draw_instanced" ), FEAT(dual_src_blend, 33, UNAVAIL, "GL_ARB_blend_func_extended", "GL_EXT_blend_func_extended" ), FEAT(depth_clamp, 32, UNAVAIL, "GL_ARB_depth_clamp", "GL_EXT_depth_clamp", "GL_NV_depth_clamp"), + FEAT(direct_state_access, 45, UNAVAIL, "GL_ARB_direct_state_access"), FEAT(enhanced_layouts, 44, UNAVAIL, "GL_ARB_enhanced_layouts"), FEAT(egl_image_external, UNAVAIL, UNAVAIL, "GL_OES_EGL_image_external"), FEAT(egl_image_storage, UNAVAIL, UNAVAIL, "GL_EXT_EGL_image_storage"), @@ -313,6 +315,27 @@ static const struct { FEAT(anisotropic_filter, 46, UNAVAIL, "GL_EXT_texture_filter_anisotropic", "GL_ARB_texture_filter_anisotropic"), }; +typedef void (*buffers_generate_f)(GLsizei n, GLuint *buffers); +typedef void (*buffer_allocate_data_f)(GLuint, GLsizeiptr size, GLbitfield flags); +typedef void (*buffer_sub_data_f)(GLuint bufid, GLintptr offset, GLsizeiptr size, const void *data); +typedef void (*buffer_storage_mem_f)(GLuint, GLsizeiptr size, unsigned memory, uint64_t offset); + +typedef void * (*buffer_map_range_f)(GLuint bufid, GLintptr offset, + GLsizeiptr length, GLbitfield access); +typedef GLboolean (*buffer_unmap_f)(GLuint bufid); + +struct buffer_interface { + buffers_generate_f generate; + buffer_allocate_data_f allocate; + buffer_sub_data_f sub_data; + buffer_storage_mem_f storage_mem; + buffer_map_range_f map_range; + buffer_map_range_f bind_if_needed_and_map_range; + buffer_unmap_f unmap; + buffer_unmap_f unmap_and_unbind; +}; + + struct global_renderer_state { struct vrend_context *ctx0; struct vrend_context *current_ctx; @@ -323,6 +346,8 @@ struct global_renderer_state { struct list_head fence_wait_list; struct vrend_fence *fence_waiting; + + int gl_major_ver; int gl_minor_ver; @@ -379,6 +404,8 @@ struct sysval_uniform_block { }; static struct global_renderer_state vrend_state; +static struct buffer_interface gl_buf; + static inline bool has_feature(enum features_id feature_id) { @@ -433,6 +460,7 @@ struct vrend_linked_shader_program { GLuint separate_virgl_block_id[PIPE_SHADER_TYPES]; GLint virgl_block_bind; + uint32_t sysvalue_data_cookie; GLint ubo_sysval_buffer_id; uint32_t images_used_mask[PIPE_SHADER_TYPES]; @@ -738,7 +766,8 @@ struct vrend_sub_context { int prim_mode; bool drawing; struct vrend_context *parent; - GLuint stipple_pattern[VREND_POLYGON_STIPPLE_SIZE]; + struct sysval_uniform_block sysvalue_data; + uint32_t sysvalue_data_cookie; }; struct vrend_untyped_resource { @@ -1634,8 +1663,8 @@ static void bind_virgl_block_loc(struct vrend_linked_shader_program *sprog, if (sprog->virgl_block_bind == -1) { sprog->virgl_block_bind = virgl_block_ubo_id; if (sprog->ubo_sysval_buffer_id == -1) { - glGenBuffers(1, (GLuint *) &sprog->ubo_sysval_buffer_id); - created_virgl_block_buffer = true; + gl_buf.generate(1, (GLuint *) &sprog->ubo_sysval_buffer_id); + created_virgl_block_buffer = true; } } @@ -1651,11 +1680,9 @@ static void bind_virgl_block_loc(struct vrend_linked_shader_program *sprog, GL_UNIFORM_BLOCK_DATA_SIZE, &virgl_block_size); assert((size_t) virgl_block_size >= sizeof(struct sysval_uniform_block)); - if (created_virgl_block_buffer) { - glBindBuffer(GL_UNIFORM_BUFFER, sprog->ubo_sysval_buffer_id); - glBufferData(GL_UNIFORM_BUFFER, virgl_block_size, NULL, GL_DYNAMIC_DRAW); - glBindBuffer(GL_UNIFORM_BUFFER, 0); - } + if (created_virgl_block_buffer) + gl_buf.allocate(sprog->ubo_sysval_buffer_id, + sizeof(struct sysval_uniform_block), 0); } } @@ -3121,8 +3148,12 @@ void vrend_set_viewport_states(struct vrend_context *ctx, } if (idx == 0) { - if (ctx->sub->viewport_is_negative != viewport_is_negative) + if (ctx->sub->viewport_is_negative != viewport_is_negative) { ctx->sub->viewport_is_negative = viewport_is_negative; + ctx->sub->sysvalue_data.winsys_adjust_y = + viewport_is_negative ? -1.f : 1.f; + ctx->sub->sysvalue_data_cookie++; + } } } } @@ -4612,7 +4643,8 @@ static void vrend_draw_bind_vertex_legacy(struct vrend_context *ctx, if (vbo->base.stride == 0) { void *data; /* for 0 stride we are kinda screwed */ - data = glMapBufferRange(GL_ARRAY_BUFFER, vbo->base.buffer_offset, ve->nr_chan * sizeof(GLfloat), GL_MAP_READ_BIT); + data = gl_buf.bind_if_needed_and_map_range(res->id, vbo->base.buffer_offset, + ve->nr_chan * sizeof(GLfloat), GL_MAP_READ_BIT); switch (ve->nr_chan) { case 1: @@ -4628,7 +4660,7 @@ static void vrend_draw_bind_vertex_legacy(struct vrend_context *ctx, glVertexAttrib4fv(loc, data); break; } - glUnmapBuffer(GL_ARRAY_BUFFER); + gl_buf.unmap_and_unbind(res->id); disable_bitmask |= (1 << loc); } else { GLint size = !vrend_state.use_gles && (va->zyxw_bitmask & (1 << i)) ? GL_BGRA : ve->nr_chan; @@ -4967,37 +4999,14 @@ static void vrend_fill_sysval_uniform_block (struct vrend_sub_context *sub_ctx) { if (sub_ctx->prog->virgl_block_bind == -1) - return; - - struct sysval_uniform_block virgl_uniform_block; - memset(&virgl_uniform_block, 0, sizeof(struct sysval_uniform_block)); - - if (vrend_state.use_core_profile) { - virgl_uniform_block.alpha_ref_val = sub_ctx->dsa_state.alpha.ref_value; + return; - /* std140 aligns array elements at 16 byte */ - for (int i = 0; i < VREND_POLYGON_STIPPLE_SIZE ; ++i) - virgl_uniform_block.stipple_pattern[i][0] = sub_ctx->stipple_pattern[i]; + if (sub_ctx->sysvalue_data_cookie != sub_ctx->prog->sysvalue_data_cookie) { + gl_buf.sub_data(sub_ctx->prog->ubo_sysval_buffer_id, 0, + sizeof(struct sysval_uniform_block), + &sub_ctx->sysvalue_data); + sub_ctx->prog->sysvalue_data_cookie = sub_ctx->sysvalue_data_cookie; } - - virgl_uniform_block.winsys_adjust_y = sub_ctx->viewport_is_negative ? -1.f : 1.f; - - if (has_feature(feat_cull_distance)) { - if (sub_ctx->rs_state.clip_plane_enable) { - virgl_uniform_block.clip_plane_enabled = 1.f; - for (int i = 0 ; i < VIRGL_NUM_CLIP_PLANES; i++) { - memcpy(&virgl_uniform_block.clipp[i], - (const GLfloat *) &sub_ctx->ucp_state.ucp[i], sizeof(GLfloat) * 4); - } - } else { - virgl_uniform_block.clip_plane_enabled = 0.f; - } - } - - glBindBuffer(GL_UNIFORM_BUFFER, sub_ctx->prog->ubo_sysval_buffer_id); - glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(struct sysval_uniform_block), - &virgl_uniform_block); - glBindBuffer(GL_UNIFORM_BUFFER, 0); } static void vrend_draw_bind_objects(struct vrend_sub_context *sub_ctx, bool new_program) @@ -6042,6 +6051,11 @@ void vrend_object_bind_dsa(struct vrend_context *ctx, ctx->sub->dsa_state = *state; ctx->sub->dsa = state; + if (ctx->sub->sysvalue_data.alpha_ref_val != state->alpha.ref_value) { + ctx->sub->sysvalue_data.alpha_ref_val = state->alpha.ref_value; + ctx->sub->sysvalue_data_cookie++; + } + vrend_hw_emit_dsa(ctx); } @@ -6290,6 +6304,13 @@ static void vrend_hw_emit_rs(struct vrend_context *ctx) else glDisable(GL_CLIP_PLANE0 + i); } + + ctx->sub->sysvalue_data_cookie++; + if (ctx->sub->rs_state.clip_plane_enable) { + ctx->sub->sysvalue_data.clip_plane_enabled = 1.f; + } else { + ctx->sub->sysvalue_data.clip_plane_enabled = 0.f; + } } if (vrend_state.use_core_profile == false) { glLineStipple(state->line_stipple_factor, state->line_stipple_pattern); @@ -6948,6 +6969,131 @@ static bool use_integer() { return false; } +static void +buffer_data(GLuint bufid, GLsizeiptr size, GLbitfield flags) +{ + if (flags == 0) + flags = GL_DYNAMIC_DRAW; + + glBindBuffer(GL_COPY_WRITE_BUFFER, bufid); + glBufferData(GL_COPY_WRITE_BUFFER, size, NULL, flags); + glBindBuffer(GL_COPY_WRITE_BUFFER, 0); +} + +static void +buffer_sub_data(GLuint bufid, GLintptr offset, GLsizeiptr size, const void *data) +{ + glBindBuffer(GL_COPY_WRITE_BUFFER, bufid); + glBufferSubData(GL_COPY_WRITE_BUFFER, offset, size, data); + glBindBuffer(GL_COPY_WRITE_BUFFER, 0); +} + +static void +buffer_storage(GLuint bufid, GLsizeiptr size, GLbitfield flags) +{ + if (flags == 0) + flags = GL_DYNAMIC_DRAW; + + glBindBuffer(GL_COPY_WRITE_BUFFER, bufid); + glBufferStorage(GL_COPY_WRITE_BUFFER, size, NULL, flags); + glBindBuffer(GL_COPY_WRITE_BUFFER, 0); +} + +static void +buffer_named_allocate(GLuint bufid, GLsizeiptr size, GLbitfield flags) +{ + if (flags == 0) + flags = GL_DYNAMIC_STORAGE_BIT | GL_MAP_WRITE_BIT | GL_MAP_READ_BIT; + + glNamedBufferStorage(bufid, size, NULL, flags); +} + +static void +buffer_storage_mem_buffer_storage(GLuint bufid, GLsizeiptr size, + GLuint memory, GLuint64 offset) +{ + glBindBuffer(GL_COPY_WRITE_BUFFER, bufid); + glBufferStorageMemEXT(GL_COPY_WRITE_BUFFER, size, memory, offset); + glBindBuffer(GL_COPY_WRITE_BUFFER, 0); +} + +static void * +buffer_map_range(GLuint bufid, GLintptr offset, + GLsizeiptr length, GLbitfield access) +{ + glBindBuffer(GL_COPY_WRITE_BUFFER, bufid); + void *retval = glMapBufferRange(GL_COPY_WRITE_BUFFER, offset, length, access); + glBindBuffer(GL_COPY_WRITE_BUFFER, 0); + return retval; +} + +static void * +buffer_bind_if_needed_and_map_range(GLuint bufid, GLintptr offset, + GLsizeiptr length, GLbitfield access) +{ + glBindBuffer(GL_COPY_WRITE_BUFFER, bufid); + return glMapBufferRange(GL_COPY_WRITE_BUFFER, offset, length, access); +} + +static GLboolean +buffer_unmap(GLuint bufid) +{ + glBindBuffer(GL_COPY_WRITE_BUFFER, bufid); + GLboolean ret = glUnmapBuffer(GL_COPY_WRITE_BUFFER); + glBindBuffer(GL_COPY_WRITE_BUFFER, 0); + return ret; +} + +static GLboolean +buffer_unmap_bound(GLuint bufid) +{ + (void)bufid; + GLboolean ret = glUnmapBuffer(GL_COPY_WRITE_BUFFER); + glBindBuffer(GL_COPY_WRITE_BUFFER, 0); + return ret; +} + +static void +buffer_storage_mem_not_supported(GLuint bufid, GLsizeiptr size, + GLuint memory, GLuint64 offset) +{ + (void)bufid; + (void)size; + (void)memory; + (void)offset; + vrend_report_context_error(vrend_state.current_ctx, VIRGL_ERROR_CTX_UNSUPPORTED_FUNCTION, bufid); +} + +static void +initialize_buffer_interface(void) +{ + memset(&gl_buf, 0, sizeof(gl_buf)); + gl_buf.generate = glGenBuffers; + gl_buf.sub_data = buffer_sub_data; + gl_buf.allocate = buffer_data; + gl_buf.storage_mem = buffer_storage_mem_not_supported; + gl_buf.map_range = buffer_map_range; + gl_buf.bind_if_needed_and_map_range = buffer_bind_if_needed_and_map_range; + gl_buf.unmap = buffer_unmap; + gl_buf.unmap_and_unbind = buffer_unmap_bound; + + if (has_feature(feat_direct_state_access)) { + gl_buf.generate = glCreateBuffers; + gl_buf.allocate = buffer_named_allocate; + gl_buf.sub_data = glNamedBufferSubData; + gl_buf.map_range = glMapNamedBufferRange; + gl_buf.bind_if_needed_and_map_range = glMapNamedBufferRange; + gl_buf.unmap = glUnmapNamedBuffer; + gl_buf.unmap_and_unbind = glUnmapNamedBuffer; + if (has_feature(feat_memory_object) || has_feature(feat_memory_object_fd)) + gl_buf.storage_mem = glNamedBufferStorageMemEXT; + } else if (has_feature(feat_arb_buffer_storage)) { + gl_buf.allocate = buffer_storage; + if (has_feature(feat_memory_object) || has_feature(feat_memory_object_fd)) + gl_buf.storage_mem = buffer_storage_mem_buffer_storage; + } +} + int vrend_renderer_init(const struct vrend_if_cbs *cbs, uint32_t flags) { bool gles; @@ -7005,6 +7151,8 @@ int vrend_renderer_init(const struct vrend_if_cbs *cbs, uint32_t flags) vrend_printf( "gl_version %d - compat profile\n", gl_ver); } + initialize_buffer_interface(); + vrend_state.use_integer = use_integer(); init_features(gles ? 0 : gl_ver, @@ -7069,6 +7217,7 @@ int vrend_renderer_init(const struct vrend_if_cbs *cbs, uint32_t flags) /* create 0 context */ vrend_state.ctx0 = vrend_create_context(0, strlen("HOST"), "HOST"); + vrend_state.eventfd = -1; if (flags & VREND_USE_THREAD_SYNC) { if (flags & VREND_USE_ASYNC_FENCE_CB) @@ -7547,12 +7696,12 @@ static void vrend_create_buffer(struct vrend_resource *gr, uint32_t width, uint3 buffer_storage_flags |= GL_MAP_COHERENT_BIT; gr->storage_bits |= VREND_STORAGE_GL_BUFFER; - glGenBuffersARB(1, &gr->id); - glBindBufferARB(gr->target, gr->id); + gl_buf.generate(1, &gr->id); + if (buffer_storage_flags) { if (has_feature(feat_arb_buffer_storage) && !vrend_state.use_external_blob) { - glBufferStorage(gr->target, width, NULL, buffer_storage_flags); + gl_buf.allocate(gr->id, width, buffer_storage_flags); gr->map_info = vrend_state.inferred_gl_caching_type; } #ifdef ENABLE_MINIGBM_ALLOCATION @@ -7577,7 +7726,7 @@ static void vrend_create_buffer(struct vrend_resource *gr, uint32_t width, uint3 glCreateMemoryObjectsEXT(1, &memobj); glImportMemoryFdEXT(memobj, width, GL_HANDLE_TYPE_OPAQUE_FD_EXT, fd); - glBufferStorageMemEXT(gr->target, width, memobj, 0); + gl_buf.storage_mem(gr->id, width, memobj, 0); gr->gbm_bo = bo; gr->memobj = memobj; gr->storage_bits |= VREND_STORAGE_GBM_BUFFER | VREND_STORAGE_GL_MEMOBJ; @@ -7597,9 +7746,7 @@ static void vrend_create_buffer(struct vrend_resource *gr, uint32_t width, uint3 gr->buffer_storage_flags = buffer_storage_flags; gr->size = width; } else - glBufferData(gr->target, width, NULL, GL_STREAM_DRAW); - - glBindBufferARB(gr->target, 0); + gl_buf.allocate(gr->id, width, 0); } static int @@ -8315,16 +8462,14 @@ static int vrend_renderer_transfer_write_iov(struct vrend_context *ctx, if (!info->synchronized) map_flags |= GL_MAP_UNSYNCHRONIZED_BIT; - glBindBufferARB(res->target, res->id); - data = glMapBufferRange(res->target, info->box->x, info->box->width, map_flags); + data = gl_buf.bind_if_needed_and_map_range(res->id, info->box->x, info->box->width, map_flags); if (data == NULL) { vrend_printf("map failed for element buffer\n"); vrend_read_from_iovec_cb(iov, num_iovs, info->offset, info->box->width, &iov_buffer_upload, &d); } else { vrend_read_from_iovec(iov, num_iovs, info->offset, data, info->box->width); - glUnmapBuffer(res->target); } - glBindBufferARB(res->target, 0); + gl_buf.unmap_and_unbind(res->id); } else { GLenum glformat; GLenum gltype; @@ -8882,14 +9027,14 @@ static int vrend_renderer_transfer_send_iov(struct vrend_context *ctx, uint32_t send_size = info->box->width * util_format_get_blocksize(res->base.format); void *data; - glBindBufferARB(res->target, res->id); - data = glMapBufferRange(res->target, info->box->x, info->box->width, GL_MAP_READ_BIT); + data = gl_buf.bind_if_needed_and_map_range(res->id, info->box->x, + info->box->width, GL_MAP_READ_BIT); + if (!data) - vrend_printf("unable to open buffer for reading %d\n", res->target); + vrend_printf("unable to open buffer for reading %d\n", res->id); else vrend_write_to_iovec(iov, num_iovs, info->offset, data, send_size); - glUnmapBuffer(res->target); - glBindBufferARB(res->target, 0); + gl_buf.unmap_and_unbind(res->id); } else { int ret = -1; bool can_readpixels = true; @@ -9232,8 +9377,11 @@ void vrend_set_polygon_stipple(struct vrend_context *ctx, struct pipe_poly_stipple *ps) { if (vrend_state.use_core_profile) { - memcpy(ctx->sub->stipple_pattern, ps->stipple, - VREND_POLYGON_STIPPLE_SIZE * sizeof(GLuint)); + + /* std140 aligns array elements at 16 byte */ + for (int i = 0; i < VREND_POLYGON_STIPPLE_SIZE ; ++i) + ctx->sub->sysvalue_data.stipple_pattern[i][0] = ps->stipple[i]; + ctx->sub->sysvalue_data_cookie++; } else { glPolygonStipple((const GLubyte *)ps->stipple); } @@ -9243,6 +9391,12 @@ void vrend_set_clip_state(struct vrend_context *ctx, struct pipe_clip_state *ucp { if (vrend_state.use_core_profile) { ctx->sub->ucp_state = *ucp; + + ctx->sub->sysvalue_data_cookie++; + for (int i = 0 ; i < VIRGL_NUM_CLIP_PLANES; i++) { + memcpy(&ctx->sub->sysvalue_data.clipp[i], + (const GLfloat *) &ctx->sub->ucp_state.ucp[i], sizeof(GLfloat) * 4); + } } else { int i, j; GLdouble val[4]; @@ -10691,11 +10845,11 @@ void vrend_get_query_result(struct vrend_context *ctx, uint32_t handle, } #define COPY_QUERY_RESULT_TO_BUFFER(resid, offset, pvalue, size, multiplier) \ - glBindBuffer(GL_QUERY_BUFFER, resid); \ value *= multiplier; \ - void* buf = glMapBufferRange(GL_QUERY_BUFFER, offset, size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT); \ + void* buf = gl_buf.bind_if_needed_and_map_range(resid, offset, size, \ + GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT); \ if (buf) memcpy(buf, &value, size); \ - glUnmapBuffer(GL_QUERY_BUFFER); + gl_buf.unmap_and_unbind(resid); static inline void *buffer_offset(intptr_t i) { @@ -11921,6 +12075,9 @@ void vrend_renderer_create_sub_ctx(struct vrend_context *ctx, int sub_ctx_id) sub->object_hash = vrend_object_init_ctx_table(); + sub->sysvalue_data.winsys_adjust_y = 1.f; + sub->sysvalue_data_cookie = 1; + ctx->sub = sub; list_add(&sub->head, &ctx->sub_ctxs); if (sub_ctx_id == 0) @@ -12185,12 +12342,10 @@ int vrend_renderer_resource_map(struct pipe_resource *pres, void **map, uint64_t if (!has_bits(res->storage_bits, VREND_STORAGE_GL_BUFFER | VREND_STORAGE_GL_IMMUTABLE)) return -EINVAL; - glBindBufferARB(res->target, res->id); - *map = glMapBufferRange(res->target, 0, res->size, res->buffer_storage_flags); + *map = gl_buf.map_range(res->id, 0, res->size, res->buffer_storage_flags); if (!*map) return -EINVAL; - glBindBufferARB(res->target, 0); *out_size = res->size; return 0; } @@ -12201,9 +12356,7 @@ int vrend_renderer_resource_unmap(struct pipe_resource *pres) if (!has_bits(res->storage_bits, VREND_STORAGE_GL_BUFFER | VREND_STORAGE_GL_IMMUTABLE)) return -EINVAL; - glBindBufferARB(res->target, res->id); - glUnmapBuffer(res->target); - glBindBufferARB(res->target, 0); + gl_buf.unmap(res->id); return 0; }