• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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