17ec681f3Smrg/* 27ec681f3Smrg * Copyright 2011 Joakim Sindholt <opensource@zhasha.com> 37ec681f3Smrg * 47ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a 57ec681f3Smrg * copy of this software and associated documentation files (the "Software"), 67ec681f3Smrg * to deal in the Software without restriction, including without limitation 77ec681f3Smrg * on the rights to use, copy, modify, merge, publish, distribute, sub 87ec681f3Smrg * license, and/or sell copies of the Software, and to permit persons to whom 97ec681f3Smrg * the Software is furnished to do so, subject to the following conditions: 107ec681f3Smrg * 117ec681f3Smrg * The above copyright notice and this permission notice (including the next 127ec681f3Smrg * paragraph) shall be included in all copies or substantial portions of the 137ec681f3Smrg * Software. 147ec681f3Smrg * 157ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 167ec681f3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 177ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 187ec681f3Smrg * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 197ec681f3Smrg * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 207ec681f3Smrg * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 217ec681f3Smrg * USE OR OTHER DEALINGS IN THE SOFTWARE. */ 227ec681f3Smrg 237ec681f3Smrg#include "nine_helpers.h" 247ec681f3Smrg#include "nine_shader.h" 257ec681f3Smrg 267ec681f3Smrg#include "pixelshader9.h" 277ec681f3Smrg 287ec681f3Smrg#include "device9.h" 297ec681f3Smrg#include "pipe/p_context.h" 307ec681f3Smrg 317ec681f3Smrg#define DBG_CHANNEL DBG_PIXELSHADER 327ec681f3Smrg 337ec681f3SmrgHRESULT 347ec681f3SmrgNinePixelShader9_ctor( struct NinePixelShader9 *This, 357ec681f3Smrg struct NineUnknownParams *pParams, 367ec681f3Smrg const DWORD *pFunction, void *cso ) 377ec681f3Smrg{ 387ec681f3Smrg struct NineDevice9 *device; 397ec681f3Smrg struct nine_shader_info info; 407ec681f3Smrg struct pipe_context *pipe; 417ec681f3Smrg HRESULT hr; 427ec681f3Smrg 437ec681f3Smrg DBG("This=%p pParams=%p pFunction=%p cso=%p\n", This, pParams, pFunction, cso); 447ec681f3Smrg 457ec681f3Smrg hr = NineUnknown_ctor(&This->base, pParams); 467ec681f3Smrg if (FAILED(hr)) 477ec681f3Smrg return hr; 487ec681f3Smrg 497ec681f3Smrg if (cso) { 507ec681f3Smrg This->ff_cso = cso; 517ec681f3Smrg return D3D_OK; 527ec681f3Smrg } 537ec681f3Smrg device = This->base.device; 547ec681f3Smrg 557ec681f3Smrg info.type = PIPE_SHADER_FRAGMENT; 567ec681f3Smrg info.byte_code = pFunction; 577ec681f3Smrg info.const_i_base = NINE_CONST_I_BASE(device->max_ps_const_f) / 16; 587ec681f3Smrg info.const_b_base = NINE_CONST_B_BASE(device->max_ps_const_f) / 16; 597ec681f3Smrg info.sampler_mask_shadow = 0x0; 607ec681f3Smrg info.fetch4 = 0x0; 617ec681f3Smrg info.sampler_ps1xtypes = 0x0; 627ec681f3Smrg info.fog_enable = 0; 637ec681f3Smrg info.projected = 0; 647ec681f3Smrg info.add_constants_defs.c_combination = NULL; 657ec681f3Smrg info.add_constants_defs.int_const_added = NULL; 667ec681f3Smrg info.add_constants_defs.bool_const_added = NULL; 677ec681f3Smrg info.process_vertices = false; 687ec681f3Smrg info.swvp_on = false; 697ec681f3Smrg 707ec681f3Smrg pipe = nine_context_get_pipe_acquire(device); 717ec681f3Smrg hr = nine_translate_shader(device, &info, pipe); 727ec681f3Smrg nine_context_get_pipe_release(device); 737ec681f3Smrg if (FAILED(hr)) 747ec681f3Smrg return hr; 757ec681f3Smrg This->byte_code.version = info.version; 767ec681f3Smrg 777ec681f3Smrg This->byte_code.tokens = mem_dup(pFunction, info.byte_size); 787ec681f3Smrg if (!This->byte_code.tokens) 797ec681f3Smrg return E_OUTOFMEMORY; 807ec681f3Smrg This->byte_code.size = info.byte_size; 817ec681f3Smrg 827ec681f3Smrg This->variant.cso = info.cso; 837ec681f3Smrg This->variant.const_ranges = info.const_ranges; 847ec681f3Smrg This->variant.const_used_size = info.const_used_size; 857ec681f3Smrg This->last_cso = info.cso; 867ec681f3Smrg This->last_const_ranges = info.const_ranges; 877ec681f3Smrg This->last_const_used_size = info.const_used_size; 887ec681f3Smrg This->last_key = 0; 897ec681f3Smrg 907ec681f3Smrg This->sampler_mask = info.sampler_mask; 917ec681f3Smrg This->rt_mask = info.rt_mask; 927ec681f3Smrg This->bumpenvmat_needed = info.bumpenvmat_needed; 937ec681f3Smrg 947ec681f3Smrg memcpy(This->int_slots_used, info.int_slots_used, sizeof(This->int_slots_used)); 957ec681f3Smrg memcpy(This->bool_slots_used, info.bool_slots_used, sizeof(This->bool_slots_used)); 967ec681f3Smrg 977ec681f3Smrg This->const_int_slots = info.const_int_slots; 987ec681f3Smrg This->const_bool_slots = info.const_bool_slots; 997ec681f3Smrg 1007ec681f3Smrg This->c_combinations = NULL; 1017ec681f3Smrg 1027ec681f3Smrg /* no constant relative addressing for ps */ 1037ec681f3Smrg assert(info.lconstf.data == NULL); 1047ec681f3Smrg assert(info.lconstf.ranges == NULL); 1057ec681f3Smrg 1067ec681f3Smrg return D3D_OK; 1077ec681f3Smrg} 1087ec681f3Smrg 1097ec681f3Smrgvoid 1107ec681f3SmrgNinePixelShader9_dtor( struct NinePixelShader9 *This ) 1117ec681f3Smrg{ 1127ec681f3Smrg DBG("This=%p\n", This); 1137ec681f3Smrg 1147ec681f3Smrg if (This->base.device) { 1157ec681f3Smrg struct pipe_context *pipe = nine_context_get_pipe_multithread(This->base.device); 1167ec681f3Smrg struct nine_shader_variant *var = &This->variant; 1177ec681f3Smrg 1187ec681f3Smrg do { 1197ec681f3Smrg if (var->cso) { 1207ec681f3Smrg if (This->base.device->context.cso_shader.ps == var->cso) 1217ec681f3Smrg pipe->bind_fs_state(pipe, NULL); 1227ec681f3Smrg pipe->delete_fs_state(pipe, var->cso); 1237ec681f3Smrg FREE(var->const_ranges); 1247ec681f3Smrg } 1257ec681f3Smrg var = var->next; 1267ec681f3Smrg } while (var); 1277ec681f3Smrg 1287ec681f3Smrg if (This->ff_cso) { 1297ec681f3Smrg if (This->ff_cso == This->base.device->context.cso_shader.ps) 1307ec681f3Smrg pipe->bind_fs_state(pipe, NULL); 1317ec681f3Smrg pipe->delete_fs_state(pipe, This->ff_cso); 1327ec681f3Smrg } 1337ec681f3Smrg } 1347ec681f3Smrg nine_shader_variants_free(&This->variant); 1357ec681f3Smrg 1367ec681f3Smrg nine_shader_constant_combination_free(This->c_combinations); 1377ec681f3Smrg 1387ec681f3Smrg FREE((void *)This->byte_code.tokens); /* const_cast */ 1397ec681f3Smrg 1407ec681f3Smrg NineUnknown_dtor(&This->base); 1417ec681f3Smrg} 1427ec681f3Smrg 1437ec681f3SmrgHRESULT NINE_WINAPI 1447ec681f3SmrgNinePixelShader9_GetFunction( struct NinePixelShader9 *This, 1457ec681f3Smrg void *pData, 1467ec681f3Smrg UINT *pSizeOfData ) 1477ec681f3Smrg{ 1487ec681f3Smrg DBG("This=%p pData=%p pSizeOfData=%p\n", This, pData, pSizeOfData); 1497ec681f3Smrg 1507ec681f3Smrg user_assert(pSizeOfData, D3DERR_INVALIDCALL); 1517ec681f3Smrg 1527ec681f3Smrg if (!pData) { 1537ec681f3Smrg *pSizeOfData = This->byte_code.size; 1547ec681f3Smrg return D3D_OK; 1557ec681f3Smrg } 1567ec681f3Smrg user_assert(*pSizeOfData >= This->byte_code.size, D3DERR_INVALIDCALL); 1577ec681f3Smrg 1587ec681f3Smrg memcpy(pData, This->byte_code.tokens, This->byte_code.size); 1597ec681f3Smrg 1607ec681f3Smrg return D3D_OK; 1617ec681f3Smrg} 1627ec681f3Smrg 1637ec681f3Smrgvoid * 1647ec681f3SmrgNinePixelShader9_GetVariant( struct NinePixelShader9 *This, 1657ec681f3Smrg unsigned **const_ranges, 1667ec681f3Smrg unsigned *const_used_size ) 1677ec681f3Smrg{ 1687ec681f3Smrg /* GetVariant is called from nine_context, thus we can 1697ec681f3Smrg * get pipe directly */ 1707ec681f3Smrg struct pipe_context *pipe = This->base.device->context.pipe; 1717ec681f3Smrg void *cso; 1727ec681f3Smrg uint64_t key; 1737ec681f3Smrg 1747ec681f3Smrg key = This->next_key; 1757ec681f3Smrg if (key == This->last_key) { 1767ec681f3Smrg *const_ranges = This->last_const_ranges; 1777ec681f3Smrg *const_used_size = This->last_const_used_size; 1787ec681f3Smrg return This->last_cso; 1797ec681f3Smrg } 1807ec681f3Smrg 1817ec681f3Smrg cso = nine_shader_variant_get(&This->variant, const_ranges, const_used_size, key); 1827ec681f3Smrg if (!cso) { 1837ec681f3Smrg struct NineDevice9 *device = This->base.device; 1847ec681f3Smrg struct nine_shader_info info; 1857ec681f3Smrg HRESULT hr; 1867ec681f3Smrg 1877ec681f3Smrg info.type = PIPE_SHADER_FRAGMENT; 1887ec681f3Smrg info.const_i_base = NINE_CONST_I_BASE(device->max_ps_const_f) / 16; 1897ec681f3Smrg info.const_b_base = NINE_CONST_B_BASE(device->max_ps_const_f) / 16; 1907ec681f3Smrg info.byte_code = This->byte_code.tokens; 1917ec681f3Smrg info.sampler_mask_shadow = key & 0xffff; 1927ec681f3Smrg /* intended overlap with sampler_mask_shadow */ 1937ec681f3Smrg if (unlikely(This->byte_code.version < 0x20)) { 1947ec681f3Smrg if (This->byte_code.version < 0x14) { 1957ec681f3Smrg info.sampler_ps1xtypes = (key >> 4) & 0xff; 1967ec681f3Smrg info.projected = (key >> 12) & 0xff; 1977ec681f3Smrg } else { 1987ec681f3Smrg info.sampler_ps1xtypes = (key >> 6) & 0xfff; 1997ec681f3Smrg info.projected = 0; 2007ec681f3Smrg } 2017ec681f3Smrg } else { 2027ec681f3Smrg info.sampler_ps1xtypes = 0; 2037ec681f3Smrg info.projected = 0; 2047ec681f3Smrg } 2057ec681f3Smrg info.fog_enable = device->context.rs[D3DRS_FOGENABLE]; 2067ec681f3Smrg info.fog_mode = device->context.rs[D3DRS_FOGTABLEMODE]; 2077ec681f3Smrg info.force_color_in_centroid = (key >> 22) & 1; 2087ec681f3Smrg info.add_constants_defs.c_combination = 2097ec681f3Smrg nine_shader_constant_combination_get(This->c_combinations, (key >> 24) & 0xff); 2107ec681f3Smrg info.add_constants_defs.int_const_added = &This->int_slots_used; 2117ec681f3Smrg info.add_constants_defs.bool_const_added = &This->bool_slots_used; 2127ec681f3Smrg info.fetch4 = key >> 32 ; 2137ec681f3Smrg info.process_vertices = false; 2147ec681f3Smrg info.swvp_on = false; 2157ec681f3Smrg 2167ec681f3Smrg hr = nine_translate_shader(This->base.device, &info, pipe); 2177ec681f3Smrg if (FAILED(hr)) 2187ec681f3Smrg return NULL; 2197ec681f3Smrg nine_shader_variant_add(&This->variant, key, info.cso, 2207ec681f3Smrg info.const_ranges, info.const_used_size); 2217ec681f3Smrg cso = info.cso; 2227ec681f3Smrg *const_ranges = info.const_ranges; 2237ec681f3Smrg *const_used_size = info.const_used_size; 2247ec681f3Smrg } 2257ec681f3Smrg 2267ec681f3Smrg This->last_key = key; 2277ec681f3Smrg This->last_cso = cso; 2287ec681f3Smrg This->last_const_ranges = *const_ranges; 2297ec681f3Smrg This->last_const_used_size = *const_used_size; 2307ec681f3Smrg 2317ec681f3Smrg return cso; 2327ec681f3Smrg} 2337ec681f3Smrg 2347ec681f3SmrgIDirect3DPixelShader9Vtbl NinePixelShader9_vtable = { 2357ec681f3Smrg (void *)NineUnknown_QueryInterface, 2367ec681f3Smrg (void *)NineUnknown_AddRef, 2377ec681f3Smrg (void *)NineUnknown_Release, 2387ec681f3Smrg (void *)NineUnknown_GetDevice, 2397ec681f3Smrg (void *)NinePixelShader9_GetFunction 2407ec681f3Smrg}; 2417ec681f3Smrg 2427ec681f3Smrgstatic const GUID *NinePixelShader9_IIDs[] = { 2437ec681f3Smrg &IID_IDirect3DPixelShader9, 2447ec681f3Smrg &IID_IUnknown, 2457ec681f3Smrg NULL 2467ec681f3Smrg}; 2477ec681f3Smrg 2487ec681f3SmrgHRESULT 2497ec681f3SmrgNinePixelShader9_new( struct NineDevice9 *pDevice, 2507ec681f3Smrg struct NinePixelShader9 **ppOut, 2517ec681f3Smrg const DWORD *pFunction, void *cso ) 2527ec681f3Smrg{ 2537ec681f3Smrg if (cso) { /* ff shader. Needs to start with bind count */ 2547ec681f3Smrg NINE_DEVICE_CHILD_BIND_NEW(PixelShader9, ppOut, pDevice, pFunction, cso); 2557ec681f3Smrg } else { 2567ec681f3Smrg NINE_DEVICE_CHILD_NEW(PixelShader9, ppOut, pDevice, pFunction, cso); 2577ec681f3Smrg } 2587ec681f3Smrg} 259