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 is_special_varying(gl_varying_slot loc
)
67 case VARYING_SLOT_POS
:
68 case VARYING_SLOT_PSIZ
:
69 case VARYING_SLOT_PNTC
:
70 case VARYING_SLOT_FACE
:
78 panfrost_emit_varying_meta(
79 void *outptr
, struct panfrost_shader_state
*ss
,
80 signed general
, signed gl_Position
,
81 signed gl_PointSize
, signed gl_PointCoord
,
82 signed gl_FrontFacing
)
84 struct mali_attr_meta
*out
= (struct mali_attr_meta
*) outptr
;
86 for (unsigned i
= 0; i
< ss
->tripipe
->varying_count
; ++i
) {
87 gl_varying_slot location
= ss
->varyings_loc
[i
];
91 case VARYING_SLOT_POS
:
94 case VARYING_SLOT_PSIZ
:
97 case VARYING_SLOT_PNTC
:
98 index
= gl_PointCoord
;
100 case VARYING_SLOT_FACE
:
101 index
= gl_FrontFacing
;
109 out
[i
].index
= index
;
114 panfrost_emit_varying_descriptor(
115 struct panfrost_context
*ctx
,
116 unsigned vertex_count
)
118 /* Load the shaders */
120 struct panfrost_shader_state
*vs
= &ctx
->shader
[PIPE_SHADER_VERTEX
]->variants
[ctx
->shader
[PIPE_SHADER_VERTEX
]->active_variant
];
121 struct panfrost_shader_state
*fs
= &ctx
->shader
[PIPE_SHADER_FRAGMENT
]->variants
[ctx
->shader
[PIPE_SHADER_FRAGMENT
]->active_variant
];
122 unsigned int num_gen_varyings
= 0;
124 /* Allocate the varying descriptor */
126 size_t vs_size
= sizeof(struct mali_attr_meta
) * vs
->tripipe
->varying_count
;
127 size_t fs_size
= sizeof(struct mali_attr_meta
) * fs
->tripipe
->varying_count
;
129 struct panfrost_transfer trans
= panfrost_allocate_transient(ctx
,
132 for (unsigned i
= 0; i
< vs
->tripipe
->varying_count
; i
++) {
133 if (!is_special_varying(vs
->varyings_loc
[i
]))
134 vs
->varyings
[i
].src_offset
= 16 * (num_gen_varyings
++);
137 for (unsigned i
= 0; i
< fs
->tripipe
->varying_count
; i
++) {
140 /* If we have a point sprite replacement, handle that here. We
141 * have to translate location first. TODO: Flip y in shader.
142 * We're already keying ... just time crunch .. */
144 unsigned loc
= fs
->varyings_loc
[i
];
146 (loc
>= VARYING_SLOT_VAR0
) ? (loc
- VARYING_SLOT_VAR0
) :
147 (loc
== VARYING_SLOT_PNTC
) ? 8 :
150 if (~pnt_loc
&& fs
->point_sprite_mask
& (1 << pnt_loc
)) {
151 /* gl_PointCoord index by convention */
152 fs
->varyings
[i
].index
= 3;
153 fs
->reads_point_coord
= true;
155 /* Swizzle out the z/w to 0/1 */
156 fs
->varyings
[i
].format
= MALI_RG16F
;
157 fs
->varyings
[i
].swizzle
=
158 panfrost_get_default_swizzle(2);
163 if (fs
->varyings
[i
].index
)
167 * Re-use the VS general purpose varying pos if it exists,
168 * create a new one otherwise.
170 for (j
= 0; j
< vs
->tripipe
->varying_count
; j
++) {
171 if (fs
->varyings_loc
[i
] == vs
->varyings_loc
[j
])
175 if (j
< vs
->tripipe
->varying_count
)
176 fs
->varyings
[i
].src_offset
= vs
->varyings
[j
].src_offset
;
178 fs
->varyings
[i
].src_offset
= 16 * (num_gen_varyings
++);
181 memcpy(trans
.cpu
, vs
->varyings
, vs_size
);
182 memcpy(trans
.cpu
+ vs_size
, fs
->varyings
, fs_size
);
184 union mali_attr varyings
[PIPE_MAX_ATTRIBS
];
187 signed general
= idx
++;
188 signed gl_Position
= idx
++;
189 signed gl_PointSize
= vs
->writes_point_size
? (idx
++) : -1;
190 signed gl_PointCoord
= fs
->reads_point_coord
? (idx
++) : -1;
191 signed gl_FrontFacing
= fs
->reads_face
? (idx
++) : -1;
193 panfrost_emit_varyings(ctx
, &varyings
[general
], num_gen_varyings
* 16,
196 /* fp32 vec4 gl_Position */
197 ctx
->payloads
[PIPE_SHADER_FRAGMENT
].postfix
.position_varying
=
198 panfrost_emit_varyings(ctx
, &varyings
[gl_Position
],
199 sizeof(float) * 4, vertex_count
);
202 if (vs
->writes_point_size
)
203 ctx
->payloads
[PIPE_SHADER_FRAGMENT
].primitive_size
.pointer
=
204 panfrost_emit_varyings(ctx
, &varyings
[gl_PointSize
],
207 if (fs
->reads_point_coord
)
208 panfrost_emit_point_coord(&varyings
[gl_PointCoord
]);
211 panfrost_emit_front_face(&varyings
[gl_FrontFacing
]);
213 /* Let's go ahead and link varying meta to the buffer in question, now
214 * that that information is available */
216 panfrost_emit_varying_meta(trans
.cpu
, vs
,
217 general
, gl_Position
, gl_PointSize
,
218 gl_PointCoord
, gl_FrontFacing
);
220 panfrost_emit_varying_meta(trans
.cpu
+ vs_size
, fs
,
221 general
, gl_Position
, gl_PointSize
,
222 gl_PointCoord
, gl_FrontFacing
);
224 mali_ptr varyings_p
= panfrost_upload_transient(ctx
, &varyings
, idx
* sizeof(union mali_attr
));
225 ctx
->payloads
[PIPE_SHADER_VERTEX
].postfix
.varyings
= varyings_p
;
226 ctx
->payloads
[PIPE_SHADER_FRAGMENT
].postfix
.varyings
= varyings_p
;
228 ctx
->payloads
[PIPE_SHADER_VERTEX
].postfix
.varying_meta
= trans
.gpu
;
229 ctx
->payloads
[PIPE_SHADER_FRAGMENT
].postfix
.varying_meta
= trans
.gpu
+ vs_size
;