Exemple #1
0
 /// <summary>
 /// Creates a new instance of the GPU state accessor for graphics shader translation.
 /// </summary>
 /// <param name="context">GPU context</param>
 /// <param name="channel">GPU channel</param>
 /// <param name="state">Current GPU state</param>
 /// <param name="stageIndex">Graphics shader stage index (0 = Vertex, 4 = Fragment)</param>
 public GpuAccessor(GpuContext context, GpuChannel channel, GpuAccessorState state, int stageIndex)
 {
     _context    = context;
     _channel    = channel;
     _state      = state;
     _stageIndex = stageIndex;
 }
Exemple #2
0
 /// <summary>
 /// Creates a new instance of the GPU state accessor for graphics shader translation.
 /// </summary>
 /// <param name="context">GPU context</param>
 /// <param name="channel">GPU channel</param>
 /// <param name="state">Current GPU state</param>
 /// <param name="tfd">Transform feedback descriptors</param>
 /// <param name="stageIndex">Graphics shader stage index (0 = Vertex, 4 = Fragment)</param>
 public GpuAccessor(GpuContext context, GpuChannel channel, GpuAccessorState state, TransformFeedbackDescriptor[] tfd, int stageIndex)
 {
     _context    = context;
     _channel    = channel;
     _state      = state;
     _tfd        = tfd;
     _stageIndex = stageIndex;
 }
Exemple #3
0
 /// <summary>
 /// Creates a new instance of the GPU state accessor for graphics shader translation.
 /// </summary>
 /// <param name="context">GPU context</param>
 /// <param name="channel">GPU channel</param>
 /// <param name="state">Current GPU state</param>
 /// <param name="stageIndex">Graphics shader stage index (0 = Vertex, 4 = Fragment)</param>
 public GpuAccessor(
     GpuContext context,
     GpuChannel channel,
     GpuAccessorState state,
     int stageIndex) : base(context, state.ResourceCounts, stageIndex)
 {
     _isVulkan   = context.Capabilities.Api == TargetApi.Vulkan;
     _channel    = channel;
     _state      = state;
     _stageIndex = stageIndex;
 }
Exemple #4
0
 /// <summary>
 /// Creates a new instance of the GPU state accessor for graphics shader translation.
 /// </summary>
 /// <param name="context">GPU context</param>
 /// <param name="channel">GPU channel</param>
 /// <param name="state">Current GPU state</param>
 /// <param name="attributeTypes">Type of the vertex attributes consumed by the shader</param>
 /// <param name="tfd">Transform feedback descriptors</param>
 /// <param name="stageIndex">Graphics shader stage index (0 = Vertex, 4 = Fragment)</param>
 public GpuAccessor(
     GpuContext context,
     GpuChannel channel,
     GpuAccessorState state,
     AttributeType[] attributeTypes,
     TransformFeedbackDescriptor[] tfd,
     int stageIndex) : base(context)
 {
     _channel        = channel;
     _state          = state;
     _attributeTypes = attributeTypes;
     _tfd            = tfd;
     _stageIndex     = stageIndex;
 }
        /// <summary>
        /// Decode the binary Maxwell shader code to a translator context.
        /// </summary>
        /// <remarks>
        /// This will combine the "Vertex A" and "Vertex B" shader stages, if specified, into one shader.
        /// </remarks>
        /// <param name="channel">GPU channel</param>
        /// <param name="gas">GPU accessor state</param>
        /// <param name="counts">Cumulative shader resource counts</param>
        /// <param name="flags">Flags that controls shader translation</param>
        /// <param name="stage">Shader stage</param>
        /// <param name="gpuVa">GPU virtual address of the shader code</param>
        /// <returns>The generated translator context</returns>
        private TranslatorContext DecodeGraphicsShader(
            GpuChannel channel,
            GpuAccessorState gas,
            TranslationCounts counts,
            TranslationFlags flags,
            ShaderStage stage,
            ulong gpuVa)
        {
            if (gpuVa == 0)
            {
                return(null);
            }

            GpuAccessor gpuAccessor = new GpuAccessor(_context, channel, gas, (int)stage - 1);

            var options = new TranslationOptions(TargetLanguage.Glsl, TargetApi.OpenGL, flags);

            return(Translator.CreateContext(gpuVa, gpuAccessor, options, counts));
        }
Exemple #6
0
 /// <summary>
 /// Creates a new instance of the GPU state accessor for compute shader translation.
 /// </summary>
 /// <param name="context">GPU context</param>
 /// <param name="channel">GPU channel</param>
 /// <param name="state">Current GPU state</param>
 /// <param name="localSizeX">Local group size X of the compute shader</param>
 /// <param name="localSizeY">Local group size Y of the compute shader</param>
 /// <param name="localSizeZ">Local group size Z of the compute shader</param>
 /// <param name="localMemorySize">Local memory size of the compute shader</param>
 /// <param name="sharedMemorySize">Shared memory size of the compute shader</param>
 public GpuAccessor(
     GpuContext context,
     GpuChannel channel,
     GpuAccessorState state,
     int localSizeX,
     int localSizeY,
     int localSizeZ,
     int localMemorySize,
     int sharedMemorySize) : base(context)
 {
     _channel          = channel;
     _state            = state;
     _compute          = true;
     _localSizeX       = localSizeX;
     _localSizeY       = localSizeY;
     _localSizeZ       = localSizeZ;
     _localMemorySize  = localMemorySize;
     _sharedMemorySize = sharedMemorySize;
 }
Exemple #7
0
        /// <summary>
        /// Decode the binary Maxwell shader code to a translator context.
        /// </summary>
        /// <remarks>
        /// This will combine the "Vertex A" and "Vertex B" shader stages, if specified, into one shader.
        /// </remarks>
        /// <param name="channel">GPU channel</param>
        /// <param name="gas">GPU accessor state</param>
        /// <param name="tfd">Transform feedback descriptors</param>
        /// <param name="flags">Flags that controls shader translation</param>
        /// <param name="stage">Shader stage</param>
        /// <param name="gpuVa">GPU virtual address of the shader code</param>
        /// <returns>The generated translator context</returns>
        private TranslatorContext DecodeGraphicsShader(
            GpuChannel channel,
            GpuAccessorState gas,
            TransformFeedbackDescriptor[] tfd,
            TranslationFlags flags,
            ShaderStage stage,
            ulong gpuVa)
        {
            if (gpuVa == 0)
            {
                return(null);
            }

            GpuAccessor gpuAccessor = new GpuAccessor(_context, channel, gas, tfd, (int)stage - 1);

            var options = CreateTranslationOptions(flags);

            return(Translator.CreateContext(gpuVa, gpuAccessor, options));
        }
        /// <summary>
        /// Decode the binary Maxwell shader code to a translator context.
        /// </summary>
        /// <param name="channel">GPU channel</param>
        /// <param name="gas">GPU accessor 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>The generated translator context</returns>
        private TranslatorContext DecodeComputeShader(
            GpuChannel channel,
            GpuAccessorState gas,
            ulong gpuVa,
            int localSizeX,
            int localSizeY,
            int localSizeZ,
            int localMemorySize,
            int sharedMemorySize)
        {
            if (gpuVa == 0)
            {
                return(null);
            }

            GpuAccessor gpuAccessor = new GpuAccessor(_context, channel, gas, localSizeX, localSizeY, localSizeZ, localMemorySize, sharedMemorySize);

            var options = new TranslationOptions(TargetLanguage.Glsl, TargetApi.OpenGL, DefaultFlags | TranslationFlags.Compute);

            return(Translator.CreateContext(gpuVa, gpuAccessor, options));
        }
Exemple #9
0
        /// <summary>
        /// Decode the binary Maxwell shader code to a translator context.
        /// </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="counts">Cumulative shader resource counts</param>
        /// <param name="flags">Flags that controls shader translation</param>
        /// <param name="stage">Shader stage</param>
        /// <param name="gpuVa">GPU virtual address of the shader code</param>
        /// <returns>The generated translator context</returns>
        private TranslatorContext DecodeGraphicsShader(
            GpuState state,
            TranslationCounts counts,
            TranslationFlags flags,
            ShaderStage stage,
            ulong gpuVa)
        {
            if (gpuVa == 0)
            {
                return(null);
            }

            GpuAccessorState gas = new GpuAccessorState(
                state.Get <PoolState>(MethodOffset.TexturePoolState).Address.Pack(),
                state.Get <PoolState>(MethodOffset.TexturePoolState).MaximumId,
                state.Get <int>(MethodOffset.TextureBufferIndex),
                state.Get <Boolean32>(MethodOffset.EarlyZForce));

            GpuAccessor gpuAccessor = new GpuAccessor(_context, state.Channel, gas, (int)stage - 1);

            var options = new TranslationOptions(TargetLanguage.Glsl, TargetApi.OpenGL, flags);

            return(Translator.CreateContext(gpuVa, gpuAccessor, options, counts));
        }
Exemple #10
0
 /// <summary>
 /// Creates a new instance of the GPU state accessor for compute shader translation.
 /// </summary>
 /// <param name="context">GPU context</param>
 /// <param name="channel">GPU channel</param>
 /// <param name="state">Current GPU state</param>
 public GpuAccessor(GpuContext context, GpuChannel channel, GpuAccessorState state) : base(context)
 {
     _channel = channel;
     _state   = state;
     _compute = true;
 }
        /// <summary>
        /// Gets a graphics shader program from the shader cache.
        /// This includes all the specified shader stages.
        /// </summary>
        /// <remarks>
        /// This automatically translates, compiles and adds the code to the cache if not present.
        /// </remarks>
        /// <param name="state">GPU state</param>
        /// <param name="channel">GPU channel</param>
        /// <param name="gas">GPU accessor state</param>
        /// <param name="addresses">Addresses of the shaders for each stage</param>
        /// <returns>Compiled graphics shader code</returns>
        public ShaderBundle GetGraphicsShader(ref ThreedClassState state, GpuChannel channel, GpuAccessorState gas, ShaderAddresses addresses)
        {
            bool isCached = _gpPrograms.TryGetValue(addresses, out List <ShaderBundle> list);

            if (isCached)
            {
                foreach (ShaderBundle cachedGpShaders in list)
                {
                    if (IsShaderEqual(channel.MemoryManager, cachedGpShaders, addresses))
                    {
                        return(cachedGpShaders);
                    }
                }
            }

            TranslatorContext[] shaderContexts = new TranslatorContext[Constants.ShaderStages + 1];

            TransformFeedbackDescriptor[] tfd = GetTransformFeedbackDescriptors(ref state);

            TranslationFlags flags = DefaultFlags;

            if (tfd != null)
            {
                flags |= TranslationFlags.Feedback;
            }

            TranslationCounts counts = new TranslationCounts();

            if (addresses.VertexA != 0)
            {
                shaderContexts[0] = DecodeGraphicsShader(channel, gas, counts, flags | TranslationFlags.VertexA, ShaderStage.Vertex, addresses.VertexA);
            }

            shaderContexts[1] = DecodeGraphicsShader(channel, gas, counts, flags, ShaderStage.Vertex, addresses.Vertex);
            shaderContexts[2] = DecodeGraphicsShader(channel, gas, counts, flags, ShaderStage.TessellationControl, addresses.TessControl);
            shaderContexts[3] = DecodeGraphicsShader(channel, gas, counts, flags, ShaderStage.TessellationEvaluation, addresses.TessEvaluation);
            shaderContexts[4] = DecodeGraphicsShader(channel, gas, counts, flags, ShaderStage.Geometry, addresses.Geometry);
            shaderContexts[5] = DecodeGraphicsShader(channel, gas, counts, flags, ShaderStage.Fragment, addresses.Fragment);

            bool isShaderCacheEnabled  = _cacheManager != null;
            bool isShaderCacheReadOnly = false;

            Hash128 programCodeHash = default;

            GuestShaderCacheEntry[] shaderCacheEntries = null;

            // Current shader cache doesn't support bindless textures
            for (int i = 0; i < shaderContexts.Length; i++)
            {
                if (shaderContexts[i] != null && shaderContexts[i].UsedFeatures.HasFlag(FeatureFlags.Bindless))
                {
                    isShaderCacheEnabled = false;
                    break;
                }
            }

            if (isShaderCacheEnabled)
            {
                isShaderCacheReadOnly = _cacheManager.IsReadOnly;

                // Compute hash and prepare data for shader disk cache comparison.
                shaderCacheEntries = CacheHelper.CreateShaderCacheEntries(channel.MemoryManager, shaderContexts);
                programCodeHash    = CacheHelper.ComputeGuestHashFromCache(shaderCacheEntries, tfd);
            }

            ShaderBundle gpShaders;

            // Search for the program hash in loaded shaders.
            if (!isShaderCacheEnabled || !_gpProgramsDiskCache.TryGetValue(programCodeHash, out gpShaders))
            {
                if (isShaderCacheEnabled)
                {
                    Logger.Debug?.Print(LogClass.Gpu, $"Shader {programCodeHash} not in cache, compiling!");
                }

                // The shader isn't currently cached, translate it and compile it.
                ShaderCodeHolder[] shaders = new ShaderCodeHolder[Constants.ShaderStages];

                for (int stageIndex = 0; stageIndex < Constants.ShaderStages; stageIndex++)
                {
                    shaders[stageIndex] = TranslateShader(_dumper, channel.MemoryManager, shaderContexts, stageIndex + 1);
                }

                List <IShader> hostShaders = new List <IShader>();

                for (int stage = 0; stage < Constants.ShaderStages; stage++)
                {
                    ShaderProgram program = shaders[stage]?.Program;

                    if (program == null)
                    {
                        continue;
                    }

                    IShader hostShader = _context.Renderer.CompileShader(program.Stage, program.Code);

                    shaders[stage].HostShader = hostShader;

                    hostShaders.Add(hostShader);
                }

                IProgram hostProgram = _context.Renderer.CreateProgram(hostShaders.ToArray(), tfd);

                hostProgram.CheckProgramLink(true);

                byte[] hostProgramBinary = HostShaderCacheEntry.Create(hostProgram.GetBinary(), shaders);

                gpShaders = new ShaderBundle(hostProgram, shaders);

                if (isShaderCacheEnabled)
                {
                    _gpProgramsDiskCache.Add(programCodeHash, gpShaders);

                    if (!isShaderCacheReadOnly)
                    {
                        _cacheManager.SaveProgram(ref programCodeHash, CacheHelper.CreateGuestProgramDump(shaderCacheEntries, tfd), hostProgramBinary);
                    }
                }
            }

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

                _gpPrograms.Add(addresses, list);
            }

            list.Add(gpShaders);

            return(gpShaders);
        }
        /// <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="channel">GPU channel</param>
        /// <param name="gas">GPU accessor 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>
        public ShaderBundle GetComputeShader(
            GpuChannel channel,
            GpuAccessorState gas,
            ulong gpuVa,
            int localSizeX,
            int localSizeY,
            int localSizeZ,
            int localMemorySize,
            int sharedMemorySize)
        {
            bool isCached = _cpPrograms.TryGetValue(gpuVa, out List <ShaderBundle> list);

            if (isCached)
            {
                foreach (ShaderBundle cachedCpShader in list)
                {
                    if (IsShaderEqual(channel.MemoryManager, cachedCpShader, gpuVa))
                    {
                        return(cachedCpShader);
                    }
                }
            }

            TranslatorContext[] shaderContexts = new TranslatorContext[1];

            shaderContexts[0] = DecodeComputeShader(
                channel,
                gas,
                gpuVa,
                localSizeX,
                localSizeY,
                localSizeZ,
                localMemorySize,
                sharedMemorySize);

            bool isShaderCacheEnabled  = _cacheManager != null;
            bool isShaderCacheReadOnly = false;

            Hash128 programCodeHash = default;

            GuestShaderCacheEntry[] shaderCacheEntries = null;

            // Current shader cache doesn't support bindless textures
            if (shaderContexts[0].UsedFeatures.HasFlag(FeatureFlags.Bindless))
            {
                isShaderCacheEnabled = false;
            }

            if (isShaderCacheEnabled)
            {
                isShaderCacheReadOnly = _cacheManager.IsReadOnly;

                // Compute hash and prepare data for shader disk cache comparison.
                shaderCacheEntries = CacheHelper.CreateShaderCacheEntries(channel.MemoryManager, shaderContexts);
                programCodeHash    = CacheHelper.ComputeGuestHashFromCache(shaderCacheEntries);
            }

            ShaderBundle cpShader;

            // Search for the program hash in loaded shaders.
            if (!isShaderCacheEnabled || !_cpProgramsDiskCache.TryGetValue(programCodeHash, out cpShader))
            {
                if (isShaderCacheEnabled)
                {
                    Logger.Debug?.Print(LogClass.Gpu, $"Shader {programCodeHash} not in cache, compiling!");
                }

                // The shader isn't currently cached, translate it and compile it.
                ShaderCodeHolder shader = TranslateShader(_dumper, channel.MemoryManager, shaderContexts[0], null, null);

                shader.HostShader = _context.Renderer.CompileShader(ShaderStage.Compute, shader.Program.Code);

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

                hostProgram.CheckProgramLink(true);

                byte[] hostProgramBinary = HostShaderCacheEntry.Create(hostProgram.GetBinary(), new ShaderCodeHolder[] { shader });

                cpShader = new ShaderBundle(hostProgram, shader);

                if (isShaderCacheEnabled)
                {
                    _cpProgramsDiskCache.Add(programCodeHash, cpShader);

                    if (!isShaderCacheReadOnly)
                    {
                        _cacheManager.SaveProgram(ref programCodeHash, CacheHelper.CreateGuestProgramDump(shaderCacheEntries), hostProgramBinary);
                    }
                }
            }

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

                _cpPrograms.Add(gpuVa, list);
            }

            list.Add(cpShader);

            return(cpShader);
        }
Exemple #13
0
 /// <summary>
 /// Creates a new instance of the GPU state accessor for compute shader translation.
 /// </summary>
 /// <param name="context">GPU context</param>
 /// <param name="channel">GPU channel</param>
 /// <param name="state">Current GPU state</param>
 public GpuAccessor(GpuContext context, GpuChannel channel, GpuAccessorState state) : base(context, state.ResourceCounts, 0)
 {
     _channel = channel;
     _state   = state;
     _compute = true;
 }