bool ShaderManagerVulkan::LoadCache(FILE *f) { VulkanCacheHeader header{}; bool success = fread(&header, sizeof(header), 1, f) == 1; if (!success || header.magic != CACHE_HEADER_MAGIC) return false; if (header.version != CACHE_VERSION) return false; if (header.featureFlags != gstate_c.featureFlags) return false; for (int i = 0; i < header.numVertexShaders; i++) { VShaderID id; if (fread(&id, sizeof(id), 1, f) != 1) { ERROR_LOG(G3D, "Vulkan shader cache truncated"); break; } bool useHWTransform = id.Bit(VS_BIT_USE_HW_TRANSFORM); GenerateVulkanGLSLVertexShader(id, codeBuffer_); VulkanVertexShader *vs = new VulkanVertexShader(vulkan_, id, codeBuffer_, useHWTransform); vsCache_.Insert(id, vs); } for (int i = 0; i < header.numFragmentShaders; i++) { FShaderID id; if (fread(&id, sizeof(id), 1, f) != 1) { ERROR_LOG(G3D, "Vulkan shader cache truncated"); break; } GenerateVulkanGLSLFragmentShader(id, codeBuffer_); VulkanFragmentShader *fs = new VulkanFragmentShader(vulkan_, id, codeBuffer_); fsCache_.Insert(id, fs); } NOTICE_LOG(G3D, "Loaded %d vertex and %d fragment shaders", header.numVertexShaders, header.numFragmentShaders); return true; }
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; }