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_ring.h"
21 
22 /* require and request at least Vulkan 1.1 at both instance and device levels
23  */
24 #define VN_MIN_RENDERER_VERSION VK_API_VERSION_1_1
25 
26 /* max advertised version at both instance and device levels */
27 #ifdef ANDROID
28 #define VN_MAX_API_VERSION VK_MAKE_VERSION(1, 1, VK_HEADER_VERSION)
29 #else
30 #define VN_MAX_API_VERSION VK_MAKE_VERSION(1, 2, VK_HEADER_VERSION)
31 #endif
32 
33 struct vn_instance {
34    struct vn_instance_base base;
35 
36    struct driOptionCache dri_options;
37    struct driOptionCache available_dri_options;
38 
39    struct vn_renderer *renderer;
40    struct vn_renderer_info renderer_info;
41 
42    /* XXX staged features to be merged to core venus protocol */
43    VkVenusExperimentalFeatures100000MESA experimental;
44 
45    struct {
46       mtx_t mutex;
47       struct vn_renderer_shmem *shmem;
48       struct vn_ring ring;
49       uint64_t id;
50 
51       struct vn_cs_encoder upload;
52       uint32_t command_dropped;
53 
54       /* to synchronize renderer/ring */
55       mtx_t roundtrip_mutex;
56       uint32_t roundtrip_next;
57    } ring;
58 
59    struct {
60       struct vn_renderer_shmem *shmem;
61       size_t size;
62       size_t used;
63       void *ptr;
64    } reply;
65 
66    /* Between the driver and the app, VN_MAX_API_VERSION is what we advertise
67     * and base.base.app_info.api_version is what the app requests.
68     *
69     * Between the driver and the renderer, renderer_api_version is the api
70     * version we request internally, which can be higher than
71     * base.base.app_info.api_version.  renderer_version is the instance
72     * version we can use internally.
73     */
74    uint32_t renderer_api_version;
75    uint32_t renderer_version;
76 
77    struct {
78       mtx_t mutex;
79       bool initialized;
80 
81       struct vn_physical_device *devices;
82       uint32_t device_count;
83       VkPhysicalDeviceGroupProperties *groups;
84       uint32_t group_count;
85    } physical_device;
86 };
87 VK_DEFINE_HANDLE_CASTS(vn_instance,
88                        base.base.base,
89                        VkInstance,
90                        VK_OBJECT_TYPE_INSTANCE)
91 
92 VkResult
93 vn_instance_submit_roundtrip(struct vn_instance *instance,
94                              uint32_t *roundtrip_seqno);
95 
96 void
97 vn_instance_wait_roundtrip(struct vn_instance *instance,
98                            uint32_t roundtrip_seqno);
99 
100 static inline void
vn_instance_roundtrip(struct vn_instance * instance)101 vn_instance_roundtrip(struct vn_instance *instance)
102 {
103    uint32_t roundtrip_seqno;
104    if (vn_instance_submit_roundtrip(instance, &roundtrip_seqno) == VK_SUCCESS)
105       vn_instance_wait_roundtrip(instance, roundtrip_seqno);
106 }
107 
108 VkResult
109 vn_instance_ring_submit(struct vn_instance *instance,
110                         const struct vn_cs_encoder *cs);
111 
112 struct vn_instance_submit_command {
113    /* empty command implies errors */
114    struct vn_cs_encoder command;
115    struct vn_cs_encoder_buffer buffer;
116    /* non-zero implies waiting */
117    size_t reply_size;
118 
119    /* when reply_size is non-zero, NULL can be returned on errors */
120    struct vn_renderer_shmem *reply_shmem;
121    struct vn_cs_decoder reply;
122 };
123 
124 static inline struct vn_cs_encoder *
vn_instance_submit_command_init(struct vn_instance * instance,struct vn_instance_submit_command * submit,void * cmd_data,size_t cmd_size,size_t reply_size)125 vn_instance_submit_command_init(struct vn_instance *instance,
126                                 struct vn_instance_submit_command *submit,
127                                 void *cmd_data,
128                                 size_t cmd_size,
129                                 size_t reply_size)
130 {
131    submit->buffer = VN_CS_ENCODER_BUFFER_INITIALIZER(cmd_data);
132    submit->command = VN_CS_ENCODER_INITIALIZER(&submit->buffer, cmd_size);
133 
134    submit->reply_size = reply_size;
135    submit->reply_shmem = NULL;
136 
137    return &submit->command;
138 }
139 
140 void
141 vn_instance_submit_command(struct vn_instance *instance,
142                            struct vn_instance_submit_command *submit);
143 
144 static inline struct vn_cs_decoder *
vn_instance_get_command_reply(struct vn_instance * instance,struct vn_instance_submit_command * submit)145 vn_instance_get_command_reply(struct vn_instance *instance,
146                               struct vn_instance_submit_command *submit)
147 {
148    return submit->reply_shmem ? &submit->reply : NULL;
149 }
150 
151 static inline void
vn_instance_free_command_reply(struct vn_instance * instance,struct vn_instance_submit_command * submit)152 vn_instance_free_command_reply(struct vn_instance *instance,
153                                struct vn_instance_submit_command *submit)
154 {
155    assert(submit->reply_shmem);
156    vn_renderer_shmem_unref(instance->renderer, submit->reply_shmem);
157 }
158 
159 #endif /* VN_INSTANCE_H */
160