1 /*
2 * Copyright (c) 2008-2024 Broadcom. All Rights Reserved.
3 * The term “Broadcom” refers to Broadcom Inc.
4 * and/or its subsidiaries.
5 * SPDX-License-Identifier: MIT
6 */
7
8 #include "util/u_inlines.h"
9 #include "pipe/p_state.h"
10 #include "svga_context.h"
11 #include "svga_shader.h"
12 #include "svga_state.h"
13 #include "svga_debug.h"
14 #include "svga_hw_reg.h"
15
16
17 static enum pipe_error
update_need_swvfetch(struct svga_context * svga,uint64_t dirty)18 update_need_swvfetch(struct svga_context *svga, uint64_t dirty)
19 {
20 if (!svga->curr.velems) {
21 /* No vertex elements bound. */
22 return PIPE_OK;
23 }
24
25 if (svga->state.sw.need_swvfetch != svga->curr.velems->need_swvfetch) {
26 svga->state.sw.need_swvfetch = svga->curr.velems->need_swvfetch;
27 svga->dirty |= SVGA_NEW_NEED_SWVFETCH;
28 }
29
30 return PIPE_OK;
31 }
32
33 struct svga_tracked_state svga_update_need_swvfetch =
34 {
35 "update need_swvfetch",
36 ( SVGA_NEW_VELEMENT ),
37 update_need_swvfetch
38 };
39
40
41
42 static enum pipe_error
update_need_pipeline(struct svga_context * svga,uint64_t dirty)43 update_need_pipeline(struct svga_context *svga, uint64_t dirty)
44 {
45 bool need_pipeline = false;
46 struct svga_vertex_shader *vs = svga->curr.vs;
47 const char *reason = "";
48
49 /* SVGA_NEW_RAST, SVGA_NEW_REDUCED_PRIMITIVE
50 */
51 if (svga->curr.rast &&
52 (svga->curr.rast->need_pipeline & (1 << svga->curr.reduced_prim))) {
53 SVGA_DBG(DEBUG_SWTNL, "%s: rast need_pipeline (0x%x) & prim (0x%x)\n",
54 __func__,
55 svga->curr.rast->need_pipeline,
56 (1 << svga->curr.reduced_prim) );
57 SVGA_DBG(DEBUG_SWTNL, "%s: rast need_pipeline tris (%s), lines (%s), points (%s)\n",
58 __func__,
59 svga->curr.rast->need_pipeline_tris_str,
60 svga->curr.rast->need_pipeline_lines_str,
61 svga->curr.rast->need_pipeline_points_str);
62 need_pipeline = true;
63
64 switch (svga->curr.reduced_prim) {
65 case MESA_PRIM_POINTS:
66 reason = svga->curr.rast->need_pipeline_points_str;
67 break;
68 case MESA_PRIM_LINES:
69 reason = svga->curr.rast->need_pipeline_lines_str;
70 break;
71 case MESA_PRIM_TRIANGLES:
72 reason = svga->curr.rast->need_pipeline_tris_str;
73 break;
74 default:
75 assert(!"Unexpected reduced prim type");
76 }
77 }
78
79 /* EDGEFLAGS
80 */
81 if (vs && vs->base.info.writes_edgeflag) {
82 SVGA_DBG(DEBUG_SWTNL, "%s: edgeflags\n", __func__);
83 need_pipeline = true;
84 reason = "edge flags";
85 }
86
87 /* SVGA_NEW_FS, SVGA_NEW_RAST, SVGA_NEW_REDUCED_PRIMITIVE
88 */
89 if (svga->curr.rast && svga->curr.reduced_prim == MESA_PRIM_POINTS) {
90 unsigned sprite_coord_gen = svga->curr.rast->templ.sprite_coord_enable;
91 unsigned generic_inputs =
92 svga->curr.fs ? svga->curr.fs->generic_inputs : 0;
93
94 if (!svga_have_vgpu10(svga) && sprite_coord_gen &&
95 (generic_inputs & ~sprite_coord_gen)) {
96 /* The fragment shader is using some generic inputs that are
97 * not being replaced by auto-generated point/sprite coords (and
98 * auto sprite coord generation is turned on).
99 * The SVGA3D interface does not support that: if we enable
100 * SVGA3D_RS_POINTSPRITEENABLE it gets enabled for _all_
101 * texture coordinate sets.
102 * To solve this, we have to use the draw-module's wide/sprite
103 * point stage.
104 */
105 need_pipeline = true;
106 reason = "point sprite coordinate generation";
107 }
108 }
109
110 if (need_pipeline != svga->state.sw.need_pipeline) {
111 svga->state.sw.need_pipeline = need_pipeline;
112 svga->dirty |= SVGA_NEW_NEED_PIPELINE;
113 }
114
115 /* debug */
116 if (0 && svga->state.sw.need_pipeline)
117 debug_printf("sw.need_pipeline = %d\n", svga->state.sw.need_pipeline);
118
119 if (svga->state.sw.need_pipeline) {
120 assert(reason);
121 util_debug_message(&svga->debug.callback, FALLBACK,
122 "Using semi-fallback for %s", reason);
123 }
124
125 return PIPE_OK;
126 }
127
128
129 struct svga_tracked_state svga_update_need_pipeline =
130 {
131 "need pipeline",
132 (SVGA_NEW_RAST |
133 SVGA_NEW_FS |
134 SVGA_NEW_VS |
135 SVGA_NEW_REDUCED_PRIMITIVE),
136 update_need_pipeline
137 };
138
139
140 static enum pipe_error
update_need_swtnl(struct svga_context * svga,uint64_t dirty)141 update_need_swtnl(struct svga_context *svga, uint64_t dirty)
142 {
143 bool need_swtnl;
144
145 if (svga->debug.no_swtnl) {
146 svga->state.sw.need_swvfetch = false;
147 svga->state.sw.need_pipeline = false;
148 }
149
150 need_swtnl = (svga->state.sw.need_swvfetch ||
151 svga->state.sw.need_pipeline);
152
153 if (svga->debug.force_swtnl) {
154 need_swtnl = true;
155 }
156
157 /*
158 * Some state changes the draw module does makes us believe we
159 * we don't need swtnl. This causes the vdecl code to pickup
160 * the wrong buffers and vertex formats. Try trivial/line-wide.
161 */
162 if (svga->state.sw.in_swtnl_draw)
163 need_swtnl = true;
164
165 if (need_swtnl != svga->state.sw.need_swtnl) {
166 SVGA_DBG(DEBUG_SWTNL|DEBUG_PERF,
167 "%s: need_swvfetch %s, need_pipeline %s\n",
168 __func__,
169 svga->state.sw.need_swvfetch ? "true" : "false",
170 svga->state.sw.need_pipeline ? "true" : "false");
171
172 svga->state.sw.need_swtnl = need_swtnl;
173 svga->dirty |= SVGA_NEW_NEED_SWTNL;
174 svga->swtnl.new_vdecl = true;
175 }
176
177 return PIPE_OK;
178 }
179
180
181 struct svga_tracked_state svga_update_need_swtnl =
182 {
183 "need swtnl",
184 (SVGA_NEW_NEED_PIPELINE |
185 SVGA_NEW_NEED_SWVFETCH),
186 update_need_swtnl
187 };
188