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
;
62 panfrost_emit_varying_descriptor(
63 struct panfrost_context
*ctx
,
64 unsigned vertex_count
)
66 /* Load the shaders */
68 struct panfrost_shader_state
*vs
= &ctx
->shader
[PIPE_SHADER_VERTEX
]->variants
[ctx
->shader
[PIPE_SHADER_VERTEX
]->active_variant
];
69 struct panfrost_shader_state
*fs
= &ctx
->shader
[PIPE_SHADER_FRAGMENT
]->variants
[ctx
->shader
[PIPE_SHADER_FRAGMENT
]->active_variant
];
70 unsigned int num_gen_varyings
= 0;
72 /* Allocate the varying descriptor */
74 size_t vs_size
= sizeof(struct mali_attr_meta
) * vs
->tripipe
->varying_count
;
75 size_t fs_size
= sizeof(struct mali_attr_meta
) * fs
->tripipe
->varying_count
;
77 struct panfrost_transfer trans
= panfrost_allocate_transient(ctx
,
81 * Assign ->src_offset now that we know about all the general purpose
82 * varyings that will be used by the fragment and vertex shaders.
84 for (unsigned i
= 0; i
< vs
->tripipe
->varying_count
; i
++) {
86 * General purpose varyings have ->index set to 0, skip other
89 if (vs
->varyings
[i
].index
)
92 vs
->varyings
[i
].src_offset
= 16 * (num_gen_varyings
++);
95 for (unsigned i
= 0; i
< fs
->tripipe
->varying_count
; i
++) {
98 /* If we have a point sprite replacement, handle that here. We
99 * have to translate location first. TODO: Flip y in shader.
100 * We're already keying ... just time crunch .. */
102 unsigned loc
= fs
->varyings_loc
[i
];
104 (loc
>= VARYING_SLOT_VAR0
) ? (loc
- VARYING_SLOT_VAR0
) :
105 (loc
== VARYING_SLOT_PNTC
) ? 8 :
108 if (~pnt_loc
&& fs
->point_sprite_mask
& (1 << pnt_loc
)) {
109 /* gl_PointCoord index by convention */
110 fs
->varyings
[i
].index
= 3;
111 fs
->reads_point_coord
= true;
113 /* Swizzle out the z/w to 0/1 */
114 fs
->varyings
[i
].format
= MALI_RG16F
;
115 fs
->varyings
[i
].swizzle
=
116 panfrost_get_default_swizzle(2);
121 if (fs
->varyings
[i
].index
)
125 * Re-use the VS general purpose varying pos if it exists,
126 * create a new one otherwise.
128 for (j
= 0; j
< vs
->tripipe
->varying_count
; j
++) {
129 if (fs
->varyings_loc
[i
] == vs
->varyings_loc
[j
])
133 if (j
< vs
->tripipe
->varying_count
)
134 fs
->varyings
[i
].src_offset
= vs
->varyings
[j
].src_offset
;
136 fs
->varyings
[i
].src_offset
= 16 * (num_gen_varyings
++);
139 memcpy(trans
.cpu
, vs
->varyings
, vs_size
);
140 memcpy(trans
.cpu
+ vs_size
, fs
->varyings
, fs_size
);
142 ctx
->payloads
[PIPE_SHADER_VERTEX
].postfix
.varying_meta
= trans
.gpu
;
143 ctx
->payloads
[PIPE_SHADER_FRAGMENT
].postfix
.varying_meta
= trans
.gpu
+ vs_size
;
145 /* Buffer indices must be in this order per our convention */
146 union mali_attr varyings
[PIPE_MAX_ATTRIBS
];
149 panfrost_emit_varyings(ctx
, &varyings
[idx
++], num_gen_varyings
* 16,
152 /* fp32 vec4 gl_Position */
153 ctx
->payloads
[PIPE_SHADER_FRAGMENT
].postfix
.position_varying
=
154 panfrost_emit_varyings(ctx
, &varyings
[idx
++],
155 sizeof(float) * 4, vertex_count
);
158 if (vs
->writes_point_size
|| fs
->reads_point_coord
) {
159 /* fp16 vec1 gl_PointSize */
160 ctx
->payloads
[PIPE_SHADER_FRAGMENT
].primitive_size
.pointer
=
161 panfrost_emit_varyings(ctx
, &varyings
[idx
++],
163 } else if (fs
->reads_face
) {
164 /* Dummy to advance index */
168 if (fs
->reads_point_coord
) {
169 /* Special descriptor */
170 panfrost_emit_point_coord(&varyings
[idx
++]);
171 } else if (fs
->reads_face
) {
175 if (fs
->reads_face
) {
176 panfrost_emit_front_face(&varyings
[idx
++]);
179 mali_ptr varyings_p
= panfrost_upload_transient(ctx
, &varyings
, idx
* sizeof(union mali_attr
));
180 ctx
->payloads
[PIPE_SHADER_VERTEX
].postfix
.varyings
= varyings_p
;
181 ctx
->payloads
[PIPE_SHADER_FRAGMENT
].postfix
.varyings
= varyings_p
;