xref: /aosp_15_r20/external/mesa3d/src/gallium/frontends/nine/vertexshader9.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright 2011 Joakim Sindholt <[email protected]>
3  * SPDX-License-Identifier: MIT
4  */
5 
6 #include "nine_helpers.h"
7 #include "nine_shader.h"
8 
9 #include "vertexdeclaration9.h"
10 #include "vertexshader9.h"
11 
12 #include "device9.h"
13 #include "pipe/p_context.h"
14 #include "cso_cache/cso_context.h"
15 
16 #define DBG_CHANNEL DBG_VERTEXSHADER
17 
18 HRESULT
NineVertexShader9_ctor(struct NineVertexShader9 * This,struct NineUnknownParams * pParams,const DWORD * pFunction,void * cso)19 NineVertexShader9_ctor( struct NineVertexShader9 *This,
20                         struct NineUnknownParams *pParams,
21                         const DWORD *pFunction, void *cso )
22 {
23     struct NineDevice9 *device;
24     struct nine_shader_info info;
25     struct pipe_context *pipe;
26     HRESULT hr;
27     unsigned i;
28 
29     DBG("This=%p pParams=%p pFunction=%p cso=%p\n",
30         This, pParams, pFunction, cso);
31 
32     hr = NineUnknown_ctor(&This->base, pParams);
33     if (FAILED(hr))
34         return hr;
35 
36     if (cso) {
37         This->ff_cso = cso;
38         return D3D_OK;
39     }
40 
41     device = This->base.device;
42 
43     info.type = PIPE_SHADER_VERTEX;
44     info.byte_code = pFunction;
45     info.const_i_base = NINE_CONST_I_BASE(device->max_vs_const_f) / 16;
46     info.const_b_base = NINE_CONST_B_BASE(device->max_vs_const_f) / 16;
47     info.sampler_mask_shadow = 0x0;
48     info.fetch4 = 0x0;
49     info.sampler_ps1xtypes = 0x0;
50     info.fog_enable = 0;
51     info.point_size_min = 0;
52     info.point_size_max = 0;
53     info.clip_plane_emulation = 0;
54     info.add_constants_defs.c_combination = NULL;
55     info.add_constants_defs.int_const_added = NULL;
56     info.add_constants_defs.bool_const_added = NULL;
57     info.swvp_on = !!(device->params.BehaviorFlags & D3DCREATE_SOFTWARE_VERTEXPROCESSING);
58     info.process_vertices = false;
59 
60     pipe = nine_context_get_pipe_acquire(device);
61     hr = nine_translate_shader(device, &info, pipe);
62     if (hr == D3DERR_INVALIDCALL &&
63         (device->params.BehaviorFlags & D3DCREATE_MIXED_VERTEXPROCESSING)) {
64         /* Retry with a swvp shader. It will require swvp to be on. */
65         info.swvp_on = true;
66         hr = nine_translate_shader(device, &info, pipe);
67     }
68     nine_context_get_pipe_release(device);
69     if (hr == D3DERR_INVALIDCALL)
70         ERR("Encountered buggy shader\n");
71     if (FAILED(hr))
72         return hr;
73     This->byte_code.version = info.version;
74     This->swvp_only = info.swvp_on;
75 
76     This->byte_code.tokens = mem_dup(pFunction, info.byte_size);
77     if (!This->byte_code.tokens)
78         return E_OUTOFMEMORY;
79     This->byte_code.size = info.byte_size;
80 
81     This->variant.cso = info.cso;
82     This->variant.const_ranges = info.const_ranges;
83     This->variant.const_used_size = info.const_used_size;
84     This->last_cso = info.cso;
85     This->last_const_ranges = info.const_ranges;
86     This->last_const_used_size = info.const_used_size;
87     This->last_key = (uint32_t) (info.swvp_on << 9);
88 
89     This->lconstf = info.lconstf;
90     This->sampler_mask = info.sampler_mask;
91     This->position_t = info.position_t;
92     This->point_size = info.point_size;
93 
94     memcpy(This->int_slots_used, info.int_slots_used, sizeof(This->int_slots_used));
95     memcpy(This->bool_slots_used, info.bool_slots_used, sizeof(This->bool_slots_used));
96 
97     This->const_int_slots = info.const_int_slots;
98     This->const_bool_slots = info.const_bool_slots;
99 
100     This->c_combinations = NULL;
101 
102     for (i = 0; i < info.num_inputs && i < ARRAY_SIZE(This->input_map); ++i)
103         This->input_map[i].ndecl = info.input_map[i];
104     This->num_inputs = i;
105 
106     return D3D_OK;
107 }
108 
109 void
NineVertexShader9_dtor(struct NineVertexShader9 * This)110 NineVertexShader9_dtor( struct NineVertexShader9 *This )
111 {
112     DBG("This=%p\n", This);
113 
114     if (This->base.device) {
115         struct pipe_context *pipe = nine_context_get_pipe_multithread(This->base.device);
116         struct nine_shader_variant *var = &This->variant;
117         struct nine_shader_variant_so *var_so = &This->variant_so;
118 
119         do {
120             if (var->cso) {
121                 if (This->base.device->context.cso_shader.vs == var->cso) {
122                     /* unbind because it is illegal to delete something bound */
123                     pipe->bind_vs_state(pipe, NULL);
124                     /* This will rebind cso_shader.vs in case somehow actually
125                      * an identical shader with same cso is bound */
126                     This->base.device->context.commit |= NINE_STATE_COMMIT_VS;
127                 }
128                 pipe->delete_vs_state(pipe, var->cso);
129                 FREE(var->const_ranges);
130             }
131             var = var->next;
132         } while (var);
133 
134         while (var_so && var_so->vdecl) {
135             if (var_so->cso) {
136                 This->base.device->pipe_sw->delete_vs_state(This->base.device->pipe_sw, var_so->cso);
137             }
138             var_so = var_so->next;
139         }
140 
141         if (This->ff_cso) {
142             if (This->ff_cso == This->base.device->context.cso_shader.vs) {
143                 pipe->bind_vs_state(pipe, NULL);
144                 This->base.device->context.commit |= NINE_STATE_COMMIT_VS;
145             }
146             pipe->delete_vs_state(pipe, This->ff_cso);
147         }
148     }
149     nine_shader_variants_free(&This->variant);
150     nine_shader_variants_so_free(&This->variant_so);
151 
152     nine_shader_constant_combination_free(This->c_combinations);
153 
154     FREE((void *)This->byte_code.tokens); /* const_cast */
155 
156     FREE(This->lconstf.data);
157     FREE(This->lconstf.ranges);
158 
159     NineUnknown_dtor(&This->base);
160 }
161 
162 HRESULT NINE_WINAPI
NineVertexShader9_GetFunction(struct NineVertexShader9 * This,void * pData,UINT * pSizeOfData)163 NineVertexShader9_GetFunction( struct NineVertexShader9 *This,
164                                void *pData,
165                                UINT *pSizeOfData )
166 {
167     user_assert(pSizeOfData, D3DERR_INVALIDCALL);
168 
169     if (!pData) {
170         *pSizeOfData = This->byte_code.size;
171         return D3D_OK;
172     }
173     user_assert(*pSizeOfData >= This->byte_code.size, D3DERR_INVALIDCALL);
174 
175     memcpy(pData, This->byte_code.tokens, This->byte_code.size);
176 
177     return D3D_OK;
178 }
179 
180 void *
NineVertexShader9_GetVariant(struct NineVertexShader9 * This,unsigned ** const_ranges,unsigned * const_used_size)181 NineVertexShader9_GetVariant( struct NineVertexShader9 *This,
182                               unsigned **const_ranges,
183                               unsigned *const_used_size )
184 {
185     /* GetVariant is called from nine_context, thus we can
186      * get pipe directly */
187     struct pipe_context *pipe = This->base.device->context.pipe;
188     void *cso;
189     uint64_t key;
190 
191     key = This->next_key;
192     if (key == This->last_key) {
193         *const_ranges = This->last_const_ranges;
194         *const_used_size = This->last_const_used_size;
195         return This->last_cso;
196     }
197 
198     cso = nine_shader_variant_get(&This->variant, const_ranges, const_used_size, key);
199     if (!cso) {
200         struct NineDevice9 *device = This->base.device;
201         struct nine_shader_info info;
202         HRESULT hr;
203 
204         info.type = PIPE_SHADER_VERTEX;
205         info.const_i_base = NINE_CONST_I_BASE(device->max_vs_const_f) / 16;
206         info.const_b_base = NINE_CONST_B_BASE(device->max_vs_const_f) / 16;
207         info.byte_code = This->byte_code.tokens;
208         info.sampler_mask_shadow = key & 0xf;
209         info.fetch4 = 0x0;
210         info.fog_enable = device->context.rs[D3DRS_FOGENABLE];
211         info.point_size_min = asfloat(device->context.rs[D3DRS_POINTSIZE_MIN]);
212         info.point_size_max = asfloat(device->context.rs[D3DRS_POINTSIZE_MAX]);
213         info.clip_plane_emulation = (key >> 24) & 0xff;
214         info.add_constants_defs.c_combination =
215             nine_shader_constant_combination_get(This->c_combinations, (key >> 16) & 0xff);
216         info.add_constants_defs.int_const_added = &This->int_slots_used;
217         info.add_constants_defs.bool_const_added = &This->bool_slots_used;
218         info.swvp_on = device->context.swvp;
219         info.process_vertices = false;
220 
221         hr = nine_translate_shader(This->base.device, &info, pipe);
222         if (FAILED(hr))
223             return NULL;
224         nine_shader_variant_add(&This->variant, key, info.cso,
225                                 info.const_ranges, info.const_used_size);
226         cso = info.cso;
227         *const_ranges = info.const_ranges;
228         *const_used_size = info.const_used_size;
229     }
230 
231     This->last_key = key;
232     This->last_cso = cso;
233     This->last_const_ranges = *const_ranges;
234     This->last_const_used_size = *const_used_size;
235 
236     return cso;
237 }
238 
239 void *
NineVertexShader9_GetVariantProcessVertices(struct NineVertexShader9 * This,struct NineVertexDeclaration9 * vdecl_out,struct pipe_stream_output_info * so)240 NineVertexShader9_GetVariantProcessVertices( struct NineVertexShader9 *This,
241                                              struct NineVertexDeclaration9 *vdecl_out,
242                                              struct pipe_stream_output_info *so )
243 {
244     struct nine_shader_info info;
245     HRESULT hr;
246     void *cso;
247 
248     cso = nine_shader_variant_so_get(&This->variant_so, vdecl_out, so);
249     if (cso)
250         return cso;
251 
252     info.type = PIPE_SHADER_VERTEX;
253     info.const_i_base = 0;
254     info.const_b_base = 0;
255     info.byte_code = This->byte_code.tokens;
256     info.sampler_mask_shadow = 0;
257     info.fetch4 = 0x0;
258     info.fog_enable = false;
259     info.point_size_min = 0;
260     info.point_size_max = 0;
261     info.add_constants_defs.c_combination = NULL;
262     info.add_constants_defs.int_const_added = NULL;
263     info.add_constants_defs.bool_const_added = NULL;
264     info.swvp_on = true;
265     info.vdecl_out = vdecl_out;
266     info.process_vertices = true;
267     hr = nine_translate_shader(This->base.device, &info, This->base.device->pipe_sw);
268     if (FAILED(hr))
269         return NULL;
270     *so = info.so;
271     nine_shader_variant_so_add(&This->variant_so, vdecl_out, so, info.cso);
272     return info.cso;
273 }
274 
275 IDirect3DVertexShader9Vtbl NineVertexShader9_vtable = {
276     (void *)NineUnknown_QueryInterface,
277     (void *)NineUnknown_AddRef,
278     (void *)NineUnknown_Release,
279     (void *)NineUnknown_GetDevice,
280     (void *)NineVertexShader9_GetFunction
281 };
282 
283 static const GUID *NineVertexShader9_IIDs[] = {
284     &IID_IDirect3DVertexShader9,
285     &IID_IUnknown,
286     NULL
287 };
288 
289 HRESULT
NineVertexShader9_new(struct NineDevice9 * pDevice,struct NineVertexShader9 ** ppOut,const DWORD * pFunction,void * cso)290 NineVertexShader9_new( struct NineDevice9 *pDevice,
291                        struct NineVertexShader9 **ppOut,
292                        const DWORD *pFunction, void *cso )
293 {
294     if (cso) {
295         NINE_DEVICE_CHILD_BIND_NEW(VertexShader9, ppOut, pDevice, pFunction, cso);
296     } else {
297         NINE_DEVICE_CHILD_NEW(VertexShader9, ppOut, pDevice, pFunction, cso);
298     }
299 }
300