252 lines
7.3 KiB
C++
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
|