Home | History | Annotate | Line # | Download | only in vulkan
      1 /*
      2  * Copyright 2019 Google LLC
      3  * SPDX-License-Identifier: MIT
      4  */
      5 
      6 #ifndef VN_CS_H
      7 #define VN_CS_H
      8 
      9 #include "vn_common.h"
     10 
     11 #define VN_CS_ENCODER_BUFFER_INITIALIZER(storage)                            \
     12    (struct vn_cs_encoder_buffer) { .base = storage, }
     13 
     14 /* note that buffers points to an unamed local variable */
     15 #define VN_CS_ENCODER_INITIALIZER_LOCAL(storage, size)                       \
     16    (struct vn_cs_encoder)                                                    \
     17    {                                                                         \
     18       .buffers = &VN_CS_ENCODER_BUFFER_INITIALIZER(storage),                 \
     19       .buffer_count = 1, .buffer_max = 1, .current_buffer_size = size,       \
     20       .cur = storage, .end = (const void *)(storage) + (size),               \
     21    }
     22 
     23 #define VN_CS_ENCODER_INITIALIZER(buf, size)                                 \
     24    (struct vn_cs_encoder)                                                    \
     25    {                                                                         \
     26       .buffers = (buf), .buffer_count = 1, .buffer_max = 1,                  \
     27       .current_buffer_size = size, .cur = (buf)->base,                       \
     28       .end = (buf)->base + (size),                                           \
     29    }
     30 
     31 #define VN_CS_DECODER_INITIALIZER(storage, size)                             \
     32    (struct vn_cs_decoder)                                                    \
     33    {                                                                         \
     34       .cur = storage, .end = (const void *)(storage) + (size),               \
     35    }
     36 
     37 struct vn_cs_encoder_buffer {
     38    struct vn_renderer_shmem *shmem;
     39    size_t offset;
     40    void *base;
     41    size_t committed_size;
     42 };
     43 
     44 struct vn_cs_encoder {
     45    struct vn_instance *instance; /* TODO shmem cache */
     46    size_t min_buffer_size;
     47    bool indirect;
     48 
     49    bool fatal_error;
     50 
     51    struct vn_cs_encoder_buffer *buffers;
     52    uint32_t buffer_count;
     53    uint32_t buffer_max;
     54    size_t total_committed_size;
     55 
     56    /* the current buffer is buffers[buffer_count - 1].shmem */
     57    size_t current_buffer_size;
     58    uint32_t current_buffer_roundtrip;
     59 
     60    /* cur is the write pointer.  When cur passes end, the slow path is
     61     * triggered.
     62     */
     63    void *cur;
     64    const void *end;
     65 };
     66 
     67 struct vn_cs_decoder {
     68    const void *cur;
     69    const void *end;
     70 };
     71 
     72 void
     73 vn_cs_encoder_init_indirect(struct vn_cs_encoder *enc,
     74                             struct vn_instance *instance,
     75                             size_t min_size);
     76 
     77 void
     78 vn_cs_encoder_fini(struct vn_cs_encoder *enc);
     79 
     80 void
     81 vn_cs_encoder_reset(struct vn_cs_encoder *enc);
     82 
     83 static inline void
     84 vn_cs_encoder_set_fatal(const struct vn_cs_encoder *enc)
     85 {
     86    /* This is fatal and should be treated as VK_ERROR_DEVICE_LOST or even
     87     * abort().  Note that vn_cs_encoder_reset does not clear this.
     88     */
     89    ((struct vn_cs_encoder *)enc)->fatal_error = true;
     90 }
     91 
     92 static inline bool
     93 vn_cs_encoder_get_fatal(const struct vn_cs_encoder *enc)
     94 {
     95    return enc->fatal_error;
     96 }
     97 
     98 static inline bool
     99 vn_cs_encoder_is_empty(const struct vn_cs_encoder *enc)
    100 {
    101    return !enc->buffer_count || enc->cur == enc->buffers[0].base;
    102 }
    103 
    104 static inline size_t
    105 vn_cs_encoder_get_len(const struct vn_cs_encoder *enc)
    106 {
    107    if (unlikely(!enc->buffer_count))
    108       return 0;
    109 
    110    size_t len = enc->total_committed_size;
    111    const struct vn_cs_encoder_buffer *cur_buf =
    112       &enc->buffers[enc->buffer_count - 1];
    113    if (!cur_buf->committed_size)
    114       len += enc->cur - cur_buf->base;
    115    return len;
    116 }
    117 
    118 bool
    119 vn_cs_encoder_reserve_internal(struct vn_cs_encoder *enc, size_t size);
    120 
    121 /**
    122  * Reserve space for commands.
    123  */
    124 static inline bool
    125 vn_cs_encoder_reserve(struct vn_cs_encoder *enc, size_t size)
    126 {
    127    if (unlikely(size > enc->end - enc->cur)) {
    128       if (!vn_cs_encoder_reserve_internal(enc, size)) {
    129          vn_cs_encoder_set_fatal(enc);
    130          return false;
    131       }
    132       assert(size <= enc->end - enc->cur);
    133    }
    134 
    135    return true;
    136 }
    137 
    138 static inline void
    139 vn_cs_encoder_write(struct vn_cs_encoder *enc,
    140                     size_t size,
    141                     const void *val,
    142                     size_t val_size)
    143 {
    144    assert(val_size <= size);
    145    assert(size <= enc->end - enc->cur);
    146 
    147    /* we should not rely on the compiler to optimize away memcpy... */
    148    memcpy(enc->cur, val, val_size);
    149    enc->cur += size;
    150 }
    151 
    152 void
    153 vn_cs_encoder_commit(struct vn_cs_encoder *enc);
    154 
    155 static inline void
    156 vn_cs_decoder_init(struct vn_cs_decoder *dec, const void *data, size_t size)
    157 {
    158    *dec = VN_CS_DECODER_INITIALIZER(data, size);
    159 }
    160 
    161 static inline void
    162 vn_cs_decoder_set_fatal(const struct vn_cs_decoder *dec)
    163 {
    164    abort();
    165 }
    166 
    167 static inline bool
    168 vn_cs_decoder_peek_internal(const struct vn_cs_decoder *dec,
    169                             size_t size,
    170                             void *val,
    171                             size_t val_size)
    172 {
    173    assert(val_size <= size);
    174 
    175    if (unlikely(size > dec->end - dec->cur)) {
    176       vn_cs_decoder_set_fatal(dec);
    177       memset(val, 0, val_size);
    178       return false;
    179    }
    180 
    181    /* we should not rely on the compiler to optimize away memcpy... */
    182    memcpy(val, dec->cur, val_size);
    183    return true;
    184 }
    185 
    186 static inline void
    187 vn_cs_decoder_read(struct vn_cs_decoder *dec,
    188                    size_t size,
    189                    void *val,
    190                    size_t val_size)
    191 {
    192    if (vn_cs_decoder_peek_internal(dec, size, val, val_size))
    193       dec->cur += size;
    194 }
    195 
    196 static inline void
    197 vn_cs_decoder_peek(const struct vn_cs_decoder *dec,
    198                    size_t size,
    199                    void *val,
    200                    size_t val_size)
    201 {
    202    vn_cs_decoder_peek_internal(dec, size, val, val_size);
    203 }
    204 
    205 static inline vn_object_id
    206 vn_cs_handle_load_id(const void **handle, VkObjectType type)
    207 {
    208    return *handle ? vn_object_get_id(*handle, type) : 0;
    209 }
    210 
    211 static inline void
    212 vn_cs_handle_store_id(void **handle, vn_object_id id, VkObjectType type)
    213 {
    214    vn_object_set_id(*handle, id, type);
    215 }
    216 
    217 #endif /* VN_CS_H */
    218