#include "hecl/Pipeline.hpp" #include "athena/FileReader.hpp" #include namespace hecl { #if HECL_RUNTIME PipelineConverterBase* conv = nullptr; class ShaderCacheZipStream : public athena::io::IStreamReader { std::unique_ptr m_compBuf; athena::io::FileReader m_reader; z_stream m_zstrm = {}; public: explicit ShaderCacheZipStream(const hecl::SystemChar* path) : m_reader(path) { if (m_reader.hasError()) return; if (m_reader.readUint32Big() != SBIG('SHAD')) return; m_compBuf.reset(new uint8_t[4096]); m_zstrm.next_in = m_compBuf.get(); m_zstrm.avail_in = 0; inflateInit(&m_zstrm); } ~ShaderCacheZipStream() override { inflateEnd(&m_zstrm); } explicit operator bool() const { return m_compBuf.operator bool(); } atUint64 readUBytesToBuf(void* buf, atUint64 len) override { m_zstrm.next_out = (Bytef*)buf; m_zstrm.avail_out = len; m_zstrm.total_out = 0; while (m_zstrm.avail_out != 0) { if (m_zstrm.avail_in == 0) { atUint64 readSz = m_reader.readUBytesToBuf(m_compBuf.get(), 4096); m_zstrm.avail_in = readSz; m_zstrm.next_in = m_compBuf.get(); } int inflateRet = inflate(&m_zstrm, Z_NO_FLUSH); if (inflateRet != Z_OK) break; } return m_zstrm.total_out; } void seek(atInt64, athena::SeekOrigin) override {} atUint64 position() const override { return 0; } atUint64 length() const override { return 0; } }; template void StageConverter::loadFromStream(FactoryCtx& ctx, ShaderCacheZipStream& r) { uint32_t count = r.readUint32Big(); for (uint32_t i = 0; i < count; ++i) { uint64_t hash = r.readUint64Big(); uint32_t size = r.readUint32Big(); StageBinaryData data = MakeStageBinaryData(size); r.readUBytesToBuf(data.get(), size); m_stageCache.insert(std::make_pair(hash, Do(ctx, StageBinary(data, size)))); } } static boo::AdditionalPipelineInfo ReadAdditionalInfo(ShaderCacheZipStream& r) { boo::AdditionalPipelineInfo additionalInfo; additionalInfo.srcFac = boo::BlendFactor(r.readUint32Big()); additionalInfo.dstFac = boo::BlendFactor(r.readUint32Big()); additionalInfo.prim = boo::Primitive(r.readUint32Big()); additionalInfo.depthTest = boo::ZTest(r.readUint32Big()); additionalInfo.depthWrite = r.readBool(); additionalInfo.colorWrite = r.readBool(); additionalInfo.alphaWrite = r.readBool(); additionalInfo.culling = boo::CullMode(r.readUint32Big()); additionalInfo.patchSize = r.readUint32Big(); additionalInfo.overwriteAlpha = r.readBool(); additionalInfo.depthAttachment = r.readBool(); return additionalInfo; } static std::vector ReadVertexFormat(ShaderCacheZipStream& r) { std::vector ret; uint32_t count = r.readUint32Big(); ret.reserve(count); for (uint32_t i = 0; i < count; ++i) { ret.emplace_back(); ret.back().semantic = boo::VertexSemantic(r.readUint32Big()); ret.back().semanticIdx = int(r.readUint32Big()); } return ret; } template bool PipelineConverter

::loadFromFile(FactoryCtx& ctx, const hecl::SystemChar* path) { ShaderCacheZipStream r(path); if (!r) return false; m_vertexConverter.loadFromStream(ctx, r); m_fragmentConverter.loadFromStream(ctx, r); m_geometryConverter.loadFromStream(ctx, r); m_controlConverter.loadFromStream(ctx, r); m_evaluationConverter.loadFromStream(ctx, r); uint32_t count = r.readUint32Big(); for (uint32_t i = 0; i < count; ++i) { uint64_t hash = r.readUint64Big(); StageRuntimeObject vertex; StageRuntimeObject fragment; StageRuntimeObject geometry; StageRuntimeObject control; StageRuntimeObject evaluation; if (uint64_t vhash = r.readUint64Big()) vertex = m_vertexConverter.m_stageCache.find(vhash)->second; if (uint64_t fhash = r.readUint64Big()) fragment = m_fragmentConverter.m_stageCache.find(fhash)->second; if (uint64_t ghash = r.readUint64Big()) geometry = m_geometryConverter.m_stageCache.find(ghash)->second; if (uint64_t chash = r.readUint64Big()) control = m_controlConverter.m_stageCache.find(chash)->second; if (uint64_t ehash = r.readUint64Big()) evaluation = m_evaluationConverter.m_stageCache.find(ehash)->second; boo::AdditionalPipelineInfo additionalInfo = ReadAdditionalInfo(r); std::vector vtxFmt = ReadVertexFormat(r); m_pipelineCache.insert( std::make_pair(hash, FinalPipeline

(*this, ctx, StageCollection>( vertex, fragment, geometry, control, evaluation, additionalInfo, boo::VertexFormatInfo(vtxFmt.size(), vtxFmt.data()))))); } return true; } #define SPECIALIZE_STAGE_CONVERTER(P) \ template class StageConverter; \ template class StageConverter; \ template class StageConverter; \ template class StageConverter; \ template class StageConverter; #if BOO_HAS_GL template class PipelineConverter; SPECIALIZE_STAGE_CONVERTER(PlatformType::OpenGL) #endif #if BOO_HAS_VULKAN template class PipelineConverter; SPECIALIZE_STAGE_CONVERTER(PlatformType::Vulkan) #endif #if _WIN32 template class PipelineConverter; SPECIALIZE_STAGE_CONVERTER(PlatformType::D3D11) #endif #if BOO_HAS_METAL template class PipelineConverter; SPECIALIZE_STAGE_CONVERTER(PlatformType::Metal) #endif #if BOO_HAS_NX template class PipelineConverter; SPECIALIZE_STAGE_CONVERTER(PlatformType::NX) #endif #endif } // namespace hecl