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:
Luke Usher 2018-02-02 21:45:51 +00:00
parent 4fb38b9636
commit 90ab16534e
2 changed files with 81 additions and 68 deletions

View File

@ -1689,54 +1689,6 @@ ULONG WINAPI XTL::EMUPATCH(D3DResource_AddRef)
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)

View File

@ -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;
return modified;
@ -3335,6 +3335,56 @@ XTL::X_D3DSurface * WINAPI XTL::EMUPATCH(D3DDevice_GetDepthStencilSurface2)()
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
// ******************************************************************
@ -7399,6 +7449,11 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_RunVertexStateShader)
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
// ******************************************************************
@ -7415,36 +7470,42 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_LoadVertexShaderProgram)
LOG_FUNC_ARG(Address)
LOG_FUNC_END;
// NOTE: Azurik needs this to work, but this implementation makes
// Sonic Heroes (E3 Demo) run slower and look a bit worse. An investigation
// may be necessary...
#if 1
DWORD Handle = g_CurrentVertexShader;
DWORD hCurrentShader = g_CurrentVertexShader;
// TODO: Cache vertex shaders? Azurik overwrites the same vertex shader
// slot over and over again with many different vertex shaders per frame...
if( VshHandleIsVertexShader(Handle) )
load_shader_program_key_t shaderCacheKey = (hCurrentShader << 32) | (DWORD)pFunction;
// 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;
// Save the contents of the existing vertex shader program
DWORD* pDeclaration = (DWORD*) malloc( pVertexShader->DeclarationSize );
memmove( pDeclaration, pVertexShader->pDeclaration, pVertexShader->DeclarationSize );
// Delete the vertex shader
EMUPATCH(D3DDevice_DeleteVertexShader)(Handle);
// Re-create the vertex shader with the new code
HRESULT hr = EMUPATCH(D3DDevice_CreateVertexShader)( pDeclaration, pFunction, &Handle, 0 );
// Create a new vertex shader with the new
HRESULT hr = EMUPATCH(D3DDevice_CreateVertexShader)( pDeclaration, pFunction, &hNewShader, 0 );
free(pDeclaration);
if( FAILED( hr ) )
CxbxKrnlCleanup( "Error re-creating vertex shader!" );
CxbxKrnlCleanup( "Error creating new vertex shader!" );
EMUPATCH(D3DDevice_LoadVertexShader)(Handle, Address);
EMUPATCH(D3DDevice_SelectVertexShader)(Handle, Address);
EMUPATCH(D3DDevice_LoadVertexShader)(hNewShader, Address);
EMUPATCH(D3DDevice_SelectVertexShader)(hNewShader, Address);
g_LoadVertexShaderProgramCache[shaderCacheKey] = hNewShader;
}
#endif
}
// ******************************************************************