void ShaderManagerVulkan::GetShaders(int prim, u32 vertType, VulkanVertexShader **vshader, VulkanFragmentShader **fshader, bool useHWTransform) { VShaderID VSID; if (gstate_c.IsDirty(DIRTY_VERTEXSHADER_STATE)) { gstate_c.Clean(DIRTY_VERTEXSHADER_STATE); ComputeVertexShaderID(&VSID, vertType, useHWTransform); } else { VSID = lastVSID_; } FShaderID FSID; if (gstate_c.IsDirty(DIRTY_FRAGMENTSHADER_STATE)) { gstate_c.Clean(DIRTY_FRAGMENTSHADER_STATE); ComputeFragmentShaderID(&FSID); } else { FSID = lastFSID_; } _dbg_assert_(G3D, FSID.Bit(FS_BIT_LMODE) == VSID.Bit(VS_BIT_LMODE)); _dbg_assert_(G3D, FSID.Bit(FS_BIT_DO_TEXTURE) == VSID.Bit(VS_BIT_DO_TEXTURE)); _dbg_assert_(G3D, FSID.Bit(FS_BIT_ENABLE_FOG) == VSID.Bit(VS_BIT_ENABLE_FOG)); _dbg_assert_(G3D, FSID.Bit(FS_BIT_FLATSHADE) == VSID.Bit(VS_BIT_FLATSHADE)); // Just update uniforms if this is the same shader as last time. if (lastVShader_ != nullptr && lastFShader_ != nullptr && VSID == lastVSID_ && FSID == lastFSID_) { *vshader = lastVShader_; *fshader = lastFShader_; _dbg_assert_msg_(G3D, (*vshader)->UseHWTransform() == useHWTransform, "Bad vshader was cached"); // Already all set, no need to look up in shader maps. return; } VulkanVertexShader *vs = vsCache_.Get(VSID); if (!vs) { // Vertex shader not in cache. Let's compile it. bool usesLighting; GenerateVulkanGLSLVertexShader(VSID, codeBuffer_, &usesLighting); vs = new VulkanVertexShader(vulkan_, VSID, codeBuffer_, vertType, useHWTransform, usesLighting); vsCache_.Insert(VSID, vs); } lastVSID_ = VSID; VulkanFragmentShader *fs = fsCache_.Get(FSID); if (!fs) { // Fragment shader not in cache. Let's compile it. GenerateVulkanGLSLFragmentShader(FSID, codeBuffer_); fs = new VulkanFragmentShader(vulkan_, FSID, codeBuffer_, useHWTransform); fsCache_.Insert(FSID, fs); } lastFSID_ = FSID; lastVShader_ = vs; lastFShader_ = fs; *vshader = vs; *fshader = fs; _dbg_assert_msg_(G3D, (*vshader)->UseHWTransform() == useHWTransform, "Bad vshader was computed"); }
void ShaderManagerVulkan::GetShaders(int prim, u32 vertType, VulkanVertexShader **vshader, VulkanFragmentShader **fshader, bool useHWTransform) { ShaderID VSID; ShaderID FSID; ComputeVertexShaderID(&VSID, vertType, useHWTransform); ComputeFragmentShaderID(&FSID); // Just update uniforms if this is the same shader as last time. if (lastVShader_ != nullptr && lastFShader_ != nullptr && VSID == lastVSID_ && FSID == lastFSID_) { *vshader = lastVShader_; *fshader = lastFShader_; // Already all set, no need to look up in shader maps. return; } VSCache::iterator vsIter = vsCache_.find(VSID); VulkanVertexShader *vs; if (vsIter == vsCache_.end()) { // Vertex shader not in cache. Let's compile it. bool usesLighting; GenerateVulkanGLSLVertexShader(VSID, codeBuffer_, &usesLighting); vs = new VulkanVertexShader(vulkan_, VSID, codeBuffer_, vertType, useHWTransform, usesLighting); vsCache_[VSID] = vs; } else { vs = vsIter->second; } lastVSID_ = VSID; FSCache::iterator fsIter = fsCache_.find(FSID); VulkanFragmentShader *fs; if (fsIter == fsCache_.end()) { // Fragment shader not in cache. Let's compile it. GenerateVulkanGLSLFragmentShader(FSID, codeBuffer_); fs = new VulkanFragmentShader(vulkan_, FSID, codeBuffer_, useHWTransform); fsCache_[FSID] = fs; } else { fs = fsIter->second; } lastFSID_ = FSID; lastVShader_ = vs; lastFShader_ = fs; *vshader = vs; *fshader = fs; }
VSShader *ShaderManagerDX9::ApplyShader(int prim, u32 vertType) { bool useHWTransform = CanUseHardwareTransform(prim); ShaderID VSID; ComputeVertexShaderID(&VSID, vertType, useHWTransform); ShaderID FSID; ComputeFragmentShaderID(&FSID); // Just update uniforms if this is the same shader as last time. if (lastVShader_ != nullptr && lastPShader_ != nullptr && VSID == lastVSID_ && FSID == lastFSID_) { if (globalDirty_) { PSUpdateUniforms(globalDirty_); VSUpdateUniforms(globalDirty_); globalDirty_ = 0; } return lastVShader_; // Already all set. } VSCache::iterator vsIter = vsCache_.find(VSID); VSShader *vs; if (vsIter == vsCache_.end()) { // Vertex shader not in cache. Let's compile it. GenerateVertexShaderDX9(VSID, codeBuffer_); vs = new VSShader(VSID, codeBuffer_, useHWTransform); if (vs->Failed()) { ERROR_LOG(HLE, "Shader compilation failed, falling back to software transform"); osm.Show("hardware transform error - falling back to software", 2.5f, 0xFF3030FF, -1, true); delete vs; ComputeVertexShaderID(&VSID, vertType, false); // TODO: Look for existing shader with the appropriate ID, use that instead of generating a new one - however, need to make sure // that that shader ID is not used when computing the linked shader ID below, because then IDs won't match // next time and we'll do this over and over... // Can still work with software transform. GenerateVertexShaderDX9(VSID, codeBuffer_); vs = new VSShader(VSID, codeBuffer_, false); } vsCache_[VSID] = vs; } else { vs = vsIter->second; } lastVSID_ = VSID; FSCache::iterator fsIter = fsCache_.find(FSID); PSShader *fs; if (fsIter == fsCache_.end()) { // Fragment shader not in cache. Let's compile it. GenerateFragmentShaderDX9(FSID, codeBuffer_); fs = new PSShader(FSID, codeBuffer_); fsCache_[FSID] = fs; } else { fs = fsIter->second; } lastFSID_ = FSID; if (globalDirty_) { PSUpdateUniforms(globalDirty_); VSUpdateUniforms(globalDirty_); globalDirty_ = 0; } pD3Ddevice->SetPixelShader(fs->shader); pD3Ddevice->SetVertexShader(vs->shader); lastPShader_ = fs; lastVShader_ = vs; return vs; }