/// <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="poolState">Texture pool state</param> /// <param name="computeState">Compute engine state</param> /// <param name="gpuVa">GPU virtual address of the binary shader code</param> /// <returns>Compiled compute shader code</returns> public CachedShaderProgram GetComputeShader( GpuChannel channel, GpuChannelPoolState poolState, GpuChannelComputeState computeState, ulong gpuVa) { if (_cpPrograms.TryGetValue(gpuVa, out var cpShader) && IsShaderEqual(channel, poolState, cpShader, gpuVa)) { return(cpShader); } if (_computeShaderCache.TryFind(channel, poolState, gpuVa, out cpShader, out byte[] cachedGuestCode))
/// <summary> /// Tries to find a cached program. /// </summary> /// <param name="channel">GPU channel</param> /// <param name="poolState">Texture pool state</param> /// <param name="gpuVa">GPU virtual address of the compute shader</param> /// <param name="program">Cached host program for the given state, if found</param> /// <param name="cachedGuestCode">Cached guest code, if any found</param> /// <returns>True if a cached host program was found, false otherwise</returns> public bool TryFind( GpuChannel channel, GpuChannelPoolState poolState, ulong gpuVa, out CachedShaderProgram program, out byte[] cachedGuestCode) { program = null; ShaderCodeAccessor codeAccessor = new ShaderCodeAccessor(channel.MemoryManager, gpuVa); bool hasSpecList = _cache.TryFindItem(codeAccessor, out var specList, out cachedGuestCode); return(hasSpecList && specList.TryFindForCompute(channel, poolState, out program)); }
/// <summary> /// Tries to find an existing compute program on the cache. /// </summary> /// <param name="channel">GPU channel</param> /// <param name="poolState">Texture pool state</param> /// <param name="program">Cached program, if found</param> /// <returns>True if a compatible program is found, false otherwise</returns> public bool TryFindForCompute(GpuChannel channel, GpuChannelPoolState poolState, out CachedShaderProgram program) { foreach (var entry in _entries) { if (entry.SpecializationState.MatchesCompute(channel, poolState, true)) { program = entry; return(true); } } program = default; return(false); }
/// <summary> /// Checks if the recorded state matches the current GPU 3D engine state. /// </summary> /// <param name="channel">GPU channel</param> /// <param name="poolState">Texture pool state</param> /// <param name="graphicsState">Graphics state</param> /// <param name="checkTextures">Indicates whether texture descriptors should be checked</param> /// <returns>True if the state matches, false otherwise</returns> public bool MatchesGraphics(GpuChannel channel, GpuChannelPoolState poolState, GpuChannelGraphicsState graphicsState, bool checkTextures) { if (graphicsState.ViewportTransformDisable != GraphicsState.ViewportTransformDisable) { return(false); } bool thisA2cDitherEnable = GraphicsState.AlphaToCoverageEnable && GraphicsState.AlphaToCoverageDitherEnable; bool otherA2cDitherEnable = graphicsState.AlphaToCoverageEnable && graphicsState.AlphaToCoverageDitherEnable; if (otherA2cDitherEnable != thisA2cDitherEnable) { return(false); } return(Matches(channel, poolState, checkTextures, isCompute: false)); }
/// <summary> /// Checks if the recorded state matches the current GPU 3D engine state. /// </summary> /// <param name="channel">GPU channel</param> /// <param name="poolState">Texture pool state</param> /// <param name="graphicsState">Graphics state</param> /// <param name="checkTextures">Indicates whether texture descriptors should be checked</param> /// <returns>True if the state matches, false otherwise</returns> public bool MatchesGraphics(GpuChannel channel, GpuChannelPoolState poolState, GpuChannelGraphicsState graphicsState, bool checkTextures) { if (graphicsState.ViewportTransformDisable != GraphicsState.ViewportTransformDisable) { return(false); } bool thisA2cDitherEnable = GraphicsState.AlphaToCoverageEnable && GraphicsState.AlphaToCoverageDitherEnable; bool otherA2cDitherEnable = graphicsState.AlphaToCoverageEnable && graphicsState.AlphaToCoverageDitherEnable; if (otherA2cDitherEnable != thisA2cDitherEnable) { return(false); } if (graphicsState.DepthMode != GraphicsState.DepthMode) { return(false); } if (graphicsState.AlphaTestEnable != GraphicsState.AlphaTestEnable) { return(false); } if (graphicsState.AlphaTestEnable && (graphicsState.AlphaTestCompare != GraphicsState.AlphaTestCompare || graphicsState.AlphaTestReference != GraphicsState.AlphaTestReference)) { return(false); } if (!graphicsState.AttributeTypes.AsSpan().SequenceEqual(GraphicsState.AttributeTypes.AsSpan())) { return(false); } return(Matches(channel, poolState, checkTextures, isCompute: false)); }
/// <summary> /// Checks if the recorded state matches the current GPU compute engine state. /// </summary> /// <param name="channel">GPU channel</param> /// <param name="poolState">Texture pool state</param> /// <param name="checkTextures">Indicates whether texture descriptors should be checked</param> /// <returns>True if the state matches, false otherwise</returns> public bool MatchesCompute(GpuChannel channel, GpuChannelPoolState poolState, bool checkTextures) { return(Matches(channel, poolState, checkTextures, isCompute: true)); }
/// <summary> /// Checks if the recorded state matches the current GPU state. /// </summary> /// <param name="channel">GPU channel</param> /// <param name="poolState">Texture pool state</param> /// <param name="isCompute">Indicates whenever the check is requested by the 3D or compute engine</param> /// <returns>True if the state matches, false otherwise</returns> private bool Matches(GpuChannel channel, GpuChannelPoolState poolState, bool isCompute) { int constantBufferUsePerStageMask = _constantBufferUsePerStage; while (constantBufferUsePerStageMask != 0) { int index = BitOperations.TrailingZeroCount(constantBufferUsePerStageMask); uint useMask = isCompute ? channel.BufferManager.GetComputeUniformBufferUseMask() : channel.BufferManager.GetGraphicsUniformBufferUseMask(index); if (ConstantBufferUse[index] != useMask) { return(false); } constantBufferUsePerStageMask &= ~(1 << index); } foreach (var kv in _textureSpecialization) { TextureKey textureKey = kv.Key; (int textureBufferIndex, int samplerBufferIndex) = TextureHandle.UnpackSlots(textureKey.CbufSlot, poolState.TextureBufferIndex); ulong textureCbAddress; ulong samplerCbAddress; if (isCompute) { textureCbAddress = channel.BufferManager.GetComputeUniformBufferAddress(textureBufferIndex); samplerCbAddress = channel.BufferManager.GetComputeUniformBufferAddress(samplerBufferIndex); } else { textureCbAddress = channel.BufferManager.GetGraphicsUniformBufferAddress(textureKey.StageIndex, textureBufferIndex); samplerCbAddress = channel.BufferManager.GetGraphicsUniformBufferAddress(textureKey.StageIndex, samplerBufferIndex); } if (!channel.MemoryManager.Physical.IsMapped(textureCbAddress) || !channel.MemoryManager.Physical.IsMapped(samplerCbAddress)) { continue; } Image.TextureDescriptor descriptor; if (isCompute) { descriptor = channel.TextureManager.GetComputeTextureDescriptor( poolState.TexturePoolGpuVa, poolState.TextureBufferIndex, poolState.TexturePoolMaximumId, textureKey.Handle, textureKey.CbufSlot); } else { descriptor = channel.TextureManager.GetGraphicsTextureDescriptor( poolState.TexturePoolGpuVa, poolState.TextureBufferIndex, poolState.TexturePoolMaximumId, textureKey.StageIndex, textureKey.Handle, textureKey.CbufSlot); } Box <TextureSpecializationState> specializationState = kv.Value; if (specializationState.Value.QueriedFlags.HasFlag(QueriedTextureStateFlags.CoordNormalized) && specializationState.Value.CoordNormalized != descriptor.UnpackTextureCoordNormalized()) { return(false); } } return(true); }
/// <summary> /// Checks if the recorded state matches the current GPU compute engine state. /// </summary> /// <param name="channel">GPU channel</param> /// <param name="poolState">Texture pool state</param> /// <returns>True if the state matches, false otherwise</returns> public bool MatchesCompute(GpuChannel channel, GpuChannelPoolState poolState) { return(Matches(channel, poolState, isCompute: true)); }
/// <summary> /// Checks if the recorded state matches the current GPU 3D engine state. /// </summary> /// <param name="channel">GPU channel</param> /// <param name="poolState">Texture pool state</param> /// <returns>True if the state matches, false otherwise</returns> public bool MatchesGraphics(GpuChannel channel, GpuChannelPoolState poolState) { return(Matches(channel, poolState, isCompute: false)); }