1 /**********************************************************
2 * Copyright 2022 VMware, Inc. All rights reserved.
3 *
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without
7 * restriction, including without limitation the rights to use, copy,
8 * modify, merge, publish, distribute, sublicense, and/or sell copies
9 * of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 *
24 **********************************************************/
25
26 #include "nir/nir_to_tgsi.h"
27 #include "util/u_inlines.h"
28 #include "util/u_memory.h"
29 #include "util/u_bitmask.h"
30 #include "tgsi/tgsi_parse.h"
31 #include "tgsi/tgsi_text.h"
32
33 #include "svga_context.h"
34 #include "svga_cmd.h"
35 #include "svga_debug.h"
36 #include "svga_shader.h"
37 #include "svga_streamout.h"
38 #include "svga_resource_buffer.h"
39 #include "svga_tgsi.h"
40
41 /**
42 * Create the compute program.
43 */
44 static void *
svga_create_compute_state(struct pipe_context * pipe,const struct pipe_compute_state * templ)45 svga_create_compute_state(struct pipe_context *pipe,
46 const struct pipe_compute_state *templ)
47 {
48 struct svga_context *svga = svga_context(pipe);
49
50 struct svga_compute_shader *cs = CALLOC_STRUCT(svga_compute_shader);
51
52 if (!cs)
53 return NULL;
54
55 SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_CREATECS);
56
57 if (templ->ir_type == PIPE_SHADER_IR_NIR) {
58 cs->base.tokens = nir_to_tgsi((void *)templ->prog, pipe->screen);
59 } else {
60 assert(templ->ir_type == PIPE_SHADER_IR_TGSI);
61 /* we need to keep a local copy of the tokens */
62 cs->base.tokens = tgsi_dup_tokens(templ->prog);
63 }
64 assert(templ->ir_type == PIPE_SHADER_IR_TGSI);
65 struct svga_shader *shader = &cs->base;
66 shader->id = svga->debug.shader_id++;
67 shader->type = templ->ir_type;
68 shader->stage = PIPE_SHADER_COMPUTE;
69
70 /* Collect shader basic info */
71 svga_tgsi_scan_shader(&cs->base);
72
73 cs->shared_mem_size = templ->req_local_mem;
74
75 SVGA_STATS_TIME_POP(svga_sws(svga));
76 return cs;
77 }
78
79
80 /**
81 * Bind the compute program.
82 */
83 static void
svga_bind_compute_state(struct pipe_context * pipe,void * shader)84 svga_bind_compute_state(struct pipe_context *pipe, void *shader)
85 {
86 struct svga_context *svga = svga_context(pipe);
87 struct svga_compute_shader *cs = (struct svga_compute_shader *)shader;
88
89 svga->curr.cs = cs;
90 svga->dirty |= SVGA_NEW_CS;
91 }
92
93
94 /**
95 * Delete the compute program.
96 */
97 static void
svga_delete_compute_state(struct pipe_context * pipe,void * shader)98 svga_delete_compute_state(struct pipe_context *pipe, void *shader)
99 {
100 struct svga_context *svga = svga_context(pipe);
101 struct svga_compute_shader *cs = (struct svga_compute_shader *)shader;
102 struct svga_compute_shader *next_cs;
103 struct svga_shader_variant *variant, *tmp;
104
105 svga_hwtnl_flush_retry(svga);
106
107 /* Free the list of compute shaders */
108 while (cs) {
109 next_cs = (struct svga_compute_shader *)cs->base.next;
110
111 for (variant = cs->base.variants; variant; variant = tmp) {
112 tmp = variant->next;
113
114 /* Check if deleting currently bound shader */
115 if (variant == svga->state.hw_draw.cs) {
116 SVGA_RETRY(svga, svga_set_shader(svga, SVGA3D_SHADERTYPE_CS, NULL));
117 svga->state.hw_draw.cs = NULL;
118 }
119
120 svga_destroy_shader_variant(svga, variant);
121 }
122
123 FREE((void *)cs->base.tokens);
124 FREE(cs);
125 cs = next_cs;
126 }
127 }
128
129
130 /**
131 * Bind an array of shader resources that will be used by the
132 * compute program. Any resources that were previously bound to
133 * the specified range will be unbound after this call.
134 */
135 static void
svga_set_compute_resources(struct pipe_context * pipe,unsigned start,unsigned count,struct pipe_surface ** resources)136 svga_set_compute_resources(struct pipe_context *pipe,
137 unsigned start, unsigned count,
138 struct pipe_surface **resources)
139 {
140 //TODO
141 return;
142 }
143
144
145 /**
146 * Bind an array of buffers to be mapped into the address space of
147 * the GLOBAL resource. Any buffers that were previously bound
148 * between [first, first + count - 1] are unbound after this call.
149 */
150 static void
svga_set_global_binding(struct pipe_context * pipe,unsigned first,unsigned count,struct pipe_resource ** resources,uint32_t ** handles)151 svga_set_global_binding(struct pipe_context *pipe,
152 unsigned first, unsigned count,
153 struct pipe_resource **resources,
154 uint32_t **handles)
155 {
156 //TODO
157 return;
158 }
159
160
161 /**
162 */
163 static void
svga_validate_compute_resources(struct svga_context * svga)164 svga_validate_compute_resources(struct svga_context *svga)
165 {
166 /* validate sampler view resources */
167 SVGA_RETRY(svga,
168 svga_validate_sampler_resources(svga, SVGA_PIPE_COMPUTE));
169
170 /* validate constant buffer resources */
171 SVGA_RETRY(svga,
172 svga_validate_constant_buffers(svga, SVGA_PIPE_COMPUTE));
173
174 /* validate image view resources */
175 SVGA_RETRY(svga,
176 svga_validate_image_views(svga, SVGA_PIPE_COMPUTE));
177
178 /* validate shader buffer resources */
179 SVGA_RETRY(svga,
180 svga_validate_shader_buffers(svga, SVGA_PIPE_COMPUTE));
181 }
182
183
184 /**
185 * Launch the compute kernel starting from instruction pc of the
186 * currently bound compute program.
187 */
188 static void
svga_launch_grid(struct pipe_context * pipe,const struct pipe_grid_info * info)189 svga_launch_grid(struct pipe_context *pipe,
190 const struct pipe_grid_info *info)
191 {
192 struct svga_context *svga = svga_context(pipe);
193 struct svga_winsys_context *swc = svga->swc;
194
195 assert(svga_have_gl43(svga));
196
197 SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_LAUNCHGRID);
198
199 if (info->indirect) {
200 svga->curr.grid_info.indirect= info->indirect;
201 }
202
203 svga_update_compute_state(svga);
204
205 /* validate compute resources */
206 svga_validate_compute_resources(svga);
207
208 if (info->indirect) {
209 struct svga_winsys_surface *indirect_surf;
210 indirect_surf = svga_buffer_handle(svga, info->indirect,
211 PIPE_BIND_COMMAND_ARGS_BUFFER);
212 SVGA_RETRY(svga, SVGA3D_sm5_DispatchIndirect(swc, indirect_surf,
213 info->indirect_offset));
214 }
215 else {
216 svga->curr.grid_info.size[0] = info->grid[0];
217 svga->curr.grid_info.size[1] = info->grid[1];
218 svga->curr.grid_info.size[2] = info->grid[2];
219
220 SVGA_RETRY(svga, SVGA3D_sm5_Dispatch(swc, info->grid));
221 }
222
223 SVGA_STATS_TIME_POP(svga_sws(svga));
224 return;
225 }
226
227
228 /**
229 * Initialize the compute interface function pointers.
230 */
231 void
svga_init_cs_functions(struct svga_context * svga)232 svga_init_cs_functions(struct svga_context *svga)
233 {
234 svga->pipe.create_compute_state = svga_create_compute_state;
235 svga->pipe.bind_compute_state = svga_bind_compute_state;
236 svga->pipe.delete_compute_state = svga_delete_compute_state;
237 svga->pipe.set_compute_resources = svga_set_compute_resources;
238 svga->pipe.set_global_binding = svga_set_global_binding;
239 svga->pipe.launch_grid = svga_launch_grid;
240 }
241