shader: Link shader command

Add a new command associated to glLinkProgram. With this we should be
able to compile and link shaders when requested by the user.

Together with the command we expect an array of shader handles attached
to the program, where each position of the array corresponds to a pipe
shader type.

Signed-off-by: Antonio Caggiano <antonio.caggiano@collabora.com>
Reviewed-by: Gert Wollny <gert.wollny@collabora.com>
macos/master
Antonio Caggiano 3 years ago committed by Gert Wollny
parent 013d0db3e0
commit ba30df1bdc
  1. 10
      src/virgl_protocol.h
  2. 1
      src/vrend_debug.c
  3. 18
      src/vrend_decode.c
  4. 31
      src/vrend_renderer.c
  5. 2
      src/vrend_renderer.h
  6. 9
      tests/test_virgl_cmd.c
  7. 12
      tests/testvirgl_encode.c
  8. 1
      tests/testvirgl_encode.h

@ -116,6 +116,7 @@ enum virgl_context_cmd {
VIRGL_CCMD_PIPE_RESOURCE_SET_TYPE,
VIRGL_CCMD_GET_MEMORY_INFO,
VIRGL_CCMD_SEND_STRING_MARKER,
VIRGL_CCMD_LINK_SHADER,
VIRGL_MAX_COMMANDS
};
@ -673,4 +674,13 @@ enum vrend_tweak_type {
#define VIRGL_SEND_STRING_MARKER_STRING_SIZE 1
#define VIRGL_SEND_STRING_MARKER_OFFSET 2
/* link shader program */
#define VIRGL_LINK_SHADER_SIZE 6
#define VIRGL_LINK_SHADER_VERTEX_HANDLE 1
#define VIRGL_LINK_SHADER_FRAGMENT_HANDLE 2
#define VIRGL_LINK_SHADER_GEOMETRY_HANDLE 3
#define VIRGL_LINK_SHADER_TESS_CTRL_HANDLE 4
#define VIRGL_LINK_SHADER_TESS_EVAL_HANDLE 5
#define VIRGL_LINK_SHADER_COMPUTE_HANDLE 6
#endif

@ -81,6 +81,7 @@ static const char *command_names[VIRGL_MAX_COMMANDS] = {
"PIPE_RESOURCE_SET_TYPE",
"GET_MEMORY_INFO",
"SEND_STRING_MARKER",
"LINK_SHADER",
};
static const char *object_type_names[VIRGL_MAX_OBJECTS] = {

@ -1155,6 +1155,23 @@ static int vrend_decode_destroy_sub_ctx(struct vrend_context *ctx, const uint32_
return 0;
}
static int vrend_decode_link_shader(struct vrend_context *ctx, const uint32_t *buf, uint32_t length)
{
if (length != VIRGL_LINK_SHADER_SIZE)
return EINVAL;
uint32_t handles[PIPE_SHADER_TYPES];
handles[PIPE_SHADER_VERTEX] = get_buf_entry(buf, VIRGL_LINK_SHADER_VERTEX_HANDLE);
handles[PIPE_SHADER_FRAGMENT] = get_buf_entry(buf, VIRGL_LINK_SHADER_FRAGMENT_HANDLE);
handles[PIPE_SHADER_GEOMETRY] = get_buf_entry(buf, VIRGL_LINK_SHADER_GEOMETRY_HANDLE);
handles[PIPE_SHADER_TESS_CTRL] = get_buf_entry(buf, VIRGL_LINK_SHADER_TESS_CTRL_HANDLE);
handles[PIPE_SHADER_TESS_EVAL] = get_buf_entry(buf, VIRGL_LINK_SHADER_TESS_EVAL_HANDLE);
handles[PIPE_SHADER_COMPUTE] = get_buf_entry(buf, VIRGL_LINK_SHADER_COMPUTE_HANDLE);
vrend_link_program(ctx, handles);
return 0;
}
static int vrend_decode_bind_shader(struct vrend_context *ctx, const uint32_t *buf, uint32_t length)
{
uint32_t handle, type;
@ -1654,6 +1671,7 @@ static const vrend_decode_callback decode_table[VIRGL_MAX_COMMANDS] = {
[VIRGL_CCMD_PIPE_RESOURCE_SET_TYPE] = vrend_decode_pipe_resource_set_type,
[VIRGL_CCMD_GET_MEMORY_INFO] = vrend_decode_get_memory_info,
[VIRGL_CCMD_SEND_STRING_MARKER] = vrend_decode_send_string_marker,
[VIRGL_CCMD_LINK_SHADER] = vrend_decode_link_shader,
};
static int vrend_decode_ctx_submit_cmd(struct virgl_context *ctx,

@ -4798,6 +4798,35 @@ vrend_select_program(struct vrend_sub_context *sub_ctx, ubyte vertices_per_patch
return new_program;
}
void vrend_link_program(struct vrend_context *ctx, uint32_t *handles)
{
/* Pre-compiling compute shaders needs some additional work */
if (handles[PIPE_SHADER_COMPUTE])
return;
struct vrend_shader_selector *prev_handles[PIPE_SHADER_TYPES];
memset(prev_handles, 0, sizeof(prev_handles));
uint32_t prev_shader_ids[PIPE_SHADER_TYPES];
memcpy(prev_shader_ids, ctx->sub->prog_ids, PIPE_SHADER_TYPES * sizeof(uint32_t));
struct vrend_linked_shader_program *prev_prog = ctx->sub->prog;
for (uint32_t type = 0; type < PIPE_SHADER_TYPES; ++type) {
vrend_shader_state_reference(&prev_handles[type], ctx->sub->shaders[type]);
vrend_bind_shader(ctx, handles[type], type);
}
ctx->sub->shader_dirty = true;
ctx->sub->cs_shader_dirty = true;
/* undo state changes */
for (uint32_t type = 0; type < PIPE_SHADER_TYPES; ++type) {
vrend_shader_state_reference(&ctx->sub->shaders[type], prev_handles[type]);
vrend_shader_state_reference(&prev_handles[type], NULL);
}
memcpy(ctx->sub->prog_ids, prev_shader_ids, PIPE_SHADER_TYPES * sizeof(uint32_t));
ctx->sub->prog = prev_prog;
}
int vrend_draw_vbo(struct vrend_context *ctx,
const struct pipe_draw_info *info,
uint32_t cso, uint32_t indirect_handle,
@ -10536,7 +10565,7 @@ static void vrend_renderer_fill_caps_v2(int gl_ver, int gles_ver, union virgl_c
* this value to avoid regressions when a guest with a new mesa version is
* run on an old virgl host. Use it also to indicate non-cap fixes on the
* host that help enable features in the guest. */
caps->v2.host_feature_check_version = 6;
caps->v2.host_feature_check_version = 7;
/* Forward host GL_RENDERER to the guest. */
strncpy(caps->v2.renderer, renderer, sizeof(caps->v2.renderer) - 1);

@ -145,6 +145,8 @@ int vrend_create_shader(struct vrend_context *ctx,
const char *shd_text, uint32_t offlen, uint32_t num_tokens,
uint32_t type, uint32_t pkt_length);
void vrend_link_program(struct vrend_context *ctx, uint32_t *handles);
void vrend_bind_shader(struct vrend_context *ctx,
uint32_t type,
uint32_t handle);

@ -372,6 +372,15 @@ START_TEST(virgl_test_render_simple)
virgl_encode_bind_shader(&ctx, fs_handle, PIPE_SHADER_FRAGMENT);
}
/* link shader */
{
uint32_t handles[PIPE_SHADER_TYPES];
memset(handles, 0, sizeof(handles));
handles[PIPE_SHADER_VERTEX] = vs_handle;
handles[PIPE_SHADER_FRAGMENT] = fs_handle;
virgl_encode_link_shader(&ctx, handles);
}
/* set blend state */
{
struct pipe_blend_state blend;

@ -942,6 +942,18 @@ int virgl_encoder_destroy_sub_ctx(struct virgl_context *ctx, uint32_t sub_ctx_id
return 0;
}
int virgl_encode_link_shader(struct virgl_context *ctx, uint32_t *handles)
{
virgl_encoder_write_cmd_dword(ctx, VIRGL_CMD0(VIRGL_CCMD_LINK_SHADER, 0, VIRGL_LINK_SHADER_SIZE));
virgl_encoder_write_dword(ctx->cbuf, handles[PIPE_SHADER_VERTEX]);
virgl_encoder_write_dword(ctx->cbuf, handles[PIPE_SHADER_FRAGMENT]);
virgl_encoder_write_dword(ctx->cbuf, handles[PIPE_SHADER_GEOMETRY]);
virgl_encoder_write_dword(ctx->cbuf, handles[PIPE_SHADER_TESS_CTRL]);
virgl_encoder_write_dword(ctx->cbuf, handles[PIPE_SHADER_TESS_EVAL]);
virgl_encoder_write_dword(ctx->cbuf, handles[PIPE_SHADER_COMPUTE]);
return 0;
}
int virgl_encode_bind_shader(struct virgl_context *ctx,
uint32_t handle, uint32_t type)
{

@ -258,6 +258,7 @@ int virgl_encoder_render_condition(struct virgl_context *ctx,
int virgl_encoder_set_sub_ctx(struct virgl_context *ctx, uint32_t sub_ctx_id);
int virgl_encoder_create_sub_ctx(struct virgl_context *ctx, uint32_t sub_ctx_id);
int virgl_encoder_destroy_sub_ctx(struct virgl_context *ctx, uint32_t sub_ctx_id);
int virgl_encode_link_shader(struct virgl_context *ctx, uint32_t *handles);
int virgl_encode_bind_shader(struct virgl_context *ctx,
uint32_t handle, uint32_t type);
#endif

Loading…
Cancel
Save