Implement new driver interface in Direct3D driver

This commit is contained in:
kaetemi 2013-09-09 16:36:29 +02:00
parent fd0b45c1db
commit 6dba9a7117
5 changed files with 482 additions and 517 deletions

View file

@ -3634,7 +3634,7 @@ void CDriverD3D::CVertexProgramPtrState::apply(CDriverD3D *driver)
void CDriverD3D::CPixelShaderPtrState::apply(CDriverD3D *driver) void CDriverD3D::CPixelShaderPtrState::apply(CDriverD3D *driver)
{ {
H_AUTO_D3D(CDriverD3D_CPixelShaderPtrState); H_AUTO_D3D(CDriverD3D_CPixelShaderPtrState);
if (!driver->supportPixelProgram()) return; if (!driver->_PixelProgram) return;
driver->_DeviceInterface->SetPixelShader(PixelShader); driver->_DeviceInterface->SetPixelShader(PixelShader);
} }

View file

@ -1092,33 +1092,103 @@ public:
virtual void setupMaterialPass(uint pass); virtual void setupMaterialPass(uint pass);
virtual void endMaterialMultiPass(); virtual void endMaterialMultiPass();
// Vertex program
virtual bool supportVertexProgram () const;
virtual bool supportPixelProgram () const;
virtual bool supportPixelProgram (CPixelProgram::TProfile profile) const;
virtual bool isVertexProgramEmulated () const;
virtual bool activeVertexProgram (CVertexProgram *program); /// \name Vertex Program
virtual bool activePixelProgram (CPixelProgram *program); // @{
virtual void setConstant (uint index, float, float, float, float);
virtual void setConstant (uint index, double, double, double, double); // Order of preference
virtual void setConstant (uint index, const NLMISC::CVector& value); // - activeVertexProgram
virtual void setConstant (uint index, const NLMISC::CVectorD& value); // - CMaterial pass[n] VP (uses activeVertexProgram, but does not override if one already set by code)
virtual void setConstant (uint index, uint num, const float *src); // - default generic VP that mimics fixed pipeline / no VP with fixed pipeline
virtual void setConstant (uint index, uint num, const double *src);
virtual void setConstantMatrix (uint index, IDriver::TMatrix matrix, IDriver::TTransform transform); /**
virtual void setConstantFog (uint index); * Does the driver supports vertex program, but emulated by CPU ?
*/
virtual bool isVertexProgramEmulated() const;
/** Return true if the driver supports the specified vertex program profile.
*/
virtual bool supportVertexProgram(CVertexProgram::TProfile profile = CVertexProgram::nelvp) const;
/** Compile the given vertex program, return if successful.
* If a vertex program was set active before compilation,
* the state of the active vertex program is undefined behaviour afterwards.
*/
virtual bool compileVertexProgram(CVertexProgram *program);
/** Set the active vertex program. This will override vertex programs specified in CMaterial render calls.
* Also used internally by setupMaterial(CMaterial) when getVertexProgram returns NULL.
* The vertex program is activated immediately.
*/
virtual bool activeVertexProgram(CVertexProgram *program);
// @}
/// \name Pixel Program
// @{
// Order of preference
// - activePixelProgram
// - CMaterial pass[n] PP (uses activePixelProgram, but does not override if one already set by code)
// - PP generated from CMaterial (uses activePixelProgram, but does not override if one already set by code)
/** Return true if the driver supports the specified pixel program profile.
*/
virtual bool supportPixelProgram(CPixelProgram::TProfile profile) const;
/** Compile the given pixel program, return if successful.
* If a pixel program was set active before compilation,
* the state of the active pixel program is undefined behaviour afterwards.
*/
virtual bool compilePixelProgram(CPixelProgram *program);
/** Set the active pixel program. This will override pixel programs specified in CMaterial render calls.
* Also used internally by setupMaterial(CMaterial) when getPixelProgram returns NULL.
* The pixel program is activated immediately.
*/
virtual bool activePixelProgram(CPixelProgram *program);
// @}
/// \name Program parameters
// @{
// Set parameters
virtual void setUniform1f(TProgram program, uint index, float f0);
virtual void setUniform2f(TProgram program, uint index, float f0, float f1);
virtual void setUniform3f(TProgram program, uint index, float f0, float f1, float f2);
virtual void setUniform4f(TProgram program, uint index, float f0, float f1, float f2, float f3);
virtual void setUniform1i(TProgram program, uint index, sint32 i0);
virtual void setUniform2i(TProgram program, uint index, sint32 i0, sint32 i1);
virtual void setUniform3i(TProgram program, uint index, sint32 i0, sint32 i1, sint32 i2);
virtual void setUniform4i(TProgram program, uint index, sint32 i0, sint32 i1, sint32 i2, sint32 i3);
virtual void setUniform1ui(TProgram program, uint index, uint32 ui0);
virtual void setUniform2ui(TProgram program, uint index, uint32 ui0, uint32 ui1);
virtual void setUniform3ui(TProgram program, uint index, uint32 ui0, uint32 ui1, uint32 ui2);
virtual void setUniform4ui(TProgram program, uint index, uint32 ui0, uint32 ui1, uint32 ui2, uint32 ui3);
virtual void setUniform3f(TProgram program, uint index, const NLMISC::CVector& v);
virtual void setUniform4f(TProgram program, uint index, const NLMISC::CVector& v, float f3);
virtual void setUniform4x4f(TProgram program, uint index, const NLMISC::CMatrix& m);
virtual void setUniform4fv(TProgram program, uint index, size_t num, const float *src);
virtual void setUniform4iv(TProgram program, uint index, size_t num, const sint32 *src);
virtual void setUniform4uiv(TProgram program, uint index, size_t num, const uint32 *src);
// Set builtin parameters
virtual void setUniformMatrix(TProgram program, uint index, TMatrix matrix, TTransform transform);
virtual void setUniformFog(TProgram program, uint index);
// @}
virtual void enableVertexProgramDoubleSidedColor(bool doubleSided); virtual void enableVertexProgramDoubleSidedColor(bool doubleSided);
virtual bool supportVertexProgramDoubleSidedColor() const; virtual bool supportVertexProgramDoubleSidedColor() const;
// Pixel program
virtual void setPixelProgramConstant (uint index, float, float, float, float);
virtual void setPixelProgramConstant (uint index, double, double, double, double);
virtual void setPixelProgramConstant (uint index, const NLMISC::CVector& value);
virtual void setPixelProgramConstant (uint index, const NLMISC::CVectorD& value);
virtual void setPixelProgramConstant (uint index, uint num, const float *src);
virtual void setPixelProgramConstant (uint index, uint num, const double *src);
virtual void setPixelProgramConstantMatrix (uint index, IDriver::TMatrix matrix, IDriver::TTransform transform);
// Occlusion query // Occlusion query
virtual bool supportOcclusionQuery() const; virtual bool supportOcclusionQuery() const;
virtual IOcclusionQuery *createOcclusionQuery(); virtual IOcclusionQuery *createOcclusionQuery();

View file

@ -54,12 +54,6 @@ CPixelProgramDrvInfosD3D::~CPixelProgramDrvInfosD3D()
// *************************************************************************** // ***************************************************************************
bool CDriverD3D::supportPixelProgram () const
{
H_AUTO_D3D(CDriverD3D_supportPixelProgram)
return _PixelProgram;
}
bool CDriverD3D::supportPixelProgram (CPixelProgram::TProfile profile) const bool CDriverD3D::supportPixelProgram (CPixelProgram::TProfile profile) const
{ {
H_AUTO_D3D(CDriverD3D_supportPixelProgram_profile) H_AUTO_D3D(CDriverD3D_supportPixelProgram_profile)
@ -69,81 +63,77 @@ bool CDriverD3D::supportPixelProgram (CPixelProgram::TProfile profile) const
// *************************************************************************** // ***************************************************************************
bool CDriverD3D::compilePixelProgram(CPixelProgram *program)
{
// Program setuped ?
if (program->_DrvInfo==NULL)
{
// Find a supported pixel program profile
CGPUProgramSource *source = NULL;
for (uint i = 0; i < program->getProgramSource()->Sources.size(); ++i)
{
if (supportPixelProgram(program->getProgramSource()->Sources[i]->Profile))
{
source = program->getProgramSource()->Sources[i];
}
}
if (!source)
{
nlwarning("No supported source profile for pixel program");
return false;
}
_GPUPrgDrvInfos.push_front (NULL);
ItGPUPrgDrvInfoPtrList itPix = _GPUPrgDrvInfos.begin();
CPixelProgramDrvInfosD3D *drvInfo;
*itPix = drvInfo = new CPixelProgramDrvInfosD3D(this, itPix);
// Create a driver info structure
program->_DrvInfo = *itPix;
LPD3DXBUFFER pShader;
LPD3DXBUFFER pErrorMsgs;
if (D3DXAssembleShader(source->SourcePtr, source->SourceLen, NULL, NULL, 0, &pShader, &pErrorMsgs) == D3D_OK)
{
if (_DeviceInterface->CreatePixelShader((DWORD*)pShader->GetBufferPointer(), &(getPixelProgramD3D(*program)->Shader)) != D3D_OK)
return false;
}
else
{
nlwarning ("Can't assemble pixel program:");
nlwarning ((const char*)pErrorMsgs->GetBufferPointer());
return false;
}
// Set parameters for assembly programs
drvInfo->ParamIndices = source->ParamIndices;
// Build the feature info
program->buildInfo(source->DisplayName.c_str(), source->Features);
}
return true;
}
// ***************************************************************************
bool CDriverD3D::activePixelProgram(CPixelProgram *program) bool CDriverD3D::activePixelProgram(CPixelProgram *program)
{ {
H_AUTO_D3D(CDriverD3D_activePixelProgram ) H_AUTO_D3D(CDriverD3D_activePixelProgram )
if (_DisableHardwarePixelProgram) if (_DisableHardwarePixelProgram)
return false; return false;
// Setup or unsetup ?
if (program)
{
// Program setuped ?
if (program->_DrvInfo==NULL)
{
// Find a supported pixel program profile
CGPUProgramSource *source = NULL;
for (uint i = 0; i < program->getProgramSource()->Sources.size(); ++i)
{
if (supportPixelProgram(program->getProgramSource()->Sources[i]->Profile))
{
source = program->getProgramSource()->Sources[i];
}
}
if (!source)
{
nlwarning("No supported source profile for pixel program");
return false;
}
_GPUPrgDrvInfos.push_front (NULL);
ItGPUPrgDrvInfoPtrList itPix = _GPUPrgDrvInfos.begin();
CPixelProgramDrvInfosD3D *drvInfo;
*itPix = drvInfo = new CPixelProgramDrvInfosD3D(this, itPix);
// Create a driver info structure
program->_DrvInfo = *itPix;
LPD3DXBUFFER pShader;
LPD3DXBUFFER pErrorMsgs;
if (D3DXAssembleShader(source->SourcePtr, source->SourceLen, NULL, NULL, 0, &pShader, &pErrorMsgs) == D3D_OK)
{
if (_DeviceInterface->CreatePixelShader((DWORD*)pShader->GetBufferPointer(), &(getPixelProgramD3D(*program)->Shader)) != D3D_OK)
return false;
}
else
{
nlwarning ("Can't assemble pixel program:");
nlwarning ((const char*)pErrorMsgs->GetBufferPointer());
return false;
}
// Set parameters for assembly programs
drvInfo->ParamIndices = source->ParamIndices;
// Build the feature info
program->buildInfo(source->DisplayName.c_str(), source->Features);
}
}
// Set the pixel program // Set the pixel program
if (program) if (program)
{ {
CPixelProgramDrvInfosD3D *info = static_cast<CPixelProgramDrvInfosD3D *>((IGPUProgramDrvInfos*)program->_DrvInfo); if (!CDriverD3D::compilePixelProgram(program)) return false;
setPixelShader (info->Shader);
float z = 0; CPixelProgramDrvInfosD3D *info = static_cast<CPixelProgramDrvInfosD3D *>((IGPUProgramDrvInfos*)program->_DrvInfo);
float o = 1; setPixelShader(info->Shader);
setRenderState (D3DRS_FOGSTART, *((DWORD*) (&o)));
setRenderState (D3DRS_FOGEND, *((DWORD*) (&z)));
} }
else else
{ {
setPixelShader (NULL); setPixelShader(NULL);
// Set the old fog range
setRenderState (D3DRS_FOGSTART, *((DWORD*) (&_FogStart)));
setRenderState (D3DRS_FOGEND, *((DWORD*) (&_FogEnd)));
} }
return true; return true;
@ -151,160 +141,6 @@ bool CDriverD3D::activePixelProgram(CPixelProgram *program)
// *************************************************************************** // ***************************************************************************
void CDriverD3D::setPixelProgramConstant (uint index, float f0, float f1, float f2, float f3)
{
H_AUTO_D3D(CDriverD3D_setPixelProgramConstant)
if (!_PixelProgram)
{
#ifdef NL_DEBUG
nlwarning("No pixel programs available!!");
#endif
return;
}
const float tabl[4] = {f0, f1, f2, f3};
setPixelShaderConstant (index, tabl);
}
// ***************************************************************************
void CDriverD3D::setPixelProgramConstant (uint index, double d0, double d1, double d2, double d3)
{
H_AUTO_D3D(CDriverD3D_setPixelProgramConstant )
if (!_PixelProgram)
{
#ifdef NL_DEBUG
nlwarning("No pixel programs available!!");
#endif
return;
}
const float tabl[4] = {(float)d0, (float)d1, (float)d2, (float)d3};
setPixelShaderConstant (index, tabl);
}
// ***************************************************************************
void CDriverD3D::setPixelProgramConstant (uint index, const NLMISC::CVector& value)
{
H_AUTO_D3D(CDriverD3D_setPixelProgramConstant )
if (!_PixelProgram)
{
#ifdef NL_DEBUG
nlwarning("No pixel programs available!!");
#endif
return;
}
const float tabl[4] = {value.x, value.y, value.z, 0};
setPixelShaderConstant (index, tabl);
}
// ***************************************************************************
void CDriverD3D::setPixelProgramConstant (uint index, const NLMISC::CVectorD& value)
{
H_AUTO_D3D(CDriverD3D_setPixelProgramConstant )
if (!_PixelProgram)
{
#ifdef NL_DEBUG
nlwarning("No pixel programs available!!");
#endif
return;
}
const float tabl[4] = {(float)value.x, (float)value.y, (float)value.z, 0};
setPixelShaderConstant (index, tabl);
}
// ***************************************************************************
void CDriverD3D::setPixelProgramConstant (uint index, uint num, const float *src)
{
H_AUTO_D3D(CDriverD3D_setPixelProgramConstant )
if (!_PixelProgram)
{
#ifdef NL_DEBUG
nlwarning("No pixel programs available!!");
#endif
return;
}
uint i;
for (i=0; i<num; i++)
setPixelShaderConstant (index+i, src+i*4);
}
// ***************************************************************************
void CDriverD3D::setPixelProgramConstant (uint index, uint num, const double *src)
{
H_AUTO_D3D(CDriverD3D_setPixelProgramConstant )
if (!_PixelProgram)
{
#ifdef NL_DEBUG
nlwarning("No pixel programs available!!");
#endif
return;
}
uint i;
for (i=0; i<num; i++)
{
const float tabl[4] = {(float)src[0], (float)src[1], (float)src[2], (float)src[3]};
setPixelShaderConstant (index+i, tabl);
src += 4;
}
}
// ***************************************************************************
void CDriverD3D::setPixelProgramConstantMatrix (uint index, IDriver::TMatrix matrix, IDriver::TTransform transform)
{
H_AUTO_D3D(CDriverD3D_setPixelProgramConstantMatrix)
if (!_PixelProgram)
{
#ifdef NL_DEBUG
nlwarning("No pixel programs available!!");
#endif
return;
}
D3DXMATRIX mat;
D3DXMATRIX *matPtr;
switch (matrix)
{
case IDriver::ModelView:
matPtr = &_D3DModelView;
break;
case IDriver::Projection:
matPtr = &(_MatrixCache[remapMatrixIndex (D3DTS_PROJECTION)].Matrix);
break;
case IDriver::ModelViewProjection:
matPtr = &_D3DModelViewProjection;
break;
}
if (transform != IDriver::Identity)
{
mat = *matPtr;
matPtr = &mat;
switch(transform)
{
case IDriver::Inverse:
D3DXMatrixInverse (&mat, NULL, &mat);
break;
case IDriver::Transpose:
D3DXMatrixTranspose (&mat, &mat);
break;
case IDriver::InverseTranspose:
D3DXMatrixInverse (&mat, NULL, &mat);
D3DXMatrixTranspose (&mat, &mat);
break;
}
}
setPixelProgramConstant (index, matPtr->_11, matPtr->_21, matPtr->_31, matPtr->_41);
setPixelProgramConstant (index+1, matPtr->_12, matPtr->_22, matPtr->_32, matPtr->_42);
setPixelProgramConstant (index+2, matPtr->_13, matPtr->_23, matPtr->_33, matPtr->_43);
setPixelProgramConstant (index+3, matPtr->_14, matPtr->_24, matPtr->_34, matPtr->_44);
}
// ***************************************************************************
void CDriverD3D::disableHardwarePixelProgram() void CDriverD3D::disableHardwarePixelProgram()
{ {
H_AUTO_D3D(CDriverD3D_disableHardwarePixelProgram) H_AUTO_D3D(CDriverD3D_disableHardwarePixelProgram)

View file

@ -0,0 +1,218 @@
// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "stddirect3d.h"
#include "driver_direct3d.h"
using namespace std;
using namespace NLMISC;
namespace NL3D
{
void CDriverD3D::setUniform4f(TProgram program, uint index, float f0, float f1, float f2, float f3)
{
H_AUTO_D3D(CDriverD3D_setUniform4f);
const float tabl[4] = { f0, f1, f2, f3 };
switch (program)
{
case VertexProgram:
if (_VertexProgram)
{
setVertexProgramConstant(index, tabl);
}
break;
case PixelProgram:
if (_PixelProgram)
{
setPixelShaderConstant(index, tabl);
}
break;
}
}
void CDriverD3D::setUniform4fv(TProgram program, uint index, size_t num, const float *src)
{
H_AUTO_D3D(CDriverD3D_setUniform4fv);
switch (program)
{
case VertexProgram:
if (_VertexProgram)
{
for (uint i = 0; i < num; ++i)
{
setVertexProgramConstant(index + i, src + (i * 4));
}
}
break;
case PixelProgram:
if (_PixelProgram)
{
for (uint i = 0; i < num; ++i)
{
setPixelShaderConstant(index + i, src + (i * 4));
}
}
break;
}
}
void CDriverD3D::setUniform1f(TProgram program, uint index, float f0)
{
CDriverD3D::setUniform4f(program, index, f0, 0.f, 0.f, 0.f);
}
void CDriverD3D::setUniform2f(TProgram program, uint index, float f0, float f1)
{
CDriverD3D::setUniform4f(program, index, f0, f1, 0.f, 0.f);
}
void CDriverD3D::setUniform3f(TProgram program, uint index, float f0, float f1, float f2)
{
CDriverD3D::setUniform4f(program, index, f0, f1, f2, 0.0f);
}
void CDriverD3D::setUniform1i(TProgram program, uint index, sint32 i0)
{
}
void CDriverD3D::setUniform2i(TProgram program, uint index, sint32 i0, sint32 i1)
{
}
void CDriverD3D::setUniform3i(TProgram program, uint index, sint32 i0, sint32 i1, sint32 i2)
{
}
void CDriverD3D::setUniform4i(TProgram program, uint index, sint32 i0, sint32 i1, sint32 i2, sint32 i3)
{
}
void CDriverD3D::setUniform1ui(TProgram program, uint index, uint32 ui0)
{
}
void CDriverD3D::setUniform2ui(TProgram program, uint index, uint32 ui0, uint32 ui1)
{
}
void CDriverD3D::setUniform3ui(TProgram program, uint index, uint32 ui0, uint32 ui1, uint32 ui2)
{
}
void CDriverD3D::setUniform4ui(TProgram program, uint index, uint32 ui0, uint32 ui1, uint32 ui2, uint32 ui3)
{
}
void CDriverD3D::setUniform3f(TProgram program, uint index, const NLMISC::CVector& v)
{
CDriverD3D::setUniform4f(program, index, v.x, v.y, v.z, 0.f);
}
void CDriverD3D::setUniform4f(TProgram program, uint index, const NLMISC::CVector& v, float f3)
{
CDriverD3D::setUniform4f(program, index, v.x, v.y, v.z, f3);
}
void CDriverD3D::setUniform4x4f(TProgram program, uint index, const NLMISC::CMatrix& m)
{
H_AUTO_D3D(CDriverD3D_setUniform4x4f);
// TODO: Verify this!
NLMISC::CMatrix mat = m;
mat.transpose();
const float *md = mat.get();
CDriverD3D::setUniform4fv(program, index, 4, md);
}
void CDriverD3D::setUniform4iv(TProgram program, uint index, size_t num, const sint32 *src)
{
}
void CDriverD3D::setUniform4uiv(TProgram program, uint index, size_t num, const uint32 *src)
{
}
void CDriverD3D::setUniformMatrix(NL3D::IDriver::TProgram program, uint index, NL3D::IDriver::TMatrix matrix, NL3D::IDriver::TTransform transform)
{
H_AUTO_D3D(CDriverD3D_setUniformMatrix);
D3DXMATRIX mat;
D3DXMATRIX *matPtr = NULL;
switch (matrix)
{
case IDriver::ModelView:
matPtr = &_D3DModelView;
break;
case IDriver::Projection:
matPtr = &(_MatrixCache[remapMatrixIndex(D3DTS_PROJECTION)].Matrix);
break;
case IDriver::ModelViewProjection:
matPtr = &_D3DModelViewProjection;
break;
}
if (transform != IDriver::Identity)
{
switch (transform)
{
case IDriver::Inverse:
D3DXMatrixInverse(&mat, NULL, matPtr);
break;
case IDriver::Transpose:
D3DXMatrixTranspose(&mat, matPtr);
break;
case IDriver::InverseTranspose:
D3DXMatrixInverse(&mat, NULL, matPtr);
D3DXMatrixTranspose(&mat, &mat);
break;
}
matPtr = &mat;
}
D3DXMatrixTranspose(&mat, matPtr);
CDriverD3D::setUniform4fv(program, index, 4, &mat.m[0][0]);
}
void CDriverD3D::setUniformFog(NL3D::IDriver::TProgram program, uint index)
{
H_AUTO_D3D(CDriverD3D_setUniformFog)
/* "oFog" must always be between [1, 0] what ever you set in D3DRS_FOGSTART and D3DRS_FOGEND (1 for no fog, 0 for full fog).
The Geforce4 TI 4200 (drivers 53.03 and 45.23) doesn't accept other values for "oFog". */
const float delta = _FogEnd - _FogStart;
CDriverD3D::setUniform4f(program, index,
-_D3DModelView._13 / delta,
-_D3DModelView._23 / delta,
-_D3DModelView._33 / delta,
1 - (_D3DModelView._43 - _FogStart) / delta);
}
} // NL3D

View file

@ -43,10 +43,10 @@ CVertexProgamDrvInfosD3D::~CVertexProgamDrvInfosD3D()
// *************************************************************************** // ***************************************************************************
bool CDriverD3D::supportVertexProgram () const bool CDriverD3D::supportVertexProgram (CVertexProgram::TProfile profile) const
{ {
H_AUTO_D3D(CDriverD3D_supportVertexProgram ) H_AUTO_D3D(CDriverD3D_supportVertexProgram )
return _VertexProgram; return (profile == CVertexProgram::nelvp) && _VertexProgram;
} }
// *************************************************************************** // ***************************************************************************
@ -262,123 +262,129 @@ void dump(const CVPParser::TProgram &prg, std::string &dest)
// *************************************************************************** // ***************************************************************************
bool CDriverD3D::compileVertexProgram(NL3D::CVertexProgram *program)
{
// Program setuped ?
if (program->_DrvInfo == NULL)
{
// Find nelvp
CGPUProgramSource *source = NULL;
for (uint i = 0; i < program->getProgramSource()->Sources.size(); ++i)
{
if (program->getProgramSource()->Sources[i]->Profile == CVertexProgram::nelvp)
{
source = program->getProgramSource()->Sources[i];
}
}
if (!source)
{
nlwarning("Direct3D driver only supports 'nelvp' profile, vertex program cannot be used");
return false;
}
_GPUPrgDrvInfos.push_front (NULL);
ItGPUPrgDrvInfoPtrList itTex = _GPUPrgDrvInfos.begin();
CVertexProgamDrvInfosD3D *drvInfo;
*itTex = drvInfo = new CVertexProgamDrvInfosD3D(this, itTex);
// Create a driver info structure
program->_DrvInfo = *itTex;
/** Check with our parser if the program will works with other implemented extensions, too. (EXT_vertex_shader ..).
* There are some incompatibilities.
*/
CVPParser parser;
CVPParser::TProgram parsedProgram;
std::string errorOutput;
bool result = parser.parse(source->SourcePtr, parsedProgram, errorOutput);
if (!result)
{
nlwarning("Unable to parse a vertex program :");
nlwarning(errorOutput.c_str());
#ifdef NL_DEBUG_D3D
nlassert(0);
#endif // NL_DEBUG_D3D
return false;
}
// tmp fix for Radeon 8500/9000/9200
// Currently they hang when PaletteSkin / SkinWeight are present in the vertex declaration, but not used
// so disable them in the vertex declaration
// We don't use these component in vertex programs currently..
#ifdef NL_DEBUG
for(uint k = 0; k < parsedProgram.size(); ++k)
{
for(uint l = 0; l < parsedProgram[k].getNumUsedSrc(); ++l)
{
const CVPOperand &op = parsedProgram[k].getSrc(l);
if (op.Type == CVPOperand::InputRegister)
{
nlassert(op.Value.InputRegisterValue != CVPOperand::IWeight);
nlassert(op.Value.InputRegisterValue != CVPOperand::IPaletteSkin);
}
}
}
#endif
// Dump the vertex program
std::string dest;
dump(parsedProgram, dest);
#ifdef NL_DEBUG_D3D
nlinfo("Assemble Vertex Shader : ");
string::size_type lineBegin = 0;
string::size_type lineEnd;
while ((lineEnd = dest.find('\n', lineBegin)) != string::npos)
{
nlinfo(dest.substr (lineBegin, lineEnd-lineBegin).c_str());
lineBegin = lineEnd+1;
}
nlinfo(dest.substr (lineBegin, lineEnd-lineBegin).c_str());
#endif // NL_DEBUG_D3D
LPD3DXBUFFER pShader;
LPD3DXBUFFER pErrorMsgs;
if (D3DXAssembleShader (dest.c_str(), (UINT)dest.size(), NULL, NULL, 0, &pShader, &pErrorMsgs) == D3D_OK)
{
if (_DeviceInterface->CreateVertexShader((DWORD*)pShader->GetBufferPointer(), &(getVertexProgramD3D(*program)->Shader)) != D3D_OK)
return false;
}
else
{
nlwarning ("Can't assemble vertex program:");
nlwarning ((const char*)pErrorMsgs->GetBufferPointer());
return false;
}
// Set parameters for assembly programs
drvInfo->ParamIndices = source->ParamIndices;
// Build the feature info
program->buildInfo(source->DisplayName.c_str(), source->Features);
}
return true;
}
// ***************************************************************************
bool CDriverD3D::activeVertexProgram (CVertexProgram *program) bool CDriverD3D::activeVertexProgram (CVertexProgram *program)
{ {
H_AUTO_D3D(CDriverD3D_activeVertexProgram ) H_AUTO_D3D(CDriverD3D_activeVertexProgram )
if (_DisableHardwareVertexProgram) if (_DisableHardwareVertexProgram)
return false; return false;
// Setup or unsetup ?
if (program)
{
// Program setuped ?
if (program->_DrvInfo==NULL)
{
// Find nelvp
CGPUProgramSource *source = NULL;
for (uint i = 0; i < program->getProgramSource()->Sources.size(); ++i)
{
if (program->getProgramSource()->Sources[i]->Profile == CVertexProgram::nelvp)
{
source = program->getProgramSource()->Sources[i];
}
}
if (!source)
{
nlwarning("Direct3D driver only supports 'nelvp' profile, vertex program cannot be used");
return false;
}
_GPUPrgDrvInfos.push_front (NULL);
ItGPUPrgDrvInfoPtrList itTex = _GPUPrgDrvInfos.begin();
CVertexProgamDrvInfosD3D *drvInfo;
*itTex = drvInfo = new CVertexProgamDrvInfosD3D(this, itTex);
// Create a driver info structure
program->_DrvInfo = *itTex;
/** Check with our parser if the program will works with other implemented extensions, too. (EXT_vertex_shader ..).
* There are some incompatibilities.
*/
CVPParser parser;
CVPParser::TProgram parsedProgram;
std::string errorOutput;
bool result = parser.parse(source->SourcePtr, parsedProgram, errorOutput);
if (!result)
{
nlwarning("Unable to parse a vertex program :");
nlwarning(errorOutput.c_str());
#ifdef NL_DEBUG_D3D
nlassert(0);
#endif // NL_DEBUG_D3D
return false;
}
// tmp fix for Radeon 8500/9000/9200
// Currently they hang when PaletteSkin / SkinWeight are present in the vertex declaration, but not used
// so disable them in the vertex declaration
// We don't use these component in vertex programs currently..
#ifdef NL_DEBUG
for(uint k = 0; k < parsedProgram.size(); ++k)
{
for(uint l = 0; l < parsedProgram[k].getNumUsedSrc(); ++l)
{
const CVPOperand &op = parsedProgram[k].getSrc(l);
if (op.Type == CVPOperand::InputRegister)
{
nlassert(op.Value.InputRegisterValue != CVPOperand::IWeight);
nlassert(op.Value.InputRegisterValue != CVPOperand::IPaletteSkin);
}
}
}
#endif
// Dump the vertex program
std::string dest;
dump(parsedProgram, dest);
#ifdef NL_DEBUG_D3D
nlinfo("Assemble Vertex Shader : ");
string::size_type lineBegin = 0;
string::size_type lineEnd;
while ((lineEnd = dest.find('\n', lineBegin)) != string::npos)
{
nlinfo(dest.substr (lineBegin, lineEnd-lineBegin).c_str());
lineBegin = lineEnd+1;
}
nlinfo(dest.substr (lineBegin, lineEnd-lineBegin).c_str());
#endif // NL_DEBUG_D3D
LPD3DXBUFFER pShader;
LPD3DXBUFFER pErrorMsgs;
if (D3DXAssembleShader (dest.c_str(), (UINT)dest.size(), NULL, NULL, 0, &pShader, &pErrorMsgs) == D3D_OK)
{
if (_DeviceInterface->CreateVertexShader((DWORD*)pShader->GetBufferPointer(), &(getVertexProgramD3D(*program)->Shader)) != D3D_OK)
return false;
}
else
{
nlwarning ("Can't assemble vertex program:");
nlwarning ((const char*)pErrorMsgs->GetBufferPointer());
return false;
}
// Set parameters for assembly programs
drvInfo->ParamIndices = source->ParamIndices;
// Build the feature info
program->buildInfo(source->DisplayName.c_str(), source->Features);
}
}
// Set the vertex program // Set the vertex program
if (program) if (program)
{ {
CVertexProgamDrvInfosD3D *info = static_cast<CVertexProgamDrvInfosD3D *>((IGPUProgramDrvInfos*)program->_DrvInfo); if (!CDriverD3D::compileVertexProgram(program)) return false;
CVertexProgamDrvInfosD3D *info = NLMISC::safe_cast<CVertexProgamDrvInfosD3D *>((IGPUProgramDrvInfos*)program->_DrvInfo);
setVertexProgram (info->Shader, program); setVertexProgram (info->Shader, program);
/* D3DRS_FOGSTART and D3DRS_FOGEND must be set with [1, 0] else the fog doesn't work properly on VertexShader and non-VertexShader objects /* D3DRS_FOGSTART and D3DRS_FOGEND must be set with [1, 0] else the fog doesn't work properly on VertexShader and non-VertexShader objects
(random fog flicking) with Geforce4 TI 4200 (drivers 53.03 and 45.23). The other cards seam to interpret the "oFog"'s values using D3DRS_FOGSTART, (random fog flicking) with Geforce4 TI 4200 (drivers 53.03 and 45.23). The other cards seam to interpret the "oFog"'s values using D3DRS_FOGSTART,
D3DRS_FOGEND. D3DRS_FOGEND.
Related to setUniformFog().
*/ */
float z = 0; float z = 0;
float o = 1; float o = 1;
@ -399,171 +405,6 @@ bool CDriverD3D::activeVertexProgram (CVertexProgram *program)
// *************************************************************************** // ***************************************************************************
void CDriverD3D::setConstant (uint index, float f0, float f1, float f2, float f3)
{
H_AUTO_D3D(CDriverD3D_setConstant )
if (!_VertexProgram)
{
#ifdef NL_DEBUG
nlwarning("No vertex programs available!!");
#endif
return;
}
const float tabl[4] = {f0, f1, f2, f3};
setVertexProgramConstant (index, tabl);
}
// ***************************************************************************
void CDriverD3D::setConstant (uint index, double d0, double d1, double d2, double d3)
{
H_AUTO_D3D(CDriverD3D_setConstant )
if (!_VertexProgram)
{
#ifdef NL_DEBUG
nlwarning("No vertex programs available!!");
#endif
return;
}
const float tabl[4] = {(float)d0, (float)d1, (float)d2, (float)d3};
setVertexProgramConstant (index, tabl);
}
// ***************************************************************************
void CDriverD3D::setConstant (uint index, const NLMISC::CVector& value)
{
H_AUTO_D3D(CDriverD3D_setConstant )
if (!_VertexProgram)
{
#ifdef NL_DEBUG
nlwarning("No vertex programs available!!");
#endif
return;
}
const float tabl[4] = {value.x, value.y, value.z, 0};
setVertexProgramConstant (index, tabl);
}
// ***************************************************************************
void CDriverD3D::setConstant (uint index, const NLMISC::CVectorD& value)
{
H_AUTO_D3D(CDriverD3D_setConstant )
if (!_VertexProgram)
{
#ifdef NL_DEBUG
nlwarning("No vertex programs available!!");
#endif
return;
}
const float tabl[4] = {(float)value.x, (float)value.y, (float)value.z, 0};
setVertexProgramConstant (index, tabl);
}
// ***************************************************************************
void CDriverD3D::setConstant (uint index, uint num, const float *src)
{
H_AUTO_D3D(CDriverD3D_setConstant )
if (!_VertexProgram)
{
#ifdef NL_DEBUG
nlwarning("No vertex programs available!!");
#endif
return;
}
uint i;
for (i=0; i<num; i++)
setVertexProgramConstant (index+i, src+i*4);
}
// ***************************************************************************
void CDriverD3D::setConstant (uint index, uint num, const double *src)
{
H_AUTO_D3D(CDriverD3D_setConstant )
if (!_VertexProgram)
{
#ifdef NL_DEBUG
nlwarning("No vertex programs available!!");
#endif
return;
}
uint i;
for (i=0; i<num; i++)
{
const float tabl[4] = {(float)src[0], (float)src[1], (float)src[2], (float)src[3]};
setVertexProgramConstant (index+i, tabl);
src += 4;
}
}
// ***************************************************************************
void CDriverD3D::setConstantMatrix (uint index, IDriver::TMatrix matrix, IDriver::TTransform transform)
{
H_AUTO_D3D(CDriverD3D_setConstantMatrix )
if (!_VertexProgram)
{
#ifdef NL_DEBUG
nlwarning("No vertex programs available!!");
#endif
return;
}
D3DXMATRIX mat;
D3DXMATRIX *matPtr = NULL;
switch (matrix)
{
case IDriver::ModelView:
matPtr = &_D3DModelView;
break;
case IDriver::Projection:
matPtr = &(_MatrixCache[remapMatrixIndex (D3DTS_PROJECTION)].Matrix);
break;
case IDriver::ModelViewProjection:
matPtr = &_D3DModelViewProjection;
break;
}
if (transform != IDriver::Identity)
{
mat = *matPtr;
matPtr = &mat;
switch(transform)
{
case IDriver::Inverse:
D3DXMatrixInverse (&mat, NULL, &mat);
break;
case IDriver::Transpose:
D3DXMatrixTranspose (&mat, &mat);
break;
case IDriver::InverseTranspose:
D3DXMatrixInverse (&mat, NULL, &mat);
D3DXMatrixTranspose (&mat, &mat);
break;
}
}
setConstant (index, matPtr->_11, matPtr->_21, matPtr->_31, matPtr->_41);
setConstant (index+1, matPtr->_12, matPtr->_22, matPtr->_32, matPtr->_42);
setConstant (index+2, matPtr->_13, matPtr->_23, matPtr->_33, matPtr->_43);
setConstant (index+3, matPtr->_14, matPtr->_24, matPtr->_34, matPtr->_44);
}
// ***************************************************************************
void CDriverD3D::setConstantFog (uint index)
{
H_AUTO_D3D(CDriverD3D_setConstantFog )
/* "oFog" must always be between [1, 0] what ever you set in D3DRS_FOGSTART and D3DRS_FOGEND (1 for no fog, 0 for full fog).
The Geforce4 TI 4200 (drivers 53.03 and 45.23) doesn't accept other values for "oFog". */
const float delta = _FogEnd-_FogStart;
setConstant (index, - _D3DModelView._13/delta, -_D3DModelView._23/delta, -_D3DModelView._33/delta, 1-(_D3DModelView._43-_FogStart)/delta);
}
// ***************************************************************************
void CDriverD3D::enableVertexProgramDoubleSidedColor(bool /* doubleSided */) void CDriverD3D::enableVertexProgramDoubleSidedColor(bool /* doubleSided */)
{ {
H_AUTO_D3D(CDriverD3D_enableVertexProgramDoubleSidedColor) H_AUTO_D3D(CDriverD3D_enableVertexProgramDoubleSidedColor)