1 /*
2 * Copyright 2023 Alyssa Rosenzweig
3 * SPDX-License-Identifier: MIT
4 */
5
6 #pragma once
7
8 #include <stdbool.h>
9 #include "asahi/compiler/agx_compile.h"
10 #include "asahi/layout/layout.h"
11 #include "pipe/p_defines.h"
12 #include "agx_pack.h"
13 #include "agx_ppp.h"
14
15 #define AGX_MAX_VIEWPORTS (16)
16
17 #define agx_push(ptr, T, cfg) \
18 for (unsigned _loop = 0; _loop < 1; ++_loop, ptr += AGX_##T##_LENGTH) \
19 agx_pack(ptr, T, cfg)
20
21 static inline enum agx_sampler_states
agx_translate_sampler_state_count(unsigned count,bool extended)22 agx_translate_sampler_state_count(unsigned count, bool extended)
23 {
24 assert(count <= 17 && "max 17 sampler state registers supported");
25
26 if (count == 0) {
27 return AGX_SAMPLER_STATES_0;
28 } else if (extended) {
29 if (count <= 8)
30 return AGX_SAMPLER_STATES_8_EXTENDED;
31 else
32 return AGX_SAMPLER_STATES_16_EXTENDED;
33 } else {
34 if (count <= 4)
35 return AGX_SAMPLER_STATES_4_COMPACT;
36 else if (count <= 8)
37 return AGX_SAMPLER_STATES_8_COMPACT;
38 else if (count <= 12)
39 return AGX_SAMPLER_STATES_12_COMPACT;
40 else
41 return AGX_SAMPLER_STATES_16_COMPACT;
42 }
43 }
44
45 /* Channels agree for RGBA but are weird for force 0/1 */
46
47 static inline enum agx_channel
agx_channel_from_pipe(enum pipe_swizzle in)48 agx_channel_from_pipe(enum pipe_swizzle in)
49 {
50 STATIC_ASSERT((enum agx_channel)PIPE_SWIZZLE_X == AGX_CHANNEL_R);
51 STATIC_ASSERT((enum agx_channel)PIPE_SWIZZLE_Y == AGX_CHANNEL_G);
52 STATIC_ASSERT((enum agx_channel)PIPE_SWIZZLE_Z == AGX_CHANNEL_B);
53 STATIC_ASSERT((enum agx_channel)PIPE_SWIZZLE_W == AGX_CHANNEL_A);
54 STATIC_ASSERT((enum agx_channel)PIPE_SWIZZLE_0 & 0x4);
55 STATIC_ASSERT((enum agx_channel)PIPE_SWIZZLE_1 & 0x4);
56 STATIC_ASSERT((enum agx_channel)PIPE_SWIZZLE_NONE & 0x4);
57
58 if ((in & 0x4) == 0)
59 return (enum agx_channel)in;
60 else if (in == PIPE_SWIZZLE_1)
61 return AGX_CHANNEL_1;
62 else
63 return AGX_CHANNEL_0;
64 }
65
66 static inline enum agx_layout
agx_translate_layout(enum ail_tiling tiling)67 agx_translate_layout(enum ail_tiling tiling)
68 {
69 switch (tiling) {
70 case AIL_TILING_TWIDDLED:
71 case AIL_TILING_TWIDDLED_COMPRESSED:
72 return AGX_LAYOUT_TWIDDLED;
73 case AIL_TILING_LINEAR:
74 return AGX_LAYOUT_LINEAR;
75 }
76
77 unreachable("Invalid tiling");
78 }
79
80 static inline enum agx_index_size
agx_translate_index_size(uint8_t size_B)81 agx_translate_index_size(uint8_t size_B)
82 {
83 /* Index sizes are encoded logarithmically */
84 STATIC_ASSERT(__builtin_ctz(1) == AGX_INDEX_SIZE_U8);
85 STATIC_ASSERT(__builtin_ctz(2) == AGX_INDEX_SIZE_U16);
86 STATIC_ASSERT(__builtin_ctz(4) == AGX_INDEX_SIZE_U32);
87
88 assert((size_B == 1) || (size_B == 2) || (size_B == 4));
89 return __builtin_ctz(size_B);
90 }
91
92 static enum agx_pass_type
agx_pass_type_for_shader(struct agx_shader_info * info)93 agx_pass_type_for_shader(struct agx_shader_info *info)
94 {
95 if (info->reads_tib && info->writes_sample_mask)
96 return AGX_PASS_TYPE_TRANSLUCENT_PUNCH_THROUGH;
97 else if (info->reads_tib)
98 return AGX_PASS_TYPE_TRANSLUCENT;
99 else if (info->writes_sample_mask)
100 return AGX_PASS_TYPE_PUNCH_THROUGH;
101 else
102 return AGX_PASS_TYPE_OPAQUE;
103 }
104
105 static enum agx_conservative_depth
agx_translate_depth_layout(enum gl_frag_depth_layout layout)106 agx_translate_depth_layout(enum gl_frag_depth_layout layout)
107 {
108 switch (layout) {
109 case FRAG_DEPTH_LAYOUT_ANY:
110 return AGX_CONSERVATIVE_DEPTH_ANY;
111 case FRAG_DEPTH_LAYOUT_LESS:
112 return AGX_CONSERVATIVE_DEPTH_LESS;
113 case FRAG_DEPTH_LAYOUT_GREATER:
114 return AGX_CONSERVATIVE_DEPTH_GREATER;
115 case FRAG_DEPTH_LAYOUT_UNCHANGED:
116 return AGX_CONSERVATIVE_DEPTH_UNCHANGED;
117 default:
118 unreachable("depth layout should have been canonicalized");
119 }
120 }
121
122 static void
agx_ppp_fragment_face_2(struct agx_ppp_update * ppp,enum agx_object_type object_type,struct agx_shader_info * info)123 agx_ppp_fragment_face_2(struct agx_ppp_update *ppp,
124 enum agx_object_type object_type,
125 struct agx_shader_info *info)
126 {
127 agx_ppp_push(ppp, FRAGMENT_FACE_2, cfg) {
128 cfg.object_type = object_type;
129 cfg.conservative_depth = agx_translate_depth_layout(info->depth_layout);
130 }
131 }
132
133 static inline uint32_t
agx_pack_line_width(float line_width)134 agx_pack_line_width(float line_width)
135 {
136 /* Line width is packed in a 4:4 fixed point format */
137 unsigned line_width_fixed = ((unsigned)(line_width * 16.0f)) - 1;
138
139 /* Clamp to maximum line width */
140 return MIN2(line_width_fixed, 0xFF);
141 }
142
143 static enum agx_shade_model
agx_translate_shade_model(struct agx_varyings_fs * fs,unsigned binding,bool first_provoking_vertex)144 agx_translate_shade_model(struct agx_varyings_fs *fs, unsigned binding,
145 bool first_provoking_vertex)
146 {
147 if (fs->bindings[binding].smooth) {
148 if (fs->bindings[binding].perspective)
149 return AGX_SHADE_MODEL_PERSPECTIVE;
150 else
151 return AGX_SHADE_MODEL_LINEAR;
152 } else {
153 if (!first_provoking_vertex)
154 return AGX_SHADE_MODEL_FLAT_VERTEX_2;
155 else
156 return AGX_SHADE_MODEL_FLAT_VERTEX_0;
157 }
158 }
159