/// <summary> /// Writes the host binary code on the host cache. /// </summary> /// <param name="context">GPU context</param> /// <param name="hostCode">Host binary code</param> /// <param name="shaders">Shader stages to be added to the host cache</param> /// <param name="streams">Output streams to use</param> /// <param name="timestamp">File creation timestamp</param> private void WriteHostCode( GpuContext context, ReadOnlySpan <byte> hostCode, CachedShaderStage[] shaders, DiskCacheOutputStreams streams, ulong timestamp) { var tocFileStream = streams != null ? streams.HostTocFileStream : DiskCacheCommon.OpenFile(_basePath, GetHostTocFileName(context), writable: true); var dataFileStream = streams != null ? streams.HostDataFileStream : DiskCacheCommon.OpenFile(_basePath, GetHostDataFileName(context), writable: true); if (tocFileStream.Length == 0) { TocHeader header = new TocHeader(); CreateToc(tocFileStream, ref header, TochMagic, 0, timestamp); } tocFileStream.Seek(0, SeekOrigin.End); dataFileStream.Seek(0, SeekOrigin.End); BinarySerializer tocWriter = new BinarySerializer(tocFileStream); BinarySerializer dataWriter = new BinarySerializer(dataFileStream); OffsetAndSize offsetAndSize = new OffsetAndSize(); offsetAndSize.Offset = (ulong)dataFileStream.Position; offsetAndSize.UncompressedSize = (uint)hostCode.Length; long dataStartPosition = dataFileStream.Position; BinarySerializer.WriteCompressed(dataFileStream, hostCode, DiskCacheCommon.GetCompressionAlgorithm()); offsetAndSize.CompressedSize = (uint)(dataFileStream.Position - dataStartPosition); tocWriter.Write(ref offsetAndSize); dataWriter.BeginCompression(DiskCacheCommon.GetCompressionAlgorithm()); for (int index = 0; index < shaders.Length; index++) { if (shaders[index] != null) { WriteShaderProgramInfo(ref dataWriter, shaders[index].Info); } } dataWriter.EndCompression(); if (streams == null) { tocFileStream.Dispose(); dataFileStream.Dispose(); } }
/// <summary> /// Writes the host binary code on the host cache. /// </summary> /// <param name="context">GPU context</param> /// <param name="hostCode">Host binary code</param> /// <param name="programIndex">Index of the program in the cache</param> /// <param name="streams">Output streams to use</param> private void WriteHostCode(GpuContext context, ReadOnlySpan <byte> hostCode, int programIndex, DiskCacheOutputStreams streams = null) { var tocFileStream = streams != null ? streams.HostTocFileStream : DiskCacheCommon.OpenFile(_basePath, GetHostTocFileName(context), writable: true); var dataFileStream = streams != null ? streams.HostDataFileStream : DiskCacheCommon.OpenFile(_basePath, GetHostDataFileName(context), writable: true); if (tocFileStream.Length == 0) { TocHeader header = new TocHeader(); CreateToc(tocFileStream, ref header, TochMagic, 0); } if (programIndex == -1) { tocFileStream.Seek(0, SeekOrigin.End); } else { tocFileStream.Seek(Unsafe.SizeOf <TocHeader>() + (programIndex * Unsafe.SizeOf <OffsetAndSize>()), SeekOrigin.Begin); } dataFileStream.Seek(0, SeekOrigin.End); BinarySerializer tocWriter = new BinarySerializer(tocFileStream); OffsetAndSize offsetAndSize = new OffsetAndSize(); offsetAndSize.Offset = (ulong)dataFileStream.Position; offsetAndSize.Size = (uint)hostCode.Length; tocWriter.Write(ref offsetAndSize); BinarySerializer.WriteCompressed(dataFileStream, hostCode, DiskCacheCommon.GetCompressionAlgorithm()); if (streams == null) { tocFileStream.Dispose(); dataFileStream.Dispose(); } }
/// <summary> /// Adds a shader to the cache. /// </summary> /// <param name="context">GPU context</param> /// <param name="program">Cached program</param> /// <param name="hostCode">Optional host binary code</param> /// <param name="streams">Output streams to use</param> public void AddShader(GpuContext context, CachedShaderProgram program, ReadOnlySpan <byte> hostCode, DiskCacheOutputStreams streams = null) { uint stagesBitMask = 0; for (int index = 0; index < program.Shaders.Length; index++) { var shader = program.Shaders[index]; if (shader == null || (shader.Info != null && shader.Info.Stage == ShaderStage.Compute)) { continue; } stagesBitMask |= 1u << index; } var tocFileStream = streams != null ? streams.TocFileStream : DiskCacheCommon.OpenFile(_basePath, SharedTocFileName, writable: true); var dataFileStream = streams != null ? streams.DataFileStream : DiskCacheCommon.OpenFile(_basePath, SharedDataFileName, writable: true); if (tocFileStream.Length == 0) { TocHeader header = new TocHeader(); CreateToc(tocFileStream, ref header, TocsMagic, CodeGenVersion); } tocFileStream.Seek(0, SeekOrigin.End); dataFileStream.Seek(0, SeekOrigin.End); BinarySerializer tocWriter = new BinarySerializer(tocFileStream); BinarySerializer dataWriter = new BinarySerializer(dataFileStream); ulong dataOffset = (ulong)dataFileStream.Position; tocWriter.Write(ref dataOffset); DataEntry entry = new DataEntry(); entry.StagesBitMask = stagesBitMask; dataWriter.BeginCompression(DiskCacheCommon.GetCompressionAlgorithm()); dataWriter.Write(ref entry); DataEntryPerStage stageEntry = new DataEntryPerStage(); for (int index = 0; index < program.Shaders.Length; index++) { var shader = program.Shaders[index]; if (shader == null) { continue; } stageEntry.GuestCodeIndex = _guestStorage.AddShader(shader.Code, shader.Cb1Data); dataWriter.Write(ref stageEntry); WriteShaderProgramInfo(ref dataWriter, shader.Info); } program.SpecializationState.Write(ref dataWriter); dataWriter.EndCompression(); if (streams == null) { tocFileStream.Dispose(); dataFileStream.Dispose(); } if (hostCode.IsEmpty) { return; } WriteHostCode(context, hostCode, -1, streams); }