void StateCache::LoadFromDisk() { std::string cache_filename = GetDiskShaderCacheFileName(API_D3D11, "pso", true, true); PipelineStateCacheInserter inserter; s_pso_disk_cache.OpenAndRead(cache_filename, inserter); if (s_cache_is_corrupted) { // If a PSO fails to create, that means either: // - The file itself is corrupt. // - A driver/HW change has occured, causing the existing cache blobs to be invalid. // // In either case, we want to re-create the disk cache. This should not be a frequent occurence. s_pso_disk_cache.Close(); s_gx_state_cache.m_small_pso_map.clear(); File::Delete(cache_filename); s_pso_disk_cache.OpenAndRead(cache_filename, inserter); s_cache_is_corrupted = false; } }
void VertexShaderCache::LoadShaderCache() { VertexShaderCacheInserter<VertexShaderUid> inserter; g_vs_disk_cache.OpenAndRead(GetDiskShaderCacheFileName(APIType::D3D, "VS", true, true), inserter); VertexShaderCacheInserter<UberShader::VertexShaderUid> uber_inserter; g_uber_vs_disk_cache.OpenAndRead(GetDiskShaderCacheFileName(APIType::D3D, "UberVS", false, true), uber_inserter); }
void VertexShaderCache::Init() { const D3D11_INPUT_ELEMENT_DESC simpleelems[2] = { {"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0}, {"TEXCOORD", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0}, }; const D3D11_INPUT_ELEMENT_DESC clearelems[2] = { {"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0}, {"COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0}, }; unsigned int cbsize = ROUND_UP(sizeof(VertexShaderConstants), 16); // must be a multiple of 16 D3D11_BUFFER_DESC cbdesc = CD3D11_BUFFER_DESC(cbsize, D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE); HRESULT hr = D3D::device->CreateBuffer(&cbdesc, nullptr, &vscbuf); CHECK(hr == S_OK, "Create vertex shader constant buffer (size=%u)", cbsize); D3D::SetDebugObjectName((ID3D11DeviceChild*)vscbuf, "vertex shader constant buffer used to emulate the GX pipeline"); D3DBlob* blob; D3D::CompileVertexShader(simple_shader_code, &blob); D3D::device->CreateInputLayout(simpleelems, 2, blob->Data(), blob->Size(), &SimpleLayout); SimpleVertexShader = D3D::CreateVertexShaderFromByteCode(blob); if (SimpleLayout == nullptr || SimpleVertexShader == nullptr) PanicAlert("Failed to create simple vertex shader or input layout at %s %d\n", __FILE__, __LINE__); blob->Release(); D3D::SetDebugObjectName((ID3D11DeviceChild*)SimpleVertexShader, "simple vertex shader"); D3D::SetDebugObjectName((ID3D11DeviceChild*)SimpleLayout, "simple input layout"); D3D::CompileVertexShader(clear_shader_code, &blob); D3D::device->CreateInputLayout(clearelems, 2, blob->Data(), blob->Size(), &ClearLayout); ClearVertexShader = D3D::CreateVertexShaderFromByteCode(blob); if (ClearLayout == nullptr || ClearVertexShader == nullptr) PanicAlert("Failed to create clear vertex shader or input layout at %s %d\n", __FILE__, __LINE__); blob->Release(); D3D::SetDebugObjectName((ID3D11DeviceChild*)ClearVertexShader, "clear vertex shader"); D3D::SetDebugObjectName((ID3D11DeviceChild*)ClearLayout, "clear input layout"); Clear(); if (!File::Exists(File::GetUserPath(D_SHADERCACHE_IDX))) File::CreateDir(File::GetUserPath(D_SHADERCACHE_IDX)); SETSTAT(stats.numVertexShadersCreated, 0); SETSTAT(stats.numVertexShadersAlive, 0); std::string cache_filename = StringFromFormat("%sdx11-%s-vs.cache", File::GetUserPath(D_SHADERCACHE_IDX).c_str(), SConfig::GetInstance().m_strUniqueID.c_str()); VertexShaderCacheInserter inserter; g_vs_disk_cache.OpenAndRead(cache_filename, inserter); if (g_Config.bEnableShaderDebugging) Clear(); last_entry = nullptr; }
void GeometryShaderCache::Init() { unsigned int gbsize = ROUND_UP(sizeof(GeometryShaderConstants), 16); // must be a multiple of 16 D3D11_BUFFER_DESC gbdesc = CD3D11_BUFFER_DESC(gbsize, D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE); HRESULT hr = D3D::device->CreateBuffer(&gbdesc, nullptr, &gscbuf); CHECK(hr == S_OK, "Create geometry shader constant buffer (size=%u)", gbsize); D3D::SetDebugObjectName((ID3D11DeviceChild*)gscbuf, "geometry shader constant buffer used to emulate the GX pipeline"); // used when drawing clear quads ClearGeometryShader = D3D::CompileAndCreateGeometryShader(clear_shader_code); CHECK(ClearGeometryShader != nullptr, "Create clear geometry shader"); D3D::SetDebugObjectName((ID3D11DeviceChild*)ClearGeometryShader, "clear geometry shader"); // used for buffer copy CopyGeometryShader = D3D::CompileAndCreateGeometryShader(copy_shader_code); CHECK(CopyGeometryShader != nullptr, "Create copy geometry shader"); D3D::SetDebugObjectName((ID3D11DeviceChild*)CopyGeometryShader, "copy geometry shader"); Clear(); if (!File::Exists(File::GetUserPath(D_SHADERCACHE_IDX))) File::CreateDir(File::GetUserPath(D_SHADERCACHE_IDX)); std::string cache_filename = StringFromFormat("%sdx11-%s-gs.cache", File::GetUserPath(D_SHADERCACHE_IDX).c_str(), SConfig::GetInstance().m_strUniqueID.c_str()); GeometryShaderCacheInserter inserter; g_gs_disk_cache.OpenAndRead(cache_filename, inserter); if (g_Config.bEnableShaderDebugging) Clear(); last_entry = nullptr; }
void StateCache::Init() { // Root signature isn't available at time of StateCache construction, so fill it in now. gx_state_cache.m_current_pso_desc.pRootSignature = D3D::default_root_signature; // Multi-sample configuration isn't available at time of StateCache construction, so fille it in // now. gx_state_cache.m_current_pso_desc.SampleDesc.Count = g_ActiveConfig.iMultisamples; gx_state_cache.m_current_pso_desc.SampleDesc.Quality = 0; if (!File::Exists(File::GetUserPath(D_SHADERCACHE_IDX))) File::CreateDir(File::GetUserPath(D_SHADERCACHE_IDX)); std::string cache_filename = StringFromFormat("%sdx12-%s-pso.cache", File::GetUserPath(D_SHADERCACHE_IDX).c_str(), SConfig::GetInstance().m_strUniqueID.c_str()); PipelineStateCacheInserter inserter; s_pso_disk_cache.OpenAndRead(cache_filename, inserter); if (s_cache_is_corrupted) { // If a PSO fails to create, that means either: // - The file itself is corrupt. // - A driver/HW change has occurred, causing the existing cache blobs to be invalid. // // In either case, we want to re-create the disk cache. This should not be a frequent occurence. s_pso_disk_cache.Close(); for (auto it : gx_state_cache.m_small_pso_map) { SAFE_RELEASE(it.second); } gx_state_cache.m_small_pso_map.clear(); File::Delete(cache_filename); s_pso_disk_cache.OpenAndRead(cache_filename, inserter); s_cache_is_corrupted = false; } }
void ProgramShaderCache::Init(void) { // We have to get the UBO alignment here because // if we generate a buffer that isn't aligned // then the UBO will fail. if (g_ActiveConfig.backend_info.bSupportsGLSLUBO) { GLint Align; glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &Align); s_ps_data_size = C_PENVCONST_END * sizeof(float) * 4; s_vs_data_size = C_VENVCONST_END * sizeof(float) * 4; s_vs_data_offset = ROUND_UP(s_ps_data_size, Align); s_ubo_buffer_size = ROUND_UP(s_ps_data_size, Align) + ROUND_UP(s_vs_data_size, Align); // We multiply by *4*4 because we need to get down to basic machine units. // So multiply by four to get how many floats we have from vec4s // Then once more to get bytes s_buffer = new StreamBuffer(GL_UNIFORM_BUFFER, UBO_LENGTH); s_ubo_buffer = new u8[s_ubo_buffer_size]; memset(s_ubo_buffer, 0, s_ubo_buffer_size); s_ubo_dirty = true; } // Read our shader cache, only if supported if (g_ogl_config.bSupportsGLSLCache) { GLint Supported; glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &Supported); if(!Supported) { ERROR_LOG(VIDEO, "GL_ARB_get_program_binary is supported, but no binary format is known. So disable shader cache."); g_ogl_config.bSupportsGLSLCache = false; } else { if (!File::Exists(File::GetUserPath(D_SHADERCACHE_IDX))) File::CreateDir(File::GetUserPath(D_SHADERCACHE_IDX).c_str()); char cache_filename[MAX_PATH]; sprintf(cache_filename, "%sogl-%s-shaders.cache", File::GetUserPath(D_SHADERCACHE_IDX).c_str(), SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str()); ProgramShaderCacheInserter inserter; g_program_disk_cache.OpenAndRead(cache_filename, inserter); } SETSTAT(stats.numPixelShadersAlive, pshaders.size()); } CreateHeader(); CurrentProgram = 0; last_entry = NULL; }
void ShaderCache::Init() { // This class intentionally shares its shader cache files with DX11, as the shaders are (right // now) identical. // Reduces unnecessary compilation when switching between APIs. s_last_geometry_shader_bytecode = {}; s_last_pixel_shader_bytecode = {}; s_last_vertex_shader_bytecode = {}; s_last_geometry_shader_uid = {}; s_last_pixel_shader_uid = {}; s_last_vertex_shader_uid = {}; // Ensure shader cache directory exists.. std::string shader_cache_path = File::GetUserPath(D_SHADERCACHE_IDX); if (!File::Exists(shader_cache_path)) File::CreateDir(File::GetUserPath(D_SHADERCACHE_IDX)); std::string title_game_id = SConfig::GetInstance().m_strGameID.c_str(); std::string gs_cache_filename = StringFromFormat("%sdx11-%s-gs.cache", shader_cache_path.c_str(), title_game_id.c_str()); std::string ps_cache_filename = StringFromFormat("%sdx11-%s-ps.cache", shader_cache_path.c_str(), title_game_id.c_str()); std::string vs_cache_filename = StringFromFormat("%sdx11-%s-vs.cache", shader_cache_path.c_str(), title_game_id.c_str()); ShaderCacheInserter<GeometryShaderUid, GsBytecodeCache, &s_gs_bytecode_cache> gs_inserter; s_gs_disk_cache.OpenAndRead(gs_cache_filename, gs_inserter); ShaderCacheInserter<PixelShaderUid, PsBytecodeCache, &s_ps_bytecode_cache> ps_inserter; s_ps_disk_cache.OpenAndRead(ps_cache_filename, ps_inserter); ShaderCacheInserter<VertexShaderUid, VsBytecodeCache, &s_vs_bytecode_cache> vs_inserter; s_vs_disk_cache.OpenAndRead(vs_cache_filename, vs_inserter); SETSTAT(stats.numPixelShadersAlive, static_cast<int>(s_ps_bytecode_cache.size())); SETSTAT(stats.numPixelShadersCreated, static_cast<int>(s_ps_bytecode_cache.size())); SETSTAT(stats.numVertexShadersAlive, static_cast<int>(s_vs_bytecode_cache.size())); SETSTAT(stats.numVertexShadersCreated, static_cast<int>(s_vs_bytecode_cache.size())); }
void PixelShaderCache::Init() { unsigned int cbsize = Common::AlignUp(static_cast<unsigned int>(sizeof(PixelShaderConstants)), 16); // must be a multiple of 16 D3D11_BUFFER_DESC cbdesc = CD3D11_BUFFER_DESC(cbsize, D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE); D3D::device->CreateBuffer(&cbdesc, nullptr, &pscbuf); CHECK(pscbuf != nullptr, "Create pixel shader constant buffer"); D3D::SetDebugObjectName((ID3D11DeviceChild*)pscbuf, "pixel shader constant buffer used to emulate the GX pipeline"); // used when drawing clear quads s_ClearProgram = D3D::CompileAndCreatePixelShader(clear_program_code); CHECK(s_ClearProgram != nullptr, "Create clear pixel shader"); D3D::SetDebugObjectName((ID3D11DeviceChild*)s_ClearProgram, "clear pixel shader"); // used for anaglyph stereoscopy s_AnaglyphProgram = D3D::CompileAndCreatePixelShader(anaglyph_program_code); CHECK(s_AnaglyphProgram != nullptr, "Create anaglyph pixel shader"); D3D::SetDebugObjectName((ID3D11DeviceChild*)s_AnaglyphProgram, "anaglyph pixel shader"); // used when copying/resolving the color buffer s_ColorCopyProgram[0] = D3D::CompileAndCreatePixelShader(color_copy_program_code); CHECK(s_ColorCopyProgram[0] != nullptr, "Create color copy pixel shader"); D3D::SetDebugObjectName((ID3D11DeviceChild*)s_ColorCopyProgram[0], "color copy pixel shader"); // used for color conversion s_ColorMatrixProgram[0] = D3D::CompileAndCreatePixelShader(color_matrix_program_code); CHECK(s_ColorMatrixProgram[0] != nullptr, "Create color matrix pixel shader"); D3D::SetDebugObjectName((ID3D11DeviceChild*)s_ColorMatrixProgram[0], "color matrix pixel shader"); // used for depth copy s_DepthMatrixProgram[0] = D3D::CompileAndCreatePixelShader(depth_matrix_program); CHECK(s_DepthMatrixProgram[0] != nullptr, "Create depth matrix pixel shader"); D3D::SetDebugObjectName((ID3D11DeviceChild*)s_DepthMatrixProgram[0], "depth matrix pixel shader"); Clear(); if (!File::Exists(File::GetUserPath(D_SHADERCACHE_IDX))) File::CreateDir(File::GetUserPath(D_SHADERCACHE_IDX)); SETSTAT(stats.numPixelShadersCreated, 0); SETSTAT(stats.numPixelShadersAlive, 0); std::string cache_filename = StringFromFormat("%sdx11-%s-ps.cache", File::GetUserPath(D_SHADERCACHE_IDX).c_str(), SConfig::GetInstance().m_strGameID.c_str()); PixelShaderCacheInserter inserter; g_ps_disk_cache.OpenAndRead(cache_filename, inserter); last_entry = nullptr; }
void PixelShaderCache::Init() { unsigned int cbsize = ((sizeof(PixelShaderConstants))&(~0xf))+0x10; // must be a multiple of 16 D3D11_BUFFER_DESC cbdesc = CD3D11_BUFFER_DESC(cbsize, D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE); D3D::device->CreateBuffer(&cbdesc, NULL, &pscbuf); CHECK(pscbuf!=NULL, "Create pixel shader constant buffer"); D3D::SetDebugObjectName((ID3D11DeviceChild*)pscbuf, "pixel shader constant buffer used to emulate the GX pipeline"); // used when drawing clear quads s_ClearProgram = D3D::CompileAndCreatePixelShader(clear_program_code, sizeof(clear_program_code)); CHECK(s_ClearProgram!=NULL, "Create clear pixel shader"); D3D::SetDebugObjectName((ID3D11DeviceChild*)s_ClearProgram, "clear pixel shader"); // used when copying/resolving the color buffer s_ColorCopyProgram[0] = D3D::CompileAndCreatePixelShader(color_copy_program_code, sizeof(color_copy_program_code)); CHECK(s_ColorCopyProgram[0]!=NULL, "Create color copy pixel shader"); D3D::SetDebugObjectName((ID3D11DeviceChild*)s_ColorCopyProgram[0], "color copy pixel shader"); // used for color conversion s_ColorMatrixProgram[0] = D3D::CompileAndCreatePixelShader(color_matrix_program_code, sizeof(color_matrix_program_code)); CHECK(s_ColorMatrixProgram[0]!=NULL, "Create color matrix pixel shader"); D3D::SetDebugObjectName((ID3D11DeviceChild*)s_ColorMatrixProgram[0], "color matrix pixel shader"); // used for depth copy s_DepthMatrixProgram[0] = D3D::CompileAndCreatePixelShader(depth_matrix_program, sizeof(depth_matrix_program)); CHECK(s_DepthMatrixProgram[0]!=NULL, "Create depth matrix pixel shader"); D3D::SetDebugObjectName((ID3D11DeviceChild*)s_DepthMatrixProgram[0], "depth matrix pixel shader"); Clear(); if (!File::Exists(File::GetUserPath(D_SHADERCACHE_IDX))) File::CreateDir(File::GetUserPath(D_SHADERCACHE_IDX).c_str()); SETSTAT(stats.numPixelShadersCreated, 0); SETSTAT(stats.numPixelShadersAlive, 0); char cache_filename[MAX_PATH]; sprintf(cache_filename, "%sdx11-%s-ps.cache", File::GetUserPath(D_SHADERCACHE_IDX).c_str(), SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str()); PixelShaderCacheInserter inserter; g_ps_disk_cache.OpenAndRead(cache_filename, inserter); if (g_Config.bEnableShaderDebugging) Clear(); last_entry = NULL; }
void ProgramShaderCache::Init() { // We have to get the UBO alignment here because // if we generate a buffer that isn't aligned // then the UBO will fail. glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &s_ubo_align); s_ubo_buffer_size = ROUND_UP(PixelShaderManager::ConstantBufferSize * sizeof(float), s_ubo_align) + ROUND_UP(VertexShaderManager::ConstantBufferSize * sizeof(float), s_ubo_align) + ROUND_UP(sizeof(GeometryShaderConstants), s_ubo_align); // We multiply by *4*4 because we need to get down to basic machine units. // So multiply by four to get how many floats we have from vec4s // Then once more to get bytes s_buffer = StreamBuffer::Create(GL_UNIFORM_BUFFER, UBO_LENGTH); // Read our shader cache, only if supported if (g_ogl_config.bSupportsGLSLCache && !g_Config.bEnableShaderDebugging) { GLint Supported; glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &Supported); if (!Supported) { ERROR_LOG(VIDEO, "GL_ARB_get_program_binary is supported, but no binary format is known. So disable shader cache."); g_ogl_config.bSupportsGLSLCache = false; } else { if (!File::Exists(File::GetUserPath(D_SHADERCACHE_IDX))) File::CreateDir(File::GetUserPath(D_SHADERCACHE_IDX)); std::string cache_filename = StringFromFormat("%sIOGL-%s-shaders.cache", File::GetUserPath(D_SHADERCACHE_IDX).c_str(), SConfig::GetInstance().m_strUniqueID.c_str()); ProgramShaderCacheInserter inserter; g_program_disk_cache.OpenAndRead(cache_filename, inserter); } SETSTAT(stats.numPixelShadersAlive, pshaders.size()); } CreateHeader(); CurrentProgram = 0; last_entry = nullptr; }
void GeometryShaderCache::Init() { unsigned int gscbuf12sizeInBytes = gscbuf12paddedSize * gscbuf12Slots; CheckHR( D3D::device12->CreateCommittedResource( &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD), D3D12_HEAP_FLAG_NONE, &CD3DX12_RESOURCE_DESC::Buffer(gscbuf12sizeInBytes), D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(&gscbuf12) ) ); D3D::SetDebugObjectName12(gscbuf12, "vertex shader constant buffer used to emulate the GX pipeline"); // Obtain persistent CPU pointer to GS Constant Buffer CheckHR(gscbuf12->Map(0, nullptr, &gscbuf12data)); // used when drawing clear quads D3D::CompileGeometryShader(clear_shader_code, &ClearGeometryShaderBlob); // used for buffer copy D3D::CompileGeometryShader(copy_shader_code, &CopyGeometryShaderBlob); Clear(); if (!File::Exists(File::GetUserPath(D_SHADERCACHE_IDX))) File::CreateDir(File::GetUserPath(D_SHADERCACHE_IDX)); // Intentionally share the same cache as DX11, as the shaders are identical. Reduces recompilation when switching APIs. std::string cache_filename = StringFromFormat("%sdx11-%s-gs.cache", File::GetUserPath(D_SHADERCACHE_IDX).c_str(), SConfig::GetInstance().m_strUniqueID.c_str()); GeometryShaderCacheInserter inserter; g_gs_disk_cache.OpenAndRead(cache_filename, inserter); if (g_Config.bEnableShaderDebugging) Clear(); last_entry = nullptr; last_uid = {}; }
void VertexShaderCache::Init() { Compiler = &HLSLAsyncCompiler::getInstance(); vshaderslock.unlock(); const char* code = "struct VSOUTPUT\n" "{\n" "float4 vPosition : POSITION;\n" "float2 vTexCoord : TEXCOORD0;\n" "float vTexCoord1 : TEXCOORD1;\n" "};\n" "VSOUTPUT main(float4 inPosition : POSITION,float2 inTEX0 : TEXCOORD0,float2 inTEX1 : TEXCOORD1,float inTEX2 : TEXCOORD2)\n" "{\n" "VSOUTPUT OUT;\n" "OUT.vPosition = inPosition;\n" "OUT.vTexCoord = inTEX0;\n" "OUT.vTexCoord1 = inTEX2;\n" "return OUT;\n" "}\0"; SimpleVertexShader[0] = D3D::CompileAndCreateVertexShader(code, (int)strlen(code)); code = "struct VSOUTPUT\n" "{\n" "float4 vPosition : POSITION;\n" "float4 vColor0 : COLOR0;\n" "};\n" "VSOUTPUT main(float4 inPosition : POSITION,float4 inColor0: COLOR0)\n" "{\n" "VSOUTPUT OUT;\n" "OUT.vPosition = inPosition;\n" "OUT.vColor0 = inColor0;\n" "return OUT;\n" "}\0"; ClearVertexShader = D3D::CompileAndCreateVertexShader(code, (int)strlen(code)); code = "struct VSOUTPUT\n" "{\n" "float4 vPosition : POSITION;\n" "float4 vTexCoord : TEXCOORD0;\n" "float vTexCoord1 : TEXCOORD1;\n" "float4 vTexCoord2 : TEXCOORD2;\n" "float4 vTexCoord3 : TEXCOORD3;\n" "};\n" "VSOUTPUT main(float4 inPosition : POSITION,float2 inTEX0 : TEXCOORD0,float2 inTEX1 : TEXCOORD1,float inTEX2 : TEXCOORD2)\n" "{\n" "VSOUTPUT OUT;" "OUT.vPosition = inPosition;\n" "OUT.vTexCoord = inTEX0.xyyx;\n" "OUT.vTexCoord1 = inTEX2.x;\n" "OUT.vTexCoord2 = inTEX0.xyyx + (float4(-0.375f,-0.125f,-0.375f, 0.125f) * inTEX1.xyyx);\n" "OUT.vTexCoord3 = inTEX0.xyyx + (float4( 0.375f, 0.125f, 0.375f,-0.125f) * inTEX1.xyyx);\n" "return OUT;\n" "}\0"; SimpleVertexShader[1] = D3D::CompileAndCreateVertexShader(code, (int)strlen(code)); Clear(); if (!File::Exists(File::GetUserPath(D_SHADERCACHE_IDX))) File::CreateDir(File::GetUserPath(D_SHADERCACHE_IDX).c_str()); SETSTAT(stats.numVertexShadersCreated, 0); SETSTAT(stats.numVertexShadersAlive, 0); char cache_filename[MAX_PATH]; sprintf(cache_filename, "%sIDX9-%s-vs.cache", File::GetUserPath(D_SHADERCACHE_IDX).c_str(), SConfig::GetInstance().m_strUniqueID.c_str()); VertexShaderCacheInserter inserter; vshaderslock.lock(); g_vs_disk_cache.OpenAndRead(cache_filename, inserter); vshaderslock.unlock(); if (g_Config.bEnableShaderDebugging) Clear(); last_entry = NULL; }
void GeometryShaderCache::LoadShaderCache() { GeometryShaderCacheInserter inserter; g_gs_disk_cache.OpenAndRead(GetDiskShaderCacheFileName(APIType::D3D, "GS", true, true), inserter); }
void VertexShaderCache::Init() { char* vProg = new char[2048]; sprintf(vProg,"struct VSOUTPUT\n" "{\n" "float4 vPosition : POSITION;\n" "float2 vTexCoord : TEXCOORD0;\n" "float vTexCoord1 : TEXCOORD1;\n" "};\n" "VSOUTPUT main(float4 inPosition : POSITION,float2 inTEX0 : TEXCOORD0,float2 inTEX1 : TEXCOORD1,float inTEX2 : TEXCOORD2)\n" "{\n" "VSOUTPUT OUT;\n" "OUT.vPosition = inPosition;\n" "OUT.vTexCoord = inTEX0;\n" "OUT.vTexCoord1 = inTEX2;\n" "return OUT;\n" "}\n"); SimpleVertexShader[0] = D3D::CompileAndCreateVertexShader(vProg, (int)strlen(vProg)); sprintf(vProg,"struct VSOUTPUT\n" "{\n" "float4 vPosition : POSITION;\n" "float4 vColor0 : COLOR0;\n" "};\n" "VSOUTPUT main(float4 inPosition : POSITION,float4 inColor0: COLOR0)\n" "{\n" "VSOUTPUT OUT;\n" "OUT.vPosition = inPosition;\n" "OUT.vColor0 = inColor0;\n" "return OUT;\n" "}\n"); ClearVertexShader = D3D::CompileAndCreateVertexShader(vProg, (int)strlen(vProg)); sprintf(vProg, "struct VSOUTPUT\n" "{\n" "float4 vPosition : POSITION;\n" "float2 vTexCoord : TEXCOORD0;\n" "float vTexCoord1 : TEXCOORD1;\n" "};\n" "VSOUTPUT main(float4 inPosition : POSITION,float2 inTEX0 : TEXCOORD0,float2 inInvTexSize : TEXCOORD1,float inTEX2 : TEXCOORD2)\n" "{\n" "VSOUTPUT OUT;" "OUT.vPosition = inPosition;\n" // HACK: Scale the texture coordinate range from (0,width) to (0,width-1), otherwise the linear filter won't average our samples correctly "OUT.vTexCoord = inTEX0 * (float2(1.f,1.f) / inInvTexSize - float2(1.f,1.f)) * inInvTexSize;\n" "OUT.vTexCoord1 = inTEX2;\n" "return OUT;\n" "}\n"); SimpleVertexShader[1] = D3D::CompileAndCreateVertexShader(vProg, (int)strlen(vProg)); sprintf(vProg, "struct VSOUTPUT\n" "{\n" "float4 vPosition : POSITION;\n" "float4 vTexCoord : TEXCOORD0;\n" "float vTexCoord1 : TEXCOORD1;\n" "float4 vTexCoord2 : TEXCOORD2;\n" "float4 vTexCoord3 : TEXCOORD3;\n" "};\n" "VSOUTPUT main(float4 inPosition : POSITION,float2 inTEX0 : TEXCOORD0,float2 inTEX1 : TEXCOORD1,float inTEX2 : TEXCOORD2)\n" "{\n" "VSOUTPUT OUT;" "OUT.vPosition = inPosition;\n" "OUT.vTexCoord = inTEX0.xyyx;\n" "OUT.vTexCoord1 = inTEX2.x;\n" "OUT.vTexCoord2 = inTEX0.xyyx + (float4(-1.0f,-0.5f, 1.0f,-0.5f) * inTEX1.xyyx);\n" "OUT.vTexCoord3 = inTEX0.xyyx + (float4( 1.0f, 0.5f,-1.0f, 0.5f) * inTEX1.xyyx);\n" "return OUT;\n" "}\n"); SimpleVertexShader[2] = D3D::CompileAndCreateVertexShader(vProg, (int)strlen(vProg)); Clear(); delete [] vProg; if (!File::Exists(File::GetUserPath(D_SHADERCACHE_IDX))) File::CreateDir(File::GetUserPath(D_SHADERCACHE_IDX).c_str()); SETSTAT(stats.numVertexShadersCreated, 0); SETSTAT(stats.numVertexShadersAlive, 0); char cache_filename[MAX_PATH]; sprintf(cache_filename, "%sdx9-%s-vs.cache", File::GetUserPath(D_SHADERCACHE_IDX).c_str(), SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str()); VertexShaderCacheInserter inserter; g_vs_disk_cache.OpenAndRead(cache_filename, inserter); }
void ShaderCache::Init() { s_compiler = &HLSLAsyncCompiler::getInstance(); s_shaders_lock.unlock(); s_pass_entry.m_compiled = true; s_pass_entry.m_initialized.test_and_set(); // This class intentionally shares its shader cache files with DX11, as the shaders are (right now) identical. // Reduces unnecessary compilation when switching between APIs. s_last_domain_shader_bytecode = &s_pass_entry; s_last_hull_shader_bytecode = &s_pass_entry; s_last_geometry_shader_bytecode = &s_pass_entry; s_last_pixel_shader_bytecode = nullptr; s_last_vertex_shader_bytecode = nullptr; s_last_geometry_shader_uid = {}; s_last_pixel_shader_uid = {}; s_last_vertex_shader_uid = {}; s_last_tessellation_shader_uid = {}; s_last_cpu_geometry_shader_uid = {}; s_last_cpu_pixel_shader_uid = {}; s_last_cpu_vertex_shader_uid = {}; s_last_cpu_tessellation_shader_uid = {}; // Ensure shader cache directory exists.. std::string shader_cache_path = File::GetUserPath(D_SHADERCACHE_IDX); if (!File::Exists(shader_cache_path)) File::CreateDir(File::GetUserPath(D_SHADERCACHE_IDX)); std::string title_unique_id = SConfig::GetInstance().m_strGameID; std::string ds_cache_filename = StringFromFormat("%sIDX11-%s-ds.cache", shader_cache_path.c_str(), title_unique_id.c_str()); std::string hs_cache_filename = StringFromFormat("%sIDX11-%s-hs.cache", shader_cache_path.c_str(), title_unique_id.c_str()); std::string gs_cache_filename = StringFromFormat("%sIDX11-%s-gs.cache", shader_cache_path.c_str(), title_unique_id.c_str()); std::string ps_cache_filename = StringFromFormat("%sIDX11-%s-ps.cache", shader_cache_path.c_str(), title_unique_id.c_str()); std::string vs_cache_filename = StringFromFormat("%sIDX11-%s-vs.cache", shader_cache_path.c_str(), title_unique_id.c_str()); pKey_t gameid = (pKey_t)GetMurmurHash3(reinterpret_cast<const u8*>(SConfig::GetInstance().m_strGameID.data()), (u32)SConfig::GetInstance().m_strGameID.size(), 0); vs_bytecode_cache = VsBytecodeCache::Create( gameid, VERTEXSHADERGEN_UID_VERSION, "Ishiiruka.vs", StringFromFormat("%s.vs", title_unique_id.c_str()) ); ps_bytecode_cache = PsBytecodeCache::Create( gameid, PIXELSHADERGEN_UID_VERSION, "Ishiiruka.ps", StringFromFormat("%s.ps", title_unique_id.c_str()) ); gs_bytecode_cache = GsBytecodeCache::Create( gameid, GEOMETRYSHADERGEN_UID_VERSION, "Ishiiruka.gs", StringFromFormat("%s.gs", title_unique_id.c_str()) ); ts_bytecode_cache = TsBytecodeCache::Create( gameid, TESSELLATIONSHADERGEN_UID_VERSION, "Ishiiruka.ts", StringFromFormat("%s.ts", title_unique_id.c_str()) ); DShaderCacheInserter ds_inserter; s_ds_disk_cache.OpenAndRead(ds_cache_filename, ds_inserter); HShaderCacheInserter hs_inserter; s_hs_disk_cache.OpenAndRead(hs_cache_filename, hs_inserter); ShaderCacheInserter<GeometryShaderUid, GsBytecodeCache, &gs_bytecode_cache> gs_inserter; s_gs_disk_cache.OpenAndRead(gs_cache_filename, gs_inserter); ShaderCacheInserter<PixelShaderUid, PsBytecodeCache, &ps_bytecode_cache> ps_inserter; s_ps_disk_cache.OpenAndRead(ps_cache_filename, ps_inserter); ShaderCacheInserter<VertexShaderUid, VsBytecodeCache, &vs_bytecode_cache> vs_inserter; s_vs_disk_cache.OpenAndRead(vs_cache_filename, vs_inserter); // Clear out disk cache when debugging shaders to ensure stale ones don't stick around.. SETSTAT(stats.numGeometryShadersAlive, static_cast<int>(gs_bytecode_cache->size())); SETSTAT(stats.numGeometryShadersCreated, 0); SETSTAT(stats.numPixelShadersAlive, static_cast<int>(ps_bytecode_cache->size())); SETSTAT(stats.numPixelShadersCreated, 0); SETSTAT(stats.numVertexShadersAlive, static_cast<int>(vs_bytecode_cache->size())); SETSTAT(stats.numVertexShadersCreated, 0); if (g_ActiveConfig.bCompileShaderOnStartup) { size_t shader_count = 0; ps_bytecode_cache->ForEachMostUsedByCategory(gameid, [&](const PixelShaderUid& it, size_t total) { PixelShaderUid item = it; item.ClearHASH(); item.CalculateUIDHash(); HandlePSUIDChange(item, true); shader_count++; if ((shader_count & 7) == 0) { Host_UpdateTitle(StringFromFormat("Compiling Pixel Shaders %i %% (%i/%i)", (shader_count * 100) / total, shader_count, total)); s_compiler->WaitForFinish(); } }, [](ByteCodeCacheEntry& entry) { return !entry.m_shader_bytecode.pShaderBytecode; } , true); shader_count = 0; vs_bytecode_cache->ForEachMostUsedByCategory(gameid, [&](const VertexShaderUid& it, size_t total) { VertexShaderUid item = it; item.ClearHASH(); item.CalculateUIDHash(); HandleVSUIDChange(item, true); shader_count++; if ((shader_count & 31) == 0) { Host_UpdateTitle(StringFromFormat("Compiling Vertex Shaders %i %% (%i/%i)", (shader_count * 100) / total, shader_count, total)); s_compiler->WaitForFinish(); } }, [](ByteCodeCacheEntry& entry) { return !entry.m_shader_bytecode.pShaderBytecode; } , true); shader_count = 0; gs_bytecode_cache->ForEachMostUsedByCategory(gameid, [&](const GeometryShaderUid& it, size_t total) { GeometryShaderUid item = it; item.ClearHASH(); item.CalculateUIDHash(); HandleGSUIDChange(item, true); shader_count++; if ((shader_count & 7) == 0) { Host_UpdateTitle(StringFromFormat("Compiling Geometry Shaders %i %% (%i/%i)", (shader_count * 100) / total, shader_count, total)); s_compiler->WaitForFinish(); } }, [](ByteCodeCacheEntry& entry) { return !entry.m_shader_bytecode.pShaderBytecode; } , true); shader_count = 0; ts_bytecode_cache->ForEachMostUsedByCategory(gameid, [&](const TessellationShaderUid& it, size_t total) { TessellationShaderUid item = it; item.ClearHASH(); item.CalculateUIDHash(); HandleTSUIDChange(item, true); shader_count++; if ((shader_count & 31) == 0) { Host_UpdateTitle(StringFromFormat("Compiling Tessellation Shaders %i %% (%i/%i)", (shader_count * 100) / total, shader_count, total)); s_compiler->WaitForFinish(); } }, [](std::pair<ByteCodeCacheEntry, ByteCodeCacheEntry>& entry) { return !entry.first.m_shader_bytecode.pShaderBytecode; } , true); s_compiler->WaitForFinish(); } }
void VertexShaderCache::Init() { char* vProg = new char[2048]; sprintf(vProg,"struct VSOUTPUT\n" "{\n" "float4 vPosition : POSITION;\n" "float2 vTexCoord : TEXCOORD0;\n" "float vTexCoord1 : TEXCOORD1;\n" "};\n" "VSOUTPUT main(float4 inPosition : POSITION,float2 inTEX0 : TEXCOORD0,float2 inTEX1 : TEXCOORD1,float inTEX2 : TEXCOORD2)\n" "{\n" "VSOUTPUT OUT;\n" "OUT.vPosition = inPosition;\n" "OUT.vTexCoord = inTEX0;\n" "OUT.vTexCoord1 = inTEX2;\n" "return OUT;\n" "}\n"); SimpleVertexShader[0] = D3D::CompileAndCreateVertexShader(vProg, (int)strlen(vProg)); sprintf(vProg,"struct VSOUTPUT\n" "{\n" "float4 vPosition : POSITION;\n" "float4 vColor0 : COLOR0;\n" "};\n" "VSOUTPUT main(float4 inPosition : POSITION,float4 inColor0: COLOR0)\n" "{\n" "VSOUTPUT OUT;\n" "OUT.vPosition = inPosition;\n" "OUT.vColor0 = inColor0;\n" "return OUT;\n" "}\n"); ClearVertexShader = D3D::CompileAndCreateVertexShader(vProg, (int)strlen(vProg)); sprintf(vProg, "struct VSOUTPUT\n" "{\n" "float4 vPosition : POSITION;\n" "float4 vTexCoord : TEXCOORD0;\n" "float vTexCoord1 : TEXCOORD1;\n" "float4 vTexCoord2 : TEXCOORD2;\n" "float4 vTexCoord3 : TEXCOORD3;\n" "};\n" "VSOUTPUT main(float4 inPosition : POSITION,float2 inTEX0 : TEXCOORD0,float2 inTEX1 : TEXCOORD1,float inTEX2 : TEXCOORD2)\n" "{\n" "VSOUTPUT OUT;" "OUT.vPosition = inPosition;\n" "OUT.vTexCoord = inTEX0.xyyx;\n" "OUT.vTexCoord1 = inTEX2.x;\n" "OUT.vTexCoord2 = inTEX0.xyyx + (float4(-0.495f,-0.495f, 0.495f,-0.495f) * inTEX1.xyyx);\n" "OUT.vTexCoord3 = inTEX0.xyyx + (float4( 0.495f, 0.495f,-0.495f, 0.495f) * inTEX1.xyyx);\n" "return OUT;\n" "}\n"); SimpleVertexShader[1] = D3D::CompileAndCreateVertexShader(vProg, (int)strlen(vProg)); sprintf(vProg, "struct VSOUTPUT\n" "{\n" "float4 vPosition : POSITION;\n" "float4 vTexCoord : TEXCOORD0;\n" "float vTexCoord1 : TEXCOORD1;\n" "float4 vTexCoord2 : TEXCOORD2;\n" "float4 vTexCoord3 : TEXCOORD3;\n" "};\n" "VSOUTPUT main(float4 inPosition : POSITION,float2 inTEX0 : TEXCOORD0,float2 inTEX1 : TEXCOORD1,float inTEX2 : TEXCOORD2)\n" "{\n" "VSOUTPUT OUT;" "OUT.vPosition = inPosition;\n" "OUT.vTexCoord = inTEX0.xyyx;\n" "OUT.vTexCoord1 = inTEX2.x;\n" "OUT.vTexCoord2 = inTEX0.xyyx + (float4(-0.9f,-0.45f, 0.9f,-0.45f) * inTEX1.xyyx);\n" "OUT.vTexCoord3 = inTEX0.xyyx + (float4( 0.9f, 0.45f,-0.9f, 0.45f) * inTEX1.xyyx);\n" "return OUT;\n" "}\n"); SimpleVertexShader[2] = D3D::CompileAndCreateVertexShader(vProg, (int)strlen(vProg)); Clear(); delete [] vProg; if (!File::Exists(File::GetUserPath(D_SHADERCACHE_IDX))) File::CreateDir(File::GetUserPath(D_SHADERCACHE_IDX).c_str()); SETSTAT(stats.numVertexShadersCreated, 0); SETSTAT(stats.numVertexShadersAlive, 0); char cache_filename[MAX_PATH]; sprintf(cache_filename, "%sdx9-%s-vs.cache", File::GetUserPath(D_SHADERCACHE_IDX).c_str(), SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str()); VertexShaderCacheInserter inserter; g_vs_disk_cache.OpenAndRead(cache_filename, inserter); if (g_Config.bEnableShaderDebugging) Clear(); last_entry = NULL; }
void VertexShaderCache::Init() { const D3D11_INPUT_ELEMENT_DESC simpleelems[2] = { { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; const D3D11_INPUT_ELEMENT_DESC clearelems[2] = { { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; unsigned int cbsize = ((sizeof(vsconstants))&(~0xf))+0x10; // must be a multiple of 16 D3D11_BUFFER_DESC cbdesc = CD3D11_BUFFER_DESC(cbsize, D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE); HRESULT hr = D3D::device->CreateBuffer(&cbdesc, NULL, &vscbuf); CHECK(hr==S_OK, "Create vertex shader constant buffer (size=%u)", cbsize); D3D::SetDebugObjectName((ID3D11DeviceChild*)vscbuf, "vertex shader constant buffer used to emulate the GX pipeline"); D3DBlob* blob; D3D::CompileVertexShader(simple_shader_code, sizeof(simple_shader_code), &blob); D3D::device->CreateInputLayout(simpleelems, 2, blob->Data(), blob->Size(), &SimpleLayout); SimpleVertexShader = D3D::CreateVertexShaderFromByteCode(blob); if (SimpleLayout == NULL || SimpleVertexShader == NULL) PanicAlert("Failed to create simple vertex shader or input layout at %s %d\n", __FILE__, __LINE__); blob->Release(); D3D::SetDebugObjectName((ID3D11DeviceChild*)SimpleVertexShader, "simple vertex shader"); D3D::SetDebugObjectName((ID3D11DeviceChild*)SimpleLayout, "simple input layout"); D3D::CompileVertexShader(clear_shader_code, sizeof(clear_shader_code), &blob); D3D::device->CreateInputLayout(clearelems, 2, blob->Data(), blob->Size(), &ClearLayout); ClearVertexShader = D3D::CreateVertexShaderFromByteCode(blob); if (ClearLayout == NULL || ClearVertexShader == NULL) PanicAlert("Failed to create clear vertex shader or input layout at %s %d\n", __FILE__, __LINE__); blob->Release(); D3D::SetDebugObjectName((ID3D11DeviceChild*)ClearVertexShader, "clear vertex shader"); D3D::SetDebugObjectName((ID3D11DeviceChild*)ClearLayout, "clear input layout"); Clear(); // these values are hardcoded, they depend on internal D3DCompile behavior // TODO: Do this with D3DReflect or something instead unsigned int k; for (k = 0;k < 6;k++) vs_constant_offset_table[C_POSNORMALMATRIX+k] = 0+4*k; for (k = 0;k < 4;k++) vs_constant_offset_table[C_PROJECTION+k] = 24+4*k; for (k = 0;k < 4;k++) vs_constant_offset_table[C_MATERIALS+k] = 40+4*k; for (k = 0;k < 40;k++) vs_constant_offset_table[C_LIGHTS+k] = 56+4*k; for (k = 0;k < 24;k++) vs_constant_offset_table[C_TEXMATRICES+k] = 216+4*k; for (k = 0;k < 64;k++) vs_constant_offset_table[C_TRANSFORMMATRICES+k] = 312+4*k; for (k = 0;k < 32;k++) vs_constant_offset_table[C_NORMALMATRICES+k] = 568+4*k; for (k = 0;k < 64;k++) vs_constant_offset_table[C_POSTTRANSFORMMATRICES+k] = 696+4*k; for (k = 0;k < 4;k++) vs_constant_offset_table[C_DEPTHPARAMS+k] = 952+4*k; if (!File::Exists(File::GetUserPath(D_SHADERCACHE_IDX))) File::CreateDir(File::GetUserPath(D_SHADERCACHE_IDX).c_str()); SETSTAT(stats.numVertexShadersCreated, 0); SETSTAT(stats.numVertexShadersAlive, 0); char cache_filename[MAX_PATH]; sprintf(cache_filename, "%sdx11-%s-vs.cache", File::GetUserPath(D_SHADERCACHE_IDX).c_str(), SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str()); VertexShaderCacheInserter inserter; g_vs_disk_cache.OpenAndRead(cache_filename, inserter); if (g_Config.bEnableShaderDebugging) Clear(); last_entry = NULL; }