vkr: split out vkr_transport.[ch]

No functional change.

Signed-off-by: Chia-I Wu <olvaffe@gmail.com>
Reviewed-by: Yiwei Zhang <zzyiwei@chromium.org>
Reviewed-by: Ryan Neph <ryanneph@google.com>
macos/master
Chia-I Wu 3 years ago
parent 6c32ccbf38
commit cf743a06ff
  1. 2
      src/meson.build
  2. 309
      src/venus/vkr_renderer.c
  3. 327
      src/venus/vkr_transport.c
  4. 14
      src/venus/vkr_transport.h

@ -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 = [

@ -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

@ -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;
}

@ -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 */
Loading…
Cancel
Save