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