Пример #1
0
        /// <summary>
        /// Gets a compute shader from the cache.
        /// </summary>
        /// <remarks>
        /// This automatically translates, compiles and adds the code to the cache if not present.
        /// </remarks>
        /// <param name="gpuVa">GPU virtual address of the binary shader code</param>
        /// <param name="sharedMemorySize">Shared memory size of the compute shader</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>
        /// <returns>Compiled compute shader code</returns>
        public ComputeShader GetComputeShader(ulong gpuVa, int sharedMemorySize, int localSizeX, int localSizeY, int localSizeZ)
        {
            bool isCached = _cpPrograms.TryGetValue(gpuVa, out List <ComputeShader> list);

            if (isCached)
            {
                foreach (ComputeShader cachedCpShader in list)
                {
                    if (!IsShaderDifferent(cachedCpShader, gpuVa))
                    {
                        return(cachedCpShader);
                    }
                }
            }

            CachedShader shader = TranslateComputeShader(gpuVa, sharedMemorySize, localSizeX, localSizeY, localSizeZ);

            shader.HostShader = _context.Renderer.CompileShader(shader.Program);

            IProgram hostProgram = _context.Renderer.CreateProgram(new IShader[] { shader.HostShader });

            ComputeShader cpShader = new ComputeShader(hostProgram, shader);

            if (!isCached)
            {
                list = new List <ComputeShader>();

                _cpPrograms.Add(gpuVa, list);
            }

            list.Add(cpShader);

            return(cpShader);
        }
Пример #2
0
        /// <summary>
        /// Checks if graphics shader code from all stages in memory is different from the cached shaders.
        /// </summary>
        /// <param name="gpShaders">Cached graphics shaders</param>
        /// <param name="addresses">GPU virtual addresses of all enabled shader stages</param>
        /// <returns>True if the code is different, false otherwise</returns>
        private bool IsShaderDifferent(GraphicsShader gpShaders, ShaderAddresses addresses)
        {
            for (int stage = 0; stage < gpShaders.Shaders.Length; stage++)
            {
                CachedShader shader = gpShaders.Shaders[stage];

                ulong gpuVa = 0;

                switch (stage)
                {
                case 0: gpuVa = addresses.Vertex;         break;

                case 1: gpuVa = addresses.TessControl;    break;

                case 2: gpuVa = addresses.TessEvaluation; break;

                case 3: gpuVa = addresses.Geometry;       break;

                case 4: gpuVa = addresses.Fragment;       break;
                }

                if (IsShaderDifferent(shader, gpuVa))
                {
                    return(true);
                }
            }

            return(false);
        }
Пример #3
0
        /// <summary>
        /// Checks if the code of the specified cached shader is different from the code in memory.
        /// </summary>
        /// <param name="shader">Cached shader to compare with</param>
        /// <param name="gpuVa">GPU virtual address of the binary shader code</param>
        /// <returns>True if the code is different, false otherwise</returns>
        private bool IsShaderDifferent(CachedShader shader, ulong gpuVa)
        {
            if (shader == null)
            {
                return(false);
            }

            ReadOnlySpan <byte> memoryCode = _context.MemoryAccessor.GetSpan(gpuVa, (ulong)shader.Code.Length * 4);

            return(!MemoryMarshal.Cast <byte, int>(memoryCode).SequenceEqual(shader.Code));
        }
Пример #4
0
        /// <summary>
        /// Checks if the code of the specified cached shader is different from the code in memory.
        /// </summary>
        /// <param name="shader">Cached shader to compare with</param>
        /// <param name="gpuVa">GPU virtual address of the binary shader code</param>
        /// <returns>True if the code is different, false otherwise</returns>
        private bool IsShaderDifferent(CachedShader shader, ulong gpuVa)
        {
            if (shader == null)
            {
                return(false);
            }

            for (int index = 0; index < shader.Code.Length; index++)
            {
                if (_context.MemoryAccessor.ReadInt32(gpuVa + (ulong)index * 4) != shader.Code[index])
                {
                    return(true);
                }
            }

            return(false);
        }
Пример #5
0
 /// <summary>
 /// Creates a new instance of the compute shader.
 /// </summary>
 /// <param name="hostProgram">Host shader program</param>
 /// <param name="shader">Cached shader</param>
 public ComputeShader(IProgram hostProgram, CachedShader shader)
 {
     HostProgram = hostProgram;
     Shader      = shader;
 }
Пример #6
0
        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;
        }