17ec681f3Smrg/*
27ec681f3Smrg * Copyright 2019 Google LLC
37ec681f3Smrg * SPDX-License-Identifier: MIT
47ec681f3Smrg */
57ec681f3Smrg
67ec681f3Smrg#ifndef VN_CS_H
77ec681f3Smrg#define VN_CS_H
87ec681f3Smrg
97ec681f3Smrg#include "vn_common.h"
107ec681f3Smrg
117ec681f3Smrg#define VN_CS_ENCODER_BUFFER_INITIALIZER(storage)                            \
127ec681f3Smrg   (struct vn_cs_encoder_buffer) { .base = storage, }
137ec681f3Smrg
147ec681f3Smrg/* note that buffers points to an unamed local variable */
157ec681f3Smrg#define VN_CS_ENCODER_INITIALIZER_LOCAL(storage, size)                       \
167ec681f3Smrg   (struct vn_cs_encoder)                                                    \
177ec681f3Smrg   {                                                                         \
187ec681f3Smrg      .buffers = &VN_CS_ENCODER_BUFFER_INITIALIZER(storage),                 \
197ec681f3Smrg      .buffer_count = 1, .buffer_max = 1, .current_buffer_size = size,       \
207ec681f3Smrg      .cur = storage, .end = (const void *)(storage) + (size),               \
217ec681f3Smrg   }
227ec681f3Smrg
237ec681f3Smrg#define VN_CS_ENCODER_INITIALIZER(buf, size)                                 \
247ec681f3Smrg   (struct vn_cs_encoder)                                                    \
257ec681f3Smrg   {                                                                         \
267ec681f3Smrg      .buffers = (buf), .buffer_count = 1, .buffer_max = 1,                  \
277ec681f3Smrg      .current_buffer_size = size, .cur = (buf)->base,                       \
287ec681f3Smrg      .end = (buf)->base + (size),                                           \
297ec681f3Smrg   }
307ec681f3Smrg
317ec681f3Smrg#define VN_CS_DECODER_INITIALIZER(storage, size)                             \
327ec681f3Smrg   (struct vn_cs_decoder)                                                    \
337ec681f3Smrg   {                                                                         \
347ec681f3Smrg      .cur = storage, .end = (const void *)(storage) + (size),               \
357ec681f3Smrg   }
367ec681f3Smrg
377ec681f3Smrgstruct vn_cs_encoder_buffer {
387ec681f3Smrg   struct vn_renderer_shmem *shmem;
397ec681f3Smrg   size_t offset;
407ec681f3Smrg   void *base;
417ec681f3Smrg   size_t committed_size;
427ec681f3Smrg};
437ec681f3Smrg
447ec681f3Smrgstruct vn_cs_encoder {
457ec681f3Smrg   struct vn_instance *instance; /* TODO shmem cache */
467ec681f3Smrg   size_t min_buffer_size;
477ec681f3Smrg   bool indirect;
487ec681f3Smrg
497ec681f3Smrg   bool fatal_error;
507ec681f3Smrg
517ec681f3Smrg   struct vn_cs_encoder_buffer *buffers;
527ec681f3Smrg   uint32_t buffer_count;
537ec681f3Smrg   uint32_t buffer_max;
547ec681f3Smrg   size_t total_committed_size;
557ec681f3Smrg
567ec681f3Smrg   /* the current buffer is buffers[buffer_count - 1].shmem */
577ec681f3Smrg   size_t current_buffer_size;
587ec681f3Smrg   uint32_t current_buffer_roundtrip;
597ec681f3Smrg
607ec681f3Smrg   /* cur is the write pointer.  When cur passes end, the slow path is
617ec681f3Smrg    * triggered.
627ec681f3Smrg    */
637ec681f3Smrg   void *cur;
647ec681f3Smrg   const void *end;
657ec681f3Smrg};
667ec681f3Smrg
677ec681f3Smrgstruct vn_cs_decoder {
687ec681f3Smrg   const void *cur;
697ec681f3Smrg   const void *end;
707ec681f3Smrg};
717ec681f3Smrg
727ec681f3Smrgvoid
737ec681f3Smrgvn_cs_encoder_init_indirect(struct vn_cs_encoder *enc,
747ec681f3Smrg                            struct vn_instance *instance,
757ec681f3Smrg                            size_t min_size);
767ec681f3Smrg
777ec681f3Smrgvoid
787ec681f3Smrgvn_cs_encoder_fini(struct vn_cs_encoder *enc);
797ec681f3Smrg
807ec681f3Smrgvoid
817ec681f3Smrgvn_cs_encoder_reset(struct vn_cs_encoder *enc);
827ec681f3Smrg
837ec681f3Smrgstatic inline void
847ec681f3Smrgvn_cs_encoder_set_fatal(const struct vn_cs_encoder *enc)
857ec681f3Smrg{
867ec681f3Smrg   /* This is fatal and should be treated as VK_ERROR_DEVICE_LOST or even
877ec681f3Smrg    * abort().  Note that vn_cs_encoder_reset does not clear this.
887ec681f3Smrg    */
897ec681f3Smrg   ((struct vn_cs_encoder *)enc)->fatal_error = true;
907ec681f3Smrg}
917ec681f3Smrg
927ec681f3Smrgstatic inline bool
937ec681f3Smrgvn_cs_encoder_get_fatal(const struct vn_cs_encoder *enc)
947ec681f3Smrg{
957ec681f3Smrg   return enc->fatal_error;
967ec681f3Smrg}
977ec681f3Smrg
987ec681f3Smrgstatic inline bool
997ec681f3Smrgvn_cs_encoder_is_empty(const struct vn_cs_encoder *enc)
1007ec681f3Smrg{
1017ec681f3Smrg   return !enc->buffer_count || enc->cur == enc->buffers[0].base;
1027ec681f3Smrg}
1037ec681f3Smrg
1047ec681f3Smrgstatic inline size_t
1057ec681f3Smrgvn_cs_encoder_get_len(const struct vn_cs_encoder *enc)
1067ec681f3Smrg{
1077ec681f3Smrg   if (unlikely(!enc->buffer_count))
1087ec681f3Smrg      return 0;
1097ec681f3Smrg
1107ec681f3Smrg   size_t len = enc->total_committed_size;
1117ec681f3Smrg   const struct vn_cs_encoder_buffer *cur_buf =
1127ec681f3Smrg      &enc->buffers[enc->buffer_count - 1];
1137ec681f3Smrg   if (!cur_buf->committed_size)
1147ec681f3Smrg      len += enc->cur - cur_buf->base;
1157ec681f3Smrg   return len;
1167ec681f3Smrg}
1177ec681f3Smrg
1187ec681f3Smrgbool
1197ec681f3Smrgvn_cs_encoder_reserve_internal(struct vn_cs_encoder *enc, size_t size);
1207ec681f3Smrg
1217ec681f3Smrg/**
1227ec681f3Smrg * Reserve space for commands.
1237ec681f3Smrg */
1247ec681f3Smrgstatic inline bool
1257ec681f3Smrgvn_cs_encoder_reserve(struct vn_cs_encoder *enc, size_t size)
1267ec681f3Smrg{
1277ec681f3Smrg   if (unlikely(size > enc->end - enc->cur)) {
1287ec681f3Smrg      if (!vn_cs_encoder_reserve_internal(enc, size)) {
1297ec681f3Smrg         vn_cs_encoder_set_fatal(enc);
1307ec681f3Smrg         return false;
1317ec681f3Smrg      }
1327ec681f3Smrg      assert(size <= enc->end - enc->cur);
1337ec681f3Smrg   }
1347ec681f3Smrg
1357ec681f3Smrg   return true;
1367ec681f3Smrg}
1377ec681f3Smrg
1387ec681f3Smrgstatic inline void
1397ec681f3Smrgvn_cs_encoder_write(struct vn_cs_encoder *enc,
1407ec681f3Smrg                    size_t size,
1417ec681f3Smrg                    const void *val,
1427ec681f3Smrg                    size_t val_size)
1437ec681f3Smrg{
1447ec681f3Smrg   assert(val_size <= size);
1457ec681f3Smrg   assert(size <= enc->end - enc->cur);
1467ec681f3Smrg
1477ec681f3Smrg   /* we should not rely on the compiler to optimize away memcpy... */
1487ec681f3Smrg   memcpy(enc->cur, val, val_size);
1497ec681f3Smrg   enc->cur += size;
1507ec681f3Smrg}
1517ec681f3Smrg
1527ec681f3Smrgvoid
1537ec681f3Smrgvn_cs_encoder_commit(struct vn_cs_encoder *enc);
1547ec681f3Smrg
1557ec681f3Smrgstatic inline void
1567ec681f3Smrgvn_cs_decoder_init(struct vn_cs_decoder *dec, const void *data, size_t size)
1577ec681f3Smrg{
1587ec681f3Smrg   *dec = VN_CS_DECODER_INITIALIZER(data, size);
1597ec681f3Smrg}
1607ec681f3Smrg
1617ec681f3Smrgstatic inline void
1627ec681f3Smrgvn_cs_decoder_set_fatal(const struct vn_cs_decoder *dec)
1637ec681f3Smrg{
1647ec681f3Smrg   abort();
1657ec681f3Smrg}
1667ec681f3Smrg
1677ec681f3Smrgstatic inline bool
1687ec681f3Smrgvn_cs_decoder_peek_internal(const struct vn_cs_decoder *dec,
1697ec681f3Smrg                            size_t size,
1707ec681f3Smrg                            void *val,
1717ec681f3Smrg                            size_t val_size)
1727ec681f3Smrg{
1737ec681f3Smrg   assert(val_size <= size);
1747ec681f3Smrg
1757ec681f3Smrg   if (unlikely(size > dec->end - dec->cur)) {
1767ec681f3Smrg      vn_cs_decoder_set_fatal(dec);
1777ec681f3Smrg      memset(val, 0, val_size);
1787ec681f3Smrg      return false;
1797ec681f3Smrg   }
1807ec681f3Smrg
1817ec681f3Smrg   /* we should not rely on the compiler to optimize away memcpy... */
1827ec681f3Smrg   memcpy(val, dec->cur, val_size);
1837ec681f3Smrg   return true;
1847ec681f3Smrg}
1857ec681f3Smrg
1867ec681f3Smrgstatic inline void
1877ec681f3Smrgvn_cs_decoder_read(struct vn_cs_decoder *dec,
1887ec681f3Smrg                   size_t size,
1897ec681f3Smrg                   void *val,
1907ec681f3Smrg                   size_t val_size)
1917ec681f3Smrg{
1927ec681f3Smrg   if (vn_cs_decoder_peek_internal(dec, size, val, val_size))
1937ec681f3Smrg      dec->cur += size;
1947ec681f3Smrg}
1957ec681f3Smrg
1967ec681f3Smrgstatic inline void
1977ec681f3Smrgvn_cs_decoder_peek(const struct vn_cs_decoder *dec,
1987ec681f3Smrg                   size_t size,
1997ec681f3Smrg                   void *val,
2007ec681f3Smrg                   size_t val_size)
2017ec681f3Smrg{
2027ec681f3Smrg   vn_cs_decoder_peek_internal(dec, size, val, val_size);
2037ec681f3Smrg}
2047ec681f3Smrg
2057ec681f3Smrgstatic inline vn_object_id
2067ec681f3Smrgvn_cs_handle_load_id(const void **handle, VkObjectType type)
2077ec681f3Smrg{
2087ec681f3Smrg   return *handle ? vn_object_get_id(*handle, type) : 0;
2097ec681f3Smrg}
2107ec681f3Smrg
2117ec681f3Smrgstatic inline void
2127ec681f3Smrgvn_cs_handle_store_id(void **handle, vn_object_id id, VkObjectType type)
2137ec681f3Smrg{
2147ec681f3Smrg   vn_object_set_id(*handle, id, type);
2157ec681f3Smrg}
2167ec681f3Smrg
2177ec681f3Smrg#endif /* VN_CS_H */
218