1/* 2 * Copyright 2019 Google LLC 3 * SPDX-License-Identifier: MIT 4 */ 5 6#ifndef VN_RENDERER_H 7#define VN_RENDERER_H 8 9#include "vn_common.h" 10 11struct vn_renderer_shmem { 12 struct vn_refcount refcount; 13 14 uint32_t res_id; 15 size_t mmap_size; /* for internal use only (i.e., munmap) */ 16 void *mmap_ptr; 17 18 struct list_head cache_head; 19 int64_t cache_timestamp; 20}; 21 22struct vn_renderer_bo { 23 struct vn_refcount refcount; 24 25 uint32_t res_id; 26 /* for internal use only */ 27 size_t mmap_size; 28 void *mmap_ptr; 29}; 30 31/* 32 * A sync consists of a uint64_t counter. The counter can be updated by CPU 33 * or by GPU. It can also be waited on by CPU or by GPU until it reaches 34 * certain values. 35 * 36 * This models after timeline VkSemaphore rather than timeline drm_syncobj. 37 * The main difference is that drm_syncobj can have unsignaled value 0. 38 */ 39struct vn_renderer_sync { 40 uint32_t sync_id; 41}; 42 43struct vn_renderer_info { 44 struct { 45 bool has_primary; 46 int primary_major; 47 int primary_minor; 48 bool has_render; 49 int render_major; 50 int render_minor; 51 } drm; 52 53 struct { 54 uint16_t vendor_id; 55 uint16_t device_id; 56 57 bool has_bus_info; 58 uint16_t domain; 59 uint8_t bus; 60 uint8_t device; 61 uint8_t function; 62 } pci; 63 64 bool has_dma_buf_import; 65 bool has_cache_management; 66 bool has_external_sync; 67 bool has_implicit_fencing; 68 bool has_guest_vram; 69 70 uint32_t max_sync_queue_count; 71 72 /* hw capset */ 73 uint32_t wire_format_version; 74 uint32_t vk_xml_version; 75 uint32_t vk_ext_command_serialization_spec_version; 76 uint32_t vk_mesa_venus_protocol_spec_version; 77 uint32_t supports_blob_id_0; 78 /* combined mask for vk_extension_mask1, 2,..., N */ 79 uint32_t vk_extension_mask[32]; 80 uint32_t allow_vk_wait_syncs; 81}; 82 83struct vn_renderer_submit_batch { 84 const void *cs_data; 85 size_t cs_size; 86 87 /* 88 * Submit cs to the virtual sync queue identified by sync_queue_index. The 89 * virtual queue is assumed to be associated with the physical VkQueue 90 * identified by vk_queue_id. After the execution completes on the 91 * VkQueue, the virtual sync queue is signaled. 92 * 93 * sync_queue_index must be less than max_sync_queue_count. 94 * 95 * vk_queue_id specifies the object id of a VkQueue. 96 * 97 * When sync_queue_cpu is true, it specifies the special CPU sync queue, 98 * and sync_queue_index/vk_queue_id are ignored. TODO revisit this later 99 */ 100 uint32_t sync_queue_index; 101 bool sync_queue_cpu; 102 vn_object_id vk_queue_id; 103 104 /* syncs to update when the virtual sync queue is signaled */ 105 struct vn_renderer_sync *const *syncs; 106 /* TODO allow NULL when syncs are all binary? */ 107 const uint64_t *sync_values; 108 uint32_t sync_count; 109}; 110 111struct vn_renderer_submit { 112 /* BOs to pin and to fence implicitly 113 * 114 * TODO track all bos and automatically pin them. We don't do it yet 115 * because each vn_command_buffer owns a bo. We can probably make do by 116 * returning the bos to a bo cache and exclude bo cache from pinning. 117 */ 118 struct vn_renderer_bo *const *bos; 119 uint32_t bo_count; 120 121 const struct vn_renderer_submit_batch *batches; 122 uint32_t batch_count; 123}; 124 125struct vn_renderer_wait { 126 bool wait_any; 127 uint64_t timeout; 128 129 struct vn_renderer_sync *const *syncs; 130 /* TODO allow NULL when syncs are all binary? */ 131 const uint64_t *sync_values; 132 uint32_t sync_count; 133}; 134 135struct vn_renderer_ops { 136 void (*destroy)(struct vn_renderer *renderer, 137 const VkAllocationCallbacks *alloc); 138 139 VkResult (*submit)(struct vn_renderer *renderer, 140 const struct vn_renderer_submit *submit); 141 142 /* 143 * On success, returns VK_SUCCESS or VK_TIMEOUT. On failure, returns 144 * VK_ERROR_DEVICE_LOST or out of device/host memory. 145 */ 146 VkResult (*wait)(struct vn_renderer *renderer, 147 const struct vn_renderer_wait *wait); 148}; 149 150struct vn_renderer_shmem_ops { 151 struct vn_renderer_shmem *(*create)(struct vn_renderer *renderer, 152 size_t size); 153 void (*destroy)(struct vn_renderer *renderer, 154 struct vn_renderer_shmem *shmem); 155}; 156 157struct vn_renderer_bo_ops { 158 VkResult (*create_from_device_memory)( 159 struct vn_renderer *renderer, 160 VkDeviceSize size, 161 vn_object_id mem_id, 162 VkMemoryPropertyFlags flags, 163 VkExternalMemoryHandleTypeFlags external_handles, 164 struct vn_renderer_bo **out_bo); 165 166 VkResult (*create_from_dma_buf)(struct vn_renderer *renderer, 167 VkDeviceSize size, 168 int fd, 169 VkMemoryPropertyFlags flags, 170 struct vn_renderer_bo **out_bo); 171 172 bool (*destroy)(struct vn_renderer *renderer, struct vn_renderer_bo *bo); 173 174 int (*export_dma_buf)(struct vn_renderer *renderer, 175 struct vn_renderer_bo *bo); 176 177 /* map is not thread-safe */ 178 void *(*map)(struct vn_renderer *renderer, struct vn_renderer_bo *bo); 179 180 void (*flush)(struct vn_renderer *renderer, 181 struct vn_renderer_bo *bo, 182 VkDeviceSize offset, 183 VkDeviceSize size); 184 void (*invalidate)(struct vn_renderer *renderer, 185 struct vn_renderer_bo *bo, 186 VkDeviceSize offset, 187 VkDeviceSize size); 188}; 189 190enum vn_renderer_sync_flags { 191 VN_RENDERER_SYNC_SHAREABLE = 1u << 0, 192 VN_RENDERER_SYNC_BINARY = 1u << 1, 193}; 194 195struct vn_renderer_sync_ops { 196 VkResult (*create)(struct vn_renderer *renderer, 197 uint64_t initial_val, 198 uint32_t flags, 199 struct vn_renderer_sync **out_sync); 200 201 VkResult (*create_from_syncobj)(struct vn_renderer *renderer, 202 int fd, 203 bool sync_file, 204 struct vn_renderer_sync **out_sync); 205 void (*destroy)(struct vn_renderer *renderer, 206 struct vn_renderer_sync *sync); 207 208 int (*export_syncobj)(struct vn_renderer *renderer, 209 struct vn_renderer_sync *sync, 210 bool sync_file); 211 212 /* reset the counter */ 213 VkResult (*reset)(struct vn_renderer *renderer, 214 struct vn_renderer_sync *sync, 215 uint64_t initial_val); 216 217 /* read the current value from the counter */ 218 VkResult (*read)(struct vn_renderer *renderer, 219 struct vn_renderer_sync *sync, 220 uint64_t *val); 221 222 /* write a new value (larger than the current one) to the counter */ 223 VkResult (*write)(struct vn_renderer *renderer, 224 struct vn_renderer_sync *sync, 225 uint64_t val); 226}; 227 228struct vn_renderer { 229 struct vn_renderer_info info; 230 struct vn_renderer_ops ops; 231 struct vn_renderer_shmem_ops shmem_ops; 232 struct vn_renderer_bo_ops bo_ops; 233 struct vn_renderer_sync_ops sync_ops; 234}; 235 236VkResult 237vn_renderer_create_virtgpu(struct vn_instance *instance, 238 const VkAllocationCallbacks *alloc, 239 struct vn_renderer **renderer); 240 241VkResult 242vn_renderer_create_vtest(struct vn_instance *instance, 243 const VkAllocationCallbacks *alloc, 244 struct vn_renderer **renderer); 245 246static inline VkResult 247vn_renderer_create(struct vn_instance *instance, 248 const VkAllocationCallbacks *alloc, 249 struct vn_renderer **renderer) 250{ 251 if (VN_DEBUG(VTEST)) { 252 VkResult result = vn_renderer_create_vtest(instance, alloc, renderer); 253 if (result == VK_SUCCESS) 254 return VK_SUCCESS; 255 } 256 257 return vn_renderer_create_virtgpu(instance, alloc, renderer); 258} 259 260static inline void 261vn_renderer_destroy(struct vn_renderer *renderer, 262 const VkAllocationCallbacks *alloc) 263{ 264 renderer->ops.destroy(renderer, alloc); 265} 266 267static inline VkResult 268vn_renderer_submit(struct vn_renderer *renderer, 269 const struct vn_renderer_submit *submit) 270{ 271 return renderer->ops.submit(renderer, submit); 272} 273 274static inline VkResult 275vn_renderer_wait(struct vn_renderer *renderer, 276 const struct vn_renderer_wait *wait) 277{ 278 return renderer->ops.wait(renderer, wait); 279} 280 281static inline struct vn_renderer_shmem * 282vn_renderer_shmem_create(struct vn_renderer *renderer, size_t size) 283{ 284 VN_TRACE_FUNC(); 285 struct vn_renderer_shmem *shmem = 286 renderer->shmem_ops.create(renderer, size); 287 if (shmem) { 288 assert(vn_refcount_is_valid(&shmem->refcount)); 289 assert(shmem->res_id); 290 assert(shmem->mmap_size >= size); 291 assert(shmem->mmap_ptr); 292 } 293 294 return shmem; 295} 296 297static inline struct vn_renderer_shmem * 298vn_renderer_shmem_ref(struct vn_renderer *renderer, 299 struct vn_renderer_shmem *shmem) 300{ 301 vn_refcount_inc(&shmem->refcount); 302 return shmem; 303} 304 305static inline void 306vn_renderer_shmem_unref(struct vn_renderer *renderer, 307 struct vn_renderer_shmem *shmem) 308{ 309 if (vn_refcount_dec(&shmem->refcount)) 310 renderer->shmem_ops.destroy(renderer, shmem); 311} 312 313static inline VkResult 314vn_renderer_bo_create_from_device_memory( 315 struct vn_renderer *renderer, 316 VkDeviceSize size, 317 vn_object_id mem_id, 318 VkMemoryPropertyFlags flags, 319 VkExternalMemoryHandleTypeFlags external_handles, 320 struct vn_renderer_bo **out_bo) 321{ 322 struct vn_renderer_bo *bo; 323 VkResult result = renderer->bo_ops.create_from_device_memory( 324 renderer, size, mem_id, flags, external_handles, &bo); 325 if (result != VK_SUCCESS) 326 return result; 327 328 assert(vn_refcount_is_valid(&bo->refcount)); 329 assert(bo->res_id); 330 assert(!bo->mmap_size || bo->mmap_size >= size); 331 332 *out_bo = bo; 333 return VK_SUCCESS; 334} 335 336static inline VkResult 337vn_renderer_bo_create_from_dma_buf(struct vn_renderer *renderer, 338 VkDeviceSize size, 339 int fd, 340 VkMemoryPropertyFlags flags, 341 struct vn_renderer_bo **out_bo) 342{ 343 struct vn_renderer_bo *bo; 344 VkResult result = 345 renderer->bo_ops.create_from_dma_buf(renderer, size, fd, flags, &bo); 346 if (result != VK_SUCCESS) 347 return result; 348 349 assert(vn_refcount_is_valid(&bo->refcount)); 350 assert(bo->res_id); 351 assert(!bo->mmap_size || bo->mmap_size >= size); 352 353 *out_bo = bo; 354 return VK_SUCCESS; 355} 356 357static inline struct vn_renderer_bo * 358vn_renderer_bo_ref(struct vn_renderer *renderer, struct vn_renderer_bo *bo) 359{ 360 vn_refcount_inc(&bo->refcount); 361 return bo; 362} 363 364static inline bool 365vn_renderer_bo_unref(struct vn_renderer *renderer, struct vn_renderer_bo *bo) 366{ 367 if (vn_refcount_dec(&bo->refcount)) 368 return renderer->bo_ops.destroy(renderer, bo); 369 return false; 370} 371 372static inline int 373vn_renderer_bo_export_dma_buf(struct vn_renderer *renderer, 374 struct vn_renderer_bo *bo) 375{ 376 return renderer->bo_ops.export_dma_buf(renderer, bo); 377} 378 379static inline void * 380vn_renderer_bo_map(struct vn_renderer *renderer, struct vn_renderer_bo *bo) 381{ 382 return renderer->bo_ops.map(renderer, bo); 383} 384 385static inline void 386vn_renderer_bo_flush(struct vn_renderer *renderer, 387 struct vn_renderer_bo *bo, 388 VkDeviceSize offset, 389 VkDeviceSize end) 390{ 391 renderer->bo_ops.flush(renderer, bo, offset, end); 392} 393 394static inline void 395vn_renderer_bo_invalidate(struct vn_renderer *renderer, 396 struct vn_renderer_bo *bo, 397 VkDeviceSize offset, 398 VkDeviceSize size) 399{ 400 renderer->bo_ops.invalidate(renderer, bo, offset, size); 401} 402 403static inline VkResult 404vn_renderer_sync_create(struct vn_renderer *renderer, 405 uint64_t initial_val, 406 uint32_t flags, 407 struct vn_renderer_sync **out_sync) 408{ 409 return renderer->sync_ops.create(renderer, initial_val, flags, out_sync); 410} 411 412static inline VkResult 413vn_renderer_sync_create_from_syncobj(struct vn_renderer *renderer, 414 int fd, 415 bool sync_file, 416 struct vn_renderer_sync **out_sync) 417{ 418 return renderer->sync_ops.create_from_syncobj(renderer, fd, sync_file, 419 out_sync); 420} 421 422static inline void 423vn_renderer_sync_destroy(struct vn_renderer *renderer, 424 struct vn_renderer_sync *sync) 425{ 426 renderer->sync_ops.destroy(renderer, sync); 427} 428 429static inline int 430vn_renderer_sync_export_syncobj(struct vn_renderer *renderer, 431 struct vn_renderer_sync *sync, 432 bool sync_file) 433{ 434 return renderer->sync_ops.export_syncobj(renderer, sync, sync_file); 435} 436 437static inline VkResult 438vn_renderer_sync_reset(struct vn_renderer *renderer, 439 struct vn_renderer_sync *sync, 440 uint64_t initial_val) 441{ 442 return renderer->sync_ops.reset(renderer, sync, initial_val); 443} 444 445static inline VkResult 446vn_renderer_sync_read(struct vn_renderer *renderer, 447 struct vn_renderer_sync *sync, 448 uint64_t *val) 449{ 450 return renderer->sync_ops.read(renderer, sync, val); 451} 452 453static inline VkResult 454vn_renderer_sync_write(struct vn_renderer *renderer, 455 struct vn_renderer_sync *sync, 456 uint64_t val) 457{ 458 return renderer->sync_ops.write(renderer, sync, val); 459} 460 461#endif /* VN_RENDERER_H */ 462