1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker * Copyright 2022 Alyssa Rosenzweig
3*61046927SAndroid Build Coastguard Worker * SPDX-License-Identifier: MIT
4*61046927SAndroid Build Coastguard Worker */
5*61046927SAndroid Build Coastguard Worker
6*61046927SAndroid Build Coastguard Worker #pragma once
7*61046927SAndroid Build Coastguard Worker
8*61046927SAndroid Build Coastguard Worker #include "asahi/genxml/agx_pack.h"
9*61046927SAndroid Build Coastguard Worker #include "agx_bo.h"
10*61046927SAndroid Build Coastguard Worker
11*61046927SAndroid Build Coastguard Worker /* Opaque structure representing a PPP update */
12*61046927SAndroid Build Coastguard Worker struct agx_ppp_update {
13*61046927SAndroid Build Coastguard Worker uint8_t *head;
14*61046927SAndroid Build Coastguard Worker uint64_t gpu_base;
15*61046927SAndroid Build Coastguard Worker size_t total_size;
16*61046927SAndroid Build Coastguard Worker
17*61046927SAndroid Build Coastguard Worker #ifndef NDEBUG
18*61046927SAndroid Build Coastguard Worker uint8_t *cpu_base;
19*61046927SAndroid Build Coastguard Worker #endif
20*61046927SAndroid Build Coastguard Worker };
21*61046927SAndroid Build Coastguard Worker
22*61046927SAndroid Build Coastguard Worker ALWAYS_INLINE static size_t
agx_ppp_update_size(struct AGX_PPP_HEADER * present)23*61046927SAndroid Build Coastguard Worker agx_ppp_update_size(struct AGX_PPP_HEADER *present)
24*61046927SAndroid Build Coastguard Worker {
25*61046927SAndroid Build Coastguard Worker size_t size = AGX_PPP_HEADER_LENGTH;
26*61046927SAndroid Build Coastguard Worker
27*61046927SAndroid Build Coastguard Worker #define PPP_CASE(x, y) \
28*61046927SAndroid Build Coastguard Worker if (present->x) \
29*61046927SAndroid Build Coastguard Worker size += AGX_##y##_LENGTH;
30*61046927SAndroid Build Coastguard Worker PPP_CASE(fragment_control, FRAGMENT_CONTROL);
31*61046927SAndroid Build Coastguard Worker PPP_CASE(fragment_control_2, FRAGMENT_CONTROL);
32*61046927SAndroid Build Coastguard Worker PPP_CASE(fragment_front_face, FRAGMENT_FACE);
33*61046927SAndroid Build Coastguard Worker PPP_CASE(fragment_front_face_2, FRAGMENT_FACE_2);
34*61046927SAndroid Build Coastguard Worker PPP_CASE(fragment_front_stencil, FRAGMENT_STENCIL);
35*61046927SAndroid Build Coastguard Worker PPP_CASE(fragment_back_face, FRAGMENT_FACE);
36*61046927SAndroid Build Coastguard Worker PPP_CASE(fragment_back_face_2, FRAGMENT_FACE_2);
37*61046927SAndroid Build Coastguard Worker PPP_CASE(fragment_back_stencil, FRAGMENT_STENCIL);
38*61046927SAndroid Build Coastguard Worker PPP_CASE(depth_bias_scissor, DEPTH_BIAS_SCISSOR);
39*61046927SAndroid Build Coastguard Worker
40*61046927SAndroid Build Coastguard Worker if (present->region_clip)
41*61046927SAndroid Build Coastguard Worker size += present->viewport_count * AGX_REGION_CLIP_LENGTH;
42*61046927SAndroid Build Coastguard Worker
43*61046927SAndroid Build Coastguard Worker if (present->viewport) {
44*61046927SAndroid Build Coastguard Worker size += AGX_VIEWPORT_CONTROL_LENGTH +
45*61046927SAndroid Build Coastguard Worker (present->viewport_count * AGX_VIEWPORT_LENGTH);
46*61046927SAndroid Build Coastguard Worker }
47*61046927SAndroid Build Coastguard Worker
48*61046927SAndroid Build Coastguard Worker PPP_CASE(w_clamp, W_CLAMP);
49*61046927SAndroid Build Coastguard Worker PPP_CASE(output_select, OUTPUT_SELECT);
50*61046927SAndroid Build Coastguard Worker PPP_CASE(varying_counts_32, VARYING_COUNTS);
51*61046927SAndroid Build Coastguard Worker PPP_CASE(varying_counts_16, VARYING_COUNTS);
52*61046927SAndroid Build Coastguard Worker PPP_CASE(cull, CULL);
53*61046927SAndroid Build Coastguard Worker PPP_CASE(cull_2, CULL_2);
54*61046927SAndroid Build Coastguard Worker
55*61046927SAndroid Build Coastguard Worker if (present->fragment_shader) {
56*61046927SAndroid Build Coastguard Worker size +=
57*61046927SAndroid Build Coastguard Worker AGX_FRAGMENT_SHADER_WORD_0_LENGTH + AGX_FRAGMENT_SHADER_WORD_1_LENGTH +
58*61046927SAndroid Build Coastguard Worker AGX_FRAGMENT_SHADER_WORD_2_LENGTH + AGX_FRAGMENT_SHADER_WORD_3_LENGTH;
59*61046927SAndroid Build Coastguard Worker }
60*61046927SAndroid Build Coastguard Worker
61*61046927SAndroid Build Coastguard Worker PPP_CASE(occlusion_query, FRAGMENT_OCCLUSION_QUERY);
62*61046927SAndroid Build Coastguard Worker PPP_CASE(occlusion_query_2, FRAGMENT_OCCLUSION_QUERY_2);
63*61046927SAndroid Build Coastguard Worker PPP_CASE(output_unknown, OUTPUT_UNKNOWN);
64*61046927SAndroid Build Coastguard Worker PPP_CASE(output_size, OUTPUT_SIZE);
65*61046927SAndroid Build Coastguard Worker PPP_CASE(varying_word_2, VARYING_2);
66*61046927SAndroid Build Coastguard Worker #undef PPP_CASE
67*61046927SAndroid Build Coastguard Worker
68*61046927SAndroid Build Coastguard Worker assert((size % 4) == 0 && "PPP updates are aligned");
69*61046927SAndroid Build Coastguard Worker return size;
70*61046927SAndroid Build Coastguard Worker }
71*61046927SAndroid Build Coastguard Worker
72*61046927SAndroid Build Coastguard Worker static inline bool
agx_ppp_validate(struct agx_ppp_update * ppp,size_t size)73*61046927SAndroid Build Coastguard Worker agx_ppp_validate(struct agx_ppp_update *ppp, size_t size)
74*61046927SAndroid Build Coastguard Worker {
75*61046927SAndroid Build Coastguard Worker #ifndef NDEBUG
76*61046927SAndroid Build Coastguard Worker /* Assert that we don't overflow. Ideally we'd assert that types match too
77*61046927SAndroid Build Coastguard Worker * but that's harder to do at the moment.
78*61046927SAndroid Build Coastguard Worker */
79*61046927SAndroid Build Coastguard Worker assert(((ppp->head - ppp->cpu_base) + size) <= ppp->total_size);
80*61046927SAndroid Build Coastguard Worker #endif
81*61046927SAndroid Build Coastguard Worker
82*61046927SAndroid Build Coastguard Worker return true;
83*61046927SAndroid Build Coastguard Worker }
84*61046927SAndroid Build Coastguard Worker
85*61046927SAndroid Build Coastguard Worker #define agx_ppp_push(ppp, T, name) \
86*61046927SAndroid Build Coastguard Worker for (bool it = agx_ppp_validate((ppp), AGX_##T##_LENGTH); it; \
87*61046927SAndroid Build Coastguard Worker it = false, (ppp)->head += AGX_##T##_LENGTH) \
88*61046927SAndroid Build Coastguard Worker agx_pack((ppp)->head, T, name)
89*61046927SAndroid Build Coastguard Worker
90*61046927SAndroid Build Coastguard Worker #define agx_ppp_push_packed(ppp, src, T) \
91*61046927SAndroid Build Coastguard Worker do { \
92*61046927SAndroid Build Coastguard Worker agx_ppp_validate((ppp), AGX_##T##_LENGTH); \
93*61046927SAndroid Build Coastguard Worker memcpy((ppp)->head, src, AGX_##T##_LENGTH); \
94*61046927SAndroid Build Coastguard Worker (ppp)->head += AGX_##T##_LENGTH; \
95*61046927SAndroid Build Coastguard Worker } while (0)
96*61046927SAndroid Build Coastguard Worker
97*61046927SAndroid Build Coastguard Worker #define agx_ppp_push_merged(ppp, T, name, merge) \
98*61046927SAndroid Build Coastguard Worker for (uint8_t _tmp[AGX_##T##_LENGTH], it = 1; it; \
99*61046927SAndroid Build Coastguard Worker it = 0, agx_ppp_push_merged_blobs(ppp, AGX_##T##_LENGTH, \
100*61046927SAndroid Build Coastguard Worker (uint32_t *)_tmp, \
101*61046927SAndroid Build Coastguard Worker (uint32_t *)&merge)) \
102*61046927SAndroid Build Coastguard Worker agx_pack(_tmp, T, name)
103*61046927SAndroid Build Coastguard Worker
104*61046927SAndroid Build Coastguard Worker ALWAYS_INLINE static struct agx_ppp_update
agx_new_ppp_update(struct agx_ptr out,size_t size,struct AGX_PPP_HEADER * present)105*61046927SAndroid Build Coastguard Worker agx_new_ppp_update(struct agx_ptr out, size_t size,
106*61046927SAndroid Build Coastguard Worker struct AGX_PPP_HEADER *present)
107*61046927SAndroid Build Coastguard Worker {
108*61046927SAndroid Build Coastguard Worker struct agx_ppp_update ppp = {
109*61046927SAndroid Build Coastguard Worker .head = out.cpu,
110*61046927SAndroid Build Coastguard Worker .gpu_base = out.gpu,
111*61046927SAndroid Build Coastguard Worker .total_size = size,
112*61046927SAndroid Build Coastguard Worker #ifndef NDEBUG
113*61046927SAndroid Build Coastguard Worker .cpu_base = out.cpu,
114*61046927SAndroid Build Coastguard Worker #endif
115*61046927SAndroid Build Coastguard Worker };
116*61046927SAndroid Build Coastguard Worker
117*61046927SAndroid Build Coastguard Worker agx_ppp_push(&ppp, PPP_HEADER, cfg) {
118*61046927SAndroid Build Coastguard Worker cfg = *present;
119*61046927SAndroid Build Coastguard Worker }
120*61046927SAndroid Build Coastguard Worker
121*61046927SAndroid Build Coastguard Worker return ppp;
122*61046927SAndroid Build Coastguard Worker }
123*61046927SAndroid Build Coastguard Worker
124*61046927SAndroid Build Coastguard Worker static inline void
agx_ppp_fini(uint8_t ** out,struct agx_ppp_update * ppp)125*61046927SAndroid Build Coastguard Worker agx_ppp_fini(uint8_t **out, struct agx_ppp_update *ppp)
126*61046927SAndroid Build Coastguard Worker {
127*61046927SAndroid Build Coastguard Worker size_t size = ppp->total_size;
128*61046927SAndroid Build Coastguard Worker assert((size % 4) == 0);
129*61046927SAndroid Build Coastguard Worker size_t size_words = size / 4;
130*61046927SAndroid Build Coastguard Worker
131*61046927SAndroid Build Coastguard Worker #ifndef NDEBUG
132*61046927SAndroid Build Coastguard Worker assert(size == (ppp->head - ppp->cpu_base) && "mismatched ppp size");
133*61046927SAndroid Build Coastguard Worker #endif
134*61046927SAndroid Build Coastguard Worker
135*61046927SAndroid Build Coastguard Worker assert(ppp->gpu_base < (1ull << 40));
136*61046927SAndroid Build Coastguard Worker assert(size_words < (1ull << 24));
137*61046927SAndroid Build Coastguard Worker
138*61046927SAndroid Build Coastguard Worker agx_pack(*out, PPP_STATE, cfg) {
139*61046927SAndroid Build Coastguard Worker cfg.pointer_hi = (ppp->gpu_base >> 32);
140*61046927SAndroid Build Coastguard Worker cfg.pointer_lo = (uint32_t)ppp->gpu_base;
141*61046927SAndroid Build Coastguard Worker cfg.size_words = size_words;
142*61046927SAndroid Build Coastguard Worker };
143*61046927SAndroid Build Coastguard Worker
144*61046927SAndroid Build Coastguard Worker *out += AGX_PPP_STATE_LENGTH;
145*61046927SAndroid Build Coastguard Worker }
146*61046927SAndroid Build Coastguard Worker
147*61046927SAndroid Build Coastguard Worker static void
agx_ppp_push_merged_blobs(struct agx_ppp_update * ppp,size_t length,void * src1_,void * src2_)148*61046927SAndroid Build Coastguard Worker agx_ppp_push_merged_blobs(struct agx_ppp_update *ppp, size_t length,
149*61046927SAndroid Build Coastguard Worker void *src1_, void *src2_)
150*61046927SAndroid Build Coastguard Worker {
151*61046927SAndroid Build Coastguard Worker assert((length & 3) == 0);
152*61046927SAndroid Build Coastguard Worker assert(((uintptr_t)src1_ & 3) == 0);
153*61046927SAndroid Build Coastguard Worker assert(((uintptr_t)src2_ & 3) == 0);
154*61046927SAndroid Build Coastguard Worker
155*61046927SAndroid Build Coastguard Worker uint32_t *dst = (uint32_t *)ppp->head;
156*61046927SAndroid Build Coastguard Worker uint32_t *src1 = (uint32_t *)src1_;
157*61046927SAndroid Build Coastguard Worker uint32_t *src2 = (uint32_t *)src2_;
158*61046927SAndroid Build Coastguard Worker
159*61046927SAndroid Build Coastguard Worker for (unsigned i = 0; i < (length / 4); ++i) {
160*61046927SAndroid Build Coastguard Worker dst[i] = src1[i] | src2[i];
161*61046927SAndroid Build Coastguard Worker }
162*61046927SAndroid Build Coastguard Worker
163*61046927SAndroid Build Coastguard Worker ppp->head += length;
164*61046927SAndroid Build Coastguard Worker }
165