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_RESOURCE_H
25 #define ZINK_RESOURCE_H
26 
27 struct pipe_screen;
28 struct sw_displaytarget;
29 struct zink_batch;
30 struct zink_context;
31 struct zink_bo;
32 
33 #include "util/hash_table.h"
34 #include "util/simple_mtx.h"
35 #include "util/u_transfer.h"
36 #include "util/u_range.h"
37 #include "util/u_dynarray.h"
38 #include "util/u_threaded_context.h"
39 
40 #include "zink_batch.h"
41 #include "zink_descriptors.h"
42 
43 #include <vulkan/vulkan.h>
44 
45 #define ZINK_MAP_TEMPORARY (PIPE_MAP_DRV_PRV << 0)
46 #define ZINK_BIND_TRANSIENT (1 << 30) //transient fb attachment
47 
48 struct mem_key {
49    unsigned seen_count;
50    struct {
51       unsigned heap_index;
52       VkMemoryRequirements reqs;
53    } key;
54 };
55 
56 struct zink_resource_object {
57    struct pipe_reference reference;
58 
59    VkPipelineStageFlagBits access_stage;
60    VkAccessFlags access;
61    bool unordered_barrier;
62 
63    unsigned persistent_maps; //if nonzero, requires vkFlushMappedMemoryRanges during batch use
64    struct zink_descriptor_refs desc_set_refs;
65 
66    struct util_dynarray tmp;
67 
68    union {
69       VkBuffer buffer;
70       VkImage image;
71    };
72 
73    VkSampleLocationsInfoEXT zs_evaluate;
74    bool needs_zs_evaluate;
75 
76    bool storage_init; //layout was set for image
77    bool transfer_dst;
78    bool is_buffer;
79    VkImageAspectFlags modifier_aspect;
80 
81    struct zink_bo *bo;
82    VkDeviceSize offset, size, alignment;
83    VkImageCreateFlags vkflags;
84    VkImageUsageFlags vkusage;
85 
86    bool host_visible;
87    bool coherent;
88 };
89 
90 struct zink_resource {
91    struct threaded_resource base;
92 
93    enum pipe_format internal_format:16;
94 
95    struct zink_resource_object *obj;
96    struct zink_resource_object *scanout_obj; //TODO: remove for wsi
97    bool scanout_obj_init;
98    union {
99       struct {
100          struct util_range valid_buffer_range;
101          uint32_t vbo_bind_mask : PIPE_MAX_ATTRIBS;
102          uint8_t ubo_bind_count[2];
103          uint8_t so_bind_count;
104          bool so_valid;
105          uint32_t ubo_bind_mask[PIPE_SHADER_TYPES];
106          uint32_t ssbo_bind_mask[PIPE_SHADER_TYPES];
107       };
108       struct {
109          VkFormat format;
110          VkImageLayout layout;
111          VkImageAspectFlags aspect;
112          bool optimal_tiling;
113          uint8_t fb_binds;
114       };
115    };
116    uint32_t sampler_binds[PIPE_SHADER_TYPES];
117    uint16_t image_bind_count[2]; //gfx, compute
118    uint16_t write_bind_count[2]; //gfx, compute
119    uint16_t bindless[2]; //tex, img
120    union {
121       uint16_t bind_count[2]; //gfx, compute
122       uint32_t all_binds;
123    };
124 
125    union {
126       struct {
127          struct hash_table bufferview_cache;
128          simple_mtx_t bufferview_mtx;
129       };
130       struct {
131          struct hash_table surface_cache;
132          simple_mtx_t surface_mtx;
133       };
134    };
135 
136    bool dmabuf_acquire;
137    struct sw_displaytarget *dt;
138    unsigned dt_stride;
139 
140    uint8_t modifiers_count;
141    uint64_t *modifiers;
142 };
143 
144 struct zink_transfer {
145    struct threaded_transfer base;
146    struct pipe_resource *staging_res;
147    unsigned offset;
148    unsigned depthPitch;
149 };
150 
151 static inline struct zink_resource *
zink_resource(struct pipe_resource * r)152 zink_resource(struct pipe_resource *r)
153 {
154    return (struct zink_resource *)r;
155 }
156 
157 bool
158 zink_screen_resource_init(struct pipe_screen *pscreen);
159 
160 void
161 zink_context_resource_init(struct pipe_context *pctx);
162 
163 void
164 zink_get_depth_stencil_resources(struct pipe_resource *res,
165                                  struct zink_resource **out_z,
166                                  struct zink_resource **out_s);
167 VkMappedMemoryRange
168 zink_resource_init_mem_range(struct zink_screen *screen, struct zink_resource_object *obj, VkDeviceSize offset, VkDeviceSize size);
169 void
170 zink_resource_setup_transfer_layouts(struct zink_context *ctx, struct zink_resource *src, struct zink_resource *dst);
171 
172 void
173 zink_destroy_resource_object(struct zink_screen *screen, struct zink_resource_object *resource_object);
174 
175 void
176 debug_describe_zink_resource_object(char *buf, const struct zink_resource_object *ptr);
177 
178 static inline void
zink_resource_object_reference(struct zink_screen * screen,struct zink_resource_object ** dst,struct zink_resource_object * src)179 zink_resource_object_reference(struct zink_screen *screen,
180                              struct zink_resource_object **dst,
181                              struct zink_resource_object *src)
182 {
183    struct zink_resource_object *old_dst = dst ? *dst : NULL;
184 
185    if (pipe_reference_described(old_dst ? &old_dst->reference : NULL, &src->reference,
186                                 (debug_reference_descriptor)debug_describe_zink_resource_object))
187       zink_destroy_resource_object(screen, old_dst);
188    if (dst) *dst = src;
189 }
190 
191 VkBuffer
192 zink_resource_tmp_buffer(struct zink_screen *screen, struct zink_resource *res, unsigned offset_add, unsigned add_binds, unsigned *offset);
193 
194 bool
195 zink_resource_object_init_storage(struct zink_context *ctx, struct zink_resource *res);
196 
197 static inline bool
zink_resource_has_binds(const struct zink_resource * res)198 zink_resource_has_binds(const struct zink_resource *res)
199 {
200    return res->all_binds > 0;
201 }
202 
203 #ifndef __cplusplus
204 #include "zink_bo.h"
205 
206 static inline bool
zink_resource_usage_is_unflushed(const struct zink_resource * res)207 zink_resource_usage_is_unflushed(const struct zink_resource *res)
208 {
209    return zink_bo_has_unflushed_usage(res->obj->bo);
210 }
211 
212 static inline bool
zink_resource_usage_is_unflushed_write(const struct zink_resource * res)213 zink_resource_usage_is_unflushed_write(const struct zink_resource *res)
214 {
215    return zink_batch_usage_is_unflushed(res->obj->bo->writes);
216 }
217 
218 
219 static inline bool
zink_resource_usage_matches(const struct zink_resource * res,const struct zink_batch_state * bs)220 zink_resource_usage_matches(const struct zink_resource *res, const struct zink_batch_state *bs)
221 {
222    return zink_bo_usage_matches(res->obj->bo, bs);
223 }
224 
225 static inline bool
zink_resource_has_usage(const struct zink_resource * res)226 zink_resource_has_usage(const struct zink_resource *res)
227 {
228    return zink_bo_has_usage(res->obj->bo);
229 }
230 
231 static inline bool
zink_resource_has_unflushed_usage(const struct zink_resource * res)232 zink_resource_has_unflushed_usage(const struct zink_resource *res)
233 {
234    return zink_bo_has_unflushed_usage(res->obj->bo);
235 }
236 
237 static inline bool
zink_resource_usage_check_completion(struct zink_screen * screen,struct zink_resource * res,enum zink_resource_access access)238 zink_resource_usage_check_completion(struct zink_screen *screen, struct zink_resource *res, enum zink_resource_access access)
239 {
240    return zink_bo_usage_check_completion(screen, res->obj->bo, access);
241 }
242 
243 static inline void
zink_resource_usage_wait(struct zink_context * ctx,struct zink_resource * res,enum zink_resource_access access)244 zink_resource_usage_wait(struct zink_context *ctx, struct zink_resource *res, enum zink_resource_access access)
245 {
246    zink_bo_usage_wait(ctx, res->obj->bo, access);
247 }
248 
249 static inline void
zink_resource_usage_set(struct zink_resource * res,struct zink_batch_state * bs,bool write)250 zink_resource_usage_set(struct zink_resource *res, struct zink_batch_state *bs, bool write)
251 {
252    zink_bo_usage_set(res->obj->bo, bs, write);
253 }
254 
255 static inline bool
zink_resource_object_usage_unset(struct zink_resource_object * obj,struct zink_batch_state * bs)256 zink_resource_object_usage_unset(struct zink_resource_object *obj, struct zink_batch_state *bs)
257 {
258    return zink_bo_usage_unset(obj->bo, bs);
259 }
260 
261 #endif
262 #endif
263