/*============================================================================ * * Copyright (C) 1999 Microsoft Corporation. All Rights Reserved. * * File: pshader.cpp * Content: pixel shader runtime object init, including basic parsing * of pixel shader instructions * ****************************************************************************/ #include "pch.cpp" #pragma hdrstop #include "fe.h" #include "ddibase.h" #include "vvm.h" //----------------------------------------------------------------------------- #undef DPF_MODNAME #define DPF_MODNAME "CreatePixelShader" HRESULT CPShader::Initialize(CONST DWORD* pCode, D3DDEVTYPE DevType) { // get shader code sizes DWORD dwCodeAndCommentSize; DWORD dwCodeOnlySize; HRESULT hr = ComputeShaderCodeSize(pCode, &dwCodeOnlySize, &dwCodeAndCommentSize, &m_dwNumConstDefs); if (hr != S_OK) return hr; // copy original code m_dwCodeSizeOrig = dwCodeAndCommentSize; m_pCodeOrig = new DWORD[m_dwCodeSizeOrig >> 2]; if (NULL == m_pCodeOrig) { D3D_ERR("Cannot allocate memory for shader"); return E_OUTOFMEMORY; } memcpy( m_pCodeOrig, pCode, m_dwCodeSizeOrig ); if( m_dwNumConstDefs ) { m_pConstDefs = new CONST_DEF[m_dwNumConstDefs]; if (NULL == m_pConstDefs) { D3D_ERR("Cannot allocate memory for shader"); return E_OUTOFMEMORY; } } // strip comments before sending on if (not CHECKED) or HAL. // Also, store def declarations in CPShader, and strip them. BOOL bIsCheckedBuild = #if DBG TRUE; #else FALSE; #endif BOOL bStripComments = (!bIsCheckedBuild) || (DevType == D3DDEVTYPE_HAL); if ( bStripComments ) { // strip comments from version to pass on to DDI m_dwCodeSize = dwCodeOnlySize; } else { // pass comments through m_dwCodeSize = m_dwCodeSizeOrig; } m_pCode = new DWORD[m_dwCodeSize >> 2]; if (NULL == m_pCode) { D3D_ERR("Cannot allocate memory for shader"); return E_OUTOFMEMORY; } DWORD* pDst = m_pCode; CONST DWORD* pSrc = pCode; DWORD dwCurrConstDef = 0; *pDst++ = *pSrc++; // copy version while (*pSrc != 0x0000FFFF) { if(IsInstructionToken(*pSrc)) { DWORD opCode = (*pSrc) & D3DSI_OPCODE_MASK; if (opCode == D3DSIO_COMMENT ) { UINT DWordSize = ((*pSrc)&D3DSI_COMMENTSIZE_MASK)>>D3DSI_COMMENTSIZE_SHIFT; // strip comments from version to pass on to DDI if( !bStripComments ) { memcpy( pDst, pSrc, (DWordSize + 1)*sizeof(DWORD) ); pDst += (DWordSize+1); } pSrc += (DWordSize+1); // comment + instruction token } else if (opCode == D3DSIO_DEF) { *pDst++ = *pSrc++; DXGASSERT(m_pConstDefs && dwCurrConstDef < m_dwNumConstDefs); // Store reg. number m_pConstDefs[dwCurrConstDef].RegNum = (*pSrc & D3DSP_REGNUM_MASK); *pDst++ = *pSrc++; // Store the const vector memcpy( m_pConstDefs[dwCurrConstDef].f,pSrc,4*sizeof(DWORD) ); memcpy( pDst,pSrc,4*sizeof(DWORD) ); pSrc += 4; pDst += 4; dwCurrConstDef++; } else { *pDst++ = *pSrc++; } } else { *pDst++ = *pSrc++; } } *pDst++ = *pSrc++; // copy END DXGASSERT(dwCurrConstDef == m_dwNumConstDefs); return S_OK; } //----------------------------------------------------------------------------- #undef DPF_MODNAME #define DPF_MODNAME "CD3DHal::GetPixelShaderConstant" HRESULT D3DAPI CD3DHal::GetPixelShaderConstant(DWORD dwRegisterAddress, LPVOID lpvConstantData, DWORD dwConstantCount) { API_ENTER(this); #if DBG // Validate Parameters if (!VALID_WRITEPTR(lpvConstantData, 4*sizeof(D3DVALUE)*dwConstantCount)) { D3D_ERR("Invalid constant data pointer. GetPixelShaderConstant failed."); return D3DERR_INVALIDCALL; } #endif GetPixelShaderConstantI( dwRegisterAddress, dwConstantCount, lpvConstantData ); return S_OK; } //----------------------------------------------------------------------------- #undef DPF_MODNAME #define DPF_MODNAME "CD3DHal::SetPixelShaderFast" HRESULT D3DAPI CD3DHal::SetPixelShaderFast(DWORD dwHandle) { try { #if DBG CheckPixelShaderHandle(dwHandle); #endif // Update constants (if any were defined in the shader code) if( dwHandle ) { CPShader* pShader = (CPShader*)m_pPShaderArray->GetObject(dwHandle); for(UINT i = 0; i < pShader->m_dwNumConstDefs; i++ ) { CONST_DEF* pConstDef = &pShader->m_pConstDefs[i]; memcpy(&(m_PShaderConstReg[pConstDef->RegNum]), pConstDef->f, 4*sizeof(D3DVALUE)); } } // No redundant handle check because shader may have embedded constant definitions which // must always be applied. if (!(m_dwRuntimeFlags & D3DRT_EXECUTESTATEMODE)) m_pDDI->SetPixelShader(dwHandle); m_dwCurrentPixelShaderHandle = dwHandle; } catch(HRESULT hr) { D3D_ERR("SetPixelShader failed."); m_dwCurrentPixelShaderHandle = 0; return hr; } return S_OK; } //----------------------------------------------------------------------------- #undef DPF_MODNAME #define DPF_MODNAME "CD3DHal::SetPixelShaderConstantFast" HRESULT D3DAPI CD3DHal::SetPixelShaderConstantFast(DWORD Register, CONST VOID* pData, DWORD count) { #if DBG // Validate Parameters if (!VALID_PTR(pData, sizeof(DWORD) * count)) { D3D_ERR("Invalid constant data pointer. SetPixelShader failed."); return D3DERR_INVALIDCALL; } if(Register >= D3DPS_CONSTREG_MAX_DX8) { D3D_ERR("Invalid Constant Register number. SetPixelShader failed."); return D3DERR_INVALIDCALL; } if( (Register + count) > D3DPS_CONSTREG_MAX_DX8 ) { D3D_ERR("Not that many constant registers in the pixel machine. SetPixelShader failed."); return D3DERR_INVALIDCALL; } #endif // Cache the constants in the CPShader structure. memcpy(&(m_PShaderConstReg[Register]), pData, count*4*sizeof(D3DVALUE)); if (!(m_dwRuntimeFlags & D3DRT_EXECUTESTATEMODE)) { try { m_pDDI->SetPixelShaderConstant(Register, pData, count); } catch(HRESULT hr) { D3D_ERR("SetPixelShaderConstant failed."); return hr; } } return S_OK; } //----------------------------------------------------------------------------- #undef DPF_MODNAME #define DPF_MODNAME "CD3DHal::GetPixelShaderConstantI" void CD3DHal::GetPixelShaderConstantI(DWORD Register, DWORD count, LPVOID pData ) { // Cache the constants in the CPShader structure. memcpy( pData, &(m_PShaderConstReg[Register]), count*4*sizeof(D3DVALUE) ); } //----------------------------------------------------------------------------- // end