Advertisement

DX8 to DX9 issues

Started by March 10, 2019 05:58 PM
3 comments, last by Pelicjan 5 years, 10 months ago

Hi, I want to change directx version that the game uses from 8 to 9 (if I succeed, maybe I will try to change to 11 in the future). I have a few problems that I can not deal with.

Firstly, I don't know how to change vertex shader declaration.

Spoiler


// template shader for fixed function vertex shader
DWORD _adwDeclTemplateFF[] = {
	D3DVSD_STREAM(0),
	D3DVSD_REG( D3DVSDE_POSITION,  D3DVSDT_FLOAT3),
	D3DVSD_STREAM(1),
	D3DVSD_REG( D3DVSDE_DIFFUSE,   D3DVSDT_D3DCOLOR),
	D3DVSD_STREAM(2),
	D3DVSD_REG( D3DVSDE_TEXCOORD0, D3DVSDT_FLOAT2),
	D3DVSD_STREAM(3),
	D3DVSD_REG( D3DVSDE_TEXCOORD1, D3DVSDT_FLOAT2),
	D3DVSD_STREAM(4),
	D3DVSD_REG( D3DVSDE_TEXCOORD2, D3DVSDT_FLOAT2),
	D3DVSD_STREAM(5),
	D3DVSD_REG( D3DVSDE_TEXCOORD3, D3DVSDT_FLOAT2),
	D3DVSD_STREAM(6),
	D3DVSD_REG( D3DVSDE_NORMAL,    D3DVSDT_FLOAT3),
	D3DVSD_STREAM(7), // not used in fixed-function vs but must be declared for stream reset
	D3DVSD_REG( NONE, NONE),
	D3DVSD_REG( NONE, NONE),
	D3DVSD_END()
};
// template shader for programmable vertex shader
DWORD _adwDeclTemplateVP[] = {
	D3DVSD_STREAM(0),
	D3DVSD_REG( 0,  D3DVSDT_FLOAT3),    // position
	D3DVSD_STREAM(1),
	D3DVSD_REG( 4,  D3DVSDT_D3DCOLOR),  // diffuse
	D3DVSD_STREAM(2),
	D3DVSD_REG( 5,  D3DVSDT_FLOAT2),    // texcoord0
	D3DVSD_STREAM(3),
	D3DVSD_REG( 6,  D3DVSDT_FLOAT2),    // texcoord1
	D3DVSD_STREAM(4),
	D3DVSD_REG( 7,  D3DVSDT_FLOAT2),    // texcoord2
	D3DVSD_STREAM(5),
	D3DVSD_REG( 8, D3DVSDT_FLOAT2),     // texcoord3
	D3DVSD_STREAM(6),
	D3DVSD_REG( 1,  D3DVSDT_FLOAT3),    // normal
	D3DVSD_STREAM(7),
	D3DVSD_REG( 3,  D3DVSDT_D3DCOLOR),  // blend indices
	D3DVSD_REG( 2,  D3DVSDT_D3DCOLOR),  // blend weights
	D3DVSD_END()
};

 

Secondly, I have a function that returns shader declaration from given flags. How to change it?

Spoiler


// Get shader stream declaration from stream flags
extern void GetShaderDeclaration_D3D(ULONG *ulRetDecl, ULONG ulStreamFlags)
{
	// if using position stream
	if(ulStreamFlags&GFX_POSITION_STREAM) {
		*(  ulRetDecl) = D3DVSD_STREAM(0);
		*(++ulRetDecl) = D3DVSD_REG( 0,  D3DVSDT_FLOAT3);
		ulStreamFlags&=~GFX_POSITION_STREAM;
	}
	// if using color stream
	if(ulStreamFlags&GFX_COLOR_STREAM) {
		*(++ulRetDecl) = D3DVSD_STREAM(1);
		*(++ulRetDecl) = D3DVSD_REG( 4,  D3DVSDT_D3DCOLOR);
		ulStreamFlags&=~GFX_COLOR_STREAM;
	}
	// if using texture unit 1
	if(ulStreamFlags&GFX_TEXCOORD0) {
		*(++ulRetDecl) = D3DVSD_STREAM(2);
		*(++ulRetDecl) = D3DVSD_REG( 5,  D3DVSDT_FLOAT2);
		ulStreamFlags&=~GFX_TEXCOORD0;
	}
	// if using texture unit 2
	if(ulStreamFlags&GFX_TEXCOORD1) {
		*(++ulRetDecl) = D3DVSD_STREAM(3);
		*(++ulRetDecl) = D3DVSD_REG( 6,  D3DVSDT_FLOAT2);
		ulStreamFlags&=~GFX_TEXCOORD1;
	}
	// if using texture unit 3
	if(ulStreamFlags&GFX_TEXCOORD2) {
		*(++ulRetDecl) = D3DVSD_STREAM(4);
		*(++ulRetDecl) = D3DVSD_REG( 7,  D3DVSDT_FLOAT2);
		ulStreamFlags&=~GFX_TEXCOORD2;
	}
	// if using texture unit 4
	if(ulStreamFlags&GFX_TEXCOORD3) {
		*(++ulRetDecl) = D3DVSD_STREAM(5);
		*(++ulRetDecl) = D3DVSD_REG( 8,  D3DVSDT_FLOAT2);
		ulStreamFlags&=~GFX_TEXCOORD3;
	}
	if(ulStreamFlags&GFX_NORMAL_STREAM) {
		*(++ulRetDecl) = D3DVSD_STREAM(6);
		*(++ulRetDecl) = D3DVSD_REG( 1,  D3DVSDT_FLOAT3);
		ulStreamFlags&=~GFX_NORMAL_STREAM;
	}
	if(ulStreamFlags&GFX_WEIGHT_STREAM) {
		*(++ulRetDecl) = D3DVSD_STREAM(7);
		*(++ulRetDecl) = D3DVSD_REG( 3,  D3DVSDT_D3DCOLOR);
		*(++ulRetDecl) = D3DVSD_REG( 2,  D3DVSDT_D3DCOLOR);
		ulStreamFlags&=~GFX_WEIGHT_STREAM;
	}
	// if using tangent
	if(ulStreamFlags&GFX_TANGENT_STREAM) {
		*(++ulRetDecl) = D3DVSD_STREAM(3);
		*(++ulRetDecl) = D3DVSD_REG( 9,  D3DVSDT_FLOAT4);
		ulStreamFlags&=~GFX_TANGENT_STREAM;
	}
	ASSERT(ulStreamFlags==0); // make sure stream flags were valid
	*(++ulRetDecl) = D3DVSD_END();
}

 

And I have one question. Is it possible to combine dx8 shaders with dx9?

Thanks for any help.

Refresh

Please help :/

Advertisement

If you have the time, give DX12 or Vulkan a chance? DX8 and DX9 are very similar and very old technology (over a decade old now). If you restrict yourself to around shader model 2 you should be able to interchange your shaders between DX8 and DX9 IIRC.

For the code conversion, I recommend using DX9 with vertex declarations instead of FVF.

Thus the first code block becomes this in DX9:


// template shader for fixed function vertex shader
D3DVERTEXELEMENT9 _awDeclTemplateFF[] = {
       {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
       {1, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
       {2, 16, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
       {3, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
       {4, 32, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 2},
       {5, 40, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 3},
       {6, 48, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
       D3DDECL_END()
};
// template shader for programmable vertex shader
D3DVERTEXELEMENT9 _awDeclTemplateVP[] = {
       {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
       {1, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
       {2, 16, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
       {3, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
       {4, 32, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 2},
       {5, 40, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 3},
       {6, 48, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
       {7, 60, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BLENDINDICES, 0},
       {7, 64, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BLENDWEIGHT, 0},
       D3DDECL_END()
};

You'll have to extrapolate the above to figure out how you want to handle your second code fragment. I recommend either thunking the DX9 vertex declaration above down to DX8 or create some abstract intermediate representation of a vertex description and return that instead.

Thank you so much. I feel that I am one step closer to the goal :D

However, I have another problem.

I have this function:

Spoiler


// construct vertex shader out of streams' bit-mask
extern DWORD SetupShader_D3D( ULONG ulStreamsMask)
{
	HRESULT hr;
	const LPDIRECT3DDEVICE8 pd3dDev = _pGfx->gl_pd3dDevice;
	const INDEX ctFixedShaders = _avsFixedShaders.Count();

	INDEX iVS;

	// delete all shaders?
	if( ulStreamsMask==NONE) {
		// first set default vertex shader
		hr = pd3dDev->SetVertexShader(D3DFVF_CTVERTEX);
		D3D_CHECKERROR(hr);
		gfxSetPixelProgram(NONE);

		for( iVS=0; iVS<ctFixedShaders; iVS++) {
			hr = pd3dDev->DeleteVertexShader(_avsFixedShaders[iVS].vs_dwHandle);
			D3D_CHECKERROR(hr);
		}

		// Delete all programable vertex and pixel programs
		extern void ClearVertexAndPixelPrograms(void);
		ClearVertexAndPixelPrograms();

		// free array
		_avsFixedShaders.PopAll();
		_dwCurrentVS = NONE;
		_dwCurrentPS = NONE;
		_dwLastVertexProgram = NONE;
		return NONE;
	}

	// see if required fixed function shader has already been created
	for( iVS=0; iVS<ctFixedShaders; iVS++) {
		if( _avsFixedShaders[iVS].vs_ulStreamMask==ulStreamsMask) return _avsFixedShaders[iVS].vs_dwHandle;
	}

	// darn, need to create shader :(

	// pre-adjustment for eventual projective mapping
	_adwDeclTemplateFF[DECLTEXOFS+1] = D3DVSD_REG( D3DVSDE_TEXCOORD0, (ulStreamsMask&0x1000) ? D3DVSDT_FLOAT4 : D3DVSDT_FLOAT2);

	ulStreamsMask &= ~0x1000;

	ULONG ulMask = ulStreamsMask;

	// process mask, bit by bit
	INDEX iSrcDecl=0, iDstDecl=0;
	INDEX iStream=0;
	while(_adwDeclTemplateFF[iSrcDecl]!=D3DVSD_END())
	{ // add declarator if used
		INDEX ctRegs = _aiStreamRegs[iStream] + 1; // n*D3DVSD_REG() + D3DVSD_STREAM()
		if( ulMask&1) {
			for(INDEX ireg=0;ireg<ctRegs;ireg++) {
				_adwCurrentDecl[iDstDecl+ireg] = _adwDeclTemplateFF[iSrcDecl+ireg];
			}
			iDstDecl+=ctRegs;
		}
		iSrcDecl+=ctRegs;
		ulMask >>= 1;
		iStream++;
	}
	// mark end
	_adwCurrentDecl[iDstDecl] = D3DVSD_END();
	ASSERT( _iTexPass>=0 && _iColPass>=0);
	ASSERT( _iVtxPos >=0 && _iVtxPos<65536);

	// create new vertex shader
	const DWORD dwFlags = (_pGfx->gl_ulFlags&GLF_D3D_USINGHWTNL) ? NONE : D3DUSAGE_SOFTWAREPROCESSING;

	VertexShader &vs = _avsFixedShaders.Push();
	vs.vs_ulStreamMask = ulStreamsMask;
	
	// create fixed shader
	hr = pd3dDev->CreateVertexShader( &_adwCurrentDecl[0], NULL, &vs.vs_dwHandle, dwFlags);
	D3D_CHECKERROR(hr);
	// reset current shader
	_pGfx->gl_dwVertexShader = NONE;
	return vs.vs_dwHandle;
}

 

Can I change


hr = pd3dDev->SetVertexShader(D3DFVF_CTVERTEX);

to


hr = _pGfx->gl_pd3dDevice->CreateVertexDeclaration(_adwDeclTemplateFF, &(_pGfx->gl_pVertexDeclaration));
hr = _pGfx->gl_pd3dDevice->SetVertexDeclaration(_pGfx->gl_pVertexDeclaration);

?

And what should I do with


hr = pd3dDev->CreateVertexShader( &_adwCurrentDecl[0], NULL, &vs.vs_dwHandle, dwFlags);

?

In DX9, CreateVertexShader accepts completely different arguments.

I don't quite understand what this function does.

I will be grateful for any help.

This topic is closed to new replies.

Advertisement