uglyily hack in simple pixel/vtx shader capability

This commit is contained in:
cxgeorge 2002-05-04 01:41:40 +00:00
parent 1fb3d30012
commit d2a1f60a49
5 changed files with 294 additions and 6 deletions

View File

@ -107,6 +107,12 @@ const bool link_tristrips = config_dxgsg.GetBool("link-tristrips", false);
// note: offset currently disabled since it wasnt working properly
DXDecalType dx_decal_type = GDT_mask;
// Note: must be a ptr not a regular string because the init-string constructor for
// a global/static string variable will run AFTER the dll static init fn
// init_libdxgsg8(), which means the string will be reset to "" after we read it in
string *pdx_vertexshader_filename=NULL;
string *pdx_pixelshader_filename=NULL;
static DXDecalType
parse_decal_type(const string &type) {
if (type == "mask") {
@ -145,6 +151,19 @@ init_libdxgsg8() {
dx_decal_type = parse_decal_type(decal_type);
}
// dont try to take the & of a soon-to-be-gone stack var string, this must be on the heap!
pdx_vertexshader_filename = new string(config_dxgsg.GetString("dx-vertexshader-filename", ""));
if(pdx_vertexshader_filename->empty()) {
delete pdx_vertexshader_filename;
pdx_vertexshader_filename=NULL;
}
pdx_pixelshader_filename = new string(config_dxgsg.GetString("dx-pixelshader-filename", ""));
if(pdx_pixelshader_filename->empty()) {
delete pdx_pixelshader_filename;
pdx_pixelshader_filename=NULL;
}
DXGraphicsStateGuardian::init_type();
DXSavedFrameBuffer::init_type();
DXTextureContext::init_type();

View File

@ -40,7 +40,8 @@ extern DWORD dx_multisample_antialiasing_level;
extern bool dx_use_triangle_mipgen_filter;
extern const char *D3DFormatStr(D3DFORMAT fmt);
extern bool dx_use_dx_cursor;
extern string *pdx_vertexshader_filename;
extern string *pdx_pixelshader_filename;
// debug flags we might want to use in full optimized build
extern bool dx_ignore_mipmaps;
extern bool dx_mipmap_everything;

View File

@ -202,12 +202,28 @@ enable_fog(bool val) {
////////////////////////////////////////////////////////////////////
INLINE void DXGraphicsStateGuardian::
set_vertex_format(DWORD NewFvfType) {
#ifdef USE_VERTEX_SHADERS
if(_CurVertexShader!=NULL) {
// this needs optimization
HRESULT hr = scrn.pD3DDevice->SetVertexShader(_CurVertexShader);
#ifndef NDEBUG
if(FAILED(hr)) {
dxgsg_cat.error() << "SetVertexShader for custom vtx shader failed" << D3DERRORSTRING(hr);
exit(1);
}
#endif
_CurFVFType = NewFvfType;
return;
}
#endif
if (_CurFVFType != NewFvfType) {
_CurFVFType = NewFvfType;
HRESULT hr = scrn.pD3DDevice->SetVertexShader(NewFvfType);
#ifndef NDEBUG
if(FAILED(hr)) {
dxgsg_cat.error() << "SetVertexShader(0x" << (void*)NewFvfType<<") failed, hr = " << D3DERRORSTRING(hr);
dxgsg_cat.error() << "SetVertexShader(0x" << (void*)NewFvfType<<") failed" << D3DERRORSTRING(hr);
exit(1);
}
#endif

View File

@ -97,6 +97,9 @@ typedef enum { NothingSet=0,NormalOnly,ColorOnly,Normal_Color,TexCoordOnly,
// DX8's SW front-end has no limit on the number of lights, but HW is usually limited to 8
#define DXGSG_MAX_LIGHTS 8
// xform mat for vshader will usually be loaded at constant regs c4-c7
#define VSHADER_XFORMMATRIX_CONSTANTREGNUMSTART 4
static D3DMATRIX matIdentity;
#define __D3DLIGHT_RANGE_MAX ((float)sqrt(FLT_MAX)) //for some reason this is missing in dx8 hdrs
@ -236,6 +239,192 @@ set_color_clear_value(const Colorf& value) {
_d3dcolor_clear_value = Colorf_to_D3DCOLOR(value);
}
DXShaderHandle DXGraphicsStateGuardian::
read_pixel_shader(string &filename) {
HRESULT hr;
DXShaderHandle hShader=NULL;
HANDLE hFile=NULL;
BYTE *pShaderBytes=NULL;
LPD3DXBUFFER pD3DXBuf_Constants=NULL,pD3DXBuf_CompiledShader=NULL,pD3DXBuf_CompilationErrors=NULL;
assert(scrn.pD3DDevice!=NULL);
assert(scrn.bCanUsePixelShaders);
bool bIsCompiledShader=(filename.find(".pso")!=string::npos);
if(bIsCompiledShader) {
hFile = CreateFile(filename.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
if(hFile == INVALID_HANDLE_VALUE) {
dxgsg_cat.error() << "Could not find shader file '"<< filename << "'\n";
return NULL;
}
UINT BytesRead,FileSize = GetFileSize(hFile, NULL);
pShaderBytes = new BYTE[FileSize];
if (pShaderBytes==NULL) {
dxgsg_cat.error() << "MemAlloc failed for shader file '"<< filename << "'\n";
goto exit_create_pshader;
}
ReadFile(hFile, (void*)pShaderBytes, FileSize, (LPDWORD)&BytesRead, NULL);
assert(BytesRead==FileSize);
} else {
#if defined(NDEBUG) && !defined(COMPILE_TEXT_SHADERFILES)
// want to keep bulky d3dx shader assembler stuff out of publish build
dxgsg_cat.error() << "publish build only reads .vso compiled shaders!\n";
exit(1);
#else
// check for file existence
WIN32_FIND_DATA Junk;
HANDLE FindFileHandle = FindFirstFile(filename.c_str(),&Junk);
if ( FindFileHandle == INVALID_HANDLE_VALUE ) {
dxgsg_cat.error() << "Could not find shader file '"<< filename << "'\n";
return NULL;
}
FindClose(FindFileHandle);
hr = D3DXAssembleShaderFromFile(filename.c_str(),D3DXASM_DEBUG,NULL,&pD3DXBuf_CompiledShader,&pD3DXBuf_CompilationErrors);
if(FAILED(hr)) {
dxgsg_cat.error() << "D3DXAssembleShader failed for '"<< filename << "' " << D3DERRORSTRING(hr);
if(pD3DXBuf_CompilationErrors!=NULL) {
dxgsg_cat.error() << "Compilation Errors: " << (char*) pD3DXBuf_CompilationErrors->GetBufferPointer() << endl;
}
exit(1);
}
assert(pD3DXBuf_CompilationErrors==NULL);
#endif
}
hr = scrn.pD3DDevice->CreatePixelShader((DWORD*) ((pD3DXBuf_CompiledShader!=NULL) ? pD3DXBuf_CompiledShader->GetBufferPointer() : pShaderBytes),
&hShader);
if (FAILED(hr)) {
dxgsg_cat.error() << "CreatePixelShader failed for '"<< filename << "' " << D3DERRORSTRING(hr);
hShader=NULL;
}
assert(hShader!=NULL); // NULL is invalid I hope
#ifdef _DEBUG
dxgsg_cat.debug() << "CreatePixelShader succeeded for "<< filename << endl;
#endif
exit_create_pshader:
SAFE_RELEASE(pD3DXBuf_CompiledShader);
if(hFile!=NULL)
CloseHandle(hFile);
SAFE_DELETE(pShaderBytes);
return hShader;
}
DXShaderHandle DXGraphicsStateGuardian::
read_vertex_shader(string &filename) {
#ifndef USE_VERTEX_SHADERS
return NULL;
#else
HRESULT hr;
DXShaderHandle hShader=NULL;
HANDLE hFile=NULL;
BYTE *pShaderBytes=NULL;
LPD3DXBUFFER pD3DXBuf_Constants=NULL,pD3DXBuf_CompiledShader=NULL,pD3DXBuf_CompilationErrors=NULL;
#define VSDDECL_BUFSIZE 1024
UINT ShaderDeclHeader[VSDDECL_BUFSIZE];
// simple decl for posn + color
// need way to encode header decl with vsh files (stick in comment?) (use ID3DXEffect files?)
UINT Predefined_DeclArray[] = {
D3DVSD_STREAM(0),
D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3 ), // input register v0
D3DVSD_REG(D3DVSDE_DIFFUSE, D3DVSDT_D3DCOLOR ), // input Register v5
// D3DVSD_CONST(0,1),*(DWORD*)&c[0],*(DWORD*)&c[1],*(DWORD*)&c[2],*(DWORD*)&c[3],
};
memcpy(ShaderDeclHeader,Predefined_DeclArray,sizeof(Predefined_DeclArray));
// need to append any compiled constants to instr array
UINT ShaderDeclHeader_UINTSize=sizeof(Predefined_DeclArray)/sizeof(UINT);
assert(scrn.pD3DDevice!=NULL);
bool bIsCompiledShader=(filename.find(".vso")!=string::npos);
if(bIsCompiledShader) {
hFile = CreateFile(filename.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
if(hFile == INVALID_HANDLE_VALUE) {
dxgsg_cat.error() << "Could not find shader file '"<< filename << "'\n";
return NULL;
}
UINT BytesRead,FileSize = GetFileSize(hFile, NULL);
pShaderBytes = new BYTE[FileSize];
if (pShaderBytes==NULL) {
dxgsg_cat.error() << "MemAlloc failed for shader file '"<< filename << "'\n";
goto exit_create_vshader;
}
ReadFile(hFile, (void*)pShaderBytes, FileSize, (LPDWORD)&BytesRead, NULL);
assert(BytesRead==FileSize);
} else {
#if defined(NDEBUG) && !defined(COMPILE_TEXT_SHADERFILES)
// want to keep bulky d3dx shader assembler stuff out of publish build
dxgsg_cat.error() << "publish build only reads .vso compiled shaders!\n";
exit(1);
#else
// check for file existence
WIN32_FIND_DATA Junk;
HANDLE FindFileHandle = FindFirstFile(filename.c_str(),&Junk);
if ( FindFileHandle == INVALID_HANDLE_VALUE ) {
dxgsg_cat.error() << "Could not find shader file '"<< filename << "'\n";
return NULL;
}
FindClose(FindFileHandle);
hr = D3DXAssembleShaderFromFile(filename.c_str(),D3DXASM_DEBUG,&pD3DXBuf_Constants,&pD3DXBuf_CompiledShader,&pD3DXBuf_CompilationErrors);
if(FAILED(hr)) {
dxgsg_cat.error() << "D3DXAssembleShader failed for '"<< filename << "' " << D3DERRORSTRING(hr);
if(pD3DXBuf_CompilationErrors!=NULL) {
dxgsg_cat.error() << "Compilation Errors: " << (char*) pD3DXBuf_CompilationErrors->GetBufferPointer() << endl;
}
exit(1);
}
assert(pD3DXBuf_CompilationErrors==NULL);
if(pD3DXBuf_Constants!=NULL) {
// need to insert defined constants after shader decl
memcpy(&ShaderDeclHeader[ShaderDeclHeader_UINTSize],pD3DXBuf_Constants->GetBufferPointer(),pD3DXBuf_Constants->GetBufferSize());
ShaderDeclHeader_UINTSize+=pD3DXBuf_Constants->GetBufferSize()/sizeof(UINT);
pD3DXBuf_Constants->Release();
}
#endif
}
assert(VSDDECL_BUFSIZE >= (ShaderDeclHeader_UINTSize+1));
ShaderDeclHeader[ShaderDeclHeader_UINTSize]=D3DVSD_END();
UINT UsageFlags = (scrn.bCanUseHWVertexShaders ? 0x0 : D3DUSAGE_SOFTWAREPROCESSING);
hr = scrn.pD3DDevice->CreateVertexShader((DWORD*)ShaderDeclHeader,
(DWORD*) ((pD3DXBuf_CompiledShader!=NULL) ? pD3DXBuf_CompiledShader->GetBufferPointer() : pShaderBytes),
&hShader, UsageFlags);
if (FAILED(hr)) {
dxgsg_cat.error() << "CreateVertexShader failed for '"<< filename << "' " << D3DERRORSTRING(hr);
hShader=NULL;
}
assert(hShader!=NULL); // NULL is invalid I hope
#ifdef _DEBUG
dxgsg_cat.debug() << "CreateVertexShader succeeded for "<< filename << endl;
#endif
exit_create_vshader:
SAFE_RELEASE(pD3DXBuf_CompiledShader);
if(hFile!=NULL)
CloseHandle(hFile);
SAFE_DELETE(pShaderBytes);
return hShader;
#endif
}
void DXGraphicsStateGuardian::
reset_panda_gsg(void) {
GraphicsStateGuardian::reset();
@ -276,6 +465,9 @@ DXGraphicsStateGuardian(GraphicsWindow *win) : GraphicsStateGuardian(win) {
_pStatMeterFont=NULL;
_bShowFPSMeter = false;
_CurVertexShader = NULL; // may persist across dx_init's?
_CurPixelShader = NULL; // may persist across dx_init's? (for dx8.1 but not dx8.0?)
// _max_light_range = __D3DLIGHT_RANGE_MAX;
// non-dx obj values inited here should not change if resize is
@ -712,6 +904,46 @@ dx_init(HCURSOR hMouseCursor) {
dwa->issue(this);
cfa->issue(this);
// initial test just allows 1 shader at a time, specified at init time
if((pdx_vertexshader_filename!=NULL) && (!pdx_vertexshader_filename->empty())) {
if((_CurVertexShader!=NULL)&&(!scrn.bIsDX81)) {
// for dx8.0, need to release and recreate shaders after Reset() has been called
hr = scrn.pD3DDevice->DeleteVertexShader(_CurVertexShader);
if(FAILED(hr))
dxgsg_cat.error() << "DeleteVertexShader failed!" << D3DERRORSTRING(hr);
_CurVertexShader=NULL;
}
// gets set in set_vertex_format()
if(_CurVertexShader==NULL)
_CurVertexShader=read_vertex_shader(*pdx_vertexshader_filename);
}
// initial test just allows 1 shader at a time, specified at init time
if((pdx_pixelshader_filename!=NULL) && (!pdx_pixelshader_filename->empty())) {
if(!scrn.bCanUsePixelShaders) {
dxgsg_cat.error() << "HW doesnt support pixel shaders!\n";
exit(1);
}
if((_CurPixelShader!=NULL)&&(!scrn.bIsDX81)) {
// for dx8.0, need to release and recreate shaders after Reset() has been called
hr = scrn.pD3DDevice->DeletePixelShader(_CurPixelShader);
if(FAILED(hr))
dxgsg_cat.error() << "DeletePixelShader failed!" << D3DERRORSTRING(hr);
_CurPixelShader=NULL;
}
if(_CurPixelShader==NULL)
_CurPixelShader=read_pixel_shader(*pdx_pixelshader_filename);
// just set it globally for testing. this really should be an object attribute
// like current-texture is so it gets set and unset during traversal
hr = scrn.pD3DDevice->SetPixelShader(_CurPixelShader);
if(FAILED(hr))
dxgsg_cat.error() << "SetPixelShader failed!" << D3DERRORSTRING(hr);
}
PRINT_REFCNT(dxgsg,scrn.pD3DDevice);
}
@ -3382,8 +3614,23 @@ enable_texturing(bool val) {
////////////////////////////////////////////////////////////////////
void DXGraphicsStateGuardian::
issue_transform(const TransformState *transform) {
scrn.pD3DDevice->SetTransform(D3DTS_WORLD,
(D3DMATRIX*)transform->get_mat().get_data());
// if we're using ONLY vertex shaders, could get avoid calling SetTrans
D3DMATRIX *pMat = (D3DMATRIX*)transform->get_mat().get_data();
scrn.pD3DDevice->SetTransform(D3DTS_WORLD,pMat);
#ifdef USE_VERTEX_SHADERS
if(_CurVertexShader!=NULL) {
// vertex shaders need access to the current xform matrix,
// so need to reset this vshader 'constant' every time view matrix changes
HRESULT hr = scrn.pD3DDevice->SetVertexShaderConstant(VSHADER_XFORMMATRIX_CONSTANTREGNUMSTART, pMat, 4);
#ifdef _DEBUG
if(FAILED(hr)) {
dxgsg_cat.error() << "SetVertexShader failed" << D3DERRORSTRING(hr);
exit(1);
}
#endif
}
#endif
}
////////////////////////////////////////////////////////////////////
@ -3393,7 +3640,7 @@ issue_transform(const TransformState *transform) {
////////////////////////////////////////////////////////////////////
void DXGraphicsStateGuardian::
issue_tex_matrix(const TexMatrixAttrib *attrib) {
// Not implemented.
// Not implemented yet.
}
////////////////////////////////////////////////////////////////////
@ -3698,7 +3945,7 @@ begin_frame() {
dxgsg_cat.debug() << "BeginScene returns DeviceLost\n";
CheckCooperativeLevel();
} else {
dxgsg_cat.error() << "BeginScene failed, unhandled error hr == " << D3DERRORSTRING(hr);
dxgsg_cat.error() << "BeginScene failed, unhandled error" << D3DERRORSTRING(hr);
exit(1);
}
return;

View File

@ -38,6 +38,8 @@
#include "fog.h"
#include "pointerToArray.h"
//#define USE_VERTEX_SHADERS
class Light;
//#if defined(NOTIFY_DEBUG) || defined(DO_PSTATS)
@ -304,6 +306,7 @@ protected:
Texture::FilterType _CurTexMagFilter,_CurTexMinFilter;
DWORD _CurTexAnisoDegree;
Texture::WrapMode _CurTexWrapModeU,_CurTexWrapModeV;
DXShaderHandle _CurVertexShader,_CurPixelShader;
LMatrix4f _current_projection_mat;
int _projection_mat_stack_count;
@ -333,6 +336,8 @@ public:
INLINE void SetDXReady(bool status) { _bDXisReady = status; }
INLINE bool GetDXReady(void) { return _bDXisReady;}
void DXGraphicsStateGuardian::SetTextureBlendMode(TextureApplyAttrib::Mode TexBlendMode,bool bJustEnable);
DXShaderHandle read_vertex_shader(string &filename);
DXShaderHandle read_pixel_shader(string &filename);
void dx_cleanup(bool bRestoreDisplayMode,bool bAtExitFnCalled);
void reset_panda_gsg(void);