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