Beispiel #1
0
void ShaderCache::HandleTSUIDChange(
	const TessellationShaderUid& ts_uid,
	bool on_gpu_thread)
{
	s_shaders_lock.lock();
	std::pair<ByteCodeCacheEntry, ByteCodeCacheEntry>& entry = ts_bytecode_cache->GetOrAdd(ts_uid);
	s_shaders_lock.unlock();
	ByteCodeCacheEntry* dentry = &entry.first;
	ByteCodeCacheEntry* hentry = &entry.second;
	if (on_gpu_thread)
	{
		if (dentry->m_compiled && hentry->m_compiled)
		{
			s_last_domain_shader_bytecode = dentry;
			s_last_hull_shader_bytecode = hentry;
		}
		else
		{
			s_last_tessellation_shader_uid = {};
			s_last_domain_shader_bytecode = &s_pass_entry;
			s_last_hull_shader_bytecode = &s_pass_entry;
		}
	}
	if (dentry->m_initialized.test_and_set())
	{
		return;
	}
	hentry->m_initialized.test_and_set();

	// Need to compile a new shader
	ShaderCode code;
	ShaderCompilerWorkUnit *wunit = s_compiler->NewUnit(TESSELLATIONSHADERGEN_BUFFERSIZE);
	ShaderCompilerWorkUnit *wunitd = s_compiler->NewUnit(TESSELLATIONSHADERGEN_BUFFERSIZE);
	code.SetBuffer(wunit->code.data());
	GenerateTessellationShaderCode(code, API_D3D11, ts_uid.GetUidData());
	memcpy(wunitd->code.data(), wunit->code.data(), code.BufferSize());

	wunit->codesize = (u32)code.BufferSize();
	wunit->entrypoint = "HS_TFO";
	wunit->flags = D3DCOMPILE_SKIP_VALIDATION | D3DCOMPILE_SKIP_OPTIMIZATION;
	wunit->target = D3D::HullShaderVersionString();

	wunitd->codesize = (u32)code.BufferSize();
	wunitd->entrypoint = "DS_TFO";
	wunitd->flags = D3DCOMPILE_SKIP_VALIDATION | D3DCOMPILE_OPTIMIZATION_LEVEL3;
	wunitd->target = D3D::DomainShaderVersionString();

	wunitd->ResultHandler = [ts_uid, dentry](ShaderCompilerWorkUnit* wunit)
	{
		if (SUCCEEDED(wunit->cresult))
		{
			D3DBlob* shaderBuffer = new D3DBlob(wunit->shaderbytecode);
			s_ds_disk_cache.Append(ts_uid, shaderBuffer->Data(), shaderBuffer->Size());
			PushByteCode(dentry, shaderBuffer);
			wunit->shaderbytecode->Release();
			wunit->shaderbytecode = nullptr;
		}
		else
		{
			static int num_failures = 0;
			std::string filename = StringFromFormat("%sbad_ds_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), num_failures++);
			std::ofstream file;
			OpenFStream(file, filename, std::ios_base::out);
			file << ((const char *)wunit->code.data());
			file << ((const char *)wunit->error->GetBufferPointer());
			file.close();

			PanicAlert("Failed to compile domain shader!\nThis usually happens when trying to use Dolphin with an outdated GPU or integrated GPU like the Intel GMA series.\n\nIf you're sure this is Dolphin's error anyway, post the contents of %s along with this error message at the forums.\n\nDebug info (%s):\n%s",
				filename,
				D3D::DomainShaderVersionString(),
				(char*)wunit->error->GetBufferPointer());
		}
	};

	wunit->ResultHandler = [ts_uid, hentry](ShaderCompilerWorkUnit* wunit)
	{
		if (SUCCEEDED(wunit->cresult))
		{
			D3DBlob* shaderBuffer = new D3DBlob(wunit->shaderbytecode);
			s_hs_disk_cache.Append(ts_uid, shaderBuffer->Data(), shaderBuffer->Size());
			PushByteCode(hentry, shaderBuffer);
			wunit->shaderbytecode->Release();
			wunit->shaderbytecode = nullptr;
		}
		else
		{
			static int num_failures = 0;
			std::string filename = StringFromFormat("%sbad_hs_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), num_failures++);
			std::ofstream file;
			OpenFStream(file, filename, std::ios_base::out);
			file << ((const char *)wunit->code.data());
			file << ((const char *)wunit->error->GetBufferPointer());
			file.close();

			PanicAlert("Failed to compile hull shader!\nThis usually happens when trying to use Dolphin with an outdated GPU or integrated GPU like the Intel GMA series.\n\nIf you're sure this is Dolphin's error anyway, post the contents of %s along with this error message at the forums.\n\nDebug info (%s):\n%s",
				filename,
				D3D::HullShaderVersionString(),
				(char*)wunit->error->GetBufferPointer());
		}
	};

	s_compiler->CompileShaderAsync(wunit);
	s_compiler->CompileShaderAsync(wunitd);
}
Beispiel #2
0
void VertexManager::vFlush(bool useDstAlpha)
{
  GLVertexFormat* nativeVertexFmt = (GLVertexFormat*)VertexLoaderManager::GetCurrentVertexFormat();
  u32 stride = nativeVertexFmt->GetVertexStride();

  if (m_last_vao != nativeVertexFmt->VAO)
  {
    glBindVertexArray(nativeVertexFmt->VAO);
    m_last_vao = nativeVertexFmt->VAO;
  }

  PrepareDrawBuffers(stride);

  // Makes sure we can actually do Dual source blending
  bool dualSourcePossible = g_ActiveConfig.backend_info.bSupportsDualSourceBlend;

  // If host supports GL_ARB_blend_func_extended, we can do dst alpha in
  // the same pass as regular rendering.
  if (useDstAlpha && dualSourcePossible)
  {
    ProgramShaderCache::SetShader(DSTALPHA_DUAL_SOURCE_BLEND, current_primitive_type);
  }
  else
  {
    ProgramShaderCache::SetShader(DSTALPHA_NONE, current_primitive_type);
  }

  // upload global constants
  ProgramShaderCache::UploadConstants();

  // setup the pointers
  nativeVertexFmt->SetupVertexPointers();

  Draw(stride);

  // run through vertex groups again to set alpha
  if (useDstAlpha && !dualSourcePossible)
  {
    ProgramShaderCache::SetShader(DSTALPHA_ALPHA_PASS, current_primitive_type);

    // only update alpha
    glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);

    glDisable(GL_BLEND);

    Draw(stride);

    // restore color mask
    g_renderer->SetColorMask();

    if (bpmem.blendmode.blendenable || bpmem.blendmode.subtract)
      glEnable(GL_BLEND);
  }

#if defined(_DEBUG) || defined(DEBUGFAST)
  if (g_ActiveConfig.iLog & CONF_SAVESHADERS)
  {
    // save the shaders
    ProgramShaderCache::PCacheEntry prog = ProgramShaderCache::GetShaderProgram();
    std::string filename = StringFromFormat(
        "%sps%.3d.txt", File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), g_ActiveConfig.iSaveTargetId);
    std::ofstream fps;
    OpenFStream(fps, filename, std::ios_base::out);
    fps << prog.shader.strpprog.c_str();

    filename = StringFromFormat("%svs%.3d.txt", File::GetUserPath(D_DUMPFRAMES_IDX).c_str(),
                                g_ActiveConfig.iSaveTargetId);
    std::ofstream fvs;
    OpenFStream(fvs, filename, std::ios_base::out);
    fvs << prog.shader.strvprog.c_str();
  }

  if (g_ActiveConfig.iLog & CONF_SAVETARGETS)
  {
    std::string filename =
        StringFromFormat("%starg%.3d.png", File::GetUserPath(D_DUMPFRAMES_IDX).c_str(),
                         g_ActiveConfig.iSaveTargetId);
    TargetRectangle tr;
    tr.left = 0;
    tr.right = Renderer::GetTargetWidth();
    tr.top = 0;
    tr.bottom = Renderer::GetTargetHeight();
    g_renderer->SaveScreenshot(filename, tr);
  }
#endif
  g_Config.iSaveTargetId++;

  ClearEFBCache();
}
Beispiel #3
0
void CGameListCtrl::ScanForISOs()
{
	ClearIsoFiles();

	// Load custom game titles from titles.txt
	// http://www.gametdb.com/Wii/Downloads
	std::unordered_map<std::string, std::string> custom_title_map;
	std::ifstream titlestxt;
	OpenFStream(titlestxt, File::GetUserPath(D_LOAD_IDX) + "titles.txt", std::ios::in);

	if (!titlestxt.is_open())
		OpenFStream(titlestxt, File::GetUserPath(D_LOAD_IDX) + "wiitdb.txt", std::ios::in);

	if (titlestxt.is_open())
	{
		std::string line;
		while (!titlestxt.eof() && std::getline(titlestxt, line))
		{
			const size_t equals_index = line.find('=');
			if (equals_index != std::string::npos)
				custom_title_map.emplace(StripSpaces(line.substr(0, equals_index)),
			                             StripSpaces(line.substr(equals_index + 1)));
		}
		titlestxt.close();
	}

	std::vector<std::string> Extensions;

	if (SConfig::GetInstance().m_ListGC)
		Extensions.push_back(".gcm");
	if (SConfig::GetInstance().m_ListWii || SConfig::GetInstance().m_ListGC)
	{
		Extensions.push_back(".iso");
		Extensions.push_back(".ciso");
		Extensions.push_back(".gcz");
		Extensions.push_back(".wbfs");
	}
	if (SConfig::GetInstance().m_ListWad)
		Extensions.push_back(".wad");
	if (SConfig::GetInstance().m_ListElfDol)
	{
		Extensions.push_back(".dol");
		Extensions.push_back(".elf");
	}

	auto rFilenames = DoFileSearch(Extensions, SConfig::GetInstance().m_ISOFolder, SConfig::GetInstance().m_RecursiveISOFolder);

	if (rFilenames.size() > 0)
	{
		wxProgressDialog dialog(
			_("Scanning for ISOs"),
			_("Scanning..."),
			(int)rFilenames.size() - 1,
			this,
			wxPD_APP_MODAL |
			wxPD_AUTO_HIDE |
			wxPD_CAN_ABORT |
			wxPD_ELAPSED_TIME | wxPD_ESTIMATED_TIME | wxPD_REMAINING_TIME |
			wxPD_SMOOTH // - makes updates as small as possible (down to 1px)
			);

		for (u32 i = 0; i < rFilenames.size(); i++)
		{
			std::string FileName;
			SplitPath(rFilenames[i], nullptr, &FileName, nullptr);

			// Update with the progress (i) and the message
			dialog.Update(i, wxString::Format(_("Scanning %s"),
				StrToWxStr(FileName)));
			if (dialog.WasCancelled())
				break;

			auto iso_file = std::make_unique<GameListItem>(rFilenames[i], custom_title_map);

			if (iso_file->IsValid())
			{
				bool list = true;

				switch(iso_file->GetPlatform())
				{
					case DiscIO::IVolume::WII_DISC:
						if (!SConfig::GetInstance().m_ListWii)
							list = false;
						break;
					case DiscIO::IVolume::WII_WAD:
						if (!SConfig::GetInstance().m_ListWad)
							list = false;
						break;
					case DiscIO::IVolume::ELF_DOL:
						if (!SConfig::GetInstance().m_ListElfDol)
							list = false;
						break;
					default:
						if (!SConfig::GetInstance().m_ListGC)
							list = false;
						break;
				}

				switch(iso_file->GetCountry())
				{
					case DiscIO::IVolume::COUNTRY_AUSTRALIA:
						if (!SConfig::GetInstance().m_ListAustralia)
							list = false;
						break;
					case DiscIO::IVolume::COUNTRY_EUROPE:
						if (!SConfig::GetInstance().m_ListPal)
							list = false;
						break;
					case DiscIO::IVolume::COUNTRY_FRANCE:
						if (!SConfig::GetInstance().m_ListFrance)
							list = false;
						break;
					case DiscIO::IVolume::COUNTRY_GERMANY:
						if (!SConfig::GetInstance().m_ListGermany)
							list = false;
						break;
					case DiscIO::IVolume::COUNTRY_ITALY:
						if (!SConfig::GetInstance().m_ListItaly)
							list = false;
						break;
					case DiscIO::IVolume::COUNTRY_JAPAN:
						if (!SConfig::GetInstance().m_ListJap)
							list = false;
						break;
					case DiscIO::IVolume::COUNTRY_KOREA:
						if (!SConfig::GetInstance().m_ListKorea)
							list = false;
						break;
					case DiscIO::IVolume::COUNTRY_NETHERLANDS:
						if (!SConfig::GetInstance().m_ListNetherlands)
							list = false;
						break;
					case DiscIO::IVolume::COUNTRY_RUSSIA:
						if (!SConfig::GetInstance().m_ListRussia)
							list = false;
						break;
					case DiscIO::IVolume::COUNTRY_SPAIN:
						if (!SConfig::GetInstance().m_ListSpain)
							list = false;
						break;
					case DiscIO::IVolume::COUNTRY_TAIWAN:
						if (!SConfig::GetInstance().m_ListTaiwan)
							list = false;
						break;
					case DiscIO::IVolume::COUNTRY_USA:
						if (!SConfig::GetInstance().m_ListUsa)
							list = false;
						break;
					case DiscIO::IVolume::COUNTRY_WORLD:
						if (!SConfig::GetInstance().m_ListWorld)
							list = false;
						break;
					case DiscIO::IVolume::COUNTRY_UNKNOWN:
					default:
						if (!SConfig::GetInstance().m_ListUnknown)
							list = false;
						break;
				}

				if (list)
					m_ISOFiles.push_back(iso_file.release());
			}
		}
	}

	if (SConfig::GetInstance().m_ListDrives)
	{
		const std::vector<std::string> drives = cdio_get_devices();

		for (const auto& drive : drives)
		{
			auto gli = std::make_unique<GameListItem>(drive, custom_title_map);

			if (gli->IsValid())
				m_ISOFiles.push_back(gli.release());
		}
	}

	std::sort(m_ISOFiles.begin(), m_ISOFiles.end());
}
Beispiel #4
0
void ShaderCache::HandleGSUIDChange(
	const GeometryShaderUid &gs_uid,
	bool on_gpu_thread)
{
	if (gs_uid.GetUidData().IsPassthrough())
	{
		s_last_geometry_shader_bytecode = &s_pass_entry;
		return;
	}

	s_shaders_lock.lock();
	ByteCodeCacheEntry* entry = &gs_bytecode_cache->GetOrAdd(gs_uid);
	s_shaders_lock.unlock();
	if (on_gpu_thread)
	{
		s_last_geometry_shader_bytecode = entry;
	}

	if (entry->m_initialized.test_and_set())
	{
		return;
	}

	// Need to compile a new shader
	ShaderCompilerWorkUnit *wunit = s_compiler->NewUnit(GEOMETRYSHADERGEN_BUFFERSIZE);
	wunit->GenerateCodeHandler = [gs_uid](ShaderCompilerWorkUnit* wunit)
	{
		ShaderCode code;
		code.SetBuffer(wunit->code.data());
		GenerateGeometryShaderCode(code, gs_uid.GetUidData(), API_D3D11);
		wunit->codesize = (u32)code.BufferSize();
	};

	wunit->entrypoint = "main";
	wunit->flags = D3DCOMPILE_SKIP_VALIDATION | D3DCOMPILE_OPTIMIZATION_LEVEL3;
	wunit->target = D3D::GeometryShaderVersionString();

	wunit->ResultHandler = [gs_uid, entry](ShaderCompilerWorkUnit* wunit)
	{
		if (SUCCEEDED(wunit->cresult))
		{
			D3DBlob* shaderBuffer = new D3DBlob(wunit->shaderbytecode);
			s_gs_disk_cache.Append(gs_uid, shaderBuffer->Data(), shaderBuffer->Size());
			PushByteCode(entry, shaderBuffer);
			wunit->shaderbytecode->Release();
			wunit->shaderbytecode = nullptr;
			SETSTAT(stats.numGeometryShadersAlive, static_cast<int>(ps_bytecode_cache->size()));
			INCSTAT(stats.numGeometryShadersCreated);
		}
		else
		{
			static int num_failures = 0;
			std::string filename = StringFromFormat("%sbad_gs_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), num_failures++);
			std::ofstream file;
			OpenFStream(file, filename, std::ios_base::out);
			file << ((const char *)wunit->code.data());
			file << ((const char *)wunit->error->GetBufferPointer());
			file.close();

			PanicAlert("Failed to compile geometry shader!\nThis usually happens when trying to use Dolphin with an outdated GPU or integrated GPU like the Intel GMA series.\n\nIf you're sure this is Dolphin's error anyway, post the contents of %s along with this error message at the forums.\n\nDebug info (%s):\n%s",
				filename,
				D3D::GeometryShaderVersionString(),
				(char*)wunit->error->GetBufferPointer());
		}
	};
	s_compiler->CompileShaderAsync(wunit);
}
Beispiel #5
0
bool ProgramShaderCache::CompileShader ( SHADER& shader, const char* vcode, const char* pcode )
{
	GLuint vsid = CompileSingleShader(GL_VERTEX_SHADER, vcode);
	GLuint psid = CompileSingleShader(GL_FRAGMENT_SHADER, pcode);

	if(!vsid || !psid)
	{
		glDeleteShader(vsid);
		glDeleteShader(psid);
		return false;
	}

	GLuint pid = shader.glprogid = glCreateProgram();;

	glAttachShader(pid, vsid);
	glAttachShader(pid, psid);

	if (g_ogl_config.bSupportsGLSLCache)
		glProgramParameteri(pid, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE);

	shader.SetProgramBindings();

	glLinkProgram(pid);

	// original shaders aren't needed any more
	glDeleteShader(vsid);
	glDeleteShader(psid);

	GLint linkStatus;
	glGetProgramiv(pid, GL_LINK_STATUS, &linkStatus);
	GLsizei length = 0;
	glGetProgramiv(pid, GL_INFO_LOG_LENGTH, &length);
	if (linkStatus != GL_TRUE || (length > 1 && DEBUG_GLSL))
	{
		GLsizei charsWritten;
		GLchar* infoLog = new GLchar[length];
		glGetProgramInfoLog(pid, length, &charsWritten, infoLog);
		ERROR_LOG(VIDEO, "Program info log:\n%s", infoLog);
		char szTemp[MAX_PATH];
		sprintf(szTemp, "%sbad_p_%d.txt", File::GetUserPath(D_DUMP_IDX).c_str(), num_failures++);
		std::ofstream file;
		OpenFStream(file, szTemp, std::ios_base::out);
		file << s_glsl_header << vcode << s_glsl_header << pcode << infoLog;
		file.close();

		if(linkStatus != GL_TRUE)
			PanicAlert("Failed to link shaders!\nThis usually happens when trying to use Dolphin with an outdated GPU or integrated GPU like the Intel GMA series.\n\nIf you're sure this is Dolphin's error anyway, post the contents of %s along with this error message at the forums.\n\nDebug info (%s, %s, %s):\n%s",
				szTemp,
				g_ogl_config.gl_vendor,
				g_ogl_config.gl_renderer,
				g_ogl_config.gl_version,
				infoLog);

		delete [] infoLog;
	}
	if (linkStatus != GL_TRUE)
	{
		// Compile failed
		ERROR_LOG(VIDEO, "Program linking failed; see info log");

		// Don't try to use this shader
		glDeleteProgram(pid);
		return false;
	}

	shader.SetProgramVariables();

	return true;
}
Beispiel #6
0
void VertexManager::vFlush()
{
	GLVertexFormat *nativeVertexFmt = (GLVertexFormat*)g_nativeVertexFmt;
	u32 stride  = nativeVertexFmt->GetVertexStride();

	if(m_last_vao != nativeVertexFmt->VAO) {
		glBindVertexArray(nativeVertexFmt->VAO);
		m_last_vao = nativeVertexFmt->VAO;
	}

	PrepareDrawBuffers(stride);
	GL_REPORT_ERRORD();

	bool useDstAlpha = !g_ActiveConfig.bDstAlphaPass && bpmem.dstalpha.enable && bpmem.blendmode.alphaupdate
		&& bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24;

	// Makes sure we can actually do Dual source blending
	bool dualSourcePossible = g_ActiveConfig.backend_info.bSupportsDualSourceBlend;

	// finally bind
	if (dualSourcePossible)
	{
		if (useDstAlpha)
		{
			// If host supports GL_ARB_blend_func_extended, we can do dst alpha in
			// the same pass as regular rendering.
			ProgramShaderCache::SetShader(DSTALPHA_DUAL_SOURCE_BLEND, g_nativeVertexFmt->m_components);
		}
		else
		{
			ProgramShaderCache::SetShader(DSTALPHA_NONE,g_nativeVertexFmt->m_components);
		}
	}
	else
	{
		ProgramShaderCache::SetShader(DSTALPHA_NONE,g_nativeVertexFmt->m_components);
	}

	// upload global constants
	ProgramShaderCache::UploadConstants();

	// setup the pointers
	if (g_nativeVertexFmt)
		g_nativeVertexFmt->SetupVertexPointers();
	GL_REPORT_ERRORD();

	g_perf_query->EnableQuery(bpmem.zcontrol.early_ztest ? PQG_ZCOMP_ZCOMPLOC : PQG_ZCOMP);
	Draw(stride);
	g_perf_query->DisableQuery(bpmem.zcontrol.early_ztest ? PQG_ZCOMP_ZCOMPLOC : PQG_ZCOMP);
	//ERROR_LOG(VIDEO, "PerfQuery result: %d", g_perf_query->GetQueryResult(bpmem.zcontrol.early_ztest ? PQ_ZCOMP_OUTPUT_ZCOMPLOC : PQ_ZCOMP_OUTPUT));

	// run through vertex groups again to set alpha
	if (useDstAlpha && !dualSourcePossible)
	{
		ProgramShaderCache::SetShader(DSTALPHA_ALPHA_PASS,g_nativeVertexFmt->m_components);

		// only update alpha
		glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);

		glDisable(GL_BLEND);

		Draw(stride);

		// restore color mask
		g_renderer->SetColorMask();

		if (bpmem.blendmode.blendenable || bpmem.blendmode.subtract)
			glEnable(GL_BLEND);
	}
	GFX_DEBUGGER_PAUSE_AT(NEXT_FLUSH, true);

#if defined(_DEBUG) || defined(DEBUGFAST)
	if (g_ActiveConfig.iLog & CONF_SAVESHADERS)
	{
		// save the shaders
		ProgramShaderCache::PCacheEntry prog = ProgramShaderCache::GetShaderProgram();
		char strfile[255];
		sprintf(strfile, "%sps%.3d.txt", File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), g_ActiveConfig.iSaveTargetId);
		std::ofstream fps;
		OpenFStream(fps, strfile, std::ios_base::out);
		fps << prog.shader.strpprog.c_str();
		sprintf(strfile, "%svs%.3d.txt", File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), g_ActiveConfig.iSaveTargetId);
		std::ofstream fvs;
		OpenFStream(fvs, strfile, std::ios_base::out);
		fvs << prog.shader.strvprog.c_str();
	}

	if (g_ActiveConfig.iLog & CONF_SAVETARGETS)
	{
		char str[128];
		sprintf(str, "%starg%.3d.png", File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), g_ActiveConfig.iSaveTargetId);
		TargetRectangle tr;
		tr.left = 0;
		tr.right = Renderer::GetTargetWidth();
		tr.top = 0;
		tr.bottom = Renderer::GetTargetHeight();
		g_renderer->SaveScreenshot(str, tr);
	}
#endif
	g_Config.iSaveTargetId++;

	ClearEFBCache();

	GL_REPORT_ERRORD();
}
Beispiel #7
0
// copies file srcFilename to destFilename, returns true on success
bool Copy(const std::string& srcFilename, const std::string& destFilename)
{
  INFO_LOG(COMMON, "Copy: %s --> %s", srcFilename.c_str(), destFilename.c_str());
#ifdef _WIN32
  if (CopyFile(UTF8ToTStr(srcFilename).c_str(), UTF8ToTStr(destFilename).c_str(), FALSE))
    return true;

  ERROR_LOG(COMMON, "Copy: failed %s --> %s: %s", srcFilename.c_str(), destFilename.c_str(),
            GetLastErrorMsg().c_str());
  return false;
#else

// buffer size
#define BSIZE 1024

  char buffer[BSIZE];

  // Open input file
  std::ifstream input;
  OpenFStream(input, srcFilename, std::ifstream::in | std::ifstream::binary);
  if (!input.is_open())
  {
    ERROR_LOG(COMMON, "Copy: input failed %s --> %s: %s", srcFilename.c_str(), destFilename.c_str(),
              GetLastErrorMsg().c_str());
    return false;
  }

  // open output file
  File::IOFile output(destFilename, "wb");

  if (!output.IsOpen())
  {
    ERROR_LOG(COMMON, "Copy: output failed %s --> %s: %s", srcFilename.c_str(),
              destFilename.c_str(), GetLastErrorMsg().c_str());
    return false;
  }

  // copy loop
  while (!input.eof())
  {
    // read input
    input.read(buffer, BSIZE);
    if (!input)
    {
      ERROR_LOG(COMMON, "Copy: failed reading from source, %s --> %s: %s", srcFilename.c_str(),
                destFilename.c_str(), GetLastErrorMsg().c_str());
      return false;
    }

    // write output
    if (!output.WriteBytes(buffer, BSIZE))
    {
      ERROR_LOG(COMMON, "Copy: failed writing to output, %s --> %s: %s", srcFilename.c_str(),
                destFilename.c_str(), GetLastErrorMsg().c_str());
      return false;
    }
  }

  return true;
#endif
}
GLuint ProgramShaderCache::CompileSingleShader(GLuint type, const char* code, const char **macros,
	const u32 count)
{
	GLuint result = glCreateShader(type);

	const char **src = new const char *[count + 2];
	src[0] = s_glsl_header;
	for (size_t i = 0; i < count; i++)
	{
		src[i + 1] = macros[i];
	}
	src[count + 2 - 1] = code;
	glShaderSource(result, count + 2, src, nullptr);
	glCompileShader(result);
	GLint compileStatus;
	glGetShaderiv(result, GL_COMPILE_STATUS, &compileStatus);
	GLsizei length = 0;
	glGetShaderiv(result, GL_INFO_LOG_LENGTH, &length);

	if (DriverDetails::HasBug(DriverDetails::BUG_BROKENINFOLOG))
		length = 1024;

	if (compileStatus != GL_TRUE || (length > 1 && DEBUG_GLSL))
	{
		GLsizei charsWritten;
		GLchar* infoLog = new GLchar[length];
		glGetShaderInfoLog(result, length, &charsWritten, infoLog);
		ERROR_LOG(VIDEO, "%s Shader info log:\n%s", type==GL_VERTEX_SHADER ? "VS" : type==GL_FRAGMENT_SHADER ? "PS" : "GS", infoLog);

		std::string filename = StringFromFormat("%sbad_%s_%04i.txt",
			File::GetUserPath(D_DUMP_IDX).c_str(),
			type==GL_VERTEX_SHADER ? "vs" : type==GL_FRAGMENT_SHADER ? "ps" : "gs",
			num_failures++);
		std::ofstream file;
		OpenFStream(file, filename, std::ios_base::out);
		file << s_glsl_header << code << infoLog;
		file.close();

		if (compileStatus != GL_TRUE)
		{
			PanicAlert("Failed to compile %s shader: %s\n"
			           "Debug info (%s, %s, %s):\n%s",
			           type == GL_VERTEX_SHADER ? "vertex" : type==GL_FRAGMENT_SHADER ? "pixel" : "geometry",
			           filename.c_str(),
			           g_ogl_config.gl_vendor, g_ogl_config.gl_renderer, g_ogl_config.gl_version, infoLog);
		}

		delete[] infoLog;
	}
	if (compileStatus != GL_TRUE)
	{
		// Compile failed
		ERROR_LOG(VIDEO, "Shader compilation failed; see info log");

		// Don't try to use this shader
		glDeleteShader(result);
		return 0;
	}

	return result;
}
Beispiel #9
0
// code->bytecode
bool CompileShader(
	ShaderType type,
	const std::string& code,
	D3DBlob& blob,
	const D3D_SHADER_MACRO* pDefines,
	const char* pEntry, bool throwerror)
{
#if defined(_DEBUG) || defined(DEBUGFAST)
	UINT flags = D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION;
#else
	UINT flags = D3DCOMPILE_SKIP_VALIDATION;
	if (type != DX11::D3D::ShaderType::Hull)
	{
		flags |= D3D10_SHADER_ENABLE_BACKWARDS_COMPATIBILITY | D3DCOMPILE_OPTIMIZATION_LEVEL3;
	}
	else
	{
		flags |= D3DCOMPILE_SKIP_OPTIMIZATION;
	}
#endif
	
	char const *profile = nullptr;
	char const *sufix = nullptr;
	switch (type) {
	case DX11::D3D::ShaderType::Vertex:
		profile = D3D::VertexShaderVersionString();
		sufix = "vs";
		break;
	case DX11::D3D::ShaderType::Pixel:
		profile = D3D::PixelShaderVersionString();
		sufix = "ps";
		break;
	case DX11::D3D::ShaderType::Geometry:
		profile = D3D::GeometryShaderVersionString();
		sufix = "gs";
		break;
	case DX11::D3D::ShaderType::Hull:
		profile = D3D::HullShaderVersionString();
		sufix = "hs";
		break;
	case DX11::D3D::ShaderType::Domain:
		profile = D3D::DomainShaderVersionString();
		sufix = "ds";
		break;
	case DX11::D3D::ShaderType::Compute:
		profile = D3D::ComputeShaderVersionString();
		sufix = "cs";
		break;
	default:
		return false;
		break;
	}



	ID3DBlobPtr shaderBuffer;
	ID3DBlobPtr errorBuffer;
	HRESULT hr = HLSLCompiler::getInstance().CompileShader(code.c_str(),
		code.length(), nullptr, pDefines, nullptr, pEntry != nullptr ? pEntry : "main", profile,
		flags, 0, ToAddr(shaderBuffer), ToAddr(errorBuffer));

	if (errorBuffer)
	{
		INFO_LOG(VIDEO, "Shader compiler messages:\n%s",
			(const char*)errorBuffer->GetBufferPointer());
	}

	if (FAILED(hr))
	{
		static int num_failures = 0;
		std::string filename = StringFromFormat("%sbad_%s_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), sufix, num_failures++);
		std::ofstream file;
		OpenFStream(file, filename, std::ios_base::out);
		file << code;
		file << "\n";
		file << (const char*)errorBuffer->GetBufferPointer();
		file.close();
		if (throwerror)
		{
			PanicAlert("Failed to compile shader: %s\nDebug info (%s):\n%s",
				filename.c_str(),
				profile,
				(char*)errorBuffer->GetBufferPointer());
		}
		blob = nullptr;
	}
	else
	{
		blob = std::move(shaderBuffer);
	}

	return SUCCEEDED(hr);
}
Beispiel #10
0
void CGameListCtrl::InsertItemInReportView(long _Index)
{
	// When using wxListCtrl, there is no hope of per-column text colors.
	// But for reference, here are the old colors that were used: (BGR)
	// title: 0xFF0000
	// company: 0x007030
	int ImageIndex = -1;

	GameListItem& rISOFile = *m_ISOFiles[_Index];

	// Insert a first row with nothing in it, that will be used as the Index
	long ItemIndex = InsertItem(_Index, wxEmptyString);

	// Insert the platform's image in the first (visible) column
	SetItemColumnImage(_Index, COLUMN_PLATFORM, m_PlatformImageIndex[rISOFile.GetPlatform()]);

	if (rISOFile.GetBitmap().IsOk())
		ImageIndex = m_imageListSmall->Add(rISOFile.GetBitmap());

	// Set the game's banner in the second column
	SetItemColumnImage(_Index, COLUMN_BANNER, ImageIndex);

	int SelectedLanguage = SConfig::GetInstance().m_LocalCoreStartupParameter.SelectedLanguage;

	// Is this sane?
	if  (rISOFile.GetPlatform() == GameListItem::WII_WAD)
	{
		SelectedLanguage = SConfig::GetInstance().m_SYSCONF->GetData<u8>("IPL.LNG");
	}

	std::string name = rISOFile.GetName(SelectedLanguage);

	std::ifstream titlestxt;
	OpenFStream(titlestxt, File::GetUserPath(D_LOAD_IDX) + "titles.txt", std::ios::in);

	if (titlestxt.is_open() && rISOFile.GetUniqueID().size() > 3)
	{
		while (!titlestxt.eof())
		{
			std::string line;

			if (!std::getline(titlestxt, line) && titlestxt.eof())
				break;

			if (line.substr(0,rISOFile.GetUniqueID().size()) == rISOFile.GetUniqueID())
			{
				name = line.substr(rISOFile.GetUniqueID().size() + 3);
				break;
			}
		}
		titlestxt.close();
	}

	std::string GameIni[3];
	GameIni[0] = File::GetUserPath(D_GAMESETTINGS_IDX) + rISOFile.GetUniqueID() + ".ini";
	GameIni[1] = File::GetSysDirectory() + GAMESETTINGS_DIR DIR_SEP + rISOFile.GetUniqueID() + std::to_string(rISOFile.GetRevision()) + ".ini";
	GameIni[2] = File::GetSysDirectory() + GAMESETTINGS_DIR DIR_SEP + rISOFile.GetUniqueID() + ".ini";
	std::string title;
	IniFile gameini;
	for (int i = 0; i < 3; ++i)
	{
		if (File::Exists(GameIni[i]))
		{
			gameini.Load(GameIni[i]);
			if (gameini.GetIfExists("EmuState", "Title", &title))
			{
				name = title;
				break;
			}
		}
	}

	SetItem(_Index, COLUMN_TITLE, StrToWxStr(name), -1);

	// We show the company string on GameCube only
	// On Wii we show the description instead as the company string is empty
	std::string const notes = (rISOFile.GetPlatform() == GameListItem::GAMECUBE_DISC) ?
		rISOFile.GetCompany() : rISOFile.GetDescription(SelectedLanguage);
	SetItem(_Index, COLUMN_NOTES, StrToWxStr(notes), -1);

	// Emulation state
	SetItemColumnImage(_Index, COLUMN_EMULATION_STATE, m_EmuStateImageIndex[rISOFile.GetEmuState()]);

	// Country
	SetItemColumnImage(_Index, COLUMN_COUNTRY, m_FlagImageIndex[rISOFile.GetCountry()]);

	// File size
	SetItem(_Index, COLUMN_SIZE, NiceSizeFormat(rISOFile.GetFileSize()), -1);

	// Game ID
	SetItem(_Index, COLUMN_ID, rISOFile.GetUniqueID(), -1);

	// Background color
	SetBackgroundColor();

	// Item data
	SetItemData(_Index, ItemIndex);
}
bool ProgramShaderCache::CompileShader(SHADER& shader, const char* vcode, const char* pcode, const char* gcode)
{
	GLuint vsid = CompileSingleShader(GL_VERTEX_SHADER, vcode);
	GLuint psid = CompileSingleShader(GL_FRAGMENT_SHADER, pcode);

	// Optional geometry shader
	GLuint gsid = 0;
	if (gcode)
		gsid = CompileSingleShader(GL_GEOMETRY_SHADER, gcode);

	if (!vsid || !psid || (gcode && !gsid))
	{
		glDeleteShader(vsid);
		glDeleteShader(psid);
		glDeleteShader(gsid);
		return false;
	}

	GLuint pid = shader.glprogid = glCreateProgram();

	glAttachShader(pid, vsid);
	glAttachShader(pid, psid);
	if (gsid)
		glAttachShader(pid, gsid);

	if (g_ogl_config.bSupportsGLSLCache)
		glProgramParameteri(pid, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE);

	shader.SetProgramBindings();

	glLinkProgram(pid);

	// original shaders aren't needed any more
	glDeleteShader(vsid);
	glDeleteShader(psid);
	glDeleteShader(gsid);

	GLint linkStatus;
	glGetProgramiv(pid, GL_LINK_STATUS, &linkStatus);
	GLsizei length = 0;
	glGetProgramiv(pid, GL_INFO_LOG_LENGTH, &length);
	if (linkStatus != GL_TRUE || (length > 1 && DEBUG_GLSL))
	{
		GLsizei charsWritten;
		GLchar* infoLog = new GLchar[length];
		glGetProgramInfoLog(pid, length, &charsWritten, infoLog);
		ERROR_LOG(VIDEO, "Program info log:\n%s", infoLog);

		std::string filename = StringFromFormat("%sbad_p_%d.txt", File::GetUserPath(D_DUMP_IDX).c_str(), num_failures++);
		std::ofstream file;
		OpenFStream(file, filename, std::ios_base::out);
		file << s_glsl_header << vcode << s_glsl_header << pcode;
		if (gcode)
			file << s_glsl_header << gcode;
		file << infoLog;
		file.close();

		if (linkStatus != GL_TRUE)
		{
			PanicAlert("Failed to link shaders: %s\n"
			           "Debug info (%s, %s, %s):\n%s",
			           filename.c_str(),
			           g_ogl_config.gl_vendor, g_ogl_config.gl_renderer, g_ogl_config.gl_version, infoLog);
		}

		delete [] infoLog;
	}
	if (linkStatus != GL_TRUE)
	{
		// Compile failed
		ERROR_LOG(VIDEO, "Program linking failed; see info log");

		// Don't try to use this shader
		glDeleteProgram(pid);
		return false;
	}

	shader.SetProgramVariables();

	return true;
}
Beispiel #12
0
void PixelShaderCache::CompilePShader(const PixelShaderUid& uid, PIXEL_SHADER_RENDER_MODE render_mode, bool ongputhread)
{
	const API_TYPE api = ((D3D::GetCaps().PixelShaderVersion >> 8) & 0xFF) < 3 ? API_D3D9_SM20 : API_D3D9_SM30;
	s_pixel_shaders_lock.lock();
	PSCacheEntry* entry = &s_pshaders->GetOrAdd(uid);
	s_pixel_shaders_lock.unlock();
	if (ongputhread)
	{
		s_last_entry[render_mode] = entry;
	}
	// Compile only when we have a new instance
	if (entry->initialized.test_and_set())
	{
		return;
	}
	// Need to compile a new shader

	ShaderCompilerWorkUnit *wunit = s_compiler->NewUnit(PIXELSHADERGEN_BUFFERSIZE);
	wunit->GenerateCodeHandler = [uid, api](ShaderCompilerWorkUnit* wunit)
	{
		ShaderCode code;
		code.SetBuffer(wunit->code.data());
		if (api == API_D3D9_SM20)
		{
			GeneratePixelShaderCodeD3D9SM2(code, uid.GetUidData());
		}
		else
		{
			GeneratePixelShaderCodeD3D9(code, uid.GetUidData());
		}
		wunit->codesize = (u32)code.BufferSize();
	};
	wunit->entrypoint = "main";
	wunit->flags = D3DCOMPILE_SKIP_VALIDATION | D3DCOMPILE_OPTIMIZATION_LEVEL3;
	wunit->target = D3D::PixelShaderVersionString();
	wunit->ResultHandler = [uid, entry](ShaderCompilerWorkUnit* wunit)
	{
		if (SUCCEEDED(wunit->cresult))
		{
			ID3DBlob* shaderBuffer = wunit->shaderbytecode;
			const u8* bytecode = (const u8*)shaderBuffer->GetBufferPointer();
			u32 bytecodelen = (u32)shaderBuffer->GetBufferSize();
			g_ps_disk_cache.Append(uid, bytecode, bytecodelen);
			PushByteCode(uid, bytecode, bytecodelen, entry);
		}
		else
		{
			static int num_failures = 0;
			std::string filename = StringFromFormat("%sbad_ps_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), num_failures++);
			std::ofstream file;
			OpenFStream(file, filename, std::ios_base::out);
			file << ((const char *)wunit->code.data());
			file << ((const char*)wunit->error->GetBufferPointer());
			file.close();

			PanicAlert("Failed to compile pixel shader!\nThis usually happens when trying to use Dolphin with an outdated GPU or integrated GPU like the Intel GMA series.\n\nIf you're sure this is Dolphin's error anyway, post the contents of %s along with this error message at the forums.\n\nDebug info (%s):\n%s",
				filename,
				D3D::VertexShaderVersionString(),
				(const char*)wunit->error->GetBufferPointer());
		}
	};
	s_compiler->CompileShaderAsync(wunit);
}
Beispiel #13
0
void GeometryShaderCache::CompileGShader(const GeometryShaderUid& uid, bool ongputhread)
{
	s_geometry_shaders_lock.lock();
	GSCacheEntry* entry = &s_geometry_shaders->GetOrAdd(uid);
	s_geometry_shaders_lock.unlock();
	if (ongputhread)
	{
		s_last_entry = entry;
	}
	// Compile only when we have a new instance
	if (entry->initialized.test_and_set())
	{
		return;
	}

	// Need to compile a new shader
	ShaderCompilerWorkUnit *wunit = s_compiler->NewUnit(GEOMETRYSHADERGEN_BUFFERSIZE);
	wunit->GenerateCodeHandler = [uid](ShaderCompilerWorkUnit* wunit)
	{
		ShaderCode code;
		code.SetBuffer(wunit->code.data());
		GenerateGeometryShaderCode(code, uid.GetUidData(), API_D3D11);
		wunit->codesize = (u32)code.BufferSize();
	};

	wunit->entrypoint = "main";
#if defined(_DEBUG) || defined(DEBUGFAST)
	wunit->flags = D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION;
#else
	wunit->flags = D3DCOMPILE_SKIP_VALIDATION | D3DCOMPILE_OPTIMIZATION_LEVEL3;
#endif
	wunit->target = D3D::GeometryShaderVersionString();

	wunit->ResultHandler = [uid, entry](ShaderCompilerWorkUnit* wunit)
	{
		if (SUCCEEDED(wunit->cresult))
		{
			ID3DBlob* shaderBuffer = wunit->shaderbytecode;
			const u8* bytecode = (const u8*)shaderBuffer->GetBufferPointer();
			u32 bytecodelen = (u32)shaderBuffer->GetBufferSize();
			g_gs_disk_cache.Append(uid, bytecode, bytecodelen);
			PushByteCode(bytecode, bytecodelen, entry);
		}
		else
		{
			static int num_failures = 0;
			char szTemp[MAX_PATH];
			sprintf(szTemp, "%sbad_gs_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), num_failures++);
			std::ofstream file;
			OpenFStream(file, szTemp, std::ios_base::out);
			file << ((const char *)wunit->code.data());
			file << ((const char *)wunit->error->GetBufferPointer());
			file.close();

			PanicAlert("Failed to compile geometry shader!\nThis usually happens when trying to use Dolphin with an outdated GPU or integrated GPU like the Intel GMA series.\n\nIf you're sure this is Dolphin's error anyway, post the contents of %s along with this error message at the forums.\n\nDebug info (%s):\n%s",
				szTemp,
				D3D::GeometryShaderVersionString(),
				(char*)wunit->error->GetBufferPointer());
		}
	};
	s_compiler->CompileShaderAsync(wunit);
}
Beispiel #14
0
FileLogListener::FileLogListener(const std::string& filename)
{
	OpenFStream(m_logfile, filename, std::ios::app);
	SetEnable(true);
}
void PixelShaderCache::PrepareShader(
	PIXEL_SHADER_RENDER_MODE render_mode,
	u32 components, 
	const XFMemory &xfr,
	const BPMemory &bpm,
	bool ongputhread)
{
	const API_TYPE api = ((D3D::GetCaps().PixelShaderVersion >> 8) & 0xFF) < 3 ? API_D3D9_SM20 : API_D3D9_SM30;
	PixelShaderUid uid;
	GetPixelShaderUID(uid, render_mode, components, xfr, bpm);
	if (ongputhread)
	{
		Compiler->ProcCompilationResults();
#if defined(_DEBUG) || defined(DEBUGFAST)
		if (g_ActiveConfig.bEnableShaderDebugging)
		{
			ShaderCode code;
			GeneratePixelShaderCodeD3D9(code, uid.GetUidData());
		}
#endif
		// Check if the shader is already set
		if (last_entry[render_mode])
		{
			if (uid == last_uid[render_mode])
			{
				return;
			}
		}
		last_uid[render_mode] = uid;
		GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true);
	}
	else
	{
		if (external_last_uid[render_mode] == uid)
		{
			return;
		}
		external_last_uid[render_mode] = uid;
	}
	PixelShadersLock.lock();
	PSCacheEntry* entry = &PixelShaders[uid];
	PixelShadersLock.unlock();
	if (ongputhread)
	{
		last_entry[render_mode] = entry;
	}
	// Compile only when we have a new instance
	if (entry->initialized.test_and_set())
	{
		return;
	}
	// Need to compile a new shader
	
	ShaderCompilerWorkUnit *wunit = Compiler->NewUnit(PIXELSHADERGEN_BUFFERSIZE);
	wunit->GenerateCodeHandler = [uid, api](ShaderCompilerWorkUnit* wunit)
	{
		ShaderCode code;
		code.SetBuffer(wunit->code.data());
		if (api == API_D3D9_SM20)
		{
			GeneratePixelShaderCodeD3D9SM2(code, uid.GetUidData());
		}
		else
		{
			GeneratePixelShaderCodeD3D9(code, uid.GetUidData());
		}
		wunit->codesize = (u32)code.BufferSize();
	};
	wunit->entrypoint = "main";
	wunit->flags = D3DCOMPILE_SKIP_VALIDATION | D3DCOMPILE_OPTIMIZATION_LEVEL3;
	wunit->target = D3D::PixelShaderVersionString();
	wunit->ResultHandler = [uid, entry](ShaderCompilerWorkUnit* wunit)
	{
		if (SUCCEEDED(wunit->cresult))
		{
			ID3DBlob* shaderBuffer = wunit->shaderbytecode;
			const u8* bytecode = (const u8*)shaderBuffer->GetBufferPointer();
			u32 bytecodelen = (u32)shaderBuffer->GetBufferSize();
			g_ps_disk_cache.Append(uid, bytecode, bytecodelen);
			PushByteCode(uid, bytecode, bytecodelen, entry);
#if defined(_DEBUG) || defined(DEBUGFAST)
			if (g_ActiveConfig.bEnableShaderDebugging)
			{
				u32 code_hash = HashAdler32((const u8 *)wunit->code.data(), wunit->codesize);
				unique_shaders.insert(code_hash);
				entry->code = wunit->code.data();
			}
			if (g_ActiveConfig.iLog & CONF_SAVESHADERS) {
				static int counter = 0;
				char szTemp[MAX_PATH];
				sprintf(szTemp, "%sps_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), counter++);

				SaveData(szTemp, wunit->code.data());
			}
#endif			
		}
		else
		{
			static int num_failures = 0;
			std::string filename = StringFromFormat("%sbad_ps_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), num_failures++);
			std::ofstream file;
			OpenFStream(file, filename, std::ios_base::out);
			file << ((const char *)wunit->code.data());
			file << ((const char*)wunit->error->GetBufferPointer());
			file.close();

			PanicAlert("Failed to compile pixel shader!\nThis usually happens when trying to use Dolphin with an outdated GPU or integrated GPU like the Intel GMA series.\n\nIf you're sure this is Dolphin's error anyway, post the contents of %s along with this error message at the forums.\n\nDebug info (%s):\n%s",
				filename,
				D3D::VertexShaderVersionString(),
				(const char*)wunit->error->GetBufferPointer());
		}
	};
	Compiler->CompileShaderAsync(wunit);
}
Beispiel #16
0
bool IniFile::Load(const std::string& filename, bool keep_current_data)
{
	if (!keep_current_data)
		sections.clear();
	// first section consists of the comments before the first real section

	// Open file
	std::ifstream in;
	OpenFStream(in, filename, std::ios::in);

	if (in.fail())
		return false;

	Section* current_section = nullptr;
	while (!in.eof())
	{
		std::string line;

		if (!std::getline(in, line))
		{
			if (in.eof())
				return true;
			else
				return false;
		}

#ifndef _WIN32
		// Check for CRLF eol and convert it to LF
		if (!line.empty() && line.at(line.size()-1) == '\r')
		{
			line.erase(line.size()-1);
		}
#endif

		if (line.size() > 0)
		{
			if (line[0] == '[')
			{
				size_t endpos = line.find("]");

				if (endpos != std::string::npos)
				{
					// New section!
					std::string sub = line.substr(1, endpos - 1);
					current_section = GetOrCreateSection(sub);
				}
			}
			else
			{
				if (current_section)
				{
					std::string key, value;
					ParseLine(line, &key, &value);

					// Lines starting with '$', '*' or '+' are kept verbatim.
					// Kind of a hack, but the support for raw lines inside an
					// INI is a hack anyway.
					if ((key == "" && value == "") ||
					    (line.size() >= 1 &&
					     (line[0] == '$' ||
					      line[0] == '+' ||
					      line[0] == '*')))
						current_section->lines.push_back(line);
					else
						current_section->Set(key, value);
				}
			}
		}
	}

	in.close();
	return true;
}
void VertexShaderCache::PrepareShader(u32 components, const XFMemory &xfr, const BPMemory &bpm, bool ongputhread)
{
	VertexShaderUid uid;
	GetVertexShaderUID(uid, components, xfr, bpm);
	if (ongputhread)
	{
		Compiler->ProcCompilationResults();
#if defined(_DEBUG) || defined(DEBUGFAST)
		if (g_ActiveConfig.bEnableShaderDebugging)
		{
			ShaderCode code;
			GenerateVertexShaderCodeD3D9(code, uid.GetUidData());
		}
#endif
		if (last_entry)
		{
			if (uid == last_uid)
			{
				return;
			}
		}
		last_uid = uid;
		GFX_DEBUGGER_PAUSE_AT(NEXT_VERTEX_SHADER_CHANGE, true);
	}
	else
	{
		if (external_last_uid == uid)
		{
			return;
		}
		external_last_uid = uid;
	}
	vshaderslock.lock();
	VSCacheEntry *entry = &vshaders[uid];
	vshaderslock.unlock();
	if (ongputhread)
	{
		last_entry = entry;
	}
	// Compile only when we have a new instance
	if (entry->initialized.test_and_set())
	{
		return;
	}
	ShaderCompilerWorkUnit *wunit = Compiler->NewUnit(VERTEXSHADERGEN_BUFFERSIZE);
	wunit->GenerateCodeHandler = [uid](ShaderCompilerWorkUnit* wunit)
	{
		ShaderCode code;
		code.SetBuffer(wunit->code.data());
		GenerateVertexShaderCodeD3D9(code, uid.GetUidData());
		wunit->codesize = (u32)code.BufferSize();
	};
	wunit->entrypoint = "main";
	wunit->flags = D3DCOMPILE_SKIP_VALIDATION | D3DCOMPILE_OPTIMIZATION_LEVEL3;
	wunit->target = D3D::VertexShaderVersionString();
	wunit->ResultHandler = [uid, entry](ShaderCompilerWorkUnit* wunit)
	{
		if (SUCCEEDED(wunit->cresult))
		{
			ID3DBlob* shaderBuffer = wunit->shaderbytecode;
			const u8* bytecode = (const u8*)shaderBuffer->GetBufferPointer();
			u32 bytecodelen = (u32)shaderBuffer->GetBufferSize();
			g_vs_disk_cache.Append(uid, bytecode, bytecodelen);
			PushByteCode(uid, bytecode, bytecodelen, entry);
#if defined(_DEBUG) || defined(DEBUGFAST)
			if (g_ActiveConfig.bEnableShaderDebugging)
			{
				entry->code = wunit->code.data();
			}
#endif
		}
		else
		{
			static int num_failures = 0;
			std::string filename = StringFromFormat("%sbad_vs_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), num_failures++);
			std::ofstream file;
			OpenFStream(file, filename, std::ios_base::out);
			file << ((const char*)wunit->code.data());
			file << ((const char*)wunit->error->GetBufferPointer());
			file.close();

			PanicAlert("Failed to compile vertex shader!\nThis usually happens when trying to use Dolphin with an outdated GPU or integrated GPU like the Intel GMA series.\n\nIf you're sure this is Dolphin's error anyway, post the contents of %s along with this error message at the forums.\n\nDebug info (%s):\n%s",
				filename,
				D3D::VertexShaderVersionString(),
				(char*)wunit->error->GetBufferPointer());
		}
	};
	Compiler->CompileShaderAsync(wunit);
}