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; }
/// <summary> /// Translates the binary Maxwell shader code to something that the host API accepts. /// </summary> /// <param name="state">Current GPU state</param> /// <param name="gpuVa">GPU virtual address of the binary shader code</param> /// <param name="localSizeX">Local group size X of the computer shader</param> /// <param name="localSizeY">Local group size Y of the computer shader</param> /// <param name="localSizeZ">Local group size Z of the computer shader</param> /// <param name="localMemorySize">Local memory size of the compute shader</param> /// <param name="sharedMemorySize">Shared memory size of the compute shader</param> /// <returns>Compiled compute shader code</returns> private CachedShader TranslateComputeShader( GpuState state, ulong gpuVa, int localSizeX, int localSizeY, int localSizeZ, int localMemorySize, int sharedMemorySize) { if (gpuVa == 0) { return null; } int index = 0; for (int stage = 0; stage < programs.Length; stage++) { ShaderProgram program = programs[stage]; if (program != null) { QueryInfoName.ComputeLocalSizeX => localSizeX, QueryInfoName.ComputeLocalSizeY => localSizeY, QueryInfoName.ComputeLocalSizeZ => localSizeZ, QueryInfoName.ComputeLocalMemorySize => localMemorySize, QueryInfoName.ComputeSharedMemorySize => sharedMemorySize, QueryInfoName.IsTextureBuffer => Convert.ToInt32(QueryIsTextureBuffer(state, 0, index, compute: true)), QueryInfoName.IsTextureRectangle => Convert.ToInt32(QueryIsTextureRectangle(state, 0, index, compute: true)), QueryInfoName.TextureFormat => (int)QueryTextureFormat(state, 0, index, compute: true), _ => QueryInfoCommon(info) }; shaders[index++] = _context.Renderer.CompileShader(program); } } IProgram hostProgram = _context.Renderer.CreateProgram(shaders); ShaderProgramInfo[] info = programs.Select(x => x?.Info).ToArray(); gs = new Shader(hostProgram, new ShaderMeta(hostProgram, info)); int insertIndex = _cache.Add(hash, gs, pack); if (Configuration.Enabled) { ShaderCacheFile.Save(Configuration.ShaderPath, info, pack, hostProgram.GetGpuBinary(), hash, insertIndex); } return gs; }