mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-26 19:20:08 +01:00
virgl: add initial ARB_compute_shader support
This hooks up compute shader creation and launch grid support. Reviewed-by: Gurchetan Singh <gurchetansingh@chromium.org>
This commit is contained in:
parent
157c6e8195
commit
f8a8ea6a2d
7 changed files with 153 additions and 7 deletions
|
|
@ -506,7 +506,7 @@ static void *virgl_shader_encoder(struct pipe_context *ctx,
|
|||
handle = virgl_object_assign_handle();
|
||||
/* encode VS state */
|
||||
ret = virgl_encode_shader_state(vctx, handle, type,
|
||||
&shader->stream_output,
|
||||
&shader->stream_output, 0,
|
||||
new_tokens);
|
||||
if (ret) {
|
||||
return NULL;
|
||||
|
|
@ -961,7 +961,7 @@ static void virgl_set_shader_buffers(struct pipe_context *ctx,
|
|||
pipe_resource_reference(&vctx->ssbos[shader][idx], NULL);
|
||||
}
|
||||
|
||||
uint32_t max_shader_buffer = shader == PIPE_SHADER_FRAGMENT ?
|
||||
uint32_t max_shader_buffer = (shader == PIPE_SHADER_FRAGMENT || shader == PIPE_SHADER_COMPUTE) ?
|
||||
rs->caps.caps.v2.max_shader_buffer_frag_compute :
|
||||
rs->caps.caps.v2.max_shader_buffer_other_stages;
|
||||
if (!max_shader_buffer)
|
||||
|
|
@ -989,7 +989,7 @@ static void virgl_set_shader_images(struct pipe_context *ctx,
|
|||
pipe_resource_reference(&vctx->images[shader][idx], NULL);
|
||||
}
|
||||
|
||||
uint32_t max_shader_images = shader == PIPE_SHADER_FRAGMENT ?
|
||||
uint32_t max_shader_images = (shader == PIPE_SHADER_FRAGMENT || shader == PIPE_SHADER_COMPUTE) ?
|
||||
rs->caps.caps.v2.max_shader_image_frag_compute :
|
||||
rs->caps.caps.v2.max_shader_image_other_stages;
|
||||
if (!max_shader_images)
|
||||
|
|
@ -1008,6 +1008,50 @@ static void virgl_memory_barrier(struct pipe_context *ctx,
|
|||
virgl_encode_memory_barrier(vctx, flags);
|
||||
}
|
||||
|
||||
static void *virgl_create_compute_state(struct pipe_context *ctx,
|
||||
const struct pipe_compute_state *state)
|
||||
{
|
||||
struct virgl_context *vctx = virgl_context(ctx);
|
||||
uint32_t handle;
|
||||
const struct tgsi_token *new_tokens = state->prog;
|
||||
struct pipe_stream_output_info so_info = {};
|
||||
int ret;
|
||||
|
||||
handle = virgl_object_assign_handle();
|
||||
ret = virgl_encode_shader_state(vctx, handle, PIPE_SHADER_COMPUTE,
|
||||
&so_info,
|
||||
state->req_local_mem,
|
||||
new_tokens);
|
||||
if (ret) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (void *)(unsigned long)handle;
|
||||
}
|
||||
|
||||
static void virgl_bind_compute_state(struct pipe_context *ctx, void *state)
|
||||
{
|
||||
uint32_t handle = (unsigned long)state;
|
||||
struct virgl_context *vctx = virgl_context(ctx);
|
||||
|
||||
virgl_encode_bind_shader(vctx, handle, PIPE_SHADER_COMPUTE);
|
||||
}
|
||||
|
||||
static void virgl_delete_compute_state(struct pipe_context *ctx, void *state)
|
||||
{
|
||||
uint32_t handle = (unsigned long)state;
|
||||
struct virgl_context *vctx = virgl_context(ctx);
|
||||
|
||||
virgl_encode_delete_object(vctx, handle, VIRGL_OBJECT_SHADER);
|
||||
}
|
||||
|
||||
static void virgl_launch_grid(struct pipe_context *ctx,
|
||||
const struct pipe_grid_info *info)
|
||||
{
|
||||
struct virgl_context *vctx = virgl_context(ctx);
|
||||
virgl_encode_launch_grid(vctx, info);
|
||||
}
|
||||
|
||||
static void
|
||||
virgl_context_destroy( struct pipe_context *ctx )
|
||||
{
|
||||
|
|
@ -1118,6 +1162,11 @@ struct pipe_context *virgl_context_create(struct pipe_screen *pscreen,
|
|||
vctx->base.delete_gs_state = virgl_delete_gs_state;
|
||||
vctx->base.delete_fs_state = virgl_delete_fs_state;
|
||||
|
||||
vctx->base.create_compute_state = virgl_create_compute_state;
|
||||
vctx->base.bind_compute_state = virgl_bind_compute_state;
|
||||
vctx->base.delete_compute_state = virgl_delete_compute_state;
|
||||
vctx->base.launch_grid = virgl_launch_grid;
|
||||
|
||||
vctx->base.clear = virgl_clear;
|
||||
vctx->base.draw_vbo = virgl_draw_vbo;
|
||||
vctx->base.flush = virgl_flush_from_st;
|
||||
|
|
|
|||
|
|
@ -241,6 +241,7 @@ int virgl_encode_shader_state(struct virgl_context *ctx,
|
|||
uint32_t handle,
|
||||
uint32_t type,
|
||||
const struct pipe_stream_output_info *so_info,
|
||||
uint32_t cs_req_local_mem,
|
||||
const struct tgsi_token *tokens)
|
||||
{
|
||||
char *str, *sptr;
|
||||
|
|
@ -298,7 +299,10 @@ int virgl_encode_shader_state(struct virgl_context *ctx,
|
|||
|
||||
virgl_emit_shader_header(ctx, handle, len, type, offlen, num_tokens);
|
||||
|
||||
virgl_emit_shader_streamout(ctx, first_pass ? so_info : NULL);
|
||||
if (type == PIPE_SHADER_COMPUTE)
|
||||
virgl_encoder_write_dword(ctx->cbuf, cs_req_local_mem);
|
||||
else
|
||||
virgl_emit_shader_streamout(ctx, first_pass ? so_info : NULL);
|
||||
|
||||
virgl_encoder_write_block(ctx->cbuf, (uint8_t *)sptr, length);
|
||||
|
||||
|
|
@ -980,3 +984,22 @@ int virgl_encode_memory_barrier(struct virgl_context *ctx,
|
|||
virgl_encoder_write_dword(ctx->cbuf, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int virgl_encode_launch_grid(struct virgl_context *ctx,
|
||||
const struct pipe_grid_info *grid_info)
|
||||
{
|
||||
virgl_encoder_write_cmd_dword(ctx, VIRGL_CMD0(VIRGL_CCMD_LAUNCH_GRID, 0, VIRGL_LAUNCH_GRID_SIZE));
|
||||
virgl_encoder_write_dword(ctx->cbuf, grid_info->block[0]);
|
||||
virgl_encoder_write_dword(ctx->cbuf, grid_info->block[1]);
|
||||
virgl_encoder_write_dword(ctx->cbuf, grid_info->block[2]);
|
||||
virgl_encoder_write_dword(ctx->cbuf, grid_info->grid[0]);
|
||||
virgl_encoder_write_dword(ctx->cbuf, grid_info->grid[1]);
|
||||
virgl_encoder_write_dword(ctx->cbuf, grid_info->grid[2]);
|
||||
if (grid_info->indirect) {
|
||||
struct virgl_resource *res = virgl_resource(grid_info->indirect);
|
||||
virgl_encoder_write_res(ctx, res);
|
||||
} else
|
||||
virgl_encoder_write_dword(ctx->cbuf, 0);
|
||||
virgl_encoder_write_dword(ctx->cbuf, grid_info->indirect_offset);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ extern int virgl_encode_shader_state(struct virgl_context *ctx,
|
|||
uint32_t handle,
|
||||
uint32_t type,
|
||||
const struct pipe_stream_output_info *so_info,
|
||||
uint32_t cs_req_local_mem,
|
||||
const struct tgsi_token *tokens);
|
||||
|
||||
int virgl_encode_stream_output_info(struct virgl_context *ctx,
|
||||
|
|
@ -269,4 +270,6 @@ int virgl_encode_set_shader_images(struct virgl_context *ctx,
|
|||
const struct pipe_image_view *images);
|
||||
int virgl_encode_memory_barrier(struct virgl_context *ctx,
|
||||
unsigned flags);
|
||||
int virgl_encode_launch_grid(struct virgl_context *ctx,
|
||||
const struct pipe_grid_info *grid_info);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -206,6 +206,7 @@ enum virgl_formats {
|
|||
#define VIRGL_CAP_TGSI_PRECISE (1 << 4)
|
||||
#define VIRGL_CAP_TXQS (1 << 5)
|
||||
#define VIRGL_CAP_MEMORY_BARRIER (1 << 6)
|
||||
#define VIRGL_CAP_COMPUTE_SHADER (1 << 7)
|
||||
|
||||
#define VIRGL_BIND_DEPTH_STENCIL (1 << 0)
|
||||
#define VIRGL_BIND_RENDER_TARGET (1 << 1)
|
||||
|
|
@ -312,6 +313,10 @@ struct virgl_caps_v2 {
|
|||
uint32_t max_shader_image_frag_compute;
|
||||
uint32_t max_shader_image_other_stages;
|
||||
uint32_t max_image_samples;
|
||||
uint32_t max_compute_work_group_invocations;
|
||||
uint32_t max_compute_shared_memory_size;
|
||||
uint32_t max_compute_grid_size[3];
|
||||
uint32_t max_compute_block_size[3];
|
||||
};
|
||||
|
||||
union virgl_caps {
|
||||
|
|
|
|||
|
|
@ -89,6 +89,7 @@ enum virgl_context_cmd {
|
|||
VIRGL_CCMD_SET_SHADER_BUFFERS,
|
||||
VIRGL_CCMD_SET_SHADER_IMAGES,
|
||||
VIRGL_CCMD_MEMORY_BARRIER,
|
||||
VIRGL_CCMD_LAUNCH_GRID,
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -518,4 +519,14 @@ enum virgl_context_cmd {
|
|||
#define VIRGL_MEMORY_BARRIER_SIZE 1
|
||||
#define VIRGL_MEMORY_BARRIER_FLAGS 1
|
||||
|
||||
#define VIRGL_LAUNCH_GRID_SIZE 8
|
||||
#define VIRGL_LAUNCH_BLOCK_X 1
|
||||
#define VIRGL_LAUNCH_BLOCK_Y 2
|
||||
#define VIRGL_LAUNCH_BLOCK_Z 3
|
||||
#define VIRGL_LAUNCH_GRID_X 4
|
||||
#define VIRGL_LAUNCH_GRID_Y 5
|
||||
#define VIRGL_LAUNCH_GRID_Z 6
|
||||
#define VIRGL_LAUNCH_INDIRECT_HANDLE 7
|
||||
#define VIRGL_LAUNCH_INDIRECT_OFFSET 8
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -139,7 +139,7 @@ virgl_get_param(struct pipe_screen *screen, enum pipe_cap param)
|
|||
case PIPE_CAP_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION:
|
||||
return 0;
|
||||
case PIPE_CAP_COMPUTE:
|
||||
return 0;
|
||||
return vscreen->caps.caps.v2.capability_bits & VIRGL_CAP_COMPUTE_SHADER;
|
||||
case PIPE_CAP_USER_VERTEX_BUFFERS:
|
||||
return 0;
|
||||
case PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT:
|
||||
|
|
@ -328,6 +328,10 @@ virgl_get_shader_param(struct pipe_screen *screen,
|
|||
!vscreen->caps.caps.v1.bset.has_tessellation_shaders)
|
||||
return 0;
|
||||
|
||||
if (shader == PIPE_SHADER_COMPUTE &&
|
||||
!(vscreen->caps.caps.v2.capability_bits & VIRGL_CAP_COMPUTE_SHADER))
|
||||
return 0;
|
||||
|
||||
switch(shader)
|
||||
{
|
||||
case PIPE_SHADER_FRAGMENT:
|
||||
|
|
@ -335,6 +339,7 @@ virgl_get_shader_param(struct pipe_screen *screen,
|
|||
case PIPE_SHADER_GEOMETRY:
|
||||
case PIPE_SHADER_TESS_CTRL:
|
||||
case PIPE_SHADER_TESS_EVAL:
|
||||
case PIPE_SHADER_COMPUTE:
|
||||
switch (param) {
|
||||
case PIPE_SHADER_CAP_MAX_INSTRUCTIONS:
|
||||
case PIPE_SHADER_CAP_MAX_ALU_INSTRUCTIONS:
|
||||
|
|
@ -373,15 +378,17 @@ virgl_get_shader_param(struct pipe_screen *screen,
|
|||
case PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE:
|
||||
return 4096 * sizeof(float[4]);
|
||||
case PIPE_SHADER_CAP_MAX_SHADER_BUFFERS:
|
||||
if (shader == PIPE_SHADER_FRAGMENT)
|
||||
if (shader == PIPE_SHADER_FRAGMENT || shader == PIPE_SHADER_COMPUTE)
|
||||
return vscreen->caps.caps.v2.max_shader_buffer_frag_compute;
|
||||
else
|
||||
return vscreen->caps.caps.v2.max_shader_buffer_other_stages;
|
||||
case PIPE_SHADER_CAP_MAX_SHADER_IMAGES:
|
||||
if (shader == PIPE_SHADER_FRAGMENT)
|
||||
if (shader == PIPE_SHADER_FRAGMENT || shader == PIPE_SHADER_COMPUTE)
|
||||
return vscreen->caps.caps.v2.max_shader_image_frag_compute;
|
||||
else
|
||||
return vscreen->caps.caps.v2.max_shader_image_other_stages;
|
||||
case PIPE_SHADER_CAP_SUPPORTED_IRS:
|
||||
return (1 << PIPE_SHADER_IR_TGSI);
|
||||
case PIPE_SHADER_CAP_LOWER_IF_THRESHOLD:
|
||||
case PIPE_SHADER_CAP_TGSI_SKIP_MERGE_REGISTERS:
|
||||
case PIPE_SHADER_CAP_INT64_ATOMICS:
|
||||
|
|
@ -426,6 +433,51 @@ virgl_get_paramf(struct pipe_screen *screen, enum pipe_capf param)
|
|||
return 0.0;
|
||||
}
|
||||
|
||||
static int
|
||||
virgl_get_compute_param(struct pipe_screen *screen,
|
||||
enum pipe_shader_ir ir_type,
|
||||
enum pipe_compute_cap param,
|
||||
void *ret)
|
||||
{
|
||||
struct virgl_screen *vscreen = virgl_screen(screen);
|
||||
if (!(vscreen->caps.caps.v2.capability_bits & VIRGL_CAP_COMPUTE_SHADER))
|
||||
return 0;
|
||||
switch (param) {
|
||||
case PIPE_COMPUTE_CAP_MAX_GRID_SIZE:
|
||||
if (ret) {
|
||||
uint64_t *grid_size = ret;
|
||||
grid_size[0] = vscreen->caps.caps.v2.max_compute_grid_size[0];
|
||||
grid_size[1] = vscreen->caps.caps.v2.max_compute_grid_size[1];
|
||||
grid_size[2] = vscreen->caps.caps.v2.max_compute_grid_size[2];
|
||||
}
|
||||
return 3 * sizeof(uint64_t) ;
|
||||
case PIPE_COMPUTE_CAP_MAX_BLOCK_SIZE:
|
||||
if (ret) {
|
||||
uint64_t *block_size = ret;
|
||||
block_size[0] = vscreen->caps.caps.v2.max_compute_block_size[0];
|
||||
block_size[1] = vscreen->caps.caps.v2.max_compute_block_size[1];
|
||||
block_size[2] = vscreen->caps.caps.v2.max_compute_block_size[2];
|
||||
}
|
||||
return 3 * sizeof(uint64_t);
|
||||
case PIPE_COMPUTE_CAP_MAX_THREADS_PER_BLOCK:
|
||||
if (ret) {
|
||||
uint64_t *max_threads_per_block = ret;
|
||||
*max_threads_per_block = vscreen->caps.caps.v2.max_compute_work_group_invocations;
|
||||
}
|
||||
return sizeof(uint64_t);
|
||||
case PIPE_COMPUTE_CAP_MAX_LOCAL_SIZE:
|
||||
if (ret) {
|
||||
uint64_t *max_local_size = ret;
|
||||
/* Value reported by the closed source driver. */
|
||||
*max_local_size = vscreen->caps.caps.v2.max_compute_shared_memory_size;
|
||||
}
|
||||
return sizeof(uint64_t);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static boolean
|
||||
virgl_is_vertex_format_supported(struct pipe_screen *screen,
|
||||
enum pipe_format format)
|
||||
|
|
@ -666,6 +718,7 @@ virgl_create_screen(struct virgl_winsys *vws)
|
|||
screen->base.get_vendor = virgl_get_vendor;
|
||||
screen->base.get_param = virgl_get_param;
|
||||
screen->base.get_shader_param = virgl_get_shader_param;
|
||||
screen->base.get_compute_param = virgl_get_compute_param;
|
||||
screen->base.get_paramf = virgl_get_paramf;
|
||||
screen->base.is_format_supported = virgl_is_format_supported;
|
||||
screen->base.destroy = virgl_destroy_screen;
|
||||
|
|
|
|||
|
|
@ -138,5 +138,7 @@ static inline void virgl_ws_fill_new_caps_defaults(struct virgl_drm_caps *caps)
|
|||
caps->caps.v2.capability_bits = 0;
|
||||
caps->caps.v2.max_vertex_attrib_stride = 0;
|
||||
caps->caps.v2.max_image_samples = 0;
|
||||
caps->caps.v2.max_compute_work_group_invocations = 0;
|
||||
caps->caps.v2.max_compute_shared_memory_size = 0;
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue