diff --git a/src/meson.build b/src/meson.build index d343cdd..0f0da2a 100644 --- a/src/meson.build +++ b/src/meson.build @@ -106,6 +106,8 @@ venus_sources = [ 'venus/vkr_renderer.h', 'venus/vkr_ring.c', 'venus/vkr_ring.h', + 'venus/vkr_transport.c', + 'venus/vkr_transport.h', ] virgl_depends = [ diff --git a/src/venus/vkr_renderer.c b/src/venus/vkr_renderer.c index 2766c56..b6f34e6 100644 --- a/src/venus/vkr_renderer.c +++ b/src/venus/vkr_renderer.c @@ -31,6 +31,7 @@ #include "vkr_queue.h" #include "vkr_render_pass.h" #include "vkr_ring.h" +#include "vkr_transport.h" static const struct debug_named_value vkr_debug_options[] = { { "validate", VKR_DEBUG_VALIDATE, "Force enabling the validation layer" }, @@ -40,300 +41,6 @@ static const struct debug_named_value vkr_debug_options[] = { uint32_t vkr_renderer_flags; uint32_t vkr_debug_flags; -static void -vkr_dispatch_vkSetReplyCommandStreamMESA( - struct vn_dispatch_context *dispatch, - struct vn_command_vkSetReplyCommandStreamMESA *args) -{ - struct vkr_context *ctx = dispatch->data; - struct vkr_resource_attachment *att; - - if (!args->pStream) { - vkr_cs_decoder_set_fatal(&ctx->decoder); - return; - } - - att = util_hash_table_get(ctx->resource_table, - uintptr_to_pointer(args->pStream->resourceId)); - if (!att) { - vkr_cs_decoder_set_fatal(&ctx->decoder); - return; - } - - vkr_cs_encoder_set_stream(&ctx->encoder, att->resource->iov, att->resource->iov_count, - args->pStream->offset, args->pStream->size); -} - -static void -vkr_dispatch_vkSeekReplyCommandStreamMESA( - struct vn_dispatch_context *dispatch, - struct vn_command_vkSeekReplyCommandStreamMESA *args) -{ - struct vkr_context *ctx = dispatch->data; - vkr_cs_encoder_seek_stream(&ctx->encoder, args->position); -} - -static void * -copy_command_stream(struct vkr_context *ctx, const VkCommandStreamDescriptionMESA *stream) -{ - struct vkr_resource_attachment *att; - struct virgl_resource *res; - - att = util_hash_table_get(ctx->resource_table, uintptr_to_pointer(stream->resourceId)); - if (!att) - return NULL; - res = att->resource; - - /* seek to offset */ - size_t iov_offset = stream->offset; - const struct iovec *iov = NULL; - for (int i = 0; i < res->iov_count; i++) { - if (iov_offset < res->iov[i].iov_len) { - iov = &res->iov[i]; - break; - } - iov_offset -= res->iov[i].iov_len; - } - if (!iov) - return NULL; - - /* XXX until the decoder supports scatter-gather and is robust enough, - * always make a copy in case the caller modifies the commands while we - * parse - */ - uint8_t *data = malloc(stream->size); - if (!data) - return NULL; - - uint32_t copied = 0; - while (true) { - const size_t s = MIN2(stream->size - copied, iov->iov_len - iov_offset); - memcpy(data + copied, (const uint8_t *)iov->iov_base + iov_offset, s); - - copied += s; - if (copied == stream->size) { - break; - } else if (iov == &res->iov[res->iov_count - 1]) { - free(data); - return NULL; - } - - iov++; - iov_offset = 0; - } - - return data; -} - -static void -vkr_dispatch_vkExecuteCommandStreamsMESA( - struct vn_dispatch_context *dispatch, - struct vn_command_vkExecuteCommandStreamsMESA *args) -{ - struct vkr_context *ctx = dispatch->data; - - if (!args->streamCount || !args->pStreams) { - vkr_cs_decoder_set_fatal(&ctx->decoder); - return; - } - - /* note that nested vkExecuteCommandStreamsMESA is not allowed */ - if (!vkr_cs_decoder_push_state(&ctx->decoder)) { - vkr_cs_decoder_set_fatal(&ctx->decoder); - return; - } - - for (uint32_t i = 0; i < args->streamCount; i++) { - const VkCommandStreamDescriptionMESA *stream = &args->pStreams[i]; - - if (args->pReplyPositions) - vkr_cs_encoder_seek_stream(&ctx->encoder, args->pReplyPositions[i]); - - if (!stream->size) - continue; - - void *data = copy_command_stream(ctx, stream); - if (!data) { - vkr_cs_decoder_set_fatal(&ctx->decoder); - break; - } - - vkr_cs_decoder_set_stream(&ctx->decoder, data, stream->size); - while (vkr_cs_decoder_has_command(&ctx->decoder)) { - vn_dispatch_command(&ctx->dispatch); - if (vkr_cs_decoder_get_fatal(&ctx->decoder)) - break; - } - - free(data); - - if (vkr_cs_decoder_get_fatal(&ctx->decoder)) - break; - } - - vkr_cs_decoder_pop_state(&ctx->decoder); -} - -static struct vkr_ring * -lookup_ring(struct vkr_context *ctx, uint64_t ring_id) -{ - struct vkr_ring *ring; - LIST_FOR_EACH_ENTRY (ring, &ctx->rings, head) { - if (ring->id == ring_id) - return ring; - } - return NULL; -} - -static void -vkr_dispatch_vkCreateRingMESA(struct vn_dispatch_context *dispatch, - struct vn_command_vkCreateRingMESA *args) -{ - struct vkr_context *ctx = dispatch->data; - const VkRingCreateInfoMESA *info = args->pCreateInfo; - const struct vkr_resource_attachment *att; - uint8_t *shared; - size_t size; - struct vkr_ring *ring; - - if (!info) { - vkr_cs_decoder_set_fatal(&ctx->decoder); - return; - } - - att = util_hash_table_get(ctx->resource_table, uintptr_to_pointer(info->resourceId)); - if (!att) { - vkr_cs_decoder_set_fatal(&ctx->decoder); - return; - } - - /* TODO support scatter-gather or require logically contiguous resources */ - if (att->resource->iov_count != 1) { - vrend_printf("vkr: no scatter-gather support for ring buffers (TODO)"); - vkr_cs_decoder_set_fatal(&ctx->decoder); - return; - } - - shared = att->resource->iov[0].iov_base; - size = att->resource->iov[0].iov_len; - if (info->offset > size || info->size > size - info->offset) { - vkr_cs_decoder_set_fatal(&ctx->decoder); - return; - } - - shared += info->offset; - size = info->size; - if (info->headOffset > size || info->tailOffset > size || info->statusOffset > size || - info->bufferOffset > size || info->extraOffset > size) { - vkr_cs_decoder_set_fatal(&ctx->decoder); - return; - } - if (sizeof(uint32_t) > size - info->headOffset || - sizeof(uint32_t) > size - info->tailOffset || - sizeof(uint32_t) > size - info->statusOffset || - info->bufferSize > size - info->bufferOffset || - info->extraSize > size - info->extraOffset) { - vkr_cs_decoder_set_fatal(&ctx->decoder); - return; - } - if (!info->bufferSize || !util_is_power_of_two(info->bufferSize)) { - vkr_cs_decoder_set_fatal(&ctx->decoder); - return; - } - - const struct vkr_ring_layout layout = { - .head_offset = info->headOffset, - .tail_offset = info->tailOffset, - .status_offset = info->statusOffset, - .buffer_offset = info->bufferOffset, - .buffer_size = info->bufferSize, - .extra_offset = info->extraOffset, - .extra_size = info->extraSize, - }; - - ring = vkr_ring_create(&layout, shared, &ctx->base, info->idleTimeout); - if (!ring) { - vkr_cs_decoder_set_fatal(&ctx->decoder); - return; - } - - ring->id = args->ring; - list_addtail(&ring->head, &ctx->rings); - - vkr_ring_start(ring); -} - -static void -vkr_dispatch_vkDestroyRingMESA(struct vn_dispatch_context *dispatch, - struct vn_command_vkDestroyRingMESA *args) -{ - struct vkr_context *ctx = dispatch->data; - struct vkr_ring *ring = lookup_ring(ctx, args->ring); - if (!ring || !vkr_ring_stop(ring)) { - vkr_cs_decoder_set_fatal(&ctx->decoder); - return; - } - - list_del(&ring->head); - vkr_ring_destroy(ring); -} - -static void -vkr_dispatch_vkNotifyRingMESA(struct vn_dispatch_context *dispatch, - struct vn_command_vkNotifyRingMESA *args) -{ - struct vkr_context *ctx = dispatch->data; - struct vkr_ring *ring = lookup_ring(ctx, args->ring); - if (!ring) { - vkr_cs_decoder_set_fatal(&ctx->decoder); - return; - } - - vkr_ring_notify(ring); -} - -static void -vkr_dispatch_vkWriteRingExtraMESA(struct vn_dispatch_context *dispatch, - struct vn_command_vkWriteRingExtraMESA *args) -{ - struct vkr_context *ctx = dispatch->data; - struct vkr_ring *ring = lookup_ring(ctx, args->ring); - if (!ring) { - vkr_cs_decoder_set_fatal(&ctx->decoder); - return; - } - - if (!vkr_ring_write_extra(ring, args->offset, args->value)) - vkr_cs_decoder_set_fatal(&ctx->decoder); -} - -static void -vkr_dispatch_vkGetVenusExperimentalFeatureData100000MESA( - struct vn_dispatch_context *dispatch, - struct vn_command_vkGetVenusExperimentalFeatureData100000MESA *args) -{ - struct vkr_context *ctx = dispatch->data; - - if (!args->pDataSize) { - vkr_cs_decoder_set_fatal(&ctx->decoder); - return; - } - - const VkVenusExperimentalFeatures100000MESA features = { - .memoryResourceAllocationSize = VK_TRUE, - }; - - vn_replace_vkGetVenusExperimentalFeatureData100000MESA_args_handle(args); - - if (!args->pData) { - *args->pDataSize = sizeof(features); - return; - } - - *args->pDataSize = MIN2(*args->pDataSize, sizeof(features)); - memcpy(args->pData, &features, *args->pDataSize); -} - static void vkr_dispatch_debug_log(UNUSED struct vn_dispatch_context *dispatch, const char *msg) { @@ -351,16 +58,7 @@ vkr_context_init_dispatch(struct vkr_context *ctx) dispatch->encoder = (struct vn_cs_encoder *)&ctx->encoder; dispatch->decoder = (struct vn_cs_decoder *)&ctx->decoder; - dispatch->dispatch_vkSetReplyCommandStreamMESA = - vkr_dispatch_vkSetReplyCommandStreamMESA; - dispatch->dispatch_vkSeekReplyCommandStreamMESA = - vkr_dispatch_vkSeekReplyCommandStreamMESA; - dispatch->dispatch_vkExecuteCommandStreamsMESA = - vkr_dispatch_vkExecuteCommandStreamsMESA; - dispatch->dispatch_vkCreateRingMESA = vkr_dispatch_vkCreateRingMESA; - dispatch->dispatch_vkDestroyRingMESA = vkr_dispatch_vkDestroyRingMESA; - dispatch->dispatch_vkNotifyRingMESA = vkr_dispatch_vkNotifyRingMESA; - dispatch->dispatch_vkWriteRingExtraMESA = vkr_dispatch_vkWriteRingExtraMESA; + vkr_context_init_transport_dispatch(ctx); vkr_context_init_instance_dispatch(ctx); vkr_context_init_physical_device_dispatch(ctx); @@ -398,9 +96,6 @@ vkr_context_init_dispatch(struct vkr_context *ctx) vkr_context_init_command_pool_dispatch(ctx); vkr_context_init_command_buffer_dispatch(ctx); - - dispatch->dispatch_vkGetVenusExperimentalFeatureData100000MESA = - vkr_dispatch_vkGetVenusExperimentalFeatureData100000MESA; } static int diff --git a/src/venus/vkr_transport.c b/src/venus/vkr_transport.c new file mode 100644 index 0000000..403f499 --- /dev/null +++ b/src/venus/vkr_transport.c @@ -0,0 +1,327 @@ +/* + * Copyright 2020 Google LLC + * SPDX-License-Identifier: MIT + */ + +#include "vkr_transport.h" + +#include "venus-protocol/vn_protocol_renderer_dispatches.h" +#include "venus-protocol/vn_protocol_renderer_transport.h" +#include "vrend_iov.h" + +#include "vkr_context.h" +#include "vkr_ring.h" + +static void +vkr_dispatch_vkSetReplyCommandStreamMESA( + struct vn_dispatch_context *dispatch, + struct vn_command_vkSetReplyCommandStreamMESA *args) +{ + struct vkr_context *ctx = dispatch->data; + struct vkr_resource_attachment *att; + + if (!args->pStream) { + vkr_cs_decoder_set_fatal(&ctx->decoder); + return; + } + + att = util_hash_table_get(ctx->resource_table, + uintptr_to_pointer(args->pStream->resourceId)); + if (!att) { + vkr_cs_decoder_set_fatal(&ctx->decoder); + return; + } + + vkr_cs_encoder_set_stream(&ctx->encoder, att->resource->iov, att->resource->iov_count, + args->pStream->offset, args->pStream->size); +} + +static void +vkr_dispatch_vkSeekReplyCommandStreamMESA( + struct vn_dispatch_context *dispatch, + struct vn_command_vkSeekReplyCommandStreamMESA *args) +{ + struct vkr_context *ctx = dispatch->data; + vkr_cs_encoder_seek_stream(&ctx->encoder, args->position); +} + +static void * +copy_command_stream(struct vkr_context *ctx, const VkCommandStreamDescriptionMESA *stream) +{ + struct vkr_resource_attachment *att; + struct virgl_resource *res; + + att = util_hash_table_get(ctx->resource_table, uintptr_to_pointer(stream->resourceId)); + if (!att) + return NULL; + res = att->resource; + + /* seek to offset */ + size_t iov_offset = stream->offset; + const struct iovec *iov = NULL; + for (int i = 0; i < res->iov_count; i++) { + if (iov_offset < res->iov[i].iov_len) { + iov = &res->iov[i]; + break; + } + iov_offset -= res->iov[i].iov_len; + } + if (!iov) + return NULL; + + /* XXX until the decoder supports scatter-gather and is robust enough, + * always make a copy in case the caller modifies the commands while we + * parse + */ + uint8_t *data = malloc(stream->size); + if (!data) + return NULL; + + uint32_t copied = 0; + while (true) { + const size_t s = MIN2(stream->size - copied, iov->iov_len - iov_offset); + memcpy(data + copied, (const uint8_t *)iov->iov_base + iov_offset, s); + + copied += s; + if (copied == stream->size) { + break; + } else if (iov == &res->iov[res->iov_count - 1]) { + free(data); + return NULL; + } + + iov++; + iov_offset = 0; + } + + return data; +} + +static void +vkr_dispatch_vkExecuteCommandStreamsMESA( + struct vn_dispatch_context *dispatch, + struct vn_command_vkExecuteCommandStreamsMESA *args) +{ + struct vkr_context *ctx = dispatch->data; + + if (!args->streamCount || !args->pStreams) { + vkr_cs_decoder_set_fatal(&ctx->decoder); + return; + } + + /* note that nested vkExecuteCommandStreamsMESA is not allowed */ + if (!vkr_cs_decoder_push_state(&ctx->decoder)) { + vkr_cs_decoder_set_fatal(&ctx->decoder); + return; + } + + for (uint32_t i = 0; i < args->streamCount; i++) { + const VkCommandStreamDescriptionMESA *stream = &args->pStreams[i]; + + if (args->pReplyPositions) + vkr_cs_encoder_seek_stream(&ctx->encoder, args->pReplyPositions[i]); + + if (!stream->size) + continue; + + void *data = copy_command_stream(ctx, stream); + if (!data) { + vkr_cs_decoder_set_fatal(&ctx->decoder); + break; + } + + vkr_cs_decoder_set_stream(&ctx->decoder, data, stream->size); + while (vkr_cs_decoder_has_command(&ctx->decoder)) { + vn_dispatch_command(&ctx->dispatch); + if (vkr_cs_decoder_get_fatal(&ctx->decoder)) + break; + } + + free(data); + + if (vkr_cs_decoder_get_fatal(&ctx->decoder)) + break; + } + + vkr_cs_decoder_pop_state(&ctx->decoder); +} + +static struct vkr_ring * +lookup_ring(struct vkr_context *ctx, uint64_t ring_id) +{ + struct vkr_ring *ring; + LIST_FOR_EACH_ENTRY (ring, &ctx->rings, head) { + if (ring->id == ring_id) + return ring; + } + return NULL; +} + +static void +vkr_dispatch_vkCreateRingMESA(struct vn_dispatch_context *dispatch, + struct vn_command_vkCreateRingMESA *args) +{ + struct vkr_context *ctx = dispatch->data; + const VkRingCreateInfoMESA *info = args->pCreateInfo; + const struct vkr_resource_attachment *att; + uint8_t *shared; + size_t size; + struct vkr_ring *ring; + + if (!info) { + vkr_cs_decoder_set_fatal(&ctx->decoder); + return; + } + + att = util_hash_table_get(ctx->resource_table, uintptr_to_pointer(info->resourceId)); + if (!att) { + vkr_cs_decoder_set_fatal(&ctx->decoder); + return; + } + + /* TODO support scatter-gather or require logically contiguous resources */ + if (att->resource->iov_count != 1) { + vrend_printf("vkr: no scatter-gather support for ring buffers (TODO)"); + vkr_cs_decoder_set_fatal(&ctx->decoder); + return; + } + + shared = att->resource->iov[0].iov_base; + size = att->resource->iov[0].iov_len; + if (info->offset > size || info->size > size - info->offset) { + vkr_cs_decoder_set_fatal(&ctx->decoder); + return; + } + + shared += info->offset; + size = info->size; + if (info->headOffset > size || info->tailOffset > size || info->statusOffset > size || + info->bufferOffset > size || info->extraOffset > size) { + vkr_cs_decoder_set_fatal(&ctx->decoder); + return; + } + if (sizeof(uint32_t) > size - info->headOffset || + sizeof(uint32_t) > size - info->tailOffset || + sizeof(uint32_t) > size - info->statusOffset || + info->bufferSize > size - info->bufferOffset || + info->extraSize > size - info->extraOffset) { + vkr_cs_decoder_set_fatal(&ctx->decoder); + return; + } + if (!info->bufferSize || !util_is_power_of_two(info->bufferSize)) { + vkr_cs_decoder_set_fatal(&ctx->decoder); + return; + } + + const struct vkr_ring_layout layout = { + .head_offset = info->headOffset, + .tail_offset = info->tailOffset, + .status_offset = info->statusOffset, + .buffer_offset = info->bufferOffset, + .buffer_size = info->bufferSize, + .extra_offset = info->extraOffset, + .extra_size = info->extraSize, + }; + + ring = vkr_ring_create(&layout, shared, &ctx->base, info->idleTimeout); + if (!ring) { + vkr_cs_decoder_set_fatal(&ctx->decoder); + return; + } + + ring->id = args->ring; + list_addtail(&ring->head, &ctx->rings); + + vkr_ring_start(ring); +} + +static void +vkr_dispatch_vkDestroyRingMESA(struct vn_dispatch_context *dispatch, + struct vn_command_vkDestroyRingMESA *args) +{ + struct vkr_context *ctx = dispatch->data; + struct vkr_ring *ring = lookup_ring(ctx, args->ring); + if (!ring || !vkr_ring_stop(ring)) { + vkr_cs_decoder_set_fatal(&ctx->decoder); + return; + } + + list_del(&ring->head); + vkr_ring_destroy(ring); +} + +static void +vkr_dispatch_vkNotifyRingMESA(struct vn_dispatch_context *dispatch, + struct vn_command_vkNotifyRingMESA *args) +{ + struct vkr_context *ctx = dispatch->data; + struct vkr_ring *ring = lookup_ring(ctx, args->ring); + if (!ring) { + vkr_cs_decoder_set_fatal(&ctx->decoder); + return; + } + + vkr_ring_notify(ring); +} + +static void +vkr_dispatch_vkWriteRingExtraMESA(struct vn_dispatch_context *dispatch, + struct vn_command_vkWriteRingExtraMESA *args) +{ + struct vkr_context *ctx = dispatch->data; + struct vkr_ring *ring = lookup_ring(ctx, args->ring); + if (!ring) { + vkr_cs_decoder_set_fatal(&ctx->decoder); + return; + } + + if (!vkr_ring_write_extra(ring, args->offset, args->value)) + vkr_cs_decoder_set_fatal(&ctx->decoder); +} + +static void +vkr_dispatch_vkGetVenusExperimentalFeatureData100000MESA( + struct vn_dispatch_context *dispatch, + struct vn_command_vkGetVenusExperimentalFeatureData100000MESA *args) +{ + struct vkr_context *ctx = dispatch->data; + + if (!args->pDataSize) { + vkr_cs_decoder_set_fatal(&ctx->decoder); + return; + } + + const VkVenusExperimentalFeatures100000MESA features = { + .memoryResourceAllocationSize = VK_TRUE, + }; + + vn_replace_vkGetVenusExperimentalFeatureData100000MESA_args_handle(args); + + if (!args->pData) { + *args->pDataSize = sizeof(features); + return; + } + + *args->pDataSize = MIN2(*args->pDataSize, sizeof(features)); + memcpy(args->pData, &features, *args->pDataSize); +} + +void +vkr_context_init_transport_dispatch(struct vkr_context *ctx) +{ + struct vn_dispatch_context *dispatch = &ctx->dispatch; + + dispatch->dispatch_vkSetReplyCommandStreamMESA = + vkr_dispatch_vkSetReplyCommandStreamMESA; + dispatch->dispatch_vkSeekReplyCommandStreamMESA = + vkr_dispatch_vkSeekReplyCommandStreamMESA; + dispatch->dispatch_vkExecuteCommandStreamsMESA = + vkr_dispatch_vkExecuteCommandStreamsMESA; + dispatch->dispatch_vkCreateRingMESA = vkr_dispatch_vkCreateRingMESA; + dispatch->dispatch_vkDestroyRingMESA = vkr_dispatch_vkDestroyRingMESA; + dispatch->dispatch_vkNotifyRingMESA = vkr_dispatch_vkNotifyRingMESA; + dispatch->dispatch_vkWriteRingExtraMESA = vkr_dispatch_vkWriteRingExtraMESA; + + dispatch->dispatch_vkGetVenusExperimentalFeatureData100000MESA = + vkr_dispatch_vkGetVenusExperimentalFeatureData100000MESA; +} diff --git a/src/venus/vkr_transport.h b/src/venus/vkr_transport.h new file mode 100644 index 0000000..7a3e0fd --- /dev/null +++ b/src/venus/vkr_transport.h @@ -0,0 +1,14 @@ +/* + * Copyright 2020 Google LLC + * SPDX-License-Identifier: MIT + */ + +#ifndef VKR_TRANSPORT_H +#define VKR_TRANSPORT_H + +#include "vkr_common.h" + +void +vkr_context_init_transport_dispatch(struct vkr_context *ctx); + +#endif /* VKR_TRANSPORT_H */