1 /*
2 * Copyright (c) 2022-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 "compiler/nir/nir.h"
9 #include "compiler/glsl/gl_nir.h"
10 #include "nir/nir_to_tgsi.h"
11
12 #include "util/u_inlines.h"
13 #include "util/u_memory.h"
14 #include "util/u_bitmask.h"
15 #include "tgsi/tgsi_parse.h"
16
17 #include "svga_context.h"
18 #include "svga_cmd.h"
19 #include "svga_debug.h"
20 #include "svga_shader.h"
21 #include "svga_streamout.h"
22 #include "svga_resource_buffer.h"
23 #include "svga_tgsi.h"
24
25 /**
26 * Create the compute program.
27 */
28 static void *
svga_create_compute_state(struct pipe_context * pipe,const struct pipe_compute_state * templ)29 svga_create_compute_state(struct pipe_context *pipe,
30 const struct pipe_compute_state *templ)
31 {
32 struct svga_context *svga = svga_context(pipe);
33
34 struct svga_compute_shader *cs = CALLOC_STRUCT(svga_compute_shader);
35 nir_shader *nir = (nir_shader *)templ->prog;
36
37 if (!cs)
38 return NULL;
39
40 SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_CREATECS);
41
42 assert(templ->ir_type == PIPE_SHADER_IR_NIR);
43 /* nir_to_tgsi requires lowered images */
44 NIR_PASS_V(nir, gl_nir_lower_images, false);
45
46 cs->base.tokens = nir_to_tgsi((void *)nir, pipe->screen);
47
48 struct svga_shader *shader = &cs->base;
49 shader->id = svga->debug.shader_id++;
50 shader->type = PIPE_SHADER_IR_TGSI;
51 shader->stage = PIPE_SHADER_COMPUTE;
52
53 /* Collect shader basic info */
54 svga_tgsi_scan_shader(&cs->base);
55
56 cs->shared_mem_size = templ->static_shared_mem;
57
58 SVGA_STATS_TIME_POP(svga_sws(svga));
59 return cs;
60 }
61
62
63 /**
64 * Bind the compute program.
65 */
66 static void
svga_bind_compute_state(struct pipe_context * pipe,void * shader)67 svga_bind_compute_state(struct pipe_context *pipe, void *shader)
68 {
69 struct svga_context *svga = svga_context(pipe);
70 struct svga_compute_shader *cs = (struct svga_compute_shader *)shader;
71
72 svga->curr.cs = cs;
73 svga->dirty |= SVGA_NEW_CS;
74
75 /* Check if the shader uses samplers */
76 svga_set_curr_shader_use_samplers_flag(svga, PIPE_SHADER_COMPUTE,
77 svga_shader_use_samplers(&cs->base));
78 }
79
80
81 /**
82 * Delete the compute program.
83 */
84 static void
svga_delete_compute_state(struct pipe_context * pipe,void * shader)85 svga_delete_compute_state(struct pipe_context *pipe, void *shader)
86 {
87 struct svga_context *svga = svga_context(pipe);
88 struct svga_compute_shader *cs = (struct svga_compute_shader *)shader;
89 struct svga_compute_shader *next_cs;
90 struct svga_shader_variant *variant, *tmp;
91
92 svga_hwtnl_flush_retry(svga);
93
94 /* Free the list of compute shaders */
95 while (cs) {
96 next_cs = (struct svga_compute_shader *)cs->base.next;
97
98 for (variant = cs->base.variants; variant; variant = tmp) {
99 tmp = variant->next;
100
101 /* Check if deleting currently bound shader */
102 if (variant == svga->state.hw_draw.cs) {
103 SVGA_RETRY(svga, svga_set_shader(svga, SVGA3D_SHADERTYPE_CS, NULL));
104 svga->state.hw_draw.cs = NULL;
105 }
106
107 svga_destroy_shader_variant(svga, variant);
108 }
109
110 FREE((void *)cs->base.tokens);
111 FREE(cs);
112 cs = next_cs;
113 }
114 }
115
116
117 /**
118 * Bind an array of shader resources that will be used by the
119 * compute program. Any resources that were previously bound to
120 * the specified range will be unbound after this call.
121 */
122 static void
svga_set_compute_resources(struct pipe_context * pipe,unsigned start,unsigned count,struct pipe_surface ** resources)123 svga_set_compute_resources(struct pipe_context *pipe,
124 unsigned start, unsigned count,
125 struct pipe_surface **resources)
126 {
127 //TODO
128 return;
129 }
130
131
132 /**
133 * Bind an array of buffers to be mapped into the address space of
134 * the GLOBAL resource. Any buffers that were previously bound
135 * between [first, first + count - 1] are unbound after this call.
136 */
137 static void
svga_set_global_binding(struct pipe_context * pipe,unsigned first,unsigned count,struct pipe_resource ** resources,uint32_t ** handles)138 svga_set_global_binding(struct pipe_context *pipe,
139 unsigned first, unsigned count,
140 struct pipe_resource **resources,
141 uint32_t **handles)
142 {
143 //TODO
144 return;
145 }
146
147
148 /**
149 */
150 static void
svga_validate_compute_resources(struct svga_context * svga)151 svga_validate_compute_resources(struct svga_context *svga)
152 {
153 /* validate sampler view resources */
154 SVGA_RETRY(svga,
155 svga_validate_sampler_resources(svga, SVGA_PIPE_COMPUTE));
156
157 /* validate constant buffer resources */
158 SVGA_RETRY(svga,
159 svga_validate_constant_buffers(svga, SVGA_PIPE_COMPUTE));
160
161 /* validate image view resources */
162 SVGA_RETRY(svga,
163 svga_validate_image_views(svga, SVGA_PIPE_COMPUTE));
164
165 /* validate shader buffer resources */
166 SVGA_RETRY(svga,
167 svga_validate_shader_buffers(svga, SVGA_PIPE_COMPUTE));
168 }
169
170
171 /**
172 * Launch the compute kernel starting from instruction pc of the
173 * currently bound compute program.
174 */
175 static void
svga_launch_grid(struct pipe_context * pipe,const struct pipe_grid_info * info)176 svga_launch_grid(struct pipe_context *pipe,
177 const struct pipe_grid_info *info)
178 {
179 struct svga_context *svga = svga_context(pipe);
180 struct svga_winsys_context *swc = svga->swc;
181
182 assert(svga_have_gl43(svga));
183
184 SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_LAUNCHGRID);
185
186 if (info->indirect) {
187 svga->curr.grid_info.indirect= info->indirect;
188 }
189
190 svga_update_compute_state(svga);
191
192 /* validate compute resources */
193 svga_validate_compute_resources(svga);
194
195 if (info->indirect) {
196 struct svga_winsys_surface *indirect_surf;
197 indirect_surf = svga_buffer_handle(svga, info->indirect,
198 PIPE_BIND_COMMAND_ARGS_BUFFER);
199 SVGA_RETRY(svga, SVGA3D_sm5_DispatchIndirect(swc, indirect_surf,
200 info->indirect_offset));
201 }
202 else {
203 svga->curr.grid_info.size[0] = info->grid[0];
204 svga->curr.grid_info.size[1] = info->grid[1];
205 svga->curr.grid_info.size[2] = info->grid[2];
206
207 SVGA_RETRY(svga, SVGA3D_sm5_Dispatch(swc, info->grid));
208 }
209
210 SVGA_STATS_TIME_POP(svga_sws(svga));
211 return;
212 }
213
214
215 /**
216 * Initialize the compute interface function pointers.
217 */
218 void
svga_init_cs_functions(struct svga_context * svga)219 svga_init_cs_functions(struct svga_context *svga)
220 {
221 svga->pipe.create_compute_state = svga_create_compute_state;
222 svga->pipe.bind_compute_state = svga_bind_compute_state;
223 svga->pipe.delete_compute_state = svga_delete_compute_state;
224 svga->pipe.set_compute_resources = svga_set_compute_resources;
225 svga->pipe.set_global_binding = svga_set_global_binding;
226 svga->pipe.launch_grid = svga_launch_grid;
227 }
228