• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2022 Alyssa Rosenzweig
3  * SPDX-License-Identifier: MIT
4  */
5 
6 #pragma once
7 
8 #include "asahi/genxml/agx_pack.h"
9 #include "asahi/lib/pool.h"
10 
11 /* Opaque structure representing a USC program being constructed */
12 struct agx_usc_builder {
13    struct agx_ptr T;
14    uint8_t *head;
15 
16 #ifndef NDEBUG
17    size_t size;
18 #endif
19 };
20 
21 static struct agx_usc_builder
agx_alloc_usc_control(struct agx_pool * pool,unsigned num_reg_bindings)22 agx_alloc_usc_control(struct agx_pool *pool, unsigned num_reg_bindings)
23 {
24    STATIC_ASSERT(AGX_USC_UNIFORM_HIGH_LENGTH == AGX_USC_UNIFORM_LENGTH);
25    STATIC_ASSERT(AGX_USC_TEXTURE_LENGTH == AGX_USC_UNIFORM_LENGTH);
26    STATIC_ASSERT(AGX_USC_SAMPLER_LENGTH == AGX_USC_UNIFORM_LENGTH);
27 
28    size_t size = AGX_USC_UNIFORM_LENGTH * num_reg_bindings;
29 
30    size += AGX_USC_SHARED_LENGTH;
31    size += AGX_USC_SHADER_LENGTH;
32    size += AGX_USC_REGISTERS_LENGTH;
33    size += MAX2(AGX_USC_NO_PRESHADER_LENGTH, AGX_USC_PRESHADER_LENGTH);
34    size += AGX_USC_FRAGMENT_PROPERTIES_LENGTH;
35 
36    struct agx_usc_builder b = {
37       .T = agx_pool_alloc_aligned(pool, size, 64),
38 
39 #ifndef NDEBUG
40       .size = size,
41 #endif
42    };
43 
44    b.head = (uint8_t *)b.T.cpu;
45 
46    return b;
47 }
48 
49 static bool
agx_usc_builder_validate(struct agx_usc_builder * b,size_t size)50 agx_usc_builder_validate(struct agx_usc_builder *b, size_t size)
51 {
52 #ifndef NDEBUG
53    assert(((b->head - (uint8_t *)b->T.cpu) + size) <= b->size);
54 #endif
55 
56    return true;
57 }
58 
59 #define agx_usc_pack(b, struct_name, template)                                 \
60    for (bool it =                                                              \
61            agx_usc_builder_validate((b), AGX_USC_##struct_name##_LENGTH);      \
62         it; it = false, (b)->head += AGX_USC_##struct_name##_LENGTH)           \
63       agx_pack((b)->head, USC_##struct_name, template)
64 
65 static void
agx_usc_uniform(struct agx_usc_builder * b,unsigned start_halfs,unsigned size_halfs,uint64_t buffer)66 agx_usc_uniform(struct agx_usc_builder *b, unsigned start_halfs,
67                 unsigned size_halfs, uint64_t buffer)
68 {
69    assert((start_halfs + size_halfs) <= (1 << 9) && "uniform file overflow");
70    assert(size_halfs <= 64 && "caller's responsibility to split");
71 
72    if (start_halfs & BITFIELD_BIT(8)) {
73       agx_usc_pack(b, UNIFORM_HIGH, cfg) {
74          cfg.start_halfs = start_halfs & BITFIELD_MASK(8);
75          cfg.size_halfs = size_halfs;
76          cfg.buffer = buffer;
77       }
78    } else {
79       agx_usc_pack(b, UNIFORM, cfg) {
80          cfg.start_halfs = start_halfs;
81          cfg.size_halfs = size_halfs;
82          cfg.buffer = buffer;
83       }
84    }
85 }
86 
87 static uint32_t
agx_usc_fini(struct agx_usc_builder * b)88 agx_usc_fini(struct agx_usc_builder *b)
89 {
90    assert(b->T.gpu <= (1ull << 32) && "pipelines must be in low memory");
91    return b->T.gpu;
92 }
93 
94 static void
agx_usc_shared_none(struct agx_usc_builder * b)95 agx_usc_shared_none(struct agx_usc_builder *b)
96 {
97    agx_usc_pack(b, SHARED, cfg) {
98       cfg.layout = AGX_SHARED_LAYOUT_VERTEX_COMPUTE;
99       cfg.bytes_per_threadgroup = 65536;
100    }
101 }
102