xref: /aosp_15_r20/external/mesa3d/src/gallium/frontends/nine/pixelshader9.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 "pixelshader9.h"
10 
11 #include "device9.h"
12 #include "pipe/p_context.h"
13 
14 #define DBG_CHANNEL DBG_PIXELSHADER
15 
16 HRESULT
NinePixelShader9_ctor(struct NinePixelShader9 * This,struct NineUnknownParams * pParams,const DWORD * pFunction,void * cso)17 NinePixelShader9_ctor( struct NinePixelShader9 *This,
18                        struct NineUnknownParams *pParams,
19                        const DWORD *pFunction, void *cso )
20 {
21     struct NineDevice9 *device;
22     struct nine_shader_info info;
23     struct pipe_context *pipe;
24     HRESULT hr;
25 
26     DBG("This=%p pParams=%p pFunction=%p cso=%p\n", This, pParams, pFunction, cso);
27 
28     hr = NineUnknown_ctor(&This->base, pParams);
29     if (FAILED(hr))
30         return hr;
31 
32     if (cso) {
33         This->ff_cso = cso;
34         return D3D_OK;
35     }
36     device = This->base.device;
37 
38     info.type = PIPE_SHADER_FRAGMENT;
39     info.byte_code = pFunction;
40     info.const_i_base = NINE_CONST_I_BASE(NINE_MAX_CONST_F_PS3) / 16;
41     info.const_b_base = NINE_CONST_B_BASE(NINE_MAX_CONST_F_PS3) / 16;
42     info.sampler_mask_shadow = 0x0;
43     info.fetch4 = 0x0;
44     info.force_color_in_centroid = 0;
45     info.sampler_ps1xtypes = 0x0;
46     info.fog_enable = 0;
47     info.projected = 0;
48     info.alpha_test_emulation = 0;
49     info.color_flatshade = 0;
50     info.add_constants_defs.c_combination = NULL;
51     info.add_constants_defs.int_const_added = NULL;
52     info.add_constants_defs.bool_const_added = NULL;
53     info.process_vertices = false;
54     info.swvp_on = false;
55 
56     pipe = nine_context_get_pipe_acquire(device);
57     hr = nine_translate_shader(device, &info, pipe);
58     nine_context_get_pipe_release(device);
59     if (FAILED(hr))
60         return hr;
61     This->byte_code.version = info.version;
62 
63     This->byte_code.tokens = mem_dup(pFunction, info.byte_size);
64     if (!This->byte_code.tokens)
65         return E_OUTOFMEMORY;
66     This->byte_code.size = info.byte_size;
67 
68     This->variant.cso = info.cso;
69     This->variant.const_ranges = info.const_ranges;
70     This->variant.const_used_size = info.const_used_size;
71     This->last_cso = info.cso;
72     This->last_const_ranges = info.const_ranges;
73     This->last_const_used_size = info.const_used_size;
74     This->last_key = 0;
75 
76     This->sampler_mask = info.sampler_mask;
77     This->rt_mask = info.rt_mask;
78     This->bumpenvmat_needed = info.bumpenvmat_needed;
79 
80     memcpy(This->int_slots_used, info.int_slots_used, sizeof(This->int_slots_used));
81     memcpy(This->bool_slots_used, info.bool_slots_used, sizeof(This->bool_slots_used));
82 
83     This->const_int_slots = info.const_int_slots;
84     This->const_bool_slots = info.const_bool_slots;
85 
86     This->c_combinations = NULL;
87 
88     /* no constant relative addressing for ps */
89     assert(info.lconstf.data == NULL);
90     assert(info.lconstf.ranges == NULL);
91 
92     return D3D_OK;
93 }
94 
95 void
NinePixelShader9_dtor(struct NinePixelShader9 * This)96 NinePixelShader9_dtor( struct NinePixelShader9 *This )
97 {
98     DBG("This=%p\n", This);
99 
100     if (This->base.device) {
101         struct pipe_context *pipe = nine_context_get_pipe_multithread(This->base.device);
102         struct nine_shader_variant *var = &This->variant;
103 
104         do {
105             if (var->cso) {
106                 if (This->base.device->context.cso_shader.ps == var->cso) {
107                     /* unbind because it is illegal to delete something bound */
108                     pipe->bind_fs_state(pipe, NULL);
109                     /* This will rebind cso_shader.ps in case somehow actually
110                      * an identical shader with same cso is bound */
111                     This->base.device->context.commit |= NINE_STATE_COMMIT_PS;
112                 }
113                 pipe->delete_fs_state(pipe, var->cso);
114                 FREE(var->const_ranges);
115             }
116             var = var->next;
117         } while (var);
118 
119         if (This->ff_cso) {
120             if (This->ff_cso == This->base.device->context.cso_shader.ps) {
121                 pipe->bind_fs_state(pipe, NULL);
122                 This->base.device->context.commit |= NINE_STATE_COMMIT_PS;
123             }
124             pipe->delete_fs_state(pipe, This->ff_cso);
125         }
126     }
127     nine_shader_variants_free(&This->variant);
128 
129     nine_shader_constant_combination_free(This->c_combinations);
130 
131     FREE((void *)This->byte_code.tokens); /* const_cast */
132 
133     NineUnknown_dtor(&This->base);
134 }
135 
136 HRESULT NINE_WINAPI
NinePixelShader9_GetFunction(struct NinePixelShader9 * This,void * pData,UINT * pSizeOfData)137 NinePixelShader9_GetFunction( struct NinePixelShader9 *This,
138                               void *pData,
139                               UINT *pSizeOfData )
140 {
141     DBG("This=%p pData=%p pSizeOfData=%p\n", This, pData, pSizeOfData);
142 
143     user_assert(pSizeOfData, D3DERR_INVALIDCALL);
144 
145     if (!pData) {
146         *pSizeOfData = This->byte_code.size;
147         return D3D_OK;
148     }
149     user_assert(*pSizeOfData >= This->byte_code.size, D3DERR_INVALIDCALL);
150 
151     memcpy(pData, This->byte_code.tokens, This->byte_code.size);
152 
153     return D3D_OK;
154 }
155 
156 void *
NinePixelShader9_GetVariant(struct NinePixelShader9 * This,unsigned ** const_ranges,unsigned * const_used_size)157 NinePixelShader9_GetVariant( struct NinePixelShader9 *This,
158                              unsigned **const_ranges,
159                              unsigned *const_used_size )
160 {
161     /* GetVariant is called from nine_context, thus we can
162      * get pipe directly */
163     struct pipe_context *pipe = This->base.device->context.pipe;
164     void *cso;
165     uint64_t key;
166 
167     key = This->next_key;
168     if (key == This->last_key) {
169         *const_ranges = This->last_const_ranges;
170         *const_used_size = This->last_const_used_size;
171         return This->last_cso;
172     }
173 
174     cso = nine_shader_variant_get(&This->variant, const_ranges, const_used_size, key);
175     if (!cso) {
176         struct NineDevice9 *device = This->base.device;
177         struct nine_shader_info info;
178         HRESULT hr;
179 
180         info.type = PIPE_SHADER_FRAGMENT;
181         info.const_i_base = NINE_CONST_I_BASE(NINE_MAX_CONST_F_PS3) / 16;
182         info.const_b_base = NINE_CONST_B_BASE(NINE_MAX_CONST_F_PS3) / 16;
183         info.byte_code = This->byte_code.tokens;
184         info.sampler_mask_shadow = key & 0xffff;
185         /* intended overlap with sampler_mask_shadow */
186         if (unlikely(This->byte_code.version < 0x20)) {
187             if (This->byte_code.version < 0x14) {
188                 info.sampler_ps1xtypes = (key >> 4) & 0xff;
189                 info.projected = (key >> 12) & 0xff;
190             } else {
191                 info.sampler_ps1xtypes = (key >> 6) & 0xfff;
192                 info.projected = 0;
193             }
194         } else {
195             info.sampler_ps1xtypes = 0;
196             info.projected = 0;
197         }
198         info.fog_enable = device->context.rs[D3DRS_FOGENABLE];
199         info.fog_mode = device->context.rs[D3DRS_FOGTABLEMODE];
200         info.zfog = device->context.zfog;
201         info.add_constants_defs.c_combination =
202             nine_shader_constant_combination_get(This->c_combinations, (key >> 24) & 0xff);
203         info.add_constants_defs.int_const_added = &This->int_slots_used;
204         info.add_constants_defs.bool_const_added = &This->bool_slots_used;
205         info.fetch4 = (key >> 32) & 0xffff;
206         info.force_color_in_centroid = (key >> 48) & 1;
207         info.alpha_test_emulation = (key >> 49) & 0x7;
208         info.color_flatshade = (key >> 52) & 1;
209         info.force_color_in_centroid &= !info.color_flatshade; /* centroid doesn't make sense with flatshade */
210         info.process_vertices = false;
211         info.swvp_on = false;
212 
213         hr = nine_translate_shader(This->base.device, &info, pipe);
214         if (FAILED(hr))
215             return NULL;
216         nine_shader_variant_add(&This->variant, key, info.cso,
217                                 info.const_ranges, info.const_used_size);
218         cso = info.cso;
219         *const_ranges = info.const_ranges;
220         *const_used_size = info.const_used_size;
221     }
222 
223     This->last_key = key;
224     This->last_cso = cso;
225     This->last_const_ranges = *const_ranges;
226     This->last_const_used_size = *const_used_size;
227 
228     return cso;
229 }
230 
231 IDirect3DPixelShader9Vtbl NinePixelShader9_vtable = {
232     (void *)NineUnknown_QueryInterface,
233     (void *)NineUnknown_AddRef,
234     (void *)NineUnknown_Release,
235     (void *)NineUnknown_GetDevice,
236     (void *)NinePixelShader9_GetFunction
237 };
238 
239 static const GUID *NinePixelShader9_IIDs[] = {
240     &IID_IDirect3DPixelShader9,
241     &IID_IUnknown,
242     NULL
243 };
244 
245 HRESULT
NinePixelShader9_new(struct NineDevice9 * pDevice,struct NinePixelShader9 ** ppOut,const DWORD * pFunction,void * cso)246 NinePixelShader9_new( struct NineDevice9 *pDevice,
247                       struct NinePixelShader9 **ppOut,
248                       const DWORD *pFunction, void *cso )
249 {
250     if (cso) { /* ff shader. Needs to start with bind count */
251         NINE_DEVICE_CHILD_BIND_NEW(PixelShader9, ppOut, pDevice, pFunction, cso);
252     } else {
253         NINE_DEVICE_CHILD_NEW(PixelShader9, ppOut, pDevice, pFunction, cso);
254     }
255 }
256