void ShaderCache::LoadAndSetActiveShaders(DSTALPHA_MODE ps_dst_alpha_mode, u32 gs_primitive_type) { SetCurrentPrimitiveTopology(gs_primitive_type); GeometryShaderUid gs_uid = GetGeometryShaderUid(gs_primitive_type); PixelShaderUid ps_uid = GetPixelShaderUid(ps_dst_alpha_mode); VertexShaderUid vs_uid = GetVertexShaderUid(); bool gs_changed = gs_uid != s_last_geometry_shader_uid; bool ps_changed = ps_uid != s_last_pixel_shader_uid; bool vs_changed = vs_uid != s_last_vertex_shader_uid; if (!gs_changed && !ps_changed && !vs_changed) { return; } if (gs_changed) { HandleGSUIDChange(gs_uid, gs_primitive_type); } if (ps_changed) { HandlePSUIDChange(ps_uid, ps_dst_alpha_mode); } if (vs_changed) { HandleVSUIDChange(vs_uid); } // A Uid has changed, so the PSO will need to be reset at next ApplyState. D3D::command_list_mgr->SetCommandListDirtyState(COMMAND_LIST_STATE_PSO, true); }
bool StateTracker::CheckForShaderChanges(u32 gx_primitive_type, u32 components, PIXEL_SHADER_RENDER_MODE dstalpha_mode) { VertexShaderUid vs_uid; GetVertexShaderUID(vs_uid, components, xfmem, bpmem); PixelShaderUid ps_uid; GetPixelShaderUID(ps_uid, dstalpha_mode, components, xfmem, bpmem); bool changed = false; if (vs_uid != m_vs_uid) { m_pipeline_state.vs = g_object_cache->GetVertexShaderForUid(vs_uid); m_vs_uid = vs_uid; changed = true; } if (g_vulkan_context->SupportsGeometryShaders()) { GeometryShaderUid gs_uid; GetGeometryShaderUid(gs_uid, gx_primitive_type, xfmem, components); if (gs_uid != m_gs_uid) { if (gs_uid.GetUidData().IsPassthrough()) m_pipeline_state.gs = VK_NULL_HANDLE; else m_pipeline_state.gs = g_object_cache->GetGeometryShaderForUid(gs_uid); m_gs_uid = gs_uid; changed = true; } } if (ps_uid != m_ps_uid) { m_pipeline_state.ps = g_object_cache->GetPixelShaderForUid(ps_uid); m_ps_uid = ps_uid; changed = true; } if (m_dstalpha_mode != dstalpha_mode) { // Switching to/from alpha pass requires a pipeline change, since the blend state // is overridden in the destination alpha pass. if (m_dstalpha_mode == PIXEL_SHADER_RENDER_MODE::PSRM_ALPHA_PASS || dstalpha_mode == PIXEL_SHADER_RENDER_MODE::PSRM_ALPHA_PASS) changed = true; m_dstalpha_mode = dstalpha_mode; } if (changed) m_dirty_flags |= DIRTY_FLAG_PIPELINE; return changed; }
bool GeometryShaderCache::SetShader(u32 primitive_type) { GeometryShaderUid uid = GetGeometryShaderUid(primitive_type); // Check if the shader is already set if (last_entry) { if (uid == last_uid) { GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true); return true; } } last_uid = uid; // Check if the shader is a pass-through shader if (uid.GetUidData()->IsPassthrough()) { // Return the default pass-through shader last_entry = &pass_entry; return true; } // Check if the shader is already in the cache GSCache::iterator iter; iter = GeometryShaders.find(uid); if (iter != GeometryShaders.end()) { const GSCacheEntry& entry = iter->second; last_entry = &entry; return (entry.shader != nullptr); } // Need to compile a new shader ShaderCode code = GenerateGeometryShaderCode(APIType::D3D, ShaderHostConfig::GetCurrent(), uid.GetUidData()); D3DBlob* pbytecode; if (!D3D::CompileGeometryShader(code.GetBuffer(), &pbytecode)) { GFX_DEBUGGER_PAUSE_AT(NEXT_ERROR, true); return false; } // Insert the bytecode into the caches g_gs_disk_cache.Append(uid, pbytecode->Data(), pbytecode->Size()); bool success = InsertByteCode(uid, pbytecode->Data(), pbytecode->Size()); pbytecode->Release(); return success; }
void ProgramShaderCache::GetShaderId(SHADERUID* uid, DSTALPHA_MODE dstAlphaMode, u32 components, u32 primitive_type) { GetPixelShaderUid(uid->puid, dstAlphaMode, API_OPENGL, components); GetVertexShaderUid(uid->vuid, components, API_OPENGL); GetGeometryShaderUid(uid->guid, primitive_type, API_OPENGL); if (g_ActiveConfig.bEnableShaderDebugging) { PixelShaderCode pcode; GeneratePixelShaderCode(pcode, dstAlphaMode, API_OPENGL, components); pixel_uid_checker.AddToIndexAndCheck(pcode, uid->puid, "Pixel", "p"); VertexShaderCode vcode; GenerateVertexShaderCode(vcode, components, API_OPENGL); vertex_uid_checker.AddToIndexAndCheck(vcode, uid->vuid, "Vertex", "v"); ShaderCode gcode; GenerateGeometryShaderCode(gcode, primitive_type, API_OPENGL); geometry_uid_checker.AddToIndexAndCheck(gcode, uid->guid, "Geometry", "g"); } }
void GeometryShaderCache::PrepareShader( u32 primitive_type, const XFMemory &xfr, const u32 components, bool ongputhread) { GeometryShaderUid uid; GetGeometryShaderUid(uid, primitive_type, xfr, components); if (ongputhread) { s_compiler->ProcCompilationResults(); // Check if the shader is already set if (s_last_entry) { if (uid == s_last_uid) { return; } } s_last_uid = uid; // Check if the shader is a pass-through shader if (uid.GetUidData().IsPassthrough()) { // Return the default pass-through shader s_last_entry = &s_pass_entry; return; } GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true); } else { if (s_external_last_uid == uid) { return; } s_external_last_uid = uid; } CompileGShader(uid, ongputhread); }
void ShaderCache::PrepareShaders(PIXEL_SHADER_RENDER_MODE render_mode, u32 gs_primitive_type, u32 components, const XFMemory &xfr, const BPMemory &bpm, bool on_gpu_thread) { SetCurrentPrimitiveTopology(gs_primitive_type); GeometryShaderUid gs_uid; GetGeometryShaderUid(gs_uid, gs_primitive_type, xfr, components); PixelShaderUid ps_uid; GetPixelShaderUID(ps_uid, render_mode, components, xfr, bpm); VertexShaderUid vs_uid; GetVertexShaderUID(vs_uid, components, xfr, bpm); TessellationShaderUid ts_uid; bool tessellationenabled = false; if (gs_primitive_type == PrimitiveType::PRIMITIVE_TRIANGLES && g_ActiveConfig.TessellationEnabled() && xfr.projection.type == GX_PERSPECTIVE && (g_ActiveConfig.bForcedLighting || g_ActiveConfig.PixelLightingEnabled(xfr, components))) { GetTessellationShaderUID(ts_uid, xfr, bpm, components); tessellationenabled = true; } bool gs_changed = false; bool ps_changed = false; bool vs_changed = false; bool ts_changed = false; if (on_gpu_thread) { s_compiler->ProcCompilationResults(); gs_changed = gs_uid != s_last_geometry_shader_uid; ps_changed = ps_uid != s_last_pixel_shader_uid; vs_changed = vs_uid != s_last_vertex_shader_uid; ts_changed = tessellationenabled && ts_uid != s_last_tessellation_shader_uid; } else { gs_changed = gs_uid != s_last_cpu_geometry_shader_uid; ps_changed = ps_uid != s_last_cpu_pixel_shader_uid; vs_changed = vs_uid != s_last_cpu_vertex_shader_uid; ts_changed = tessellationenabled && ts_uid != s_last_cpu_tessellation_shader_uid; } if (!gs_changed && !ps_changed && !vs_changed && !ts_changed) { return; } if (on_gpu_thread) { if (gs_changed) { s_last_geometry_shader_uid = gs_uid; } if (ps_changed) { s_last_pixel_shader_uid = ps_uid; } if (vs_changed) { s_last_vertex_shader_uid = vs_uid; } if (ts_changed) { s_last_tessellation_shader_uid = ts_uid; } // A Uid has changed, so the PSO will need to be reset at next ApplyState. D3D::command_list_mgr->SetCommandListDirtyState(COMMAND_LIST_STATE_PSO, true); } else { if (gs_changed) { s_last_cpu_geometry_shader_uid = gs_uid; } if (ps_changed) { s_last_cpu_pixel_shader_uid = ps_uid; } if (vs_changed) { s_last_cpu_vertex_shader_uid = vs_uid; } if (ts_changed) { s_last_cpu_tessellation_shader_uid = ts_uid; } } if (vs_changed) { HandleVSUIDChange(vs_uid, on_gpu_thread); } if (ts_changed) { HandleTSUIDChange(ts_uid, on_gpu_thread); } else { if (on_gpu_thread) { s_last_domain_shader_bytecode = &s_pass_entry; s_last_hull_shader_bytecode = &s_pass_entry; } } if (gs_changed) { HandleGSUIDChange(gs_uid, on_gpu_thread); } if (ps_changed) { HandlePSUIDChange(ps_uid, on_gpu_thread); } }
bool GeometryShaderCache::SetShader(u32 primitive_type) { switch (primitive_type) { case PRIMITIVE_TRIANGLES: currentPrimitiveTopology = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; break; case PRIMITIVE_LINES: currentPrimitiveTopology = D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE; break; case PRIMITIVE_POINTS: currentPrimitiveTopology = D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT; break; default: CHECK(0, "Invalid primitive type."); break; } GeometryShaderUid uid = GetGeometryShaderUid(primitive_type, API_D3D); // Check if the shader is already set if (uid == last_uid) { GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE,true); return true; } last_uid = uid; D3D::commandListMgr->dirtyPso = true; if (g_ActiveConfig.bEnableShaderDebugging) { ShaderCode code = GenerateGeometryShaderCode(primitive_type, API_D3D); geometry_uid_checker.AddToIndexAndCheck(code, uid, "Geometry", "g"); } // Check if the shader is a pass-through shader if (uid.GetUidData()->IsPassthrough()) { // Return the default pass-through shader last_entry = &pass_entry; return true; } // Check if the shader is already in the cache GSCache::iterator iter; iter = GeometryShaders.find(uid); if (iter != GeometryShaders.end()) { const GSCacheEntry &entry = iter->second; last_entry = &entry; return (entry.shader12.pShaderBytecode != nullptr); } // Need to compile a new shader ShaderCode code = GenerateGeometryShaderCode(primitive_type, API_D3D); D3DBlob* pbytecode; if (!D3D::CompileGeometryShader(code.GetBuffer(), &pbytecode)) { GFX_DEBUGGER_PAUSE_AT(NEXT_ERROR, true); return false; } // Insert the bytecode into the caches g_gs_disk_cache.Append(uid, pbytecode->Data(), pbytecode->Size()); bool success = InsertByteCode(uid, pbytecode->Data(), pbytecode->Size()); pbytecode->Release(); if (g_ActiveConfig.bEnableShaderDebugging && success) { GeometryShaders[uid].code = code.GetBuffer(); } return success; }
bool GeometryShaderCache::SetShader(u32 primitive_type) { GeometryShaderUid uid; GetGeometryShaderUid(uid, primitive_type, API_D3D); if (g_ActiveConfig.bEnableShaderDebugging) { ShaderCode code; GenerateGeometryShaderCode(code, primitive_type, API_D3D); geometry_uid_checker.AddToIndexAndCheck(code, uid, "Geometry", "g"); } // Check if the shader is already set if (last_entry) { if (uid == last_uid) { GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE,true); return true; } } last_uid = uid; // Check if the shader is a pass-through shader if (uid.GetUidData()->IsPassthrough()) { // Return the default pass-through shader last_entry = &pass_entry; return true; } // Check if the shader is already in the cache GSCache::iterator iter; iter = GeometryShaders.find(uid); if (iter != GeometryShaders.end()) { const GSCacheEntry &entry = iter->second; last_entry = &entry; return (entry.shader != nullptr); } // Need to compile a new shader ShaderCode code; GenerateGeometryShaderCode(code, primitive_type, API_D3D); D3DBlob* pbytecode; if (!D3D::CompileGeometryShader(code.GetBuffer(), &pbytecode)) { GFX_DEBUGGER_PAUSE_AT(NEXT_ERROR, true); return false; } // Insert the bytecode into the caches g_gs_disk_cache.Append(uid, pbytecode->Data(), pbytecode->Size()); bool success = InsertByteCode(uid, pbytecode->Data(), pbytecode->Size()); pbytecode->Release(); if (g_ActiveConfig.bEnableShaderDebugging && success) { GeometryShaders[uid].code = code.GetBuffer(); } return success; }