FRAGMENTSHADER* PixelShaderCache::SetShader(DSTALPHA_MODE dstAlphaMode, u32 components)
{
	PIXELSHADERUID uid;
	GetPixelShaderId(&uid, dstAlphaMode, components);
	
	// Check if the shader is already set
	if (last_entry)
	{
		if (uid == last_uid)
		{
			GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true);
			ValidatePixelShaderIDs(API_OPENGL, last_entry->safe_uid, last_entry->shader.strprog, dstAlphaMode, components);
			return &last_entry->shader;
		}
	}

	last_uid = uid;

	PSCache::iterator iter = PixelShaders.find(uid);
	if (iter != PixelShaders.end())
	{
		PSCacheEntry &entry = iter->second;
		last_entry = &entry;

		GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true);
		ValidatePixelShaderIDs(API_OPENGL, entry.safe_uid, entry.shader.strprog, dstAlphaMode, components);
		return &last_entry->shader;
	}

	// Make an entry in the table
	PSCacheEntry& newentry = PixelShaders[uid];
	last_entry = &newentry;
	const char *code = GeneratePixelShaderCode(dstAlphaMode, API_OPENGL, components);

	if (g_ActiveConfig.bEnableShaderDebugging && code)
	{
		GetSafePixelShaderId(&newentry.safe_uid, dstAlphaMode, components);
		newentry.shader.strprog = code;
	}

#if defined(_DEBUG) || defined(DEBUGFAST)
	if (g_ActiveConfig.iLog & CONF_SAVESHADERS && code) {	
		static int counter = 0;
		char szTemp[MAX_PATH];
		sprintf(szTemp, "%sps_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), counter++);
		
		SaveData(szTemp, code);
	}
#endif

	if (!code || !CompilePixelShader(newentry.shader, code)) {
		GFX_DEBUGGER_PAUSE_AT(NEXT_ERROR, true);
		return NULL;
	}
	
	INCSTAT(stats.numPixelShadersCreated);
	SETSTAT(stats.numPixelShadersAlive, PixelShaders.size());
	GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true);
	return &last_entry->shader;
}
示例#2
0
bool PixelShaderCache::SetShader(PSGRENDER_MODE PSGRenderMode, u32 components)
{
	const API_TYPE api = ((D3D::GetCaps().PixelShaderVersion >> 8) & 0xFF) < 3 ? API_D3D9_SM20 : API_D3D9_SM30;
	PIXELSHADERUID uid;
	GetPixelShaderId(&uid, PSGRenderMode, components);

	// Check if the shader is already set
	if (last_entry)
	{
		if (uid == last_uid)
		{
			GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true);
			ValidatePixelShaderIDs(api, last_entry->safe_uid, last_entry->code, PSGRenderMode, components);
			return last_entry->shader != NULL;
		}
	}

	last_uid = uid;

	// Check if the shader is already in the cache
	PSCache::iterator iter;
	iter = PixelShaders.find(uid);
	if (iter != PixelShaders.end())
	{
		const PSCacheEntry &entry = iter->second;
		last_entry = &entry;

		if (entry.shader) D3D::SetPixelShader(entry.shader);
		GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true);
		ValidatePixelShaderIDs(api, entry.safe_uid, entry.code, PSGRenderMode, components);
		return (entry.shader != NULL);
	}


	// Need to compile a new shader
	const char *code = GeneratePixelShaderCode(PSGRenderMode, api, components);

	if (g_ActiveConfig.bEnableShaderDebugging)
	{
		u32 code_hash = HashAdler32((const u8 *)code, strlen(code));
		unique_shaders.insert(code_hash);
		SETSTAT(stats.numUniquePixelShaders, unique_shaders.size());
	}

#if defined(_DEBUG) || defined(DEBUGFAST)
	if (g_ActiveConfig.iLog & CONF_SAVESHADERS && code) {
		static int counter = 0;
		char szTemp[MAX_PATH];
		sprintf(szTemp, "%sps_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), counter++);

		SaveData(szTemp, code);
	}
#endif

	u8 *bytecode = 0;
	int bytecodelen = 0;
	if (!D3D::CompilePixelShader(code, (int)strlen(code), &bytecode, &bytecodelen)) {
		GFX_DEBUGGER_PAUSE_AT(NEXT_ERROR, true);
		return false;
	}

	// Insert the bytecode into the caches
	g_ps_disk_cache.Append(uid, bytecode, bytecodelen);

	// And insert it into the shader cache.
	bool success = InsertByteCode(uid, bytecode, bytecodelen, true);
	delete [] bytecode;

	if (g_ActiveConfig.bEnableShaderDebugging && success)
	{
		PixelShaders[uid].code = code;
		GetSafePixelShaderId(&PixelShaders[uid].safe_uid, PSGRenderMode, components);
	}

	GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true);
	return success;
}