You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

153 lines
3.7 KiB

/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "hsConfig.h"
#include "hsWindows.h"
#include <D3d9.h>
#include <D3dx9core.h>
#include "hsTypes.h"
#include "plDXVertexShader.h"
#include "plSurface/plShader.h"
#include "plGBufferGroup.h"
#include "plDXPipeline.h"
plDXVertexShader::plDXVertexShader(plShader* owner)
: plDXShader(owner), fHandle(nil)
{
}
plDXVertexShader::~plDXVertexShader()
{
Release();
}
void plDXVertexShader::Release()
{
ReleaseObject(fHandle);
fHandle = nil;
fPipe = nil;
ISetError(nil);
}
hsBool plDXVertexShader::VerifyFormat(UInt8 format) const
{
return (fOwner->GetInputFormat() & format) == fOwner->GetInputFormat();
}
IDirect3DVertexShader9 *plDXVertexShader::GetShader(plDXPipeline* pipe)
{
HRESULT hr = S_OK;
if ( !fHandle )
{
if( FAILED(hr = ICreate(pipe)) )
return nil;
}
if( FAILED(hr = ISetConstants(pipe)) )
return nil;
return fHandle;
}
HRESULT plDXVertexShader::ICreate(plDXPipeline* pipe)
{
fHandle = nil; // in case something goes wrong.
fPipe = nil;
ISetError(nil);
#ifdef HS_DEBUGGING
DWORD flags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
#else // HS_DEBUGGING
DWORD flags = 0;
#endif // HS_DEBUGGING
// We could store the compiled buffer and skip the assembly step
// if we need to recreate the shader (e.g. on device lost).
// But whatever.
DWORD* shaderCodes = nil;
HRESULT hr = S_OK;
if( plShaderTable::LoadFromFile() || !fOwner->GetDecl()->GetCodes() )
{
if( fOwner->GetDecl()->GetFileName() )
{
LPD3DXBUFFER compiledShader = nil;
LPD3DXBUFFER compilationErrors = nil;
hr = D3DXAssembleShaderFromFile(
fOwner->GetDecl()->GetFileName(),
NULL, NULL, flags,
&compiledShader,
&compilationErrors);
if( FAILED(hr) )
{
return IOnError(hr, compilationErrors ? (char*)compilationErrors->GetBufferPointer() : "File not found");
}
shaderCodes = (DWORD*)(compiledShader->GetBufferPointer());
}
}
if( !shaderCodes )
{
shaderCodes = (DWORD*)(fOwner->GetDecl()->GetCodes());
}
if( !shaderCodes )
return IOnError(-1, "No file and no compiled codes");
hr = pipe->GetD3DDevice()->CreateVertexShader(shaderCodes, &fHandle);
if( FAILED(hr) )
return IOnError(hr, "Error on CreateVertexShader");
hsAssert(fHandle, "No error, but no vertex shader handle. Grrrr.");
fPipe = pipe;
return S_OK;
}
HRESULT plDXVertexShader::ISetConstants(plDXPipeline* pipe)
{
hsAssert(fHandle, "Vertex shader called to set constants without initialization");
if( fOwner->GetNumConsts() )
{
HRESULT hr = pipe->GetD3DDevice()->SetVertexShaderConstantF(0,
(float*)fOwner->GetConstBasePtr(),
fOwner->GetNumConsts());
if( FAILED(hr) )
return IOnError(hr, "Failure setting vertex shader constants");
}
return S_OK;
}