xref: /aosp_15_r20/external/mesa3d/src/asahi/vulkan/hk_device.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Copyright 2024 Valve Corporation
3*61046927SAndroid Build Coastguard Worker  * Copyright 2024 Alyssa Rosenzweig
4*61046927SAndroid Build Coastguard Worker  * Copyright 2022-2023 Collabora Ltd. and Red Hat Inc.
5*61046927SAndroid Build Coastguard Worker  * SPDX-License-Identifier: MIT
6*61046927SAndroid Build Coastguard Worker  */
7*61046927SAndroid Build Coastguard Worker #include "hk_device.h"
8*61046927SAndroid Build Coastguard Worker 
9*61046927SAndroid Build Coastguard Worker #include "agx_bg_eot.h"
10*61046927SAndroid Build Coastguard Worker #include "agx_helpers.h"
11*61046927SAndroid Build Coastguard Worker #include "agx_opcodes.h"
12*61046927SAndroid Build Coastguard Worker #include "agx_scratch.h"
13*61046927SAndroid Build Coastguard Worker #include "hk_cmd_buffer.h"
14*61046927SAndroid Build Coastguard Worker #include "hk_descriptor_table.h"
15*61046927SAndroid Build Coastguard Worker #include "hk_entrypoints.h"
16*61046927SAndroid Build Coastguard Worker #include "hk_instance.h"
17*61046927SAndroid Build Coastguard Worker #include "hk_physical_device.h"
18*61046927SAndroid Build Coastguard Worker #include "hk_shader.h"
19*61046927SAndroid Build Coastguard Worker 
20*61046927SAndroid Build Coastguard Worker #include "asahi/genxml/agx_pack.h"
21*61046927SAndroid Build Coastguard Worker #include "asahi/lib/agx_bo.h"
22*61046927SAndroid Build Coastguard Worker #include "asahi/lib/agx_device.h"
23*61046927SAndroid Build Coastguard Worker #include "asahi/lib/shaders/geometry.h"
24*61046927SAndroid Build Coastguard Worker #include "util/hash_table.h"
25*61046927SAndroid Build Coastguard Worker #include "util/os_file.h"
26*61046927SAndroid Build Coastguard Worker #include "util/ralloc.h"
27*61046927SAndroid Build Coastguard Worker #include "util/simple_mtx.h"
28*61046927SAndroid Build Coastguard Worker #include "vulkan/vulkan_core.h"
29*61046927SAndroid Build Coastguard Worker #include "vulkan/wsi/wsi_common.h"
30*61046927SAndroid Build Coastguard Worker #include "vk_cmd_enqueue_entrypoints.h"
31*61046927SAndroid Build Coastguard Worker #include "vk_common_entrypoints.h"
32*61046927SAndroid Build Coastguard Worker #include "vk_pipeline_cache.h"
33*61046927SAndroid Build Coastguard Worker 
34*61046927SAndroid Build Coastguard Worker #include <fcntl.h>
35*61046927SAndroid Build Coastguard Worker #include <xf86drm.h>
36*61046927SAndroid Build Coastguard Worker 
37*61046927SAndroid Build Coastguard Worker /*
38*61046927SAndroid Build Coastguard Worker  * We preupload some constants so we can cheaply reference later without extra
39*61046927SAndroid Build Coastguard Worker  * allocation and copying.
40*61046927SAndroid Build Coastguard Worker  *
41*61046927SAndroid Build Coastguard Worker  * TODO: This is small, don't waste a whole BO.
42*61046927SAndroid Build Coastguard Worker  */
43*61046927SAndroid Build Coastguard Worker static VkResult
hk_upload_rodata(struct hk_device * dev)44*61046927SAndroid Build Coastguard Worker hk_upload_rodata(struct hk_device *dev)
45*61046927SAndroid Build Coastguard Worker {
46*61046927SAndroid Build Coastguard Worker    dev->rodata.bo =
47*61046927SAndroid Build Coastguard Worker       agx_bo_create(&dev->dev, AGX_SAMPLER_LENGTH, 0, 0, "Read only data");
48*61046927SAndroid Build Coastguard Worker 
49*61046927SAndroid Build Coastguard Worker    if (!dev->rodata.bo)
50*61046927SAndroid Build Coastguard Worker       return VK_ERROR_OUT_OF_HOST_MEMORY;
51*61046927SAndroid Build Coastguard Worker 
52*61046927SAndroid Build Coastguard Worker    uint8_t *map = dev->rodata.bo->map;
53*61046927SAndroid Build Coastguard Worker    uint32_t offs = 0;
54*61046927SAndroid Build Coastguard Worker 
55*61046927SAndroid Build Coastguard Worker    offs = align(offs, 8);
56*61046927SAndroid Build Coastguard Worker    agx_pack(&dev->rodata.txf_sampler, USC_SAMPLER, cfg) {
57*61046927SAndroid Build Coastguard Worker       cfg.start = 0;
58*61046927SAndroid Build Coastguard Worker       cfg.count = 1;
59*61046927SAndroid Build Coastguard Worker       cfg.buffer = dev->rodata.bo->va->addr + offs;
60*61046927SAndroid Build Coastguard Worker    }
61*61046927SAndroid Build Coastguard Worker 
62*61046927SAndroid Build Coastguard Worker    agx_pack_txf_sampler((struct agx_sampler_packed *)(map + offs));
63*61046927SAndroid Build Coastguard Worker    offs += AGX_SAMPLER_LENGTH;
64*61046927SAndroid Build Coastguard Worker 
65*61046927SAndroid Build Coastguard Worker    /* The image heap is allocated on the device prior to the rodata. The heap
66*61046927SAndroid Build Coastguard Worker     * lives as long as the device does and has a stable address (requiring
67*61046927SAndroid Build Coastguard Worker     * sparse binding to grow dynamically). That means its address is effectively
68*61046927SAndroid Build Coastguard Worker     * rodata and can be uploaded now. agx_usc_uniform requires an indirection to
69*61046927SAndroid Build Coastguard Worker     * push the heap address, so this takes care of that indirection up front to
70*61046927SAndroid Build Coastguard Worker     * cut an alloc/upload at draw time.
71*61046927SAndroid Build Coastguard Worker     */
72*61046927SAndroid Build Coastguard Worker    offs = align(offs, sizeof(uint64_t));
73*61046927SAndroid Build Coastguard Worker    agx_pack(&dev->rodata.image_heap, USC_UNIFORM, cfg) {
74*61046927SAndroid Build Coastguard Worker       cfg.start_halfs = HK_IMAGE_HEAP_UNIFORM;
75*61046927SAndroid Build Coastguard Worker       cfg.size_halfs = 4;
76*61046927SAndroid Build Coastguard Worker       cfg.buffer = dev->rodata.bo->va->addr + offs;
77*61046927SAndroid Build Coastguard Worker    }
78*61046927SAndroid Build Coastguard Worker 
79*61046927SAndroid Build Coastguard Worker    uint64_t *image_heap_ptr = dev->rodata.bo->map + offs;
80*61046927SAndroid Build Coastguard Worker    *image_heap_ptr = dev->images.bo->va->addr;
81*61046927SAndroid Build Coastguard Worker    offs += sizeof(uint64_t);
82*61046927SAndroid Build Coastguard Worker 
83*61046927SAndroid Build Coastguard Worker    /* The geometry state buffer isn't strictly readonly data, but we only have a
84*61046927SAndroid Build Coastguard Worker     * single instance of it device-wide and -- after initializing at heap
85*61046927SAndroid Build Coastguard Worker     * allocate time -- it is read-only from the CPU perspective. The GPU uses it
86*61046927SAndroid Build Coastguard Worker     * for scratch, but is required to reset it after use to ensure resubmitting
87*61046927SAndroid Build Coastguard Worker     * the same command buffer works.
88*61046927SAndroid Build Coastguard Worker     *
89*61046927SAndroid Build Coastguard Worker     * So, we allocate it here for convenience.
90*61046927SAndroid Build Coastguard Worker     */
91*61046927SAndroid Build Coastguard Worker    offs = align(offs, sizeof(uint64_t));
92*61046927SAndroid Build Coastguard Worker    dev->rodata.geometry_state = dev->rodata.bo->va->addr + offs;
93*61046927SAndroid Build Coastguard Worker    offs += sizeof(struct agx_geometry_state);
94*61046927SAndroid Build Coastguard Worker 
95*61046927SAndroid Build Coastguard Worker    /* For null readonly buffers, we need to allocate 16 bytes of zeroes for
96*61046927SAndroid Build Coastguard Worker     * robustness2 semantics on read.
97*61046927SAndroid Build Coastguard Worker     */
98*61046927SAndroid Build Coastguard Worker    offs = align(offs, 16);
99*61046927SAndroid Build Coastguard Worker    dev->rodata.zero_sink = dev->rodata.bo->va->addr + offs;
100*61046927SAndroid Build Coastguard Worker    memset(dev->rodata.bo->map + offs, 0, 16);
101*61046927SAndroid Build Coastguard Worker    offs += 16;
102*61046927SAndroid Build Coastguard Worker 
103*61046927SAndroid Build Coastguard Worker    /* For null storage descriptors, we need to reserve 16 bytes to catch writes.
104*61046927SAndroid Build Coastguard Worker     * No particular content is required; we cannot get robustness2 semantics
105*61046927SAndroid Build Coastguard Worker     * without more work.
106*61046927SAndroid Build Coastguard Worker     */
107*61046927SAndroid Build Coastguard Worker    offs = align(offs, 16);
108*61046927SAndroid Build Coastguard Worker    dev->rodata.null_sink = dev->rodata.bo->va->addr + offs;
109*61046927SAndroid Build Coastguard Worker    offs += 16;
110*61046927SAndroid Build Coastguard Worker 
111*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
112*61046927SAndroid Build Coastguard Worker }
113*61046927SAndroid Build Coastguard Worker 
114*61046927SAndroid Build Coastguard Worker static uint32_t
internal_key_hash(const void * key_)115*61046927SAndroid Build Coastguard Worker internal_key_hash(const void *key_)
116*61046927SAndroid Build Coastguard Worker {
117*61046927SAndroid Build Coastguard Worker    const struct hk_internal_key *key = key_;
118*61046927SAndroid Build Coastguard Worker 
119*61046927SAndroid Build Coastguard Worker    return _mesa_hash_data(key, sizeof(struct hk_internal_key) + key->key_size);
120*61046927SAndroid Build Coastguard Worker }
121*61046927SAndroid Build Coastguard Worker 
122*61046927SAndroid Build Coastguard Worker static bool
internal_key_equal(const void * a_,const void * b_)123*61046927SAndroid Build Coastguard Worker internal_key_equal(const void *a_, const void *b_)
124*61046927SAndroid Build Coastguard Worker {
125*61046927SAndroid Build Coastguard Worker    const struct hk_internal_key *a = a_;
126*61046927SAndroid Build Coastguard Worker    const struct hk_internal_key *b = b_;
127*61046927SAndroid Build Coastguard Worker 
128*61046927SAndroid Build Coastguard Worker    return a->builder == b->builder && a->key_size == b->key_size &&
129*61046927SAndroid Build Coastguard Worker           memcmp(a->key, b->key, a->key_size) == 0;
130*61046927SAndroid Build Coastguard Worker }
131*61046927SAndroid Build Coastguard Worker 
132*61046927SAndroid Build Coastguard Worker static VkResult
hk_init_internal_shaders(struct hk_internal_shaders * s)133*61046927SAndroid Build Coastguard Worker hk_init_internal_shaders(struct hk_internal_shaders *s)
134*61046927SAndroid Build Coastguard Worker {
135*61046927SAndroid Build Coastguard Worker    s->ht = _mesa_hash_table_create(NULL, internal_key_hash, internal_key_equal);
136*61046927SAndroid Build Coastguard Worker    if (!s->ht)
137*61046927SAndroid Build Coastguard Worker       return VK_ERROR_OUT_OF_HOST_MEMORY;
138*61046927SAndroid Build Coastguard Worker 
139*61046927SAndroid Build Coastguard Worker    simple_mtx_init(&s->lock, mtx_plain);
140*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
141*61046927SAndroid Build Coastguard Worker }
142*61046927SAndroid Build Coastguard Worker 
143*61046927SAndroid Build Coastguard Worker static void
hk_destroy_internal_shaders(struct hk_device * dev,struct hk_internal_shaders * s,bool part)144*61046927SAndroid Build Coastguard Worker hk_destroy_internal_shaders(struct hk_device *dev,
145*61046927SAndroid Build Coastguard Worker                             struct hk_internal_shaders *s, bool part)
146*61046927SAndroid Build Coastguard Worker {
147*61046927SAndroid Build Coastguard Worker    hash_table_foreach(s->ht, ent) {
148*61046927SAndroid Build Coastguard Worker       if (part) {
149*61046927SAndroid Build Coastguard Worker          struct agx_shader_part *part = ent->data;
150*61046927SAndroid Build Coastguard Worker          free(part->binary);
151*61046927SAndroid Build Coastguard Worker 
152*61046927SAndroid Build Coastguard Worker          /* The agx_shader_part itself is ralloc'd against the hash table so
153*61046927SAndroid Build Coastguard Worker           * will be freed.
154*61046927SAndroid Build Coastguard Worker           */
155*61046927SAndroid Build Coastguard Worker       } else {
156*61046927SAndroid Build Coastguard Worker          struct hk_api_shader *obj = ent->data;
157*61046927SAndroid Build Coastguard Worker          hk_api_shader_destroy(&dev->vk, &obj->vk, NULL);
158*61046927SAndroid Build Coastguard Worker       }
159*61046927SAndroid Build Coastguard Worker    }
160*61046927SAndroid Build Coastguard Worker 
161*61046927SAndroid Build Coastguard Worker    _mesa_hash_table_destroy(s->ht, NULL);
162*61046927SAndroid Build Coastguard Worker    simple_mtx_destroy(&s->lock);
163*61046927SAndroid Build Coastguard Worker }
164*61046927SAndroid Build Coastguard Worker 
165*61046927SAndroid Build Coastguard Worker DERIVE_HASH_TABLE(agx_sampler_packed);
166*61046927SAndroid Build Coastguard Worker 
167*61046927SAndroid Build Coastguard Worker static VkResult
hk_init_sampler_heap(struct hk_device * dev,struct hk_sampler_heap * h)168*61046927SAndroid Build Coastguard Worker hk_init_sampler_heap(struct hk_device *dev, struct hk_sampler_heap *h)
169*61046927SAndroid Build Coastguard Worker {
170*61046927SAndroid Build Coastguard Worker    h->ht = agx_sampler_packed_table_create(NULL);
171*61046927SAndroid Build Coastguard Worker    if (!h->ht)
172*61046927SAndroid Build Coastguard Worker       return VK_ERROR_OUT_OF_HOST_MEMORY;
173*61046927SAndroid Build Coastguard Worker 
174*61046927SAndroid Build Coastguard Worker    VkResult result =
175*61046927SAndroid Build Coastguard Worker       hk_descriptor_table_init(dev, &h->table, AGX_SAMPLER_LENGTH, 1024, 1024);
176*61046927SAndroid Build Coastguard Worker 
177*61046927SAndroid Build Coastguard Worker    if (result != VK_SUCCESS) {
178*61046927SAndroid Build Coastguard Worker       ralloc_free(h->ht);
179*61046927SAndroid Build Coastguard Worker       return result;
180*61046927SAndroid Build Coastguard Worker    }
181*61046927SAndroid Build Coastguard Worker 
182*61046927SAndroid Build Coastguard Worker    simple_mtx_init(&h->lock, mtx_plain);
183*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
184*61046927SAndroid Build Coastguard Worker }
185*61046927SAndroid Build Coastguard Worker 
186*61046927SAndroid Build Coastguard Worker static void
hk_destroy_sampler_heap(struct hk_device * dev,struct hk_sampler_heap * h)187*61046927SAndroid Build Coastguard Worker hk_destroy_sampler_heap(struct hk_device *dev, struct hk_sampler_heap *h)
188*61046927SAndroid Build Coastguard Worker {
189*61046927SAndroid Build Coastguard Worker    hk_descriptor_table_finish(dev, &h->table);
190*61046927SAndroid Build Coastguard Worker    ralloc_free(h->ht);
191*61046927SAndroid Build Coastguard Worker    simple_mtx_destroy(&h->lock);
192*61046927SAndroid Build Coastguard Worker }
193*61046927SAndroid Build Coastguard Worker 
194*61046927SAndroid Build Coastguard Worker static VkResult
hk_sampler_heap_add_locked(struct hk_device * dev,struct hk_sampler_heap * h,struct agx_sampler_packed desc,struct hk_rc_sampler ** out)195*61046927SAndroid Build Coastguard Worker hk_sampler_heap_add_locked(struct hk_device *dev, struct hk_sampler_heap *h,
196*61046927SAndroid Build Coastguard Worker                            struct agx_sampler_packed desc,
197*61046927SAndroid Build Coastguard Worker                            struct hk_rc_sampler **out)
198*61046927SAndroid Build Coastguard Worker {
199*61046927SAndroid Build Coastguard Worker    struct hash_entry *ent = _mesa_hash_table_search(h->ht, &desc);
200*61046927SAndroid Build Coastguard Worker    if (ent != NULL) {
201*61046927SAndroid Build Coastguard Worker       *out = ent->data;
202*61046927SAndroid Build Coastguard Worker 
203*61046927SAndroid Build Coastguard Worker       assert((*out)->refcount != 0);
204*61046927SAndroid Build Coastguard Worker       (*out)->refcount++;
205*61046927SAndroid Build Coastguard Worker 
206*61046927SAndroid Build Coastguard Worker       return VK_SUCCESS;
207*61046927SAndroid Build Coastguard Worker    }
208*61046927SAndroid Build Coastguard Worker 
209*61046927SAndroid Build Coastguard Worker    struct hk_rc_sampler *rc = ralloc(h->ht, struct hk_rc_sampler);
210*61046927SAndroid Build Coastguard Worker    if (!rc)
211*61046927SAndroid Build Coastguard Worker       return VK_ERROR_OUT_OF_HOST_MEMORY;
212*61046927SAndroid Build Coastguard Worker 
213*61046927SAndroid Build Coastguard Worker    uint32_t index;
214*61046927SAndroid Build Coastguard Worker    VkResult result =
215*61046927SAndroid Build Coastguard Worker       hk_descriptor_table_add(dev, &h->table, &desc, sizeof(desc), &index);
216*61046927SAndroid Build Coastguard Worker    if (result != VK_SUCCESS) {
217*61046927SAndroid Build Coastguard Worker       ralloc_free(rc);
218*61046927SAndroid Build Coastguard Worker       return result;
219*61046927SAndroid Build Coastguard Worker    }
220*61046927SAndroid Build Coastguard Worker 
221*61046927SAndroid Build Coastguard Worker    *rc = (struct hk_rc_sampler){
222*61046927SAndroid Build Coastguard Worker       .key = desc,
223*61046927SAndroid Build Coastguard Worker       .refcount = 1,
224*61046927SAndroid Build Coastguard Worker       .index = index,
225*61046927SAndroid Build Coastguard Worker    };
226*61046927SAndroid Build Coastguard Worker 
227*61046927SAndroid Build Coastguard Worker    _mesa_hash_table_insert(h->ht, &rc->key, rc);
228*61046927SAndroid Build Coastguard Worker    *out = rc;
229*61046927SAndroid Build Coastguard Worker 
230*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
231*61046927SAndroid Build Coastguard Worker }
232*61046927SAndroid Build Coastguard Worker 
233*61046927SAndroid Build Coastguard Worker VkResult
hk_sampler_heap_add(struct hk_device * dev,struct agx_sampler_packed desc,struct hk_rc_sampler ** out)234*61046927SAndroid Build Coastguard Worker hk_sampler_heap_add(struct hk_device *dev, struct agx_sampler_packed desc,
235*61046927SAndroid Build Coastguard Worker                     struct hk_rc_sampler **out)
236*61046927SAndroid Build Coastguard Worker {
237*61046927SAndroid Build Coastguard Worker    struct hk_sampler_heap *h = &dev->samplers;
238*61046927SAndroid Build Coastguard Worker 
239*61046927SAndroid Build Coastguard Worker    simple_mtx_lock(&h->lock);
240*61046927SAndroid Build Coastguard Worker    VkResult result = hk_sampler_heap_add_locked(dev, h, desc, out);
241*61046927SAndroid Build Coastguard Worker    simple_mtx_unlock(&h->lock);
242*61046927SAndroid Build Coastguard Worker 
243*61046927SAndroid Build Coastguard Worker    return result;
244*61046927SAndroid Build Coastguard Worker }
245*61046927SAndroid Build Coastguard Worker 
246*61046927SAndroid Build Coastguard Worker static void
hk_sampler_heap_remove_locked(struct hk_device * dev,struct hk_sampler_heap * h,struct hk_rc_sampler * rc)247*61046927SAndroid Build Coastguard Worker hk_sampler_heap_remove_locked(struct hk_device *dev, struct hk_sampler_heap *h,
248*61046927SAndroid Build Coastguard Worker                               struct hk_rc_sampler *rc)
249*61046927SAndroid Build Coastguard Worker {
250*61046927SAndroid Build Coastguard Worker    assert(rc->refcount != 0);
251*61046927SAndroid Build Coastguard Worker    rc->refcount--;
252*61046927SAndroid Build Coastguard Worker 
253*61046927SAndroid Build Coastguard Worker    if (rc->refcount == 0) {
254*61046927SAndroid Build Coastguard Worker       hk_descriptor_table_remove(dev, &h->table, rc->index);
255*61046927SAndroid Build Coastguard Worker       _mesa_hash_table_remove_key(h->ht, &rc->key);
256*61046927SAndroid Build Coastguard Worker       ralloc_free(rc);
257*61046927SAndroid Build Coastguard Worker    }
258*61046927SAndroid Build Coastguard Worker }
259*61046927SAndroid Build Coastguard Worker 
260*61046927SAndroid Build Coastguard Worker void
hk_sampler_heap_remove(struct hk_device * dev,struct hk_rc_sampler * rc)261*61046927SAndroid Build Coastguard Worker hk_sampler_heap_remove(struct hk_device *dev, struct hk_rc_sampler *rc)
262*61046927SAndroid Build Coastguard Worker {
263*61046927SAndroid Build Coastguard Worker    struct hk_sampler_heap *h = &dev->samplers;
264*61046927SAndroid Build Coastguard Worker 
265*61046927SAndroid Build Coastguard Worker    simple_mtx_lock(&h->lock);
266*61046927SAndroid Build Coastguard Worker    hk_sampler_heap_remove_locked(dev, h, rc);
267*61046927SAndroid Build Coastguard Worker    simple_mtx_unlock(&h->lock);
268*61046927SAndroid Build Coastguard Worker }
269*61046927SAndroid Build Coastguard Worker 
270*61046927SAndroid Build Coastguard Worker /*
271*61046927SAndroid Build Coastguard Worker  * To implement nullDescriptor, the descriptor set code will reference
272*61046927SAndroid Build Coastguard Worker  * preuploaded null descriptors at fixed offsets in the image heap. Here we
273*61046927SAndroid Build Coastguard Worker  * upload those descriptors, initializing the image heap.
274*61046927SAndroid Build Coastguard Worker  */
275*61046927SAndroid Build Coastguard Worker static void
hk_upload_null_descriptors(struct hk_device * dev)276*61046927SAndroid Build Coastguard Worker hk_upload_null_descriptors(struct hk_device *dev)
277*61046927SAndroid Build Coastguard Worker {
278*61046927SAndroid Build Coastguard Worker    struct agx_texture_packed null_tex;
279*61046927SAndroid Build Coastguard Worker    struct agx_pbe_packed null_pbe;
280*61046927SAndroid Build Coastguard Worker    uint32_t offset_tex, offset_pbe;
281*61046927SAndroid Build Coastguard Worker 
282*61046927SAndroid Build Coastguard Worker    agx_set_null_texture(&null_tex, dev->rodata.null_sink);
283*61046927SAndroid Build Coastguard Worker    agx_set_null_pbe(&null_pbe, dev->rodata.null_sink);
284*61046927SAndroid Build Coastguard Worker 
285*61046927SAndroid Build Coastguard Worker    hk_descriptor_table_add(dev, &dev->images, &null_tex, sizeof(null_tex),
286*61046927SAndroid Build Coastguard Worker                            &offset_tex);
287*61046927SAndroid Build Coastguard Worker 
288*61046927SAndroid Build Coastguard Worker    hk_descriptor_table_add(dev, &dev->images, &null_pbe, sizeof(null_pbe),
289*61046927SAndroid Build Coastguard Worker                            &offset_pbe);
290*61046927SAndroid Build Coastguard Worker 
291*61046927SAndroid Build Coastguard Worker    assert((offset_tex * HK_IMAGE_STRIDE) == HK_NULL_TEX_OFFSET && "static");
292*61046927SAndroid Build Coastguard Worker    assert((offset_pbe * HK_IMAGE_STRIDE) == HK_NULL_PBE_OFFSET && "static");
293*61046927SAndroid Build Coastguard Worker }
294*61046927SAndroid Build Coastguard Worker 
295*61046927SAndroid Build Coastguard Worker VKAPI_ATTR VkResult VKAPI_CALL
hk_CreateDevice(VkPhysicalDevice physicalDevice,const VkDeviceCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkDevice * pDevice)296*61046927SAndroid Build Coastguard Worker hk_CreateDevice(VkPhysicalDevice physicalDevice,
297*61046927SAndroid Build Coastguard Worker                 const VkDeviceCreateInfo *pCreateInfo,
298*61046927SAndroid Build Coastguard Worker                 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice)
299*61046927SAndroid Build Coastguard Worker {
300*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(hk_physical_device, pdev, physicalDevice);
301*61046927SAndroid Build Coastguard Worker    VkResult result = VK_ERROR_OUT_OF_HOST_MEMORY;
302*61046927SAndroid Build Coastguard Worker    struct hk_device *dev;
303*61046927SAndroid Build Coastguard Worker 
304*61046927SAndroid Build Coastguard Worker    dev = vk_zalloc2(&pdev->vk.instance->alloc, pAllocator, sizeof(*dev), 8,
305*61046927SAndroid Build Coastguard Worker                     VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
306*61046927SAndroid Build Coastguard Worker    if (!dev)
307*61046927SAndroid Build Coastguard Worker       return vk_error(pdev, VK_ERROR_OUT_OF_HOST_MEMORY);
308*61046927SAndroid Build Coastguard Worker 
309*61046927SAndroid Build Coastguard Worker    struct vk_device_dispatch_table dispatch_table;
310*61046927SAndroid Build Coastguard Worker 
311*61046927SAndroid Build Coastguard Worker    /* For secondary command buffer support, overwrite any command entrypoints
312*61046927SAndroid Build Coastguard Worker     * in the main device-level dispatch table with
313*61046927SAndroid Build Coastguard Worker     * vk_cmd_enqueue_unless_primary_Cmd*.
314*61046927SAndroid Build Coastguard Worker     */
315*61046927SAndroid Build Coastguard Worker    vk_device_dispatch_table_from_entrypoints(
316*61046927SAndroid Build Coastguard Worker       &dispatch_table, &vk_cmd_enqueue_unless_primary_device_entrypoints, true);
317*61046927SAndroid Build Coastguard Worker 
318*61046927SAndroid Build Coastguard Worker    vk_device_dispatch_table_from_entrypoints(&dispatch_table,
319*61046927SAndroid Build Coastguard Worker                                              &hk_device_entrypoints, false);
320*61046927SAndroid Build Coastguard Worker    vk_device_dispatch_table_from_entrypoints(&dispatch_table,
321*61046927SAndroid Build Coastguard Worker                                              &wsi_device_entrypoints, false);
322*61046927SAndroid Build Coastguard Worker 
323*61046927SAndroid Build Coastguard Worker    /* Populate primary cmd_dispatch table */
324*61046927SAndroid Build Coastguard Worker    vk_device_dispatch_table_from_entrypoints(&dev->cmd_dispatch,
325*61046927SAndroid Build Coastguard Worker                                              &hk_device_entrypoints, true);
326*61046927SAndroid Build Coastguard Worker    vk_device_dispatch_table_from_entrypoints(&dev->cmd_dispatch,
327*61046927SAndroid Build Coastguard Worker                                              &wsi_device_entrypoints, false);
328*61046927SAndroid Build Coastguard Worker    vk_device_dispatch_table_from_entrypoints(
329*61046927SAndroid Build Coastguard Worker       &dev->cmd_dispatch, &vk_common_device_entrypoints, false);
330*61046927SAndroid Build Coastguard Worker 
331*61046927SAndroid Build Coastguard Worker    result = vk_device_init(&dev->vk, &pdev->vk, &dispatch_table, pCreateInfo,
332*61046927SAndroid Build Coastguard Worker                            pAllocator);
333*61046927SAndroid Build Coastguard Worker    if (result != VK_SUCCESS)
334*61046927SAndroid Build Coastguard Worker       goto fail_alloc;
335*61046927SAndroid Build Coastguard Worker 
336*61046927SAndroid Build Coastguard Worker    dev->vk.shader_ops = &hk_device_shader_ops;
337*61046927SAndroid Build Coastguard Worker    dev->vk.command_dispatch_table = &dev->cmd_dispatch;
338*61046927SAndroid Build Coastguard Worker 
339*61046927SAndroid Build Coastguard Worker    drmDevicePtr drm_device = NULL;
340*61046927SAndroid Build Coastguard Worker    int ret = drmGetDeviceFromDevId(pdev->render_dev, 0, &drm_device);
341*61046927SAndroid Build Coastguard Worker    if (ret != 0) {
342*61046927SAndroid Build Coastguard Worker       result = vk_errorf(dev, VK_ERROR_INITIALIZATION_FAILED,
343*61046927SAndroid Build Coastguard Worker                          "Failed to get DRM device: %m");
344*61046927SAndroid Build Coastguard Worker       goto fail_init;
345*61046927SAndroid Build Coastguard Worker    }
346*61046927SAndroid Build Coastguard Worker 
347*61046927SAndroid Build Coastguard Worker    const char *path = drm_device->nodes[DRM_NODE_RENDER];
348*61046927SAndroid Build Coastguard Worker    dev->dev.fd = open(path, O_RDWR | O_CLOEXEC);
349*61046927SAndroid Build Coastguard Worker    if (dev->dev.fd < 0) {
350*61046927SAndroid Build Coastguard Worker       drmFreeDevice(&drm_device);
351*61046927SAndroid Build Coastguard Worker       result = vk_errorf(dev, VK_ERROR_INITIALIZATION_FAILED,
352*61046927SAndroid Build Coastguard Worker                          "failed to open device %s", path);
353*61046927SAndroid Build Coastguard Worker       goto fail_init;
354*61046927SAndroid Build Coastguard Worker    }
355*61046927SAndroid Build Coastguard Worker 
356*61046927SAndroid Build Coastguard Worker    bool succ = agx_open_device(NULL, &dev->dev);
357*61046927SAndroid Build Coastguard Worker    drmFreeDevice(&drm_device);
358*61046927SAndroid Build Coastguard Worker    if (!succ) {
359*61046927SAndroid Build Coastguard Worker       result = vk_errorf(dev, VK_ERROR_INITIALIZATION_FAILED,
360*61046927SAndroid Build Coastguard Worker                          "Failed to get DRM device: %m");
361*61046927SAndroid Build Coastguard Worker       goto fail_fd;
362*61046927SAndroid Build Coastguard Worker    }
363*61046927SAndroid Build Coastguard Worker 
364*61046927SAndroid Build Coastguard Worker    vk_device_set_drm_fd(&dev->vk, dev->dev.fd);
365*61046927SAndroid Build Coastguard Worker    dev->vk.command_buffer_ops = &hk_cmd_buffer_ops;
366*61046927SAndroid Build Coastguard Worker 
367*61046927SAndroid Build Coastguard Worker    result = hk_descriptor_table_init(dev, &dev->images, AGX_TEXTURE_LENGTH,
368*61046927SAndroid Build Coastguard Worker                                      1024, 1024 * 1024);
369*61046927SAndroid Build Coastguard Worker    if (result != VK_SUCCESS)
370*61046927SAndroid Build Coastguard Worker       goto fail_dev;
371*61046927SAndroid Build Coastguard Worker 
372*61046927SAndroid Build Coastguard Worker    result = hk_init_sampler_heap(dev, &dev->samplers);
373*61046927SAndroid Build Coastguard Worker    if (result != VK_SUCCESS)
374*61046927SAndroid Build Coastguard Worker       goto fail_images;
375*61046927SAndroid Build Coastguard Worker 
376*61046927SAndroid Build Coastguard Worker    result = hk_descriptor_table_init(
377*61046927SAndroid Build Coastguard Worker       dev, &dev->occlusion_queries, sizeof(uint64_t), AGX_MAX_OCCLUSION_QUERIES,
378*61046927SAndroid Build Coastguard Worker       AGX_MAX_OCCLUSION_QUERIES);
379*61046927SAndroid Build Coastguard Worker    if (result != VK_SUCCESS)
380*61046927SAndroid Build Coastguard Worker       goto fail_samplers;
381*61046927SAndroid Build Coastguard Worker 
382*61046927SAndroid Build Coastguard Worker    result = hk_upload_rodata(dev);
383*61046927SAndroid Build Coastguard Worker    if (result != VK_SUCCESS)
384*61046927SAndroid Build Coastguard Worker       goto fail_queries;
385*61046927SAndroid Build Coastguard Worker 
386*61046927SAndroid Build Coastguard Worker    /* Depends on rodata */
387*61046927SAndroid Build Coastguard Worker    hk_upload_null_descriptors(dev);
388*61046927SAndroid Build Coastguard Worker 
389*61046927SAndroid Build Coastguard Worker    /* XXX: error handling, and should this even go on the device? */
390*61046927SAndroid Build Coastguard Worker    agx_bg_eot_init(&dev->bg_eot, &dev->dev);
391*61046927SAndroid Build Coastguard Worker    if (!dev->bg_eot.ht) {
392*61046927SAndroid Build Coastguard Worker       result = VK_ERROR_OUT_OF_HOST_MEMORY;
393*61046927SAndroid Build Coastguard Worker       goto fail_rodata;
394*61046927SAndroid Build Coastguard Worker    }
395*61046927SAndroid Build Coastguard Worker 
396*61046927SAndroid Build Coastguard Worker    result = hk_init_internal_shaders(&dev->prolog_epilog);
397*61046927SAndroid Build Coastguard Worker    if (result != VK_SUCCESS)
398*61046927SAndroid Build Coastguard Worker       goto fail_bg_eot;
399*61046927SAndroid Build Coastguard Worker 
400*61046927SAndroid Build Coastguard Worker    result = hk_init_internal_shaders(&dev->kernels);
401*61046927SAndroid Build Coastguard Worker    if (result != VK_SUCCESS)
402*61046927SAndroid Build Coastguard Worker       goto fail_internal_shaders;
403*61046927SAndroid Build Coastguard Worker 
404*61046927SAndroid Build Coastguard Worker    result =
405*61046927SAndroid Build Coastguard Worker       hk_queue_init(dev, &dev->queue, &pCreateInfo->pQueueCreateInfos[0], 0);
406*61046927SAndroid Build Coastguard Worker    if (result != VK_SUCCESS)
407*61046927SAndroid Build Coastguard Worker       goto fail_internal_shaders_2;
408*61046927SAndroid Build Coastguard Worker 
409*61046927SAndroid Build Coastguard Worker    struct vk_pipeline_cache_create_info cache_info = {
410*61046927SAndroid Build Coastguard Worker       .weak_ref = true,
411*61046927SAndroid Build Coastguard Worker    };
412*61046927SAndroid Build Coastguard Worker    dev->mem_cache = vk_pipeline_cache_create(&dev->vk, &cache_info, NULL);
413*61046927SAndroid Build Coastguard Worker    if (dev->mem_cache == NULL) {
414*61046927SAndroid Build Coastguard Worker       result = VK_ERROR_OUT_OF_HOST_MEMORY;
415*61046927SAndroid Build Coastguard Worker       goto fail_queue;
416*61046927SAndroid Build Coastguard Worker    }
417*61046927SAndroid Build Coastguard Worker 
418*61046927SAndroid Build Coastguard Worker    result = hk_device_init_meta(dev);
419*61046927SAndroid Build Coastguard Worker    if (result != VK_SUCCESS)
420*61046927SAndroid Build Coastguard Worker       goto fail_mem_cache;
421*61046927SAndroid Build Coastguard Worker 
422*61046927SAndroid Build Coastguard Worker    *pDevice = hk_device_to_handle(dev);
423*61046927SAndroid Build Coastguard Worker 
424*61046927SAndroid Build Coastguard Worker    simple_mtx_init(&dev->scratch.lock, mtx_plain);
425*61046927SAndroid Build Coastguard Worker    agx_scratch_init(&dev->dev, &dev->scratch.vs);
426*61046927SAndroid Build Coastguard Worker    agx_scratch_init(&dev->dev, &dev->scratch.fs);
427*61046927SAndroid Build Coastguard Worker    agx_scratch_init(&dev->dev, &dev->scratch.cs);
428*61046927SAndroid Build Coastguard Worker 
429*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
430*61046927SAndroid Build Coastguard Worker 
431*61046927SAndroid Build Coastguard Worker fail_mem_cache:
432*61046927SAndroid Build Coastguard Worker    vk_pipeline_cache_destroy(dev->mem_cache, NULL);
433*61046927SAndroid Build Coastguard Worker fail_queue:
434*61046927SAndroid Build Coastguard Worker    hk_queue_finish(dev, &dev->queue);
435*61046927SAndroid Build Coastguard Worker fail_rodata:
436*61046927SAndroid Build Coastguard Worker    agx_bo_unreference(&dev->dev, dev->rodata.bo);
437*61046927SAndroid Build Coastguard Worker fail_bg_eot:
438*61046927SAndroid Build Coastguard Worker    agx_bg_eot_cleanup(&dev->bg_eot);
439*61046927SAndroid Build Coastguard Worker fail_internal_shaders_2:
440*61046927SAndroid Build Coastguard Worker    hk_destroy_internal_shaders(dev, &dev->kernels, false);
441*61046927SAndroid Build Coastguard Worker fail_internal_shaders:
442*61046927SAndroid Build Coastguard Worker    hk_destroy_internal_shaders(dev, &dev->prolog_epilog, true);
443*61046927SAndroid Build Coastguard Worker fail_queries:
444*61046927SAndroid Build Coastguard Worker    hk_descriptor_table_finish(dev, &dev->occlusion_queries);
445*61046927SAndroid Build Coastguard Worker fail_samplers:
446*61046927SAndroid Build Coastguard Worker    hk_destroy_sampler_heap(dev, &dev->samplers);
447*61046927SAndroid Build Coastguard Worker fail_images:
448*61046927SAndroid Build Coastguard Worker    hk_descriptor_table_finish(dev, &dev->images);
449*61046927SAndroid Build Coastguard Worker fail_dev:
450*61046927SAndroid Build Coastguard Worker    agx_close_device(&dev->dev);
451*61046927SAndroid Build Coastguard Worker fail_fd:
452*61046927SAndroid Build Coastguard Worker    close(dev->dev.fd);
453*61046927SAndroid Build Coastguard Worker fail_init:
454*61046927SAndroid Build Coastguard Worker    vk_device_finish(&dev->vk);
455*61046927SAndroid Build Coastguard Worker fail_alloc:
456*61046927SAndroid Build Coastguard Worker    vk_free(&dev->vk.alloc, dev);
457*61046927SAndroid Build Coastguard Worker    return result;
458*61046927SAndroid Build Coastguard Worker }
459*61046927SAndroid Build Coastguard Worker 
460*61046927SAndroid Build Coastguard Worker VKAPI_ATTR void VKAPI_CALL
hk_DestroyDevice(VkDevice _device,const VkAllocationCallbacks * pAllocator)461*61046927SAndroid Build Coastguard Worker hk_DestroyDevice(VkDevice _device, const VkAllocationCallbacks *pAllocator)
462*61046927SAndroid Build Coastguard Worker {
463*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(hk_device, dev, _device);
464*61046927SAndroid Build Coastguard Worker 
465*61046927SAndroid Build Coastguard Worker    if (!dev)
466*61046927SAndroid Build Coastguard Worker       return;
467*61046927SAndroid Build Coastguard Worker 
468*61046927SAndroid Build Coastguard Worker    hk_device_finish_meta(dev);
469*61046927SAndroid Build Coastguard Worker    hk_destroy_internal_shaders(dev, &dev->kernels, false);
470*61046927SAndroid Build Coastguard Worker    hk_destroy_internal_shaders(dev, &dev->prolog_epilog, true);
471*61046927SAndroid Build Coastguard Worker 
472*61046927SAndroid Build Coastguard Worker    vk_pipeline_cache_destroy(dev->mem_cache, NULL);
473*61046927SAndroid Build Coastguard Worker    hk_queue_finish(dev, &dev->queue);
474*61046927SAndroid Build Coastguard Worker    vk_device_finish(&dev->vk);
475*61046927SAndroid Build Coastguard Worker 
476*61046927SAndroid Build Coastguard Worker    agx_scratch_fini(&dev->scratch.vs);
477*61046927SAndroid Build Coastguard Worker    agx_scratch_fini(&dev->scratch.fs);
478*61046927SAndroid Build Coastguard Worker    agx_scratch_fini(&dev->scratch.cs);
479*61046927SAndroid Build Coastguard Worker    simple_mtx_destroy(&dev->scratch.lock);
480*61046927SAndroid Build Coastguard Worker 
481*61046927SAndroid Build Coastguard Worker    hk_destroy_sampler_heap(dev, &dev->samplers);
482*61046927SAndroid Build Coastguard Worker    hk_descriptor_table_finish(dev, &dev->images);
483*61046927SAndroid Build Coastguard Worker    hk_descriptor_table_finish(dev, &dev->occlusion_queries);
484*61046927SAndroid Build Coastguard Worker    agx_bo_unreference(&dev->dev, dev->rodata.bo);
485*61046927SAndroid Build Coastguard Worker    agx_bo_unreference(&dev->dev, dev->heap);
486*61046927SAndroid Build Coastguard Worker    agx_bg_eot_cleanup(&dev->bg_eot);
487*61046927SAndroid Build Coastguard Worker    agx_close_device(&dev->dev);
488*61046927SAndroid Build Coastguard Worker    vk_free(&dev->vk.alloc, dev);
489*61046927SAndroid Build Coastguard Worker }
490*61046927SAndroid Build Coastguard Worker 
491*61046927SAndroid Build Coastguard Worker VKAPI_ATTR VkResult VKAPI_CALL
hk_GetCalibratedTimestampsKHR(VkDevice _device,uint32_t timestampCount,const VkCalibratedTimestampInfoKHR * pTimestampInfos,uint64_t * pTimestamps,uint64_t * pMaxDeviation)492*61046927SAndroid Build Coastguard Worker hk_GetCalibratedTimestampsKHR(
493*61046927SAndroid Build Coastguard Worker    VkDevice _device, uint32_t timestampCount,
494*61046927SAndroid Build Coastguard Worker    const VkCalibratedTimestampInfoKHR *pTimestampInfos, uint64_t *pTimestamps,
495*61046927SAndroid Build Coastguard Worker    uint64_t *pMaxDeviation)
496*61046927SAndroid Build Coastguard Worker {
497*61046927SAndroid Build Coastguard Worker    // VK_FROM_HANDLE(hk_device, dev, _device);
498*61046927SAndroid Build Coastguard Worker    // struct hk_physical_device *pdev = hk_device_physical(dev);
499*61046927SAndroid Build Coastguard Worker    uint64_t max_clock_period = 0;
500*61046927SAndroid Build Coastguard Worker    uint64_t begin, end;
501*61046927SAndroid Build Coastguard Worker    int d;
502*61046927SAndroid Build Coastguard Worker 
503*61046927SAndroid Build Coastguard Worker #ifdef CLOCK_MONOTONIC_RAW
504*61046927SAndroid Build Coastguard Worker    begin = vk_clock_gettime(CLOCK_MONOTONIC_RAW);
505*61046927SAndroid Build Coastguard Worker #else
506*61046927SAndroid Build Coastguard Worker    begin = vk_clock_gettime(CLOCK_MONOTONIC);
507*61046927SAndroid Build Coastguard Worker #endif
508*61046927SAndroid Build Coastguard Worker 
509*61046927SAndroid Build Coastguard Worker    for (d = 0; d < timestampCount; d++) {
510*61046927SAndroid Build Coastguard Worker       switch (pTimestampInfos[d].timeDomain) {
511*61046927SAndroid Build Coastguard Worker       case VK_TIME_DOMAIN_DEVICE_KHR:
512*61046927SAndroid Build Coastguard Worker          unreachable("todo");
513*61046927SAndroid Build Coastguard Worker          // pTimestamps[d] = agx_get_gpu_timestamp(&pdev->dev);
514*61046927SAndroid Build Coastguard Worker          max_clock_period = MAX2(
515*61046927SAndroid Build Coastguard Worker             max_clock_period, 1); /* FIXME: Is timestamp period actually 1? */
516*61046927SAndroid Build Coastguard Worker          break;
517*61046927SAndroid Build Coastguard Worker       case VK_TIME_DOMAIN_CLOCK_MONOTONIC_KHR:
518*61046927SAndroid Build Coastguard Worker          pTimestamps[d] = vk_clock_gettime(CLOCK_MONOTONIC);
519*61046927SAndroid Build Coastguard Worker          max_clock_period = MAX2(max_clock_period, 1);
520*61046927SAndroid Build Coastguard Worker          break;
521*61046927SAndroid Build Coastguard Worker 
522*61046927SAndroid Build Coastguard Worker #ifdef CLOCK_MONOTONIC_RAW
523*61046927SAndroid Build Coastguard Worker       case VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_KHR:
524*61046927SAndroid Build Coastguard Worker          pTimestamps[d] = begin;
525*61046927SAndroid Build Coastguard Worker          break;
526*61046927SAndroid Build Coastguard Worker #endif
527*61046927SAndroid Build Coastguard Worker       default:
528*61046927SAndroid Build Coastguard Worker          pTimestamps[d] = 0;
529*61046927SAndroid Build Coastguard Worker          break;
530*61046927SAndroid Build Coastguard Worker       }
531*61046927SAndroid Build Coastguard Worker    }
532*61046927SAndroid Build Coastguard Worker 
533*61046927SAndroid Build Coastguard Worker #ifdef CLOCK_MONOTONIC_RAW
534*61046927SAndroid Build Coastguard Worker    end = vk_clock_gettime(CLOCK_MONOTONIC_RAW);
535*61046927SAndroid Build Coastguard Worker #else
536*61046927SAndroid Build Coastguard Worker    end = vk_clock_gettime(CLOCK_MONOTONIC);
537*61046927SAndroid Build Coastguard Worker #endif
538*61046927SAndroid Build Coastguard Worker 
539*61046927SAndroid Build Coastguard Worker    *pMaxDeviation = vk_time_max_deviation(begin, end, max_clock_period);
540*61046927SAndroid Build Coastguard Worker 
541*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
542*61046927SAndroid Build Coastguard Worker }
543