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 "util/u_inlines.h"
27bf215546Sopenharmony_ci#include "util/u_memory.h"
28bf215546Sopenharmony_ci#include "util/u_bitmask.h"
29bf215546Sopenharmony_ci#include "translate/translate.h"
30bf215546Sopenharmony_ci#include "tgsi/tgsi_ureg.h"
31bf215546Sopenharmony_ci
32bf215546Sopenharmony_ci#include "svga_context.h"
33bf215546Sopenharmony_ci#include "svga_cmd.h"
34bf215546Sopenharmony_ci#include "svga_shader.h"
35bf215546Sopenharmony_ci#include "svga_tgsi.h"
36bf215546Sopenharmony_ci
37bf215546Sopenharmony_ci
38bf215546Sopenharmony_ci/**
39bf215546Sopenharmony_ci * Create compute shader compile key.
40bf215546Sopenharmony_ci */
41bf215546Sopenharmony_cistatic void
42bf215546Sopenharmony_cimake_cs_key(struct svga_context *svga,
43bf215546Sopenharmony_ci            struct svga_compile_key *key)
44bf215546Sopenharmony_ci{
45bf215546Sopenharmony_ci   struct svga_compute_shader *cs = svga->curr.cs;
46bf215546Sopenharmony_ci
47bf215546Sopenharmony_ci   memset(key, 0, sizeof *key);
48bf215546Sopenharmony_ci
49bf215546Sopenharmony_ci   svga_init_shader_key_common(svga, PIPE_SHADER_COMPUTE, &cs->base, key);
50bf215546Sopenharmony_ci
51bf215546Sopenharmony_ci   key->cs.grid_size[0] = svga->curr.grid_info.size[0];
52bf215546Sopenharmony_ci   key->cs.grid_size[1] = svga->curr.grid_info.size[1];
53bf215546Sopenharmony_ci   key->cs.grid_size[2] = svga->curr.grid_info.size[2];
54bf215546Sopenharmony_ci   key->cs.mem_size = cs->shared_mem_size;
55bf215546Sopenharmony_ci
56bf215546Sopenharmony_ci   if (svga->curr.grid_info.indirect && cs->base.info.uses_grid_size) {
57bf215546Sopenharmony_ci      struct pipe_transfer *transfer = NULL;
58bf215546Sopenharmony_ci      const void *map = NULL;
59bf215546Sopenharmony_ci      map = pipe_buffer_map(&svga->pipe, svga->curr.grid_info.indirect,
60bf215546Sopenharmony_ci                            PIPE_MAP_READ, &transfer);
61bf215546Sopenharmony_ci      memcpy(key->cs.grid_size, map, 3 * sizeof(uint));
62bf215546Sopenharmony_ci      pipe_buffer_unmap(&svga->pipe, transfer);
63bf215546Sopenharmony_ci   }
64bf215546Sopenharmony_ci}
65bf215546Sopenharmony_ci
66bf215546Sopenharmony_ci
67bf215546Sopenharmony_ci/**
68bf215546Sopenharmony_ci * Emit current compute shader to device.
69bf215546Sopenharmony_ci */
70bf215546Sopenharmony_cistatic enum pipe_error
71bf215546Sopenharmony_ciemit_hw_cs(struct svga_context *svga, uint64_t dirty)
72bf215546Sopenharmony_ci{
73bf215546Sopenharmony_ci   struct svga_shader_variant *variant;
74bf215546Sopenharmony_ci   struct svga_compute_shader *cs = svga->curr.cs;
75bf215546Sopenharmony_ci   enum pipe_error ret = PIPE_OK;
76bf215546Sopenharmony_ci   struct svga_compile_key key;
77bf215546Sopenharmony_ci
78bf215546Sopenharmony_ci   assert(svga_have_sm5(svga));
79bf215546Sopenharmony_ci
80bf215546Sopenharmony_ci   SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_EMITCS);
81bf215546Sopenharmony_ci
82bf215546Sopenharmony_ci   if (!cs) {
83bf215546Sopenharmony_ci      if (svga->state.hw_draw.cs != NULL) {
84bf215546Sopenharmony_ci
85bf215546Sopenharmony_ci         /** The previous compute shader is made inactive.
86bf215546Sopenharmony_ci          *  Needs to unbind the compute shader.
87bf215546Sopenharmony_ci          */
88bf215546Sopenharmony_ci         ret = svga_set_shader(svga, SVGA3D_SHADERTYPE_CS, NULL);
89bf215546Sopenharmony_ci         if (ret != PIPE_OK)
90bf215546Sopenharmony_ci            goto done;
91bf215546Sopenharmony_ci         svga->state.hw_draw.cs = NULL;
92bf215546Sopenharmony_ci      }
93bf215546Sopenharmony_ci      goto done;
94bf215546Sopenharmony_ci   }
95bf215546Sopenharmony_ci
96bf215546Sopenharmony_ci   make_cs_key(svga, &key);
97bf215546Sopenharmony_ci
98bf215546Sopenharmony_ci   /* See if we already have a CS variant that matches the key */
99bf215546Sopenharmony_ci   variant = svga_search_shader_key(&cs->base, &key);
100bf215546Sopenharmony_ci
101bf215546Sopenharmony_ci   if (!variant) {
102bf215546Sopenharmony_ci      ret = svga_compile_shader(svga, &cs->base, &key, &variant);
103bf215546Sopenharmony_ci      if (ret != PIPE_OK)
104bf215546Sopenharmony_ci         goto done;
105bf215546Sopenharmony_ci   }
106bf215546Sopenharmony_ci
107bf215546Sopenharmony_ci   if (variant != svga->state.hw_draw.cs) {
108bf215546Sopenharmony_ci      /* Bind the new variant */
109bf215546Sopenharmony_ci      ret = svga_set_shader(svga, SVGA3D_SHADERTYPE_CS, variant);
110bf215546Sopenharmony_ci      if (ret != PIPE_OK)
111bf215546Sopenharmony_ci         goto done;
112bf215546Sopenharmony_ci
113bf215546Sopenharmony_ci      svga->rebind.flags.cs = FALSE;
114bf215546Sopenharmony_ci      svga->dirty |= SVGA_NEW_CS_VARIANT;
115bf215546Sopenharmony_ci      svga->state.hw_draw.cs = variant;
116bf215546Sopenharmony_ci   }
117bf215546Sopenharmony_ci
118bf215546Sopenharmony_cidone:
119bf215546Sopenharmony_ci   SVGA_STATS_TIME_POP(svga_sws(svga));
120bf215546Sopenharmony_ci   return ret;
121bf215546Sopenharmony_ci}
122bf215546Sopenharmony_ci
123bf215546Sopenharmony_cistruct svga_tracked_state svga_hw_cs =
124bf215546Sopenharmony_ci{
125bf215546Sopenharmony_ci   "compute shader",
126bf215546Sopenharmony_ci   (SVGA_NEW_CS |
127bf215546Sopenharmony_ci    SVGA_NEW_TEXTURE_BINDING |
128bf215546Sopenharmony_ci    SVGA_NEW_SAMPLER |
129bf215546Sopenharmony_ci    SVGA_NEW_CS_RAW_BUFFER),
130bf215546Sopenharmony_ci   emit_hw_cs
131bf215546Sopenharmony_ci};
132