mesa/src/virtio/vulkan/vn_cs.h
Chia-I Wu 862244ccc6 venus: add and use VN_CS_ENCODER_INITIALIZER
Signed-off-by: Chia-I Wu <olvaffe@gmail.com>
Reviewed-by: Yiwei Zhang <zzyiwei@chromium.org>
Reviewed-by: Ryan Neph <ryanneph@google.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12568>
2021-09-08 16:38:24 +00:00

217 lines
5.8 KiB
C

/*
* Copyright 2019 Google LLC
* SPDX-License-Identifier: MIT
*/
#ifndef VN_CS_H
#define VN_CS_H
#include "vn_common.h"
#define VN_CS_ENCODER_BUFFER_INITIALIZER(storage) \
(struct vn_cs_encoder_buffer) { .base = storage, }
/* note that buffers points to an unamed local variable */
#define VN_CS_ENCODER_INITIALIZER_LOCAL(storage, size) \
(struct vn_cs_encoder) \
{ \
.buffers = &VN_CS_ENCODER_BUFFER_INITIALIZER(storage), \
.buffer_count = 1, .buffer_max = 1, .current_buffer_size = size, \
.cur = storage, .end = (const void *)(storage) + (size), \
}
#define VN_CS_ENCODER_INITIALIZER(buf, size) \
(struct vn_cs_encoder) \
{ \
.buffers = (buf), .buffer_count = 1, .buffer_max = 1, \
.current_buffer_size = size, .cur = (buf)->base, \
.end = (buf)->base + (size), \
}
#define VN_CS_DECODER_INITIALIZER(storage, size) \
(struct vn_cs_decoder) \
{ \
.cur = storage, .end = (const void *)(storage) + (size), \
}
struct vn_cs_encoder_buffer {
struct vn_renderer_shmem *shmem;
size_t offset;
void *base;
size_t committed_size;
};
struct vn_cs_encoder {
struct vn_instance *instance; /* TODO shmem cache */
size_t min_buffer_size;
bool indirect;
bool fatal_error;
struct vn_cs_encoder_buffer *buffers;
uint32_t buffer_count;
uint32_t buffer_max;
size_t total_committed_size;
/* the current buffer is buffers[buffer_count - 1].shmem */
size_t current_buffer_size;
uint32_t current_buffer_roundtrip;
/* cur is the write pointer. When cur passes end, the slow path is
* triggered.
*/
void *cur;
const void *end;
};
struct vn_cs_decoder {
const void *cur;
const void *end;
};
void
vn_cs_encoder_init_indirect(struct vn_cs_encoder *enc,
struct vn_instance *instance,
size_t min_size);
void
vn_cs_encoder_fini(struct vn_cs_encoder *enc);
void
vn_cs_encoder_reset(struct vn_cs_encoder *enc);
static inline void
vn_cs_encoder_set_fatal(const struct vn_cs_encoder *enc)
{
/* This is fatal and should be treated as VK_ERROR_DEVICE_LOST or even
* abort(). Note that vn_cs_encoder_reset does not clear this.
*/
((struct vn_cs_encoder *)enc)->fatal_error = true;
}
static inline bool
vn_cs_encoder_get_fatal(const struct vn_cs_encoder *enc)
{
return enc->fatal_error;
}
static inline bool
vn_cs_encoder_is_empty(const struct vn_cs_encoder *enc)
{
return !enc->buffer_count || enc->cur == enc->buffers[0].base;
}
static inline size_t
vn_cs_encoder_get_len(const struct vn_cs_encoder *enc)
{
if (unlikely(!enc->buffer_count))
return 0;
size_t len = enc->total_committed_size;
const struct vn_cs_encoder_buffer *cur_buf =
&enc->buffers[enc->buffer_count - 1];
if (!cur_buf->committed_size)
len += enc->cur - cur_buf->base;
return len;
}
bool
vn_cs_encoder_reserve_internal(struct vn_cs_encoder *enc, size_t size);
/**
* Reserve space for commands.
*/
static inline bool
vn_cs_encoder_reserve(struct vn_cs_encoder *enc, size_t size)
{
if (unlikely(size > enc->end - enc->cur)) {
if (!vn_cs_encoder_reserve_internal(enc, size)) {
vn_cs_encoder_set_fatal(enc);
return false;
}
assert(size <= enc->end - enc->cur);
}
return true;
}
static inline void
vn_cs_encoder_write(struct vn_cs_encoder *enc,
size_t size,
const void *val,
size_t val_size)
{
assert(val_size <= size);
assert(size <= enc->end - enc->cur);
/* we should not rely on the compiler to optimize away memcpy... */
memcpy(enc->cur, val, val_size);
enc->cur += size;
}
void
vn_cs_encoder_commit(struct vn_cs_encoder *enc);
static inline void
vn_cs_decoder_init(struct vn_cs_decoder *dec, const void *data, size_t size)
{
*dec = VN_CS_DECODER_INITIALIZER(data, size);
}
static inline void
vn_cs_decoder_set_fatal(const struct vn_cs_decoder *dec)
{
abort();
}
static inline bool
vn_cs_decoder_peek_internal(const struct vn_cs_decoder *dec,
size_t size,
void *val,
size_t val_size)
{
assert(val_size <= size);
if (unlikely(size > dec->end - dec->cur)) {
vn_cs_decoder_set_fatal(dec);
memset(val, 0, val_size);
return false;
}
/* we should not rely on the compiler to optimize away memcpy... */
memcpy(val, dec->cur, val_size);
return true;
}
static inline void
vn_cs_decoder_read(struct vn_cs_decoder *dec,
size_t size,
void *val,
size_t val_size)
{
if (vn_cs_decoder_peek_internal(dec, size, val, val_size))
dec->cur += size;
}
static inline void
vn_cs_decoder_peek(const struct vn_cs_decoder *dec,
size_t size,
void *val,
size_t val_size)
{
vn_cs_decoder_peek_internal(dec, size, val, val_size);
}
static inline vn_object_id
vn_cs_handle_load_id(const void **handle, VkObjectType type)
{
return *handle ? vn_object_get_id(*handle, type) : 0;
}
static inline void
vn_cs_handle_store_id(void **handle, vn_object_id id, VkObjectType type)
{
vn_object_set_id(*handle, id, type);
}
#endif /* VN_CS_H */