1/*
2 * Copyright 2019 Google LLC
3 * SPDX-License-Identifier: MIT
4 *
5 * based in part on anv and radv which are:
6 * Copyright © 2015 Intel Corporation
7 * Copyright © 2016 Red Hat.
8 * Copyright © 2016 Bas Nieuwenhuizen
9 */
10
11#ifndef VN_INSTANCE_H
12#define VN_INSTANCE_H
13
14#include "vn_common.h"
15
16#include "venus-protocol/vn_protocol_driver_defines.h"
17
18#include "vn_cs.h"
19#include "vn_renderer.h"
20#include "vn_renderer_util.h"
21#include "vn_ring.h"
22
23/* require and request at least Vulkan 1.1 at both instance and device levels
24 */
25#define VN_MIN_RENDERER_VERSION VK_API_VERSION_1_1
26
27/* max advertised version at both instance and device levels */
28#ifdef ANDROID
29#define VN_MAX_API_VERSION VK_MAKE_VERSION(1, 1, VK_HEADER_VERSION)
30#else
31#define VN_MAX_API_VERSION VK_MAKE_VERSION(1, 2, VK_HEADER_VERSION)
32#endif
33
34struct vn_instance {
35   struct vn_instance_base base;
36
37   struct driOptionCache dri_options;
38   struct driOptionCache available_dri_options;
39
40   struct vn_renderer *renderer;
41
42   struct vn_renderer_shmem_pool reply_shmem_pool;
43
44   /* XXX staged features to be merged to core venus protocol */
45   VkVenusExperimentalFeatures100000MESA experimental;
46
47   struct {
48      mtx_t mutex;
49      struct vn_renderer_shmem *shmem;
50      struct vn_ring ring;
51      uint64_t id;
52
53      struct vn_cs_encoder upload;
54      uint32_t command_dropped;
55
56      /* to synchronize renderer/ring */
57      mtx_t roundtrip_mutex;
58      uint32_t roundtrip_next;
59   } ring;
60
61   /* Between the driver and the app, VN_MAX_API_VERSION is what we advertise
62    * and base.base.app_info.api_version is what the app requests.
63    *
64    * Between the driver and the renderer, renderer_api_version is the api
65    * version we request internally, which can be higher than
66    * base.base.app_info.api_version.  renderer_version is the instance
67    * version we can use internally.
68    */
69   uint32_t renderer_api_version;
70   uint32_t renderer_version;
71
72   /* for VN_CS_ENCODER_STORAGE_SHMEM_POOL */
73   struct {
74      mtx_t mutex;
75      struct vn_renderer_shmem_pool pool;
76   } cs_shmem;
77
78   struct {
79      mtx_t mutex;
80      bool initialized;
81
82      struct vn_physical_device *devices;
83      uint32_t device_count;
84      VkPhysicalDeviceGroupProperties *groups;
85      uint32_t group_count;
86   } physical_device;
87};
88VK_DEFINE_HANDLE_CASTS(vn_instance,
89                       base.base.base,
90                       VkInstance,
91                       VK_OBJECT_TYPE_INSTANCE)
92
93VkResult
94vn_instance_submit_roundtrip(struct vn_instance *instance,
95                             uint32_t *roundtrip_seqno);
96
97void
98vn_instance_wait_roundtrip(struct vn_instance *instance,
99                           uint32_t roundtrip_seqno);
100
101static inline void
102vn_instance_roundtrip(struct vn_instance *instance)
103{
104   uint32_t roundtrip_seqno;
105   if (vn_instance_submit_roundtrip(instance, &roundtrip_seqno) == VK_SUCCESS)
106      vn_instance_wait_roundtrip(instance, roundtrip_seqno);
107}
108
109VkResult
110vn_instance_ring_submit(struct vn_instance *instance,
111                        const struct vn_cs_encoder *cs);
112
113static inline void
114vn_instance_ring_wait(struct vn_instance *instance)
115{
116   struct vn_ring *ring = &instance->ring.ring;
117   vn_ring_wait_all(ring);
118}
119
120struct vn_instance_submit_command {
121   /* empty command implies errors */
122   struct vn_cs_encoder command;
123   struct vn_cs_encoder_buffer buffer;
124   /* non-zero implies waiting */
125   size_t reply_size;
126
127   /* when reply_size is non-zero, NULL can be returned on errors */
128   struct vn_renderer_shmem *reply_shmem;
129   struct vn_cs_decoder reply;
130};
131
132static inline struct vn_cs_encoder *
133vn_instance_submit_command_init(struct vn_instance *instance,
134                                struct vn_instance_submit_command *submit,
135                                void *cmd_data,
136                                size_t cmd_size,
137                                size_t reply_size)
138{
139   submit->buffer = VN_CS_ENCODER_BUFFER_INITIALIZER(cmd_data);
140   submit->command = VN_CS_ENCODER_INITIALIZER(&submit->buffer, cmd_size);
141
142   submit->reply_size = reply_size;
143   submit->reply_shmem = NULL;
144
145   return &submit->command;
146}
147
148void
149vn_instance_submit_command(struct vn_instance *instance,
150                           struct vn_instance_submit_command *submit);
151
152static inline struct vn_cs_decoder *
153vn_instance_get_command_reply(struct vn_instance *instance,
154                              struct vn_instance_submit_command *submit)
155{
156   return submit->reply_shmem ? &submit->reply : NULL;
157}
158
159static inline void
160vn_instance_free_command_reply(struct vn_instance *instance,
161                               struct vn_instance_submit_command *submit)
162{
163   assert(submit->reply_shmem);
164   vn_renderer_shmem_unref(instance->renderer, submit->reply_shmem);
165}
166
167static inline struct vn_renderer_shmem *
168vn_instance_cs_shmem_alloc(struct vn_instance *instance,
169                           size_t size,
170                           size_t *out_offset)
171{
172   struct vn_renderer_shmem *shmem;
173
174   mtx_lock(&instance->cs_shmem.mutex);
175   shmem = vn_renderer_shmem_pool_alloc(
176      instance->renderer, &instance->cs_shmem.pool, size, out_offset);
177   mtx_unlock(&instance->cs_shmem.mutex);
178
179   return shmem;
180}
181
182#endif /* VN_INSTANCE_H */
183