1bf215546Sopenharmony_ci/**************************************************************************
2bf215546Sopenharmony_ci *
3bf215546Sopenharmony_ci * Copyright 2007 VMware, Inc.
4bf215546Sopenharmony_ci * All Rights Reserved.
5bf215546Sopenharmony_ci *
6bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
7bf215546Sopenharmony_ci * copy of this software and associated documentation files (the
8bf215546Sopenharmony_ci * "Software"), to deal in the Software without restriction, including
9bf215546Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish,
10bf215546Sopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to
11bf215546Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to
12bf215546Sopenharmony_ci * the following conditions:
13bf215546Sopenharmony_ci *
14bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the
15bf215546Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions
16bf215546Sopenharmony_ci * of the Software.
17bf215546Sopenharmony_ci *
18bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21bf215546Sopenharmony_ci * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22bf215546Sopenharmony_ci * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23bf215546Sopenharmony_ci * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24bf215546Sopenharmony_ci * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25bf215546Sopenharmony_ci *
26bf215546Sopenharmony_ci **************************************************************************/
27bf215546Sopenharmony_ci
28bf215546Sopenharmony_ci#include "sp_context.h"
29bf215546Sopenharmony_ci#include "sp_screen.h"
30bf215546Sopenharmony_ci#include "sp_state.h"
31bf215546Sopenharmony_ci#include "sp_fs.h"
32bf215546Sopenharmony_ci#include "sp_texture.h"
33bf215546Sopenharmony_ci
34bf215546Sopenharmony_ci#include "nir.h"
35bf215546Sopenharmony_ci#include "nir/nir_to_tgsi.h"
36bf215546Sopenharmony_ci#include "pipe/p_defines.h"
37bf215546Sopenharmony_ci#include "util/ralloc.h"
38bf215546Sopenharmony_ci#include "util/u_memory.h"
39bf215546Sopenharmony_ci#include "util/u_inlines.h"
40bf215546Sopenharmony_ci#include "draw/draw_context.h"
41bf215546Sopenharmony_ci#include "draw/draw_vs.h"
42bf215546Sopenharmony_ci#include "draw/draw_gs.h"
43bf215546Sopenharmony_ci#include "tgsi/tgsi_dump.h"
44bf215546Sopenharmony_ci#include "tgsi/tgsi_from_mesa.h"
45bf215546Sopenharmony_ci#include "tgsi/tgsi_scan.h"
46bf215546Sopenharmony_ci#include "tgsi/tgsi_parse.h"
47bf215546Sopenharmony_ci#include "compiler/shader_enums.h"
48bf215546Sopenharmony_ci
49bf215546Sopenharmony_ci
50bf215546Sopenharmony_ci/**
51bf215546Sopenharmony_ci * Create a new fragment shader variant.
52bf215546Sopenharmony_ci */
53bf215546Sopenharmony_cistatic struct sp_fragment_shader_variant *
54bf215546Sopenharmony_cicreate_fs_variant(struct softpipe_context *softpipe,
55bf215546Sopenharmony_ci                  struct sp_fragment_shader *fs,
56bf215546Sopenharmony_ci                  const struct sp_fragment_shader_variant_key *key)
57bf215546Sopenharmony_ci{
58bf215546Sopenharmony_ci   struct sp_fragment_shader_variant *var;
59bf215546Sopenharmony_ci   struct pipe_shader_state *curfs = &fs->shader;
60bf215546Sopenharmony_ci
61bf215546Sopenharmony_ci   /* codegen, create variant object */
62bf215546Sopenharmony_ci   var = softpipe_create_fs_variant_exec(softpipe);
63bf215546Sopenharmony_ci
64bf215546Sopenharmony_ci   if (var) {
65bf215546Sopenharmony_ci      var->key = *key;
66bf215546Sopenharmony_ci
67bf215546Sopenharmony_ci      var->tokens = tgsi_dup_tokens(curfs->tokens);
68bf215546Sopenharmony_ci
69bf215546Sopenharmony_ci      tgsi_scan_shader(var->tokens, &var->info);
70bf215546Sopenharmony_ci
71bf215546Sopenharmony_ci      /* See comments elsewhere about draw fragment shaders */
72bf215546Sopenharmony_ci#if 0
73bf215546Sopenharmony_ci      /* draw's fs state */
74bf215546Sopenharmony_ci      var->draw_shader = draw_create_fragment_shader(softpipe->draw,
75bf215546Sopenharmony_ci                                                     &fs->shader);
76bf215546Sopenharmony_ci      if (!var->draw_shader) {
77bf215546Sopenharmony_ci         var->delete(var);
78bf215546Sopenharmony_ci         FREE((void *) var->tokens);
79bf215546Sopenharmony_ci         return NULL;
80bf215546Sopenharmony_ci      }
81bf215546Sopenharmony_ci#endif
82bf215546Sopenharmony_ci
83bf215546Sopenharmony_ci      /* insert variant into linked list */
84bf215546Sopenharmony_ci      var->next = fs->variants;
85bf215546Sopenharmony_ci      fs->variants = var;
86bf215546Sopenharmony_ci   }
87bf215546Sopenharmony_ci
88bf215546Sopenharmony_ci   return var;
89bf215546Sopenharmony_ci}
90bf215546Sopenharmony_ci
91bf215546Sopenharmony_ci
92bf215546Sopenharmony_cistruct sp_fragment_shader_variant *
93bf215546Sopenharmony_cisoftpipe_find_fs_variant(struct softpipe_context *sp,
94bf215546Sopenharmony_ci                         struct sp_fragment_shader *fs,
95bf215546Sopenharmony_ci                         const struct sp_fragment_shader_variant_key *key)
96bf215546Sopenharmony_ci{
97bf215546Sopenharmony_ci   struct sp_fragment_shader_variant *var;
98bf215546Sopenharmony_ci
99bf215546Sopenharmony_ci   for (var = fs->variants; var; var = var->next) {
100bf215546Sopenharmony_ci      if (memcmp(&var->key, key, sizeof(*key)) == 0) {
101bf215546Sopenharmony_ci         /* found it */
102bf215546Sopenharmony_ci         return var;
103bf215546Sopenharmony_ci      }
104bf215546Sopenharmony_ci   }
105bf215546Sopenharmony_ci
106bf215546Sopenharmony_ci   return create_fs_variant(sp, fs, key);
107bf215546Sopenharmony_ci}
108bf215546Sopenharmony_ci
109bf215546Sopenharmony_cistatic void
110bf215546Sopenharmony_cisoftpipe_shader_db(struct pipe_context *pipe, const struct tgsi_token *tokens)
111bf215546Sopenharmony_ci{
112bf215546Sopenharmony_ci   struct softpipe_context *softpipe = softpipe_context(pipe);
113bf215546Sopenharmony_ci
114bf215546Sopenharmony_ci   struct tgsi_shader_info info;
115bf215546Sopenharmony_ci   tgsi_scan_shader(tokens, &info);
116bf215546Sopenharmony_ci   util_debug_message(&softpipe->debug, SHADER_INFO, "%s shader: %d inst, %d loops, %d temps, %d const, %d imm",
117bf215546Sopenharmony_ci                      _mesa_shader_stage_to_abbrev(tgsi_processor_to_shader_stage(info.processor)),
118bf215546Sopenharmony_ci                      info.num_instructions,
119bf215546Sopenharmony_ci                      info.opcode_count[TGSI_OPCODE_BGNLOOP],
120bf215546Sopenharmony_ci                      info.file_max[TGSI_FILE_TEMPORARY] + 1,
121bf215546Sopenharmony_ci                      info.file_max[TGSI_FILE_CONSTANT] + 1,
122bf215546Sopenharmony_ci                      info.immediate_count);
123bf215546Sopenharmony_ci}
124bf215546Sopenharmony_ci
125bf215546Sopenharmony_cistatic void
126bf215546Sopenharmony_cisoftpipe_create_shader_state(struct pipe_context *pipe,
127bf215546Sopenharmony_ci                             struct pipe_shader_state *shader,
128bf215546Sopenharmony_ci                             const struct pipe_shader_state *templ,
129bf215546Sopenharmony_ci                             bool debug)
130bf215546Sopenharmony_ci{
131bf215546Sopenharmony_ci   if (templ->type == PIPE_SHADER_IR_NIR) {
132bf215546Sopenharmony_ci      if (debug)
133bf215546Sopenharmony_ci         nir_print_shader(templ->ir.nir, stderr);
134bf215546Sopenharmony_ci
135bf215546Sopenharmony_ci      shader->tokens = nir_to_tgsi(templ->ir.nir, pipe->screen);
136bf215546Sopenharmony_ci   } else {
137bf215546Sopenharmony_ci      assert(templ->type == PIPE_SHADER_IR_TGSI);
138bf215546Sopenharmony_ci      /* we need to keep a local copy of the tokens */
139bf215546Sopenharmony_ci      shader->tokens = tgsi_dup_tokens(templ->tokens);
140bf215546Sopenharmony_ci   }
141bf215546Sopenharmony_ci
142bf215546Sopenharmony_ci   shader->type = PIPE_SHADER_IR_TGSI;
143bf215546Sopenharmony_ci
144bf215546Sopenharmony_ci   shader->stream_output = templ->stream_output;
145bf215546Sopenharmony_ci
146bf215546Sopenharmony_ci   if (debug)
147bf215546Sopenharmony_ci      tgsi_dump(shader->tokens, 0);
148bf215546Sopenharmony_ci
149bf215546Sopenharmony_ci   softpipe_shader_db(pipe, shader->tokens);
150bf215546Sopenharmony_ci}
151bf215546Sopenharmony_ci
152bf215546Sopenharmony_cistatic void *
153bf215546Sopenharmony_cisoftpipe_create_fs_state(struct pipe_context *pipe,
154bf215546Sopenharmony_ci                         const struct pipe_shader_state *templ)
155bf215546Sopenharmony_ci{
156bf215546Sopenharmony_ci   struct softpipe_context *softpipe = softpipe_context(pipe);
157bf215546Sopenharmony_ci   struct sp_fragment_shader *state = CALLOC_STRUCT(sp_fragment_shader);
158bf215546Sopenharmony_ci
159bf215546Sopenharmony_ci   softpipe_create_shader_state(pipe, &state->shader, templ,
160bf215546Sopenharmony_ci                                sp_debug & SP_DBG_FS);
161bf215546Sopenharmony_ci
162bf215546Sopenharmony_ci   /* draw's fs state */
163bf215546Sopenharmony_ci   state->draw_shader = draw_create_fragment_shader(softpipe->draw,
164bf215546Sopenharmony_ci                                                    &state->shader);
165bf215546Sopenharmony_ci   if (!state->draw_shader) {
166bf215546Sopenharmony_ci      tgsi_free_tokens(state->shader.tokens);
167bf215546Sopenharmony_ci      FREE(state);
168bf215546Sopenharmony_ci      return NULL;
169bf215546Sopenharmony_ci   }
170bf215546Sopenharmony_ci
171bf215546Sopenharmony_ci   return state;
172bf215546Sopenharmony_ci}
173bf215546Sopenharmony_ci
174bf215546Sopenharmony_ci
175bf215546Sopenharmony_cistatic void
176bf215546Sopenharmony_cisoftpipe_bind_fs_state(struct pipe_context *pipe, void *fs)
177bf215546Sopenharmony_ci{
178bf215546Sopenharmony_ci   struct softpipe_context *softpipe = softpipe_context(pipe);
179bf215546Sopenharmony_ci   struct sp_fragment_shader *state = (struct sp_fragment_shader *) fs;
180bf215546Sopenharmony_ci
181bf215546Sopenharmony_ci   if (softpipe->fs == fs)
182bf215546Sopenharmony_ci      return;
183bf215546Sopenharmony_ci
184bf215546Sopenharmony_ci   draw_flush(softpipe->draw);
185bf215546Sopenharmony_ci
186bf215546Sopenharmony_ci   softpipe->fs = fs;
187bf215546Sopenharmony_ci
188bf215546Sopenharmony_ci   /* This depends on the current fragment shader and must always be
189bf215546Sopenharmony_ci    * re-validated before use.
190bf215546Sopenharmony_ci    */
191bf215546Sopenharmony_ci   softpipe->fs_variant = NULL;
192bf215546Sopenharmony_ci
193bf215546Sopenharmony_ci   if (state)
194bf215546Sopenharmony_ci      draw_bind_fragment_shader(softpipe->draw,
195bf215546Sopenharmony_ci                                state->draw_shader);
196bf215546Sopenharmony_ci   else
197bf215546Sopenharmony_ci      draw_bind_fragment_shader(softpipe->draw, NULL);
198bf215546Sopenharmony_ci
199bf215546Sopenharmony_ci   softpipe->dirty |= SP_NEW_FS;
200bf215546Sopenharmony_ci}
201bf215546Sopenharmony_ci
202bf215546Sopenharmony_ci
203bf215546Sopenharmony_cistatic void
204bf215546Sopenharmony_cisoftpipe_delete_fs_state(struct pipe_context *pipe, void *fs)
205bf215546Sopenharmony_ci{
206bf215546Sopenharmony_ci   struct softpipe_context *softpipe = softpipe_context(pipe);
207bf215546Sopenharmony_ci   struct sp_fragment_shader *state = fs;
208bf215546Sopenharmony_ci   struct sp_fragment_shader_variant *var, *next_var;
209bf215546Sopenharmony_ci
210bf215546Sopenharmony_ci   assert(fs != softpipe->fs);
211bf215546Sopenharmony_ci
212bf215546Sopenharmony_ci   /* delete variants */
213bf215546Sopenharmony_ci   for (var = state->variants; var; var = next_var) {
214bf215546Sopenharmony_ci      next_var = var->next;
215bf215546Sopenharmony_ci
216bf215546Sopenharmony_ci      assert(var != softpipe->fs_variant);
217bf215546Sopenharmony_ci
218bf215546Sopenharmony_ci      /* See comments elsewhere about draw fragment shaders */
219bf215546Sopenharmony_ci#if 0
220bf215546Sopenharmony_ci      draw_delete_fragment_shader(softpipe->draw, var->draw_shader);
221bf215546Sopenharmony_ci#endif
222bf215546Sopenharmony_ci
223bf215546Sopenharmony_ci      var->delete(var, softpipe->fs_machine);
224bf215546Sopenharmony_ci   }
225bf215546Sopenharmony_ci
226bf215546Sopenharmony_ci   draw_delete_fragment_shader(softpipe->draw, state->draw_shader);
227bf215546Sopenharmony_ci
228bf215546Sopenharmony_ci   tgsi_free_tokens(state->shader.tokens);
229bf215546Sopenharmony_ci   FREE(state);
230bf215546Sopenharmony_ci}
231bf215546Sopenharmony_ci
232bf215546Sopenharmony_ci
233bf215546Sopenharmony_cistatic void *
234bf215546Sopenharmony_cisoftpipe_create_vs_state(struct pipe_context *pipe,
235bf215546Sopenharmony_ci                         const struct pipe_shader_state *templ)
236bf215546Sopenharmony_ci{
237bf215546Sopenharmony_ci   struct softpipe_context *softpipe = softpipe_context(pipe);
238bf215546Sopenharmony_ci   struct sp_vertex_shader *state;
239bf215546Sopenharmony_ci
240bf215546Sopenharmony_ci   state = CALLOC_STRUCT(sp_vertex_shader);
241bf215546Sopenharmony_ci   if (!state)
242bf215546Sopenharmony_ci      goto fail;
243bf215546Sopenharmony_ci
244bf215546Sopenharmony_ci   softpipe_create_shader_state(pipe, &state->shader, templ,
245bf215546Sopenharmony_ci                                sp_debug & SP_DBG_VS);
246bf215546Sopenharmony_ci   if (!state->shader.tokens)
247bf215546Sopenharmony_ci      goto fail;
248bf215546Sopenharmony_ci
249bf215546Sopenharmony_ci   state->draw_data = draw_create_vertex_shader(softpipe->draw, &state->shader);
250bf215546Sopenharmony_ci   if (state->draw_data == NULL)
251bf215546Sopenharmony_ci      goto fail;
252bf215546Sopenharmony_ci
253bf215546Sopenharmony_ci   state->max_sampler = state->draw_data->info.file_max[TGSI_FILE_SAMPLER];
254bf215546Sopenharmony_ci
255bf215546Sopenharmony_ci   return state;
256bf215546Sopenharmony_ci
257bf215546Sopenharmony_cifail:
258bf215546Sopenharmony_ci   if (state) {
259bf215546Sopenharmony_ci      tgsi_free_tokens(state->shader.tokens);
260bf215546Sopenharmony_ci      FREE( state->draw_data );
261bf215546Sopenharmony_ci      FREE( state );
262bf215546Sopenharmony_ci   }
263bf215546Sopenharmony_ci   return NULL;
264bf215546Sopenharmony_ci}
265bf215546Sopenharmony_ci
266bf215546Sopenharmony_ci
267bf215546Sopenharmony_cistatic void
268bf215546Sopenharmony_cisoftpipe_bind_vs_state(struct pipe_context *pipe, void *vs)
269bf215546Sopenharmony_ci{
270bf215546Sopenharmony_ci   struct softpipe_context *softpipe = softpipe_context(pipe);
271bf215546Sopenharmony_ci
272bf215546Sopenharmony_ci   softpipe->vs = (struct sp_vertex_shader *) vs;
273bf215546Sopenharmony_ci
274bf215546Sopenharmony_ci   draw_bind_vertex_shader(softpipe->draw,
275bf215546Sopenharmony_ci                           (softpipe->vs ? softpipe->vs->draw_data : NULL));
276bf215546Sopenharmony_ci
277bf215546Sopenharmony_ci   softpipe->dirty |= SP_NEW_VS;
278bf215546Sopenharmony_ci}
279bf215546Sopenharmony_ci
280bf215546Sopenharmony_ci
281bf215546Sopenharmony_cistatic void
282bf215546Sopenharmony_cisoftpipe_delete_vs_state(struct pipe_context *pipe, void *vs)
283bf215546Sopenharmony_ci{
284bf215546Sopenharmony_ci   struct softpipe_context *softpipe = softpipe_context(pipe);
285bf215546Sopenharmony_ci
286bf215546Sopenharmony_ci   struct sp_vertex_shader *state = (struct sp_vertex_shader *) vs;
287bf215546Sopenharmony_ci
288bf215546Sopenharmony_ci   draw_delete_vertex_shader(softpipe->draw, state->draw_data);
289bf215546Sopenharmony_ci   tgsi_free_tokens(state->shader.tokens);
290bf215546Sopenharmony_ci   FREE( state );
291bf215546Sopenharmony_ci}
292bf215546Sopenharmony_ci
293bf215546Sopenharmony_ci
294bf215546Sopenharmony_cistatic void *
295bf215546Sopenharmony_cisoftpipe_create_gs_state(struct pipe_context *pipe,
296bf215546Sopenharmony_ci                         const struct pipe_shader_state *templ)
297bf215546Sopenharmony_ci{
298bf215546Sopenharmony_ci   struct softpipe_context *softpipe = softpipe_context(pipe);
299bf215546Sopenharmony_ci   struct sp_geometry_shader *state;
300bf215546Sopenharmony_ci
301bf215546Sopenharmony_ci   state = CALLOC_STRUCT(sp_geometry_shader);
302bf215546Sopenharmony_ci   if (!state)
303bf215546Sopenharmony_ci      goto fail;
304bf215546Sopenharmony_ci
305bf215546Sopenharmony_ci   softpipe_create_shader_state(pipe, &state->shader, templ,
306bf215546Sopenharmony_ci                                sp_debug & SP_DBG_GS);
307bf215546Sopenharmony_ci
308bf215546Sopenharmony_ci   if (state->shader.tokens) {
309bf215546Sopenharmony_ci      state->draw_data = draw_create_geometry_shader(softpipe->draw,
310bf215546Sopenharmony_ci                                                     &state->shader);
311bf215546Sopenharmony_ci      if (state->draw_data == NULL)
312bf215546Sopenharmony_ci         goto fail;
313bf215546Sopenharmony_ci
314bf215546Sopenharmony_ci      state->max_sampler = state->draw_data->info.file_max[TGSI_FILE_SAMPLER];
315bf215546Sopenharmony_ci   }
316bf215546Sopenharmony_ci
317bf215546Sopenharmony_ci   return state;
318bf215546Sopenharmony_ci
319bf215546Sopenharmony_cifail:
320bf215546Sopenharmony_ci   if (state) {
321bf215546Sopenharmony_ci      tgsi_free_tokens(state->shader.tokens);
322bf215546Sopenharmony_ci      FREE( state->draw_data );
323bf215546Sopenharmony_ci      FREE( state );
324bf215546Sopenharmony_ci   }
325bf215546Sopenharmony_ci   return NULL;
326bf215546Sopenharmony_ci}
327bf215546Sopenharmony_ci
328bf215546Sopenharmony_ci
329bf215546Sopenharmony_cistatic void
330bf215546Sopenharmony_cisoftpipe_bind_gs_state(struct pipe_context *pipe, void *gs)
331bf215546Sopenharmony_ci{
332bf215546Sopenharmony_ci   struct softpipe_context *softpipe = softpipe_context(pipe);
333bf215546Sopenharmony_ci
334bf215546Sopenharmony_ci   softpipe->gs = (struct sp_geometry_shader *)gs;
335bf215546Sopenharmony_ci
336bf215546Sopenharmony_ci   draw_bind_geometry_shader(softpipe->draw,
337bf215546Sopenharmony_ci                             (softpipe->gs ? softpipe->gs->draw_data : NULL));
338bf215546Sopenharmony_ci
339bf215546Sopenharmony_ci   softpipe->dirty |= SP_NEW_GS;
340bf215546Sopenharmony_ci}
341bf215546Sopenharmony_ci
342bf215546Sopenharmony_ci
343bf215546Sopenharmony_cistatic void
344bf215546Sopenharmony_cisoftpipe_delete_gs_state(struct pipe_context *pipe, void *gs)
345bf215546Sopenharmony_ci{
346bf215546Sopenharmony_ci   struct softpipe_context *softpipe = softpipe_context(pipe);
347bf215546Sopenharmony_ci
348bf215546Sopenharmony_ci   struct sp_geometry_shader *state =
349bf215546Sopenharmony_ci      (struct sp_geometry_shader *)gs;
350bf215546Sopenharmony_ci
351bf215546Sopenharmony_ci   draw_delete_geometry_shader(softpipe->draw,
352bf215546Sopenharmony_ci                               (state) ? state->draw_data : 0);
353bf215546Sopenharmony_ci
354bf215546Sopenharmony_ci   tgsi_free_tokens(state->shader.tokens);
355bf215546Sopenharmony_ci   FREE(state);
356bf215546Sopenharmony_ci}
357bf215546Sopenharmony_ci
358bf215546Sopenharmony_ci
359bf215546Sopenharmony_cistatic void
360bf215546Sopenharmony_cisoftpipe_set_constant_buffer(struct pipe_context *pipe,
361bf215546Sopenharmony_ci                             enum pipe_shader_type shader, uint index,
362bf215546Sopenharmony_ci                             bool take_ownership,
363bf215546Sopenharmony_ci                             const struct pipe_constant_buffer *cb)
364bf215546Sopenharmony_ci{
365bf215546Sopenharmony_ci   struct softpipe_context *softpipe = softpipe_context(pipe);
366bf215546Sopenharmony_ci   struct pipe_resource *constants = cb ? cb->buffer : NULL;
367bf215546Sopenharmony_ci   unsigned size;
368bf215546Sopenharmony_ci   const void *data;
369bf215546Sopenharmony_ci
370bf215546Sopenharmony_ci   assert(shader < PIPE_SHADER_TYPES);
371bf215546Sopenharmony_ci
372bf215546Sopenharmony_ci   if (cb && cb->user_buffer) {
373bf215546Sopenharmony_ci      constants = softpipe_user_buffer_create(pipe->screen,
374bf215546Sopenharmony_ci                                              (void *) cb->user_buffer,
375bf215546Sopenharmony_ci                                              cb->buffer_size,
376bf215546Sopenharmony_ci                                              PIPE_BIND_CONSTANT_BUFFER);
377bf215546Sopenharmony_ci   }
378bf215546Sopenharmony_ci
379bf215546Sopenharmony_ci   size = cb ? cb->buffer_size : 0;
380bf215546Sopenharmony_ci   data = constants ? softpipe_resource_data(constants) : NULL;
381bf215546Sopenharmony_ci   if (data)
382bf215546Sopenharmony_ci      data = (const char *) data + cb->buffer_offset;
383bf215546Sopenharmony_ci
384bf215546Sopenharmony_ci   draw_flush(softpipe->draw);
385bf215546Sopenharmony_ci
386bf215546Sopenharmony_ci   /* note: reference counting */
387bf215546Sopenharmony_ci   if (take_ownership) {
388bf215546Sopenharmony_ci      pipe_resource_reference(&softpipe->constants[shader][index], NULL);
389bf215546Sopenharmony_ci      softpipe->constants[shader][index] = constants;
390bf215546Sopenharmony_ci   } else {
391bf215546Sopenharmony_ci      pipe_resource_reference(&softpipe->constants[shader][index], constants);
392bf215546Sopenharmony_ci   }
393bf215546Sopenharmony_ci
394bf215546Sopenharmony_ci   if (shader == PIPE_SHADER_VERTEX || shader == PIPE_SHADER_GEOMETRY) {
395bf215546Sopenharmony_ci      draw_set_mapped_constant_buffer(softpipe->draw, shader, index, data, size);
396bf215546Sopenharmony_ci   }
397bf215546Sopenharmony_ci
398bf215546Sopenharmony_ci   softpipe->mapped_constants[shader][index] = data;
399bf215546Sopenharmony_ci   softpipe->const_buffer_size[shader][index] = size;
400bf215546Sopenharmony_ci
401bf215546Sopenharmony_ci   softpipe->dirty |= SP_NEW_CONSTANTS;
402bf215546Sopenharmony_ci
403bf215546Sopenharmony_ci   if (cb && cb->user_buffer) {
404bf215546Sopenharmony_ci      pipe_resource_reference(&constants, NULL);
405bf215546Sopenharmony_ci   }
406bf215546Sopenharmony_ci}
407bf215546Sopenharmony_ci
408bf215546Sopenharmony_cistatic void *
409bf215546Sopenharmony_cisoftpipe_create_compute_state(struct pipe_context *pipe,
410bf215546Sopenharmony_ci                              const struct pipe_compute_state *templ)
411bf215546Sopenharmony_ci{
412bf215546Sopenharmony_ci   struct sp_compute_shader *state = CALLOC_STRUCT(sp_compute_shader);
413bf215546Sopenharmony_ci
414bf215546Sopenharmony_ci   state->shader = *templ;
415bf215546Sopenharmony_ci
416bf215546Sopenharmony_ci   if (templ->ir_type == PIPE_SHADER_IR_NIR) {
417bf215546Sopenharmony_ci      nir_shader *s = (void *)templ->prog;
418bf215546Sopenharmony_ci
419bf215546Sopenharmony_ci      if (sp_debug & SP_DBG_CS)
420bf215546Sopenharmony_ci         nir_print_shader(s, stderr);
421bf215546Sopenharmony_ci
422bf215546Sopenharmony_ci      state->tokens = (void *)nir_to_tgsi(s, pipe->screen);
423bf215546Sopenharmony_ci   } else {
424bf215546Sopenharmony_ci      assert(templ->ir_type == PIPE_SHADER_IR_TGSI);
425bf215546Sopenharmony_ci      /* we need to keep a local copy of the tokens */
426bf215546Sopenharmony_ci      state->tokens = tgsi_dup_tokens(templ->prog);
427bf215546Sopenharmony_ci   }
428bf215546Sopenharmony_ci
429bf215546Sopenharmony_ci   if (sp_debug & SP_DBG_CS)
430bf215546Sopenharmony_ci      tgsi_dump(state->tokens, 0);
431bf215546Sopenharmony_ci
432bf215546Sopenharmony_ci   softpipe_shader_db(pipe, state->tokens);
433bf215546Sopenharmony_ci
434bf215546Sopenharmony_ci   tgsi_scan_shader(state->tokens, &state->info);
435bf215546Sopenharmony_ci
436bf215546Sopenharmony_ci   state->max_sampler = state->info.file_max[TGSI_FILE_SAMPLER];
437bf215546Sopenharmony_ci
438bf215546Sopenharmony_ci   return state;
439bf215546Sopenharmony_ci}
440bf215546Sopenharmony_ci
441bf215546Sopenharmony_cistatic void
442bf215546Sopenharmony_cisoftpipe_bind_compute_state(struct pipe_context *pipe,
443bf215546Sopenharmony_ci                            void *cs)
444bf215546Sopenharmony_ci{
445bf215546Sopenharmony_ci   struct softpipe_context *softpipe = softpipe_context(pipe);
446bf215546Sopenharmony_ci   struct sp_compute_shader *state = (struct sp_compute_shader *)cs;
447bf215546Sopenharmony_ci   if (softpipe->cs == state)
448bf215546Sopenharmony_ci      return;
449bf215546Sopenharmony_ci
450bf215546Sopenharmony_ci   softpipe->cs = state;
451bf215546Sopenharmony_ci}
452bf215546Sopenharmony_ci
453bf215546Sopenharmony_cistatic void
454bf215546Sopenharmony_cisoftpipe_delete_compute_state(struct pipe_context *pipe,
455bf215546Sopenharmony_ci                              void *cs)
456bf215546Sopenharmony_ci{
457bf215546Sopenharmony_ci   ASSERTED struct softpipe_context *softpipe = softpipe_context(pipe);
458bf215546Sopenharmony_ci   struct sp_compute_shader *state = (struct sp_compute_shader *)cs;
459bf215546Sopenharmony_ci
460bf215546Sopenharmony_ci   assert(softpipe->cs != state);
461bf215546Sopenharmony_ci   tgsi_free_tokens(state->tokens);
462bf215546Sopenharmony_ci   FREE(state);
463bf215546Sopenharmony_ci}
464bf215546Sopenharmony_ci
465bf215546Sopenharmony_civoid
466bf215546Sopenharmony_cisoftpipe_init_shader_funcs(struct pipe_context *pipe)
467bf215546Sopenharmony_ci{
468bf215546Sopenharmony_ci   pipe->create_fs_state = softpipe_create_fs_state;
469bf215546Sopenharmony_ci   pipe->bind_fs_state   = softpipe_bind_fs_state;
470bf215546Sopenharmony_ci   pipe->delete_fs_state = softpipe_delete_fs_state;
471bf215546Sopenharmony_ci
472bf215546Sopenharmony_ci   pipe->create_vs_state = softpipe_create_vs_state;
473bf215546Sopenharmony_ci   pipe->bind_vs_state   = softpipe_bind_vs_state;
474bf215546Sopenharmony_ci   pipe->delete_vs_state = softpipe_delete_vs_state;
475bf215546Sopenharmony_ci
476bf215546Sopenharmony_ci   pipe->create_gs_state = softpipe_create_gs_state;
477bf215546Sopenharmony_ci   pipe->bind_gs_state   = softpipe_bind_gs_state;
478bf215546Sopenharmony_ci   pipe->delete_gs_state = softpipe_delete_gs_state;
479bf215546Sopenharmony_ci
480bf215546Sopenharmony_ci   pipe->set_constant_buffer = softpipe_set_constant_buffer;
481bf215546Sopenharmony_ci
482bf215546Sopenharmony_ci   pipe->create_compute_state = softpipe_create_compute_state;
483bf215546Sopenharmony_ci   pipe->bind_compute_state = softpipe_bind_compute_state;
484bf215546Sopenharmony_ci   pipe->delete_compute_state = softpipe_delete_compute_state;
485bf215546Sopenharmony_ci}
486