blob: c383597cd2d5723f53b0ce8c0799d4e8c12ade5f [file] [log] [blame]
/*
* Copyright 2021 Google LLC
* SPDX-License-Identifier: MIT
*/
#ifndef VKR_COMMON_H
#define VKR_COMMON_H
#include "config.h"
#include <assert.h>
#include <errno.h>
#include <inttypes.h>
#include <stdatomic.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "c11/threads.h"
#include "util/hash_table.h"
#include "util/macros.h"
#include "util/os_file.h"
#include "util/os_misc.h"
#include "util/u_double_list.h"
#include "util/u_math.h"
#include "util/u_memory.h"
#include "util/u_pointer.h"
#include "util/u_thread.h"
#include "venus-protocol/vulkan.h"
#include "virgl_context.h"
#include "virgl_util.h"
#include "virglrenderer.h"
#include "vkr_renderer.h"
/* cap instance and device api versions to this */
#define VKR_MAX_API_VERSION VK_API_VERSION_1_3
#define VKR_DEBUG(category) (unlikely(vkr_debug_flags & VKR_DEBUG_##category))
/* define a type-safe cast function */
#define VKR_DEFINE_OBJECT_CAST(vkr_type, vk_enum, vk_type) \
static inline struct vkr_##vkr_type *vkr_##vkr_type##_from_handle(vk_type handle) \
{ \
struct vkr_##vkr_type *obj = (struct vkr_##vkr_type *)(uintptr_t)handle; \
if (obj) { \
assert(obj->base.type == vk_enum); \
assert(obj->base.id); \
assert(obj->base.handle.vkr_type); \
assert((uintptr_t)obj->base.handle.vkr_type == obj->base.handle.u64); \
} \
return obj; \
}
/* vkr_region_is_valid should be used to check for overflows */
#define VKR_REGION_INIT(offset, size) \
{ \
.begin = (offset), .end = (offset) + (size) \
}
struct vn_info_extension_table;
struct vkr_context;
struct vkr_ring;
struct vkr_instance;
struct vkr_physical_device;
struct vkr_device;
struct vkr_queue;
struct vkr_fence;
struct vkr_semaphore;
struct vkr_event;
struct vkr_device_memory;
struct vkr_buffer;
struct vkr_buffer_view;
struct vkr_image;
struct vkr_image_view;
struct vkr_sampler;
struct vkr_sampler_ycbcr_conversion;
struct vkr_descriptor_set_layout;
struct vkr_descriptor_pool;
struct vkr_descriptor_set;
struct vkr_descriptor_update_template;
struct vkr_render_pass;
struct vkr_framebuffer;
struct vkr_query_pool;
struct vkr_shader_module;
struct vkr_pipeline_layout;
struct vkr_pipeline_cache;
struct vkr_pipeline;
struct vkr_command_pool;
struct vkr_command_buffer;
typedef uint64_t vkr_object_id;
enum vkr_debug_flags {
VKR_DEBUG_VALIDATE = 1 << 0,
};
/* base class for all objects */
struct vkr_object {
VkObjectType type;
vkr_object_id id;
union {
uint64_t u64;
VkInstance instance;
VkPhysicalDevice physical_device;
VkDevice device;
VkQueue queue;
VkCommandBuffer command_buffer;
VkBuffer buffer;
VkImage image;
VkSemaphore semaphore;
VkFence fence;
VkDeviceMemory device_memory;
VkEvent event;
VkQueryPool query_pool;
VkBufferView buffer_view;
VkImageView image_view;
VkShaderModule shader_module;
VkPipelineCache pipeline_cache;
VkPipelineLayout pipeline_layout;
VkPipeline pipeline;
VkRenderPass render_pass;
VkDescriptorSetLayout descriptor_set_layout;
VkSampler sampler;
VkDescriptorSet descriptor_set;
VkDescriptorPool descriptor_pool;
VkFramebuffer framebuffer;
VkCommandPool command_pool;
VkSamplerYcbcrConversion sampler_ycbcr_conversion;
VkDescriptorUpdateTemplate descriptor_update_template;
} handle;
struct list_head track_head;
};
struct object_array {
uint32_t count;
void **objects;
void *handle_storage;
/* true if the ownership of the objects has been transferred (to
* vkr_context::object_table)
*/
bool objects_stolen;
};
struct vkr_region {
size_t begin;
size_t end;
};
extern uint32_t vkr_debug_flags;
void
vkr_debug_init(void);
void
vkr_log(const char *fmt, ...);
static inline uint32_t
vkr_api_version_cap_minor(uint32_t version, uint32_t cap)
{
assert(VK_API_VERSION_MAJOR(version) == VK_API_VERSION_MAJOR(cap));
if (VK_API_VERSION_MINOR(version) > VK_API_VERSION_MINOR(cap))
version = cap - VK_API_VERSION_PATCH(cap) + VK_API_VERSION_PATCH(version);
return version;
}
void
vkr_extension_table_init(struct vn_info_extension_table *table,
const char *const *exts,
uint32_t count);
uint32_t
vkr_extension_get_spec_version(const char *name);
bool
object_array_init(struct vkr_context *ctx,
struct object_array *arr,
uint32_t count,
VkObjectType obj_type,
size_t obj_size,
size_t handle_size,
const void *handles);
void
object_array_fini(struct object_array *arr);
static inline void *
vkr_find_struct(const void *chain, VkStructureType type)
{
VkBaseOutStructure *s = (VkBaseOutStructure *)chain;
while (s) {
if (s->sType == type)
return s;
s = s->pNext;
}
return NULL;
}
/*
* Find struct in the pNext of chain and return its previous struct.
*/
static inline void *
vkr_find_prev_struct(const void *chain, VkStructureType type)
{
VkBaseOutStructure *prev = (VkBaseOutStructure *)chain;
while (prev->pNext) {
if (prev->pNext->sType == type)
return prev;
prev = prev->pNext;
}
return NULL;
}
static inline bool
vkr_is_recognized_object_type(VkObjectType type)
{
switch (type) {
/* VK_VERSION_1_0 */
case VK_OBJECT_TYPE_INSTANCE:
case VK_OBJECT_TYPE_PHYSICAL_DEVICE:
case VK_OBJECT_TYPE_DEVICE:
case VK_OBJECT_TYPE_QUEUE:
case VK_OBJECT_TYPE_SEMAPHORE:
case VK_OBJECT_TYPE_COMMAND_BUFFER:
case VK_OBJECT_TYPE_FENCE:
case VK_OBJECT_TYPE_DEVICE_MEMORY:
case VK_OBJECT_TYPE_BUFFER:
case VK_OBJECT_TYPE_IMAGE:
case VK_OBJECT_TYPE_EVENT:
case VK_OBJECT_TYPE_QUERY_POOL:
case VK_OBJECT_TYPE_BUFFER_VIEW:
case VK_OBJECT_TYPE_IMAGE_VIEW:
case VK_OBJECT_TYPE_SHADER_MODULE:
case VK_OBJECT_TYPE_PIPELINE_CACHE:
case VK_OBJECT_TYPE_PIPELINE_LAYOUT:
case VK_OBJECT_TYPE_RENDER_PASS:
case VK_OBJECT_TYPE_PIPELINE:
case VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT:
case VK_OBJECT_TYPE_SAMPLER:
case VK_OBJECT_TYPE_DESCRIPTOR_POOL:
case VK_OBJECT_TYPE_DESCRIPTOR_SET:
case VK_OBJECT_TYPE_FRAMEBUFFER:
case VK_OBJECT_TYPE_COMMAND_POOL:
/* VK_VERSION_1_1 */
case VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION:
case VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE:
return true;
default:
return false;
}
}
static inline void *
vkr_object_alloc(size_t size, VkObjectType type, vkr_object_id id)
{
assert(size >= sizeof(struct vkr_object));
assert(vkr_is_recognized_object_type(type));
struct vkr_object *obj = calloc(1, size);
if (!obj)
return NULL;
/* obj is only half-initialized */
obj->type = type;
obj->id = id;
return obj;
}
static inline bool
vkr_region_is_valid(const struct vkr_region *region)
{
return region->begin <= region->end;
}
static inline size_t
vkr_region_size(const struct vkr_region *region)
{
return region->end - region->begin;
}
static inline bool
vkr_region_is_aligned(const struct vkr_region *region, size_t align)
{
assert(util_is_power_of_two_nonzero(align));
return !((region->begin | region->end) & (align - 1));
}
static inline bool
vkr_region_is_disjoint(const struct vkr_region *region, const struct vkr_region *other)
{
return region->begin >= other->end || region->end <= other->begin;
}
static inline bool
vkr_region_is_within(const struct vkr_region *region, const struct vkr_region *other)
{
/* note that when region regresses to a point at other->end, both this
* function and vkr_region_is_disjoint return true
*/
return region->begin >= other->begin && region->end <= other->end;
}
static inline struct vkr_region
vkr_region_make_relative(const struct vkr_region *region)
{
return (struct vkr_region){
.end = region->end - region->begin,
};
}
#endif /* VKR_COMMON_H */