Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/drivers/freedreno/a6xx/fd6_zsa.c
4574 views
1
/*
2
* Copyright (C) 2016 Rob Clark <[email protected]>
3
* Copyright © 2018 Google, Inc.
4
*
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:
11
*
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
14
* Software.
15
*
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
22
* SOFTWARE.
23
*
24
* Authors:
25
* Rob Clark <[email protected]>
26
*/
27
28
#include "pipe/p_state.h"
29
#include "util/u_memory.h"
30
#include "util/u_string.h"
31
32
#include "fd6_context.h"
33
#include "fd6_format.h"
34
#include "fd6_zsa.h"
35
36
/* update lza state based on stencil-test func:
37
*
38
* Conceptually the order of the pipeline is:
39
*
40
*
41
* FS -> Alpha-Test -> Stencil-Test -> Depth-Test
42
* | |
43
* if wrmask != 0 if wrmask != 0
44
* | |
45
* v v
46
* Stencil-Write Depth-Write
47
*
48
* Because Stencil-Test can have side effects (Stencil-Write) prior
49
* to depth test, in this case we potentially need to disable early
50
* lrz-test. See:
51
*
52
* https://www.khronos.org/opengl/wiki/Per-Sample_Processing
53
*/
54
static void
55
update_lrz_stencil(struct fd6_zsa_stateobj *so, enum pipe_compare_func func,
56
bool stencil_write)
57
{
58
switch (func) {
59
case PIPE_FUNC_ALWAYS:
60
/* nothing to do for LRZ, but for stencil test when stencil-
61
* write is enabled, we need to disable lrz-test, since
62
* conceptually stencil test and write happens before depth-
63
* test:
64
*/
65
if (stencil_write) {
66
so->lrz.enable = false;
67
so->lrz.test = false;
68
}
69
break;
70
case PIPE_FUNC_NEVER:
71
/* fragment never passes, disable lrz_write for this draw: */
72
so->lrz.write = false;
73
break;
74
default:
75
/* whether the fragment passes or not depends on result
76
* of stencil test, which we cannot know when doing binning
77
* pass:
78
*/
79
so->lrz.write = false;
80
/* similarly to the PIPE_FUNC_ALWAY case, if there are side-
81
* effects from stencil test we need to disable lrz-test.
82
*/
83
if (stencil_write) {
84
so->lrz.enable = false;
85
so->lrz.test = false;
86
}
87
break;
88
}
89
}
90
91
void *
92
fd6_zsa_state_create(struct pipe_context *pctx,
93
const struct pipe_depth_stencil_alpha_state *cso)
94
{
95
struct fd_context *ctx = fd_context(pctx);
96
struct fd6_zsa_stateobj *so;
97
98
so = CALLOC_STRUCT(fd6_zsa_stateobj);
99
if (!so)
100
return NULL;
101
102
so->base = *cso;
103
104
so->writes_zs = util_writes_depth_stencil(cso);
105
106
so->rb_depth_cntl |=
107
A6XX_RB_DEPTH_CNTL_ZFUNC(cso->depth_func); /* maps 1:1 */
108
109
if (cso->depth_enabled) {
110
so->rb_depth_cntl |=
111
A6XX_RB_DEPTH_CNTL_Z_ENABLE | A6XX_RB_DEPTH_CNTL_Z_TEST_ENABLE;
112
113
so->lrz.test = true;
114
115
if (cso->depth_writemask) {
116
so->lrz.write = true;
117
}
118
119
switch (cso->depth_func) {
120
case PIPE_FUNC_LESS:
121
case PIPE_FUNC_LEQUAL:
122
so->lrz.enable = true;
123
so->lrz.direction = FD_LRZ_LESS;
124
break;
125
126
case PIPE_FUNC_GREATER:
127
case PIPE_FUNC_GEQUAL:
128
so->lrz.enable = true;
129
so->lrz.direction = FD_LRZ_GREATER;
130
break;
131
132
case PIPE_FUNC_NEVER:
133
so->lrz.enable = true;
134
so->lrz.write = false;
135
so->lrz.direction = FD_LRZ_LESS;
136
break;
137
138
/* TODO revisit these: */
139
case PIPE_FUNC_EQUAL:
140
case PIPE_FUNC_NOTEQUAL:
141
case PIPE_FUNC_ALWAYS:
142
so->lrz.write = false;
143
so->invalidate_lrz = true;
144
break;
145
}
146
}
147
148
if (cso->depth_writemask)
149
so->rb_depth_cntl |= A6XX_RB_DEPTH_CNTL_Z_WRITE_ENABLE;
150
151
if (cso->stencil[0].enabled) {
152
const struct pipe_stencil_state *s = &cso->stencil[0];
153
154
/* stencil test happens before depth test, so without performing
155
* stencil test we don't really know what the updates to the
156
* depth buffer will be.
157
*/
158
update_lrz_stencil(so, s->func, !!s->writemask);
159
160
so->rb_stencil_control |=
161
A6XX_RB_STENCIL_CONTROL_STENCIL_READ |
162
A6XX_RB_STENCIL_CONTROL_STENCIL_ENABLE |
163
A6XX_RB_STENCIL_CONTROL_FUNC(s->func) | /* maps 1:1 */
164
A6XX_RB_STENCIL_CONTROL_FAIL(fd_stencil_op(s->fail_op)) |
165
A6XX_RB_STENCIL_CONTROL_ZPASS(fd_stencil_op(s->zpass_op)) |
166
A6XX_RB_STENCIL_CONTROL_ZFAIL(fd_stencil_op(s->zfail_op));
167
168
so->rb_stencilmask = A6XX_RB_STENCILMASK_MASK(s->valuemask);
169
so->rb_stencilwrmask = A6XX_RB_STENCILWRMASK_WRMASK(s->writemask);
170
171
if (cso->stencil[1].enabled) {
172
const struct pipe_stencil_state *bs = &cso->stencil[1];
173
174
update_lrz_stencil(so, bs->func, !!bs->writemask);
175
176
so->rb_stencil_control |=
177
A6XX_RB_STENCIL_CONTROL_STENCIL_ENABLE_BF |
178
A6XX_RB_STENCIL_CONTROL_FUNC_BF(bs->func) | /* maps 1:1 */
179
A6XX_RB_STENCIL_CONTROL_FAIL_BF(fd_stencil_op(bs->fail_op)) |
180
A6XX_RB_STENCIL_CONTROL_ZPASS_BF(fd_stencil_op(bs->zpass_op)) |
181
A6XX_RB_STENCIL_CONTROL_ZFAIL_BF(fd_stencil_op(bs->zfail_op));
182
183
so->rb_stencilmask |= A6XX_RB_STENCILMASK_BFMASK(bs->valuemask);
184
so->rb_stencilwrmask |= A6XX_RB_STENCILWRMASK_BFWRMASK(bs->writemask);
185
}
186
}
187
188
if (cso->alpha_enabled) {
189
/* Alpha test is functionally a conditional discard, so we can't
190
* write LRZ before seeing if we end up discarding or not
191
*/
192
if (cso->alpha_func != PIPE_FUNC_ALWAYS) {
193
so->lrz.write = false;
194
so->alpha_test = true;
195
}
196
197
uint32_t ref = cso->alpha_ref_value * 255.0;
198
so->rb_alpha_control =
199
A6XX_RB_ALPHA_CONTROL_ALPHA_TEST |
200
A6XX_RB_ALPHA_CONTROL_ALPHA_REF(ref) |
201
A6XX_RB_ALPHA_CONTROL_ALPHA_TEST_FUNC(cso->alpha_func);
202
}
203
204
for (int i = 0; i < 4; i++) {
205
struct fd_ringbuffer *ring = fd_ringbuffer_new_object(ctx->pipe, 9 * 4);
206
207
OUT_PKT4(ring, REG_A6XX_RB_ALPHA_CONTROL, 1);
208
OUT_RING(ring,
209
(i & FD6_ZSA_NO_ALPHA)
210
? so->rb_alpha_control & ~A6XX_RB_ALPHA_CONTROL_ALPHA_TEST
211
: so->rb_alpha_control);
212
213
OUT_PKT4(ring, REG_A6XX_RB_STENCIL_CONTROL, 1);
214
OUT_RING(ring, so->rb_stencil_control);
215
216
OUT_PKT4(ring, REG_A6XX_RB_DEPTH_CNTL, 1);
217
OUT_RING(ring,
218
so->rb_depth_cntl | COND(i & FD6_ZSA_DEPTH_CLAMP,
219
A6XX_RB_DEPTH_CNTL_Z_CLAMP_ENABLE));
220
221
OUT_PKT4(ring, REG_A6XX_RB_STENCILMASK, 2);
222
OUT_RING(ring, so->rb_stencilmask);
223
OUT_RING(ring, so->rb_stencilwrmask);
224
225
so->stateobj[i] = ring;
226
}
227
228
return so;
229
}
230
231
void
232
fd6_zsa_state_delete(struct pipe_context *pctx, void *hwcso)
233
{
234
struct fd6_zsa_stateobj *so = hwcso;
235
236
for (int i = 0; i < ARRAY_SIZE(so->stateobj); i++)
237
fd_ringbuffer_del(so->stateobj[i]);
238
FREE(hwcso);
239
}
240
241