diff --git a/src/virgl_protocol.h b/src/virgl_protocol.h index bf5a02f..ca3142f 100644 --- a/src/virgl_protocol.h +++ b/src/virgl_protocol.h @@ -82,7 +82,7 @@ enum virgl_context_cmd { VIRGL_CCMD_SET_SUB_CTX, VIRGL_CCMD_CREATE_SUB_CTX, VIRGL_CCMD_DESTROY_SUB_CTX, - + VIRGL_CCMD_BIND_SHADER, }; /* @@ -460,4 +460,9 @@ enum virgl_context_cmd { /* polygon stipple */ #define VIRGL_POLYGON_STIPPLE_SIZE 32 #define VIRGL_POLYGON_STIPPLE_P0 1 + +#define VIRGL_BIND_SHADER_SIZE 2 +#define VIRGL_BIND_SHADER_HANDLE 1 +#define VIRGL_BIND_SHADER_TYPE 2 + #endif diff --git a/src/vrend_decode.c b/src/vrend_decode.c index 256f16e..1d1b2a2 100644 --- a/src/vrend_decode.c +++ b/src/vrend_decode.c @@ -682,9 +682,6 @@ static int vrend_decode_bind_object(struct vrend_decode_ctx *ctx, uint16_t lengt case VIRGL_OBJECT_RASTERIZER: vrend_object_bind_rasterizer(ctx->grctx, handle); break; - case VIRGL_OBJECT_SHADER: - vrend_bind_shader(ctx->grctx, handle); - break; case VIRGL_OBJECT_VERTEX_ELEMENTS: vrend_bind_vertex_elements_state(ctx->grctx, handle); break; @@ -970,6 +967,19 @@ static int vrend_decode_destroy_sub_ctx(struct vrend_decode_ctx *ctx, int length return 0; } +static int vrend_decode_bind_shader(struct vrend_decode_ctx *ctx, int length) +{ + uint32_t handle, type; + if (length != VIRGL_BIND_SHADER_SIZE) + return EINVAL; + + handle = get_buf_entry(ctx, VIRGL_BIND_SHADER_HANDLE); + type = get_buf_entry(ctx, VIRGL_BIND_SHADER_TYPE); + + vrend_bind_shader(ctx->grctx, handle, type); + return 0; +} + static int vrend_decode_set_streamout_targets(struct vrend_decode_ctx *ctx, uint16_t length) { @@ -1176,6 +1186,9 @@ int vrend_decode_block(uint32_t ctx_id, uint32_t *block, int ndw) case VIRGL_CCMD_DESTROY_SUB_CTX: ret = vrend_decode_destroy_sub_ctx(gdctx, len); break; + case VIRGL_CCMD_BIND_SHADER: + ret = vrend_decode_bind_shader(gdctx, len); + break; } if (ret == EINVAL) { diff --git a/src/vrend_renderer.c b/src/vrend_renderer.c index 37e7748..5e03433 100644 --- a/src/vrend_renderer.c +++ b/src/vrend_renderer.c @@ -2166,13 +2166,26 @@ int vrend_create_shader(struct vrend_context *ctx, } void vrend_bind_shader(struct vrend_context *ctx, - uint32_t handle) + uint32_t handle, uint32_t type) { struct vrend_shader_selector *sel; + if (type > PIPE_SHADER_GEOMETRY) + return; + + if (handle == 0) { + ctx->sub->shader_dirty = true; + vrend_shader_state_reference(&ctx->sub->shaders[type], NULL); + return; + } + sel = vrend_object_lookup(ctx->sub->object_hash, handle, VIRGL_OBJECT_SHADER); if (!sel) return; + + if (sel->type != type) + return; + if (ctx->sub->shaders[sel->type] != sel) ctx->sub->shader_dirty = true; vrend_shader_state_reference(&ctx->sub->shaders[sel->type], sel); diff --git a/src/vrend_renderer.h b/src/vrend_renderer.h index 6efa05e..ee26993 100644 --- a/src/vrend_renderer.h +++ b/src/vrend_renderer.h @@ -109,6 +109,7 @@ int vrend_create_shader(struct vrend_context *ctx, int type, uint32_t pkt_length); void vrend_bind_shader(struct vrend_context *ctx, + uint32_t type, uint32_t handle); void vrend_bind_vs_so(struct vrend_context *ctx, diff --git a/tests/test_virgl_cmd.c b/tests/test_virgl_cmd.c index 525cef3..c91d70a 100644 --- a/tests/test_virgl_cmd.c +++ b/tests/test_virgl_cmd.c @@ -346,7 +346,7 @@ START_TEST(virgl_test_render_simple) vs_handle = ctx_handle++; virgl_encode_shader_state(&ctx, vs_handle, PIPE_SHADER_VERTEX, &vs, text); - virgl_encode_bind_object(&ctx, vs_handle, VIRGL_OBJECT_SHADER); + virgl_encode_bind_shader(&ctx, vs_handle, PIPE_SHADER_VERTEX); } /* create fragment shader */ @@ -363,7 +363,7 @@ START_TEST(virgl_test_render_simple) virgl_encode_shader_state(&ctx, fs_handle, PIPE_SHADER_FRAGMENT, &fs, text); - virgl_encode_bind_object(&ctx, fs_handle, VIRGL_OBJECT_SHADER); + virgl_encode_bind_shader(&ctx, fs_handle, PIPE_SHADER_FRAGMENT); } /* set blend state */ @@ -571,7 +571,7 @@ START_TEST(virgl_test_render_geom_simple) vs_handle = ctx_handle++; virgl_encode_shader_state(&ctx, vs_handle, PIPE_SHADER_VERTEX, &vs, text); - virgl_encode_bind_object(&ctx, vs_handle, VIRGL_OBJECT_SHADER); + virgl_encode_bind_shader(&ctx, vs_handle, PIPE_SHADER_VERTEX); } /* create geometry shader */ @@ -602,7 +602,7 @@ START_TEST(virgl_test_render_geom_simple) gs_handle = ctx_handle++; virgl_encode_shader_state(&ctx, gs_handle, PIPE_SHADER_GEOMETRY, &gs, text); - virgl_encode_bind_object(&ctx, gs_handle, VIRGL_OBJECT_SHADER); + virgl_encode_bind_shader(&ctx, gs_handle, PIPE_SHADER_GEOMETRY); } /* create fragment shader */ @@ -619,7 +619,7 @@ START_TEST(virgl_test_render_geom_simple) virgl_encode_shader_state(&ctx, fs_handle, PIPE_SHADER_FRAGMENT, &fs, text); - virgl_encode_bind_object(&ctx, fs_handle, VIRGL_OBJECT_SHADER); + virgl_encode_bind_shader(&ctx, fs_handle, PIPE_SHADER_FRAGMENT); } /* set blend state */ @@ -847,7 +847,7 @@ START_TEST(virgl_test_render_xfb) vs.stream_output.output[0].num_components = 4; virgl_encode_shader_state(&ctx, vs_handle, PIPE_SHADER_VERTEX, &vs, text); - virgl_encode_bind_object(&ctx, vs_handle, VIRGL_OBJECT_SHADER); + virgl_encode_bind_shader(&ctx, vs_handle, PIPE_SHADER_VERTEX); } /* create fragment shader */ @@ -863,8 +863,7 @@ START_TEST(virgl_test_render_xfb) fs_handle = ctx_handle++; virgl_encode_shader_state(&ctx, fs_handle, PIPE_SHADER_FRAGMENT, &fs, text); - - virgl_encode_bind_object(&ctx, fs_handle, VIRGL_OBJECT_SHADER); + virgl_encode_bind_shader(&ctx, fs_handle, PIPE_SHADER_FRAGMENT); } /* set blend state */ @@ -998,7 +997,7 @@ START_TEST(virgl_test_large_shader) virgl_encode_shader_state(&ctx, fs_handle, PIPE_SHADER_FRAGMENT, &fs, text); - virgl_encode_bind_object(&ctx, fs_handle, VIRGL_OBJECT_SHADER); + virgl_encode_bind_shader(&ctx, fs_handle, PIPE_SHADER_FRAGMENT); } testvirgl_fini_ctx_cmdbuf(&ctx); diff --git a/tests/testvirgl_encode.c b/tests/testvirgl_encode.c index f1d5409..ce62ecc 100644 --- a/tests/testvirgl_encode.c +++ b/tests/testvirgl_encode.c @@ -897,3 +897,12 @@ int virgl_encoder_destroy_sub_ctx(struct virgl_context *ctx, uint32_t sub_ctx_id virgl_encoder_write_dword(ctx->cbuf, sub_ctx_id); return 0; } + +int virgl_encode_bind_shader(struct virgl_context *ctx, + uint32_t handle, uint32_t type) +{ + virgl_encoder_write_cmd_dword(ctx, VIRGL_CMD0(VIRGL_CCMD_BIND_SHADER, 0, 2)); + virgl_encoder_write_dword(ctx->cbuf, handle); + virgl_encoder_write_dword(ctx->cbuf, type); + return 0; +} diff --git a/tests/testvirgl_encode.h b/tests/testvirgl_encode.h index d717749..310cb14 100644 --- a/tests/testvirgl_encode.h +++ b/tests/testvirgl_encode.h @@ -229,4 +229,6 @@ 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_bind_shader(struct virgl_context *ctx, + uint32_t handle, uint32_t type); #endif