windows-nt/Source/XPSP1/NT/multimedia/directx/dxg/d3d8/fe/pshader.cpp
2020-09-26 16:20:57 +08:00

252 lines
7.3 KiB
C++

/*============================================================================
*
* 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