/// <summary> /// Translates the binary Maxwell shader code to something that the host API accepts. /// </summary> /// <remarks> /// This will combine the "Vertex A" and "Vertex B" shader stages, if specified, into one shader. /// </remarks> /// <param name="state">Current GPU state</param> /// <param name="stage">Shader stage</param> /// <param name="gpuVa">GPU virtual address of the shader code</param> /// <returns>Compiled graphics shader code</returns> private ShaderProgram TranslateGraphicsShader(GpuState state, ShaderStage stage, ulong gpuVa) { if (gpuVa == 0) { return null; } int QueryInfo(QueryInfoName info, int index) { return info switch { QueryInfoName.IsTextureBuffer => Convert.ToInt32(QueryIsTextureBuffer(state, (int)stage - 1, index, compute: false)), QueryInfoName.IsTextureRectangle => Convert.ToInt32(QueryIsTextureRectangle(state, (int)stage - 1, index, compute: false)), QueryInfoName.PrimitiveTopology => (int)QueryPrimitiveTopology(), QueryInfoName.TextureFormat => (int)QueryTextureFormat(state, (int)stage - 1, index, compute: false), _ => QueryInfoCommon(info) }; } TranslatorCallbacks callbacks = new TranslatorCallbacks(QueryInfo, PrintLog); ReadOnlySpan<byte> code = GetShaderCode(gpuVa); _dumper.Dump(code, compute: false, out string fullPath, out string codePath); ShaderProgram program = Translator.Translate(code, callbacks, DefaultFlags); if (fullPath != null && codePath != null) { program.Prepend("// " + codePath); program.Prepend("// " + fullPath); } return program; }
public Shader GetComputeShader( ulong gpuVa, int localSizeX, int localSizeY, int localSizeZ, int localMemorySize, int sharedMemorySize) { if (gpuVa == 0) { return null; } ShaderPack pack = new ShaderPack(); ReadOnlySpan<byte> code = GetShaderCodeHeaderless(gpuVa); pack.Add(code); Shader cs = _cache.Get(pack, out int hash); if (cs != null) { return cs; } _dumper.Dump(code, compute: true, out string fullPath, out string codePath); int QueryInfo(QueryInfoName info, int index) { return info switch { QueryInfoName.ComputeLocalSizeX => localSizeX, QueryInfoName.ComputeLocalSizeY => localSizeY, QueryInfoName.ComputeLocalSizeZ => localSizeZ, QueryInfoName.ComputeLocalMemorySize => localMemorySize, QueryInfoName.ComputeSharedMemorySize => sharedMemorySize, _ => QueryInfoCommon(info) }; } CachedShader shader = TranslateComputeShader( state, gpuVa, localSizeX, localSizeY, localSizeZ, localMemorySize, sharedMemorySize); TranslatorCallbacks callbacks = new TranslatorCallbacks(QueryInfo, PrintLog); ShaderProgram program = Translator.Translate(code, callbacks, DefaultFlags | TranslationFlags.Compute); if (fullPath != null && codePath != null) { program.Prepend("// " + codePath); program.Prepend("// " + fullPath); } IShader shader = _context.Renderer.CompileShader(program); IProgram hostProgram = _context.Renderer.CreateProgram(new IShader[] { shader }); cs = new Shader(hostProgram, new ShaderMeta(hostProgram, program.Info)); int insertIndex = _cache.Add(hash, cs, pack); if (Configuration.Enabled) { ShaderProgramInfo[] info = new ShaderProgramInfo[] { program.Info }; ShaderCacheFile.Save(Configuration.ShaderPath, info, pack, hostProgram.GetGpuBinary(), hash, insertIndex); } return cs; }