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); }
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(); }
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()); }
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); }
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; }
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(); }
// 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; }
// 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); }
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; }
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); }
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); }
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); }
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); }