2 * Copyright (C) 2018-2019 Alyssa Rosenzweig
3 * Copyright (C) 2019 Collabora, Ltd.
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 #include "pan_context.h"
29 panfrost_emit_varyings(
30 struct panfrost_context
*ctx
,
31 union mali_attr
*slot
,
35 /* Fill out the descriptor */
36 slot
->stride
= stride
;
37 slot
->size
= stride
* count
;
38 slot
->shift
= slot
->extra_flags
= 0;
40 struct panfrost_transfer transfer
=
41 panfrost_allocate_transient(ctx
, slot
->size
);
43 slot
->elements
= transfer
.gpu
| MALI_ATTR_LINEAR
;
49 panfrost_emit_point_coord(union mali_attr
*slot
)
51 slot
->elements
= MALI_VARYING_POINT_COORD
| MALI_ATTR_LINEAR
;
52 slot
->stride
= slot
->size
= slot
->shift
= slot
->extra_flags
= 0;
56 panfrost_emit_front_face(union mali_attr
*slot
)
58 slot
->elements
= MALI_VARYING_FRONT_FACING
| MALI_ATTR_INTERNAL
;
61 /* Given a shader and buffer indices, link varying metadata together */
64 panfrost_emit_varying_meta(
65 void *outptr
, struct panfrost_shader_state
*ss
,
66 signed general
, signed gl_Position
,
67 signed gl_PointSize
, signed gl_PointCoord
,
68 signed gl_FrontFacing
)
70 struct mali_attr_meta
*out
= (struct mali_attr_meta
*) outptr
;
72 for (unsigned i
= 0; i
< ss
->tripipe
->varying_count
; ++i
) {
73 gl_varying_slot location
= ss
->varyings_loc
[i
];
77 case VARYING_SLOT_POS
:
80 case VARYING_SLOT_PSIZ
:
83 case VARYING_SLOT_PNTC
:
84 index
= gl_PointCoord
;
86 case VARYING_SLOT_FACE
:
87 index
= gl_FrontFacing
;
100 panfrost_emit_varying_descriptor(
101 struct panfrost_context
*ctx
,
102 unsigned vertex_count
)
104 /* Load the shaders */
106 struct panfrost_shader_state
*vs
= &ctx
->shader
[PIPE_SHADER_VERTEX
]->variants
[ctx
->shader
[PIPE_SHADER_VERTEX
]->active_variant
];
107 struct panfrost_shader_state
*fs
= &ctx
->shader
[PIPE_SHADER_FRAGMENT
]->variants
[ctx
->shader
[PIPE_SHADER_FRAGMENT
]->active_variant
];
108 unsigned int num_gen_varyings
= 0;
110 /* Allocate the varying descriptor */
112 size_t vs_size
= sizeof(struct mali_attr_meta
) * vs
->tripipe
->varying_count
;
113 size_t fs_size
= sizeof(struct mali_attr_meta
) * fs
->tripipe
->varying_count
;
115 struct panfrost_transfer trans
= panfrost_allocate_transient(ctx
,
119 * Assign ->src_offset now that we know about all the general purpose
120 * varyings that will be used by the fragment and vertex shaders.
122 for (unsigned i
= 0; i
< vs
->tripipe
->varying_count
; i
++) {
124 * General purpose varyings have ->index set to 0, skip other
127 if (vs
->varyings
[i
].index
)
130 vs
->varyings
[i
].src_offset
= 16 * (num_gen_varyings
++);
133 for (unsigned i
= 0; i
< fs
->tripipe
->varying_count
; i
++) {
136 /* If we have a point sprite replacement, handle that here. We
137 * have to translate location first. TODO: Flip y in shader.
138 * We're already keying ... just time crunch .. */
140 unsigned loc
= fs
->varyings_loc
[i
];
142 (loc
>= VARYING_SLOT_VAR0
) ? (loc
- VARYING_SLOT_VAR0
) :
143 (loc
== VARYING_SLOT_PNTC
) ? 8 :
146 if (~pnt_loc
&& fs
->point_sprite_mask
& (1 << pnt_loc
)) {
147 /* gl_PointCoord index by convention */
148 fs
->varyings
[i
].index
= 3;
149 fs
->reads_point_coord
= true;
151 /* Swizzle out the z/w to 0/1 */
152 fs
->varyings
[i
].format
= MALI_RG16F
;
153 fs
->varyings
[i
].swizzle
=
154 panfrost_get_default_swizzle(2);
159 if (fs
->varyings
[i
].index
)
163 * Re-use the VS general purpose varying pos if it exists,
164 * create a new one otherwise.
166 for (j
= 0; j
< vs
->tripipe
->varying_count
; j
++) {
167 if (fs
->varyings_loc
[i
] == vs
->varyings_loc
[j
])
171 if (j
< vs
->tripipe
->varying_count
)
172 fs
->varyings
[i
].src_offset
= vs
->varyings
[j
].src_offset
;
174 fs
->varyings
[i
].src_offset
= 16 * (num_gen_varyings
++);
177 memcpy(trans
.cpu
, vs
->varyings
, vs_size
);
178 memcpy(trans
.cpu
+ vs_size
, fs
->varyings
, fs_size
);
180 /* Buffer indices must be in this order per our convention */
181 union mali_attr varyings
[PIPE_MAX_ATTRIBS
];
184 signed general
= idx
++;
185 signed gl_Position
= idx
++;
186 signed gl_PointSize
= (vs
->writes_point_size
|| fs
->reads_point_coord
|| fs
->reads_face
) ? (idx
++) : -1;
187 signed gl_PointCoord
= (fs
->reads_point_coord
|| fs
->reads_face
) ? (idx
++) : -1;
188 signed gl_FrontFacing
= (fs
->reads_face
) ? (idx
++) : -1;
190 panfrost_emit_varyings(ctx
, &varyings
[general
], num_gen_varyings
* 16,
193 /* fp32 vec4 gl_Position */
194 ctx
->payloads
[PIPE_SHADER_FRAGMENT
].postfix
.position_varying
=
195 panfrost_emit_varyings(ctx
, &varyings
[gl_Position
],
196 sizeof(float) * 4, vertex_count
);
199 if (vs
->writes_point_size
|| fs
->reads_point_coord
) {
200 /* fp16 vec1 gl_PointSize */
201 ctx
->payloads
[PIPE_SHADER_FRAGMENT
].primitive_size
.pointer
=
202 panfrost_emit_varyings(ctx
, &varyings
[gl_PointSize
],
204 } else if (fs
->reads_face
) {
205 /* Dummy to advance index */
209 if (fs
->reads_point_coord
) {
210 /* Special descriptor */
211 panfrost_emit_point_coord(&varyings
[gl_PointCoord
]);
212 } else if (fs
->reads_face
) {
216 if (fs
->reads_face
) {
217 panfrost_emit_front_face(&varyings
[gl_FrontFacing
]);
220 /* Let's go ahead and link varying meta to the buffer in question, now
221 * that that information is available */
223 panfrost_emit_varying_meta(trans
.cpu
, vs
,
224 general
, gl_Position
, gl_PointSize
,
225 gl_PointCoord
, gl_FrontFacing
);
227 panfrost_emit_varying_meta(trans
.cpu
+ vs_size
, fs
,
228 general
, gl_Position
, gl_PointSize
,
229 gl_PointCoord
, gl_FrontFacing
);
231 mali_ptr varyings_p
= panfrost_upload_transient(ctx
, &varyings
, idx
* sizeof(union mali_attr
));
232 ctx
->payloads
[PIPE_SHADER_VERTEX
].postfix
.varyings
= varyings_p
;
233 ctx
->payloads
[PIPE_SHADER_FRAGMENT
].postfix
.varyings
= varyings_p
;
235 ctx
->payloads
[PIPE_SHADER_VERTEX
].postfix
.varying_meta
= trans
.gpu
;
236 ctx
->payloads
[PIPE_SHADER_FRAGMENT
].postfix
.varying_meta
= trans
.gpu
+ vs_size
;