예제 #1
0
        /// <summary>
        /// Gets the texture descriptor for a given texture handle.
        /// </summary>
        /// <param name="poolGpuVa">GPU virtual address of the texture pool</param>
        /// <param name="bufferIndex">Index of the constant buffer with texture handles</param>
        /// <param name="maximumId">Maximum ID of the texture pool</param>
        /// <param name="stageIndex">The stage number where the texture is bound</param>
        /// <param name="handle">The texture handle</param>
        /// <param name="cbufSlot">The texture handle's constant buffer slot</param>
        /// <returns>The texture descriptor for the specified texture</returns>
        public TextureDescriptor GetTextureDescriptor(
            ulong poolGpuVa,
            int bufferIndex,
            int maximumId,
            int stageIndex,
            int handle,
            int cbufSlot)
        {
            (int textureBufferIndex, int samplerBufferIndex) = TextureHandle.UnpackSlots(cbufSlot, bufferIndex);

            int packedId  = ReadPackedId(stageIndex, handle, textureBufferIndex, samplerBufferIndex);
            int textureId = UnpackTextureId(packedId);

            ulong poolAddress = _channel.MemoryManager.Translate(poolGpuVa);

            TexturePool texturePool = _texturePoolCache.FindOrCreate(_channel, poolAddress, maximumId);

            return(texturePool.GetDescriptor(textureId));
        }
예제 #2
0
        /// <summary>
        /// Ensures that the texture bindings are visible to the host GPU.
        /// Note: this actually performs the binding using the host graphics API.
        /// </summary>
        /// <param name="pool">The current texture pool</param>
        /// <param name="stage">The shader stage using the textures to be bound</param>
        /// <param name="stageIndex">The stage number of the specified shader stage</param>
        private void CommitTextureBindings(TexturePool pool, ShaderStage stage, int stageIndex)
        {
            int textureCount = _textureBindingsCount[stageIndex];

            if (textureCount == 0)
            {
                return;
            }

            var samplerPool = _samplerPool;

            if (pool == null)
            {
                Logger.Error?.Print(LogClass.Gpu, $"Shader stage \"{stage}\" uses textures, but texture pool was not set.");
                return;
            }

            for (int index = 0; index < textureCount; index++)
            {
                TextureBindingInfo bindingInfo = _textureBindings[stageIndex][index];

                (int textureBufferIndex, int samplerBufferIndex) = TextureHandle.UnpackSlots(bindingInfo.CbufSlot, _textureBufferIndex);

                int packedId  = ReadPackedId(stageIndex, bindingInfo.Handle, textureBufferIndex, samplerBufferIndex);
                int textureId = UnpackTextureId(packedId);
                int samplerId;

                if (_samplerIndex == SamplerIndex.ViaHeaderIndex)
                {
                    samplerId = textureId;
                }
                else
                {
                    samplerId = UnpackSamplerId(packedId);
                }

                Texture texture = pool.Get(textureId);

                ITexture hostTexture = texture?.GetTargetTexture(bindingInfo.Target);

                if (hostTexture != null && texture.Target == Target.TextureBuffer)
                {
                    // Ensure that the buffer texture is using the correct buffer as storage.
                    // Buffers are frequently re-created to accomodate larger data, so we need to re-bind
                    // to ensure we're not using a old buffer that was already deleted.
                    _channel.BufferManager.SetBufferTextureStorage(hostTexture, texture.Range.GetSubRange(0).Address, texture.Size, bindingInfo, bindingInfo.Format, false);
                }
                else
                {
                    if (_textureState[stageIndex][index].Texture != hostTexture || _rebind)
                    {
                        if (UpdateScale(texture, bindingInfo, index, stage))
                        {
                            hostTexture = texture?.GetTargetTexture(bindingInfo.Target);
                        }

                        _textureState[stageIndex][index].Texture = hostTexture;

                        _context.Renderer.Pipeline.SetTexture(bindingInfo.Binding, hostTexture);
                    }

                    Sampler sampler = samplerPool?.Get(samplerId);

                    ISampler hostSampler = sampler?.GetHostSampler(texture);

                    if (_textureState[stageIndex][index].Sampler != hostSampler || _rebind)
                    {
                        _textureState[stageIndex][index].Sampler = hostSampler;

                        _context.Renderer.Pipeline.SetSampler(bindingInfo.Binding, hostSampler);
                    }
                }
            }
        }
예제 #3
0
        /// <summary>
        /// Ensures that the image bindings are visible to the host GPU.
        /// Note: this actually performs the binding using the host graphics API.
        /// </summary>
        /// <param name="pool">The current texture pool</param>
        /// <param name="stage">The shader stage using the textures to be bound</param>
        /// <param name="stageIndex">The stage number of the specified shader stage</param>
        private void CommitImageBindings(TexturePool pool, ShaderStage stage, int stageIndex)
        {
            int imageCount = _imageBindingsCount[stageIndex];

            if (imageCount == 0)
            {
                return;
            }

            if (pool == null)
            {
                Logger.Error?.Print(LogClass.Gpu, $"Shader stage \"{stage}\" uses images, but texture pool was not set.");
                return;
            }

            // Scales for images appear after the texture ones.
            int baseScaleIndex = _textureBindingsCount[stageIndex];

            for (int index = 0; index < imageCount; index++)
            {
                TextureBindingInfo bindingInfo = _imageBindings[stageIndex][index];

                (int textureBufferIndex, int samplerBufferIndex) = TextureHandle.UnpackSlots(bindingInfo.CbufSlot, _textureBufferIndex);

                int packedId  = ReadPackedId(stageIndex, bindingInfo.Handle, textureBufferIndex, samplerBufferIndex);
                int textureId = UnpackTextureId(packedId);

                Texture texture = pool.Get(textureId);

                ITexture hostTexture = texture?.GetTargetTexture(bindingInfo.Target);

                bool isStore = bindingInfo.Flags.HasFlag(TextureUsageFlags.ImageStore);

                if (hostTexture != null && texture.Target == Target.TextureBuffer)
                {
                    // Ensure that the buffer texture is using the correct buffer as storage.
                    // Buffers are frequently re-created to accomodate larger data, so we need to re-bind
                    // to ensure we're not using a old buffer that was already deleted.

                    Format format = bindingInfo.Format;

                    if (format == 0 && texture != null)
                    {
                        format = texture.Format;
                    }

                    _channel.BufferManager.SetBufferTextureStorage(hostTexture, texture.Range.GetSubRange(0).Address, texture.Size, bindingInfo, format, true);
                }
                else
                {
                    if (isStore)
                    {
                        texture?.SignalModified();
                    }

                    if (_imageState[stageIndex][index].Texture != hostTexture || _rebind)
                    {
                        if (UpdateScale(texture, bindingInfo, baseScaleIndex + index, stage))
                        {
                            hostTexture = texture?.GetTargetTexture(bindingInfo.Target);
                        }

                        _imageState[stageIndex][index].Texture = hostTexture;

                        Format format = bindingInfo.Format;

                        if (format == 0 && texture != null)
                        {
                            format = texture.Format;
                        }

                        _context.Renderer.Pipeline.SetImage(bindingInfo.Binding, hostTexture, format);
                    }
                }
            }
        }
예제 #4
0
        /// <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);
        }