Introduce LoadVertexShaderCache
- (Sonic Heroes E3 Demo goes from ~5fps to 60fps) Restore patching of CreatePalette - Egg Mania renders better - Fonts in Burnout render better
This commit is contained in:
parent
4fb38b9636
commit
90ab16534e
|
@ -1689,54 +1689,6 @@ ULONG WINAPI XTL::EMUPATCH(D3DResource_AddRef)
|
||||||
return uRet;
|
return uRet;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ******************************************************************
|
|
||||||
// * patch: D3DDevice_CreatePalette
|
|
||||||
// ******************************************************************
|
|
||||||
HRESULT WINAPI XTL::EMUPATCH(D3DDevice_CreatePalette)
|
|
||||||
(
|
|
||||||
X_D3DPALETTESIZE Size,
|
|
||||||
X_D3DPalette **ppPalette
|
|
||||||
)
|
|
||||||
{
|
|
||||||
// FUNC_EXPORTS
|
|
||||||
|
|
||||||
LOG_FORWARD("D3DDevice_CreatePalette2");
|
|
||||||
|
|
||||||
*ppPalette = EMUPATCH(D3DDevice_CreatePalette2)(Size);
|
|
||||||
|
|
||||||
return D3D_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ******************************************************************
|
|
||||||
// * patch: D3DDevice_CreatePalette2
|
|
||||||
// ******************************************************************
|
|
||||||
XTL::X_D3DPalette * WINAPI XTL::EMUPATCH(D3DDevice_CreatePalette2)
|
|
||||||
(
|
|
||||||
X_D3DPALETTESIZE Size
|
|
||||||
)
|
|
||||||
{
|
|
||||||
// FUNC_EXPORTS
|
|
||||||
|
|
||||||
LOG_FUNC_ONE_ARG(Size);
|
|
||||||
|
|
||||||
X_D3DPalette *pPalette = EmuNewD3DPalette();
|
|
||||||
|
|
||||||
pPalette->Common |= (Size << X_D3DPALETTE_COMMON_PALETTESIZE_SHIFT);
|
|
||||||
pPalette->Data = (DWORD)g_VMManager.Allocate(XboxD3DPaletteSizeToBytes(Size), 0, (~((::ULONG_PTR)0)), PAGE_SIZE, PAGE_EXECUTE_READWRITE, false);
|
|
||||||
pPalette->Lock = X_D3DRESOURCE_LOCK_PALETTE; // emulated reference count for palettes
|
|
||||||
|
|
||||||
// TODO: Should't we register the palette with a call to
|
|
||||||
// EmuIDirect3DResource8_Register? So far, it doesn't look
|
|
||||||
// like the palette registration code gets used. If not, then we
|
|
||||||
// need to cache the palette manually during any calls to
|
|
||||||
// EmuD3DDevice_SetPalette for 8-bit textures to work properly.
|
|
||||||
|
|
||||||
DbgPrintf("pPalette: = 0x%.08X\n", pPalette);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return pPalette;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#if 0 // DISABLED (Just calls MmAllocateContiguousMemory)
|
#if 0 // DISABLED (Just calls MmAllocateContiguousMemory)
|
||||||
|
|
|
@ -843,7 +843,7 @@ bool HostResourceRequiresUpdate(resource_key_t key)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the next hash lifetime based on the hash lifetime
|
// Update the next hash time based on the hash lifetime
|
||||||
it->second.nextHashTime = now + it->second.hashLifeTime;
|
it->second.nextHashTime = now + it->second.hashLifeTime;
|
||||||
|
|
||||||
return modified;
|
return modified;
|
||||||
|
@ -3335,6 +3335,56 @@ XTL::X_D3DSurface * WINAPI XTL::EMUPATCH(D3DDevice_GetDepthStencilSurface2)()
|
||||||
RETURN(result);
|
RETURN(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ******************************************************************
|
||||||
|
// * patch: D3DDevice_CreatePalette
|
||||||
|
// ******************************************************************
|
||||||
|
HRESULT WINAPI XTL::EMUPATCH(D3DDevice_CreatePalette)
|
||||||
|
(
|
||||||
|
X_D3DPALETTESIZE Size,
|
||||||
|
X_D3DPalette **ppPalette
|
||||||
|
)
|
||||||
|
{
|
||||||
|
FUNC_EXPORTS
|
||||||
|
|
||||||
|
LOG_FORWARD("D3DDevice_CreatePalette2");
|
||||||
|
|
||||||
|
*ppPalette = EMUPATCH(D3DDevice_CreatePalette2)(Size);
|
||||||
|
|
||||||
|
return D3D_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ******************************************************************
|
||||||
|
// * patch: D3DDevice_CreatePalette2
|
||||||
|
// ******************************************************************
|
||||||
|
XTL::X_D3DPalette * WINAPI XTL::EMUPATCH(D3DDevice_CreatePalette2)
|
||||||
|
(
|
||||||
|
X_D3DPALETTESIZE Size
|
||||||
|
)
|
||||||
|
{
|
||||||
|
FUNC_EXPORTS
|
||||||
|
|
||||||
|
LOG_FUNC_ONE_ARG(Size);
|
||||||
|
|
||||||
|
X_D3DPalette *pPalette = EmuNewD3DPalette();
|
||||||
|
|
||||||
|
pPalette->Common |= (Size << X_D3DPALETTE_COMMON_PALETTESIZE_SHIFT);
|
||||||
|
pPalette->Data = (DWORD)g_VMManager.Allocate(XboxD3DPaletteSizeToBytes(Size), 0, (~((::ULONG_PTR)0)), PAGE_SIZE, PAGE_EXECUTE_READWRITE, false);
|
||||||
|
pPalette->Lock = X_D3DRESOURCE_LOCK_PALETTE; // emulated reference count for palettes
|
||||||
|
|
||||||
|
// TODO: Should't we register the palette with a call to
|
||||||
|
// EmuIDirect3DResource8_Register? So far, it doesn't look
|
||||||
|
// like the palette registration code gets used. If not, then we
|
||||||
|
// need to cache the palette manually during any calls to
|
||||||
|
// EmuD3DDevice_SetPalette for 8-bit textures to work properly.
|
||||||
|
|
||||||
|
DbgPrintf("pPalette: = 0x%.08X\n", pPalette);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return pPalette;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// ******************************************************************
|
// ******************************************************************
|
||||||
// * patch: D3DDevice_CreateVertexShader
|
// * patch: D3DDevice_CreateVertexShader
|
||||||
// ******************************************************************
|
// ******************************************************************
|
||||||
|
@ -7399,6 +7449,11 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_RunVertexStateShader)
|
||||||
LOG_UNIMPLEMENTED();
|
LOG_UNIMPLEMENTED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Maps pFunction defintions to pre-compiled shaders
|
||||||
|
// to reduce the speed impact of LoadVertexShaderProgram
|
||||||
|
typedef uint64_t load_shader_program_key_t;
|
||||||
|
std::map<load_shader_program_key_t, DWORD> g_LoadVertexShaderProgramCache;
|
||||||
|
|
||||||
// ******************************************************************
|
// ******************************************************************
|
||||||
// * patch: D3DDevice_LoadVertexShaderProgram
|
// * patch: D3DDevice_LoadVertexShaderProgram
|
||||||
// ******************************************************************
|
// ******************************************************************
|
||||||
|
@ -7415,36 +7470,42 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_LoadVertexShaderProgram)
|
||||||
LOG_FUNC_ARG(Address)
|
LOG_FUNC_ARG(Address)
|
||||||
LOG_FUNC_END;
|
LOG_FUNC_END;
|
||||||
|
|
||||||
// NOTE: Azurik needs this to work, but this implementation makes
|
DWORD hCurrentShader = g_CurrentVertexShader;
|
||||||
// Sonic Heroes (E3 Demo) run slower and look a bit worse. An investigation
|
|
||||||
// may be necessary...
|
|
||||||
#if 1
|
|
||||||
DWORD Handle = g_CurrentVertexShader;
|
|
||||||
|
|
||||||
// TODO: Cache vertex shaders? Azurik overwrites the same vertex shader
|
|
||||||
// slot over and over again with many different vertex shaders per frame...
|
load_shader_program_key_t shaderCacheKey = (hCurrentShader << 32) | (DWORD)pFunction;
|
||||||
if( VshHandleIsVertexShader(Handle) )
|
|
||||||
|
// If the shader key was located in the cache, use the cached shader
|
||||||
|
// TODO: When do we clear the cache? In this approach, shaders are
|
||||||
|
// never freed...
|
||||||
|
auto it = g_LoadVertexShaderProgramCache.find(shaderCacheKey);
|
||||||
|
if (it != g_LoadVertexShaderProgramCache.end()) {
|
||||||
|
EMUPATCH(D3DDevice_LoadVertexShader)(it->second, Address);
|
||||||
|
EMUPATCH(D3DDevice_SelectVertexShader)(it->second, Address);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( VshHandleIsVertexShader(hCurrentShader) )
|
||||||
{
|
{
|
||||||
X_D3DVertexShader *pD3DVertexShader = (X_D3DVertexShader *)(Handle & 0x7FFFFFFF);
|
DWORD hNewShader = 0;
|
||||||
|
X_D3DVertexShader *pD3DVertexShader = (X_D3DVertexShader *)(hCurrentShader & 0x7FFFFFFF);
|
||||||
VERTEX_SHADER *pVertexShader = (VERTEX_SHADER *)pD3DVertexShader->Handle;
|
VERTEX_SHADER *pVertexShader = (VERTEX_SHADER *)pD3DVertexShader->Handle;
|
||||||
|
|
||||||
// Save the contents of the existing vertex shader program
|
// Save the contents of the existing vertex shader program
|
||||||
DWORD* pDeclaration = (DWORD*) malloc( pVertexShader->DeclarationSize );
|
DWORD* pDeclaration = (DWORD*) malloc( pVertexShader->DeclarationSize );
|
||||||
memmove( pDeclaration, pVertexShader->pDeclaration, pVertexShader->DeclarationSize );
|
memmove( pDeclaration, pVertexShader->pDeclaration, pVertexShader->DeclarationSize );
|
||||||
|
|
||||||
// Delete the vertex shader
|
// Create a new vertex shader with the new
|
||||||
EMUPATCH(D3DDevice_DeleteVertexShader)(Handle);
|
HRESULT hr = EMUPATCH(D3DDevice_CreateVertexShader)( pDeclaration, pFunction, &hNewShader, 0 );
|
||||||
|
|
||||||
// Re-create the vertex shader with the new code
|
|
||||||
HRESULT hr = EMUPATCH(D3DDevice_CreateVertexShader)( pDeclaration, pFunction, &Handle, 0 );
|
|
||||||
free(pDeclaration);
|
free(pDeclaration);
|
||||||
if( FAILED( hr ) )
|
if( FAILED( hr ) )
|
||||||
CxbxKrnlCleanup( "Error re-creating vertex shader!" );
|
CxbxKrnlCleanup( "Error creating new vertex shader!" );
|
||||||
|
|
||||||
EMUPATCH(D3DDevice_LoadVertexShader)(Handle, Address);
|
EMUPATCH(D3DDevice_LoadVertexShader)(hNewShader, Address);
|
||||||
EMUPATCH(D3DDevice_SelectVertexShader)(Handle, Address);
|
EMUPATCH(D3DDevice_SelectVertexShader)(hNewShader, Address);
|
||||||
|
|
||||||
|
g_LoadVertexShaderProgramCache[shaderCacheKey] = hNewShader;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ******************************************************************
|
// ******************************************************************
|
||||||
|
|
Loading…
Reference in New Issue