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
parent
6c32ccbf38
commit
cf743a06ff
@ -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…
Reference in new issue