1/*
2 * Copyright 2018 Collabora Ltd.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * on the rights to use, copy, modify, merge, publish, distribute, sub
8 * license, and/or sell copies of the Software, and to permit persons to whom
9 * the Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21 * USE OR OTHER DEALINGS IN THE SOFTWARE.
22 */
23
24#ifndef ZINK_SCREEN_H
25#define ZINK_SCREEN_H
26
27#include "zink_device_info.h"
28#include "zink_instance.h"
29#include "vk_dispatch_table.h"
30
31#include "util/u_idalloc.h"
32#include "pipe/p_screen.h"
33#include "util/slab.h"
34#include "compiler/nir/nir.h"
35#include "util/disk_cache.h"
36#include "util/log.h"
37#include "util/simple_mtx.h"
38#include "util/u_queue.h"
39#include "util/u_live_shader_cache.h"
40#include "pipebuffer/pb_cache.h"
41#include "pipebuffer/pb_slab.h"
42#include <vulkan/vulkan.h>
43
44extern uint32_t zink_debug;
45struct hash_table;
46
47struct zink_batch_state;
48struct zink_context;
49struct zink_descriptor_layout_key;
50struct zink_program;
51struct zink_shader;
52enum zink_descriptor_type;
53
54/* this is the spec minimum */
55#define ZINK_SPARSE_BUFFER_PAGE_SIZE (64 * 1024)
56
57#define ZINK_DEBUG_NIR 0x1
58#define ZINK_DEBUG_SPIRV 0x2
59#define ZINK_DEBUG_TGSI 0x4
60#define ZINK_DEBUG_VALIDATION 0x8
61
62#define NUM_SLAB_ALLOCATORS 3
63
64enum zink_descriptor_mode {
65   ZINK_DESCRIPTOR_MODE_AUTO,
66   ZINK_DESCRIPTOR_MODE_LAZY,
67   ZINK_DESCRIPTOR_MODE_NOFALLBACK,
68   ZINK_DESCRIPTOR_MODE_NOTEMPLATES,
69};
70
71struct zink_modifier_prop {
72    uint32_t                             drmFormatModifierCount;
73    VkDrmFormatModifierPropertiesEXT*    pDrmFormatModifierProperties;
74};
75
76struct zink_screen {
77   struct pipe_screen base;
78   bool threaded;
79   uint32_t curr_batch; //the current batch id
80   uint32_t last_finished; //this is racy but ultimately doesn't matter
81   VkSemaphore sem;
82   VkSemaphore prev_sem;
83   struct util_queue flush_queue;
84
85   unsigned buffer_rebind_counter;
86
87   bool device_lost;
88   struct sw_winsys *winsys;
89   int drm_fd;
90
91   struct hash_table framebuffer_cache;
92   simple_mtx_t framebuffer_mtx;
93
94   struct slab_parent_pool transfer_pool;
95   struct disk_cache *disk_cache;
96   struct util_queue cache_put_thread;
97   struct util_queue cache_get_thread;
98
99   struct util_live_shader_cache shaders;
100
101   struct {
102      struct pb_cache bo_cache;
103      struct pb_slabs bo_slabs[NUM_SLAB_ALLOCATORS];
104      unsigned min_alloc_size;
105      struct hash_table *bo_export_table;
106      simple_mtx_t bo_export_table_lock;
107      uint32_t next_bo_unique_id;
108   } pb;
109   uint8_t heap_map[VK_MAX_MEMORY_TYPES];
110   bool resizable_bar;
111
112   uint64_t total_video_mem;
113   uint64_t clamp_video_mem;
114   uint64_t total_mem;
115
116   VkInstance instance;
117   struct zink_instance_info instance_info;
118
119   VkPhysicalDevice pdev;
120   uint32_t vk_version, spirv_version;
121   struct util_idalloc_mt buffer_ids;
122
123   struct zink_device_info info;
124   struct nir_shader_compiler_options nir_options;
125
126   bool have_X8_D24_UNORM_PACK32;
127   bool have_D24_UNORM_S8_UINT;
128   bool have_triangle_fans;
129
130   uint32_t gfx_queue;
131   uint32_t max_queues;
132   uint32_t timestamp_valid_bits;
133   VkDevice dev;
134   VkQueue queue; //gfx+compute
135   VkQueue thread_queue; //gfx+compute
136   simple_mtx_t queue_lock;
137   VkDebugUtilsMessengerEXT debugUtilsCallbackHandle;
138
139   uint32_t cur_custom_border_color_samplers;
140
141   bool needs_mesa_wsi;
142   bool needs_mesa_flush_wsi;
143
144   struct vk_dispatch_table vk;
145
146   bool (*descriptor_program_init)(struct zink_context *ctx, struct zink_program *pg);
147   void (*descriptor_program_deinit)(struct zink_screen *screen, struct zink_program *pg);
148   void (*descriptors_update)(struct zink_context *ctx, bool is_compute);
149   void (*context_update_descriptor_states)(struct zink_context *ctx, bool is_compute);
150   void (*context_invalidate_descriptor_state)(struct zink_context *ctx, enum pipe_shader_type shader,
151                                               enum zink_descriptor_type type,
152                                               unsigned start, unsigned count);
153   bool (*batch_descriptor_init)(struct zink_screen *screen, struct zink_batch_state *bs);
154   void (*batch_descriptor_reset)(struct zink_screen *screen, struct zink_batch_state *bs);
155   void (*batch_descriptor_deinit)(struct zink_screen *screen, struct zink_batch_state *bs);
156   bool (*descriptors_init)(struct zink_context *ctx);
157   void (*descriptors_deinit)(struct zink_context *ctx);
158   enum zink_descriptor_mode descriptor_mode;
159
160   struct {
161      bool dual_color_blend_by_location;
162      bool inline_uniforms;
163   } driconf;
164
165   VkFormatProperties format_props[PIPE_FORMAT_COUNT];
166   struct zink_modifier_prop modifier_props[PIPE_FORMAT_COUNT];
167   struct {
168      uint32_t image_view;
169      uint32_t buffer_view;
170   } null_descriptor_hashes;
171
172   VkExtent2D maxSampleLocationGridSize[5];
173};
174
175
176/* update last_finished to account for batch_id wrapping */
177static inline void
178zink_screen_update_last_finished(struct zink_screen *screen, uint32_t batch_id)
179{
180   /* last_finished may have wrapped */
181   if (screen->last_finished < UINT_MAX / 2) {
182      /* last_finished has wrapped, batch_id has not */
183      if (batch_id > UINT_MAX / 2)
184         return;
185   } else if (batch_id < UINT_MAX / 2) {
186      /* batch_id has wrapped, last_finished has not */
187      screen->last_finished = batch_id;
188      return;
189   }
190   /* neither have wrapped */
191   screen->last_finished = MAX2(batch_id, screen->last_finished);
192}
193
194/* check a batch_id against last_finished while accounting for wrapping */
195static inline bool
196zink_screen_check_last_finished(struct zink_screen *screen, uint32_t batch_id)
197{
198   /* last_finished may have wrapped */
199   if (screen->last_finished < UINT_MAX / 2) {
200      /* last_finished has wrapped, batch_id has not */
201      if (batch_id > UINT_MAX / 2)
202         return true;
203   } else if (batch_id < UINT_MAX / 2) {
204      /* batch_id has wrapped, last_finished has not */
205      return false;
206   }
207   return screen->last_finished >= batch_id;
208}
209
210bool
211zink_screen_init_semaphore(struct zink_screen *screen);
212
213static inline bool
214zink_screen_handle_vkresult(struct zink_screen *screen, VkResult ret)
215{
216   bool success = false;
217   switch (ret) {
218   case VK_SUCCESS:
219      success = true;
220      break;
221   case VK_ERROR_DEVICE_LOST:
222      screen->device_lost = true;
223      FALLTHROUGH;
224   default:
225      success = false;
226      break;
227   }
228   return success;
229}
230
231static inline struct zink_screen *
232zink_screen(struct pipe_screen *pipe)
233{
234   return (struct zink_screen *)pipe;
235}
236
237
238struct mem_cache_entry {
239   VkDeviceMemory mem;
240   void *map;
241};
242
243#define VKCTX(fn) zink_screen(ctx->base.screen)->vk.fn
244#define VKSCR(fn) screen->vk.fn
245
246VkFormat
247zink_get_format(struct zink_screen *screen, enum pipe_format format);
248
249bool
250zink_screen_batch_id_wait(struct zink_screen *screen, uint32_t batch_id, uint64_t timeout);
251
252bool
253zink_screen_timeline_wait(struct zink_screen *screen, uint32_t batch_id, uint64_t timeout);
254
255bool
256zink_is_depth_format_supported(struct zink_screen *screen, VkFormat format);
257
258#define GET_PROC_ADDR_INSTANCE_LOCAL(instance, x) PFN_vk##x vk_##x = (PFN_vk##x)vkGetInstanceProcAddr(instance, "vk"#x)
259
260void
261zink_screen_update_pipeline_cache(struct zink_screen *screen, struct zink_program *pg);
262
263void
264zink_screen_get_pipeline_cache(struct zink_screen *screen, struct zink_program *pg);
265
266void
267zink_screen_init_descriptor_funcs(struct zink_screen *screen, bool fallback);
268
269void
270zink_stub_function_not_loaded(void);
271
272#define warn_missing_feature(feat) \
273   do { \
274      static bool warned = false; \
275      if (!warned) { \
276         fprintf(stderr, "WARNING: Incorrect rendering will happen, " \
277                         "because the Vulkan device doesn't support " \
278                         "the %s feature\n", feat); \
279         warned = true; \
280      } \
281   } while (0)
282
283#endif
284