/// <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) { if (_textureBindings[stageIndex] == null) { return; } for (int index = 0; index < _textureBindings[stageIndex].Length; index++) { TextureBindingInfo bindingInfo = _textureBindings[stageIndex][index]; int textureBufferIndex = bindingInfo.CbufSlot < 0 ? _textureBufferIndex : bindingInfo.CbufSlot; int packedId = ReadPackedId(stageIndex, bindingInfo.Handle, textureBufferIndex); 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 (_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); } 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. _context.Methods.BufferManager.SetBufferTextureStorage(hostTexture, texture.Range.GetSubRange(0).Address, texture.Size, bindingInfo, bindingInfo.Format, false); } Sampler sampler = _samplerPool.Get(samplerId); ISampler hostSampler = sampler?.HostSampler; if (_textureState[stageIndex][index].Sampler != hostSampler || _rebind) { _textureState[stageIndex][index].Sampler = hostSampler; _context.Renderer.Pipeline.SetSampler(bindingInfo.Binding, hostSampler); } } }
/// <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) { if (_textureBindings[stageIndex] == null || _textureBindings[stageIndex].Length == 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; } if (samplerPool == null) { Logger.Error?.Print(LogClass.Gpu, $"Shader stage \"{stage}\" uses textures, but sampler pool was not set."); return; } for (int index = 0; index < _textureBindings[stageIndex].Length; index++) { TextureBindingInfo bindingInfo = _textureBindings[stageIndex][index]; int textureBufferIndex; int samplerBufferIndex; if (bindingInfo.CbufSlot < 0) { textureBufferIndex = _textureBufferIndex; samplerBufferIndex = textureBufferIndex; } else { textureBufferIndex = bindingInfo.CbufSlot & SlotMask; samplerBufferIndex = ((bindingInfo.CbufSlot >> SlotHigh) != 0) ? (bindingInfo.CbufSlot >> SlotHigh) - 1 : 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); Sampler sampler = _samplerPool.Get(samplerId); ITexture hostTexture = texture?.GetTargetTexture(bindingInfo.Target); ISampler hostSampler = sampler?.HostSampler; if (_textureState[stageIndex][index].Texture != hostTexture || _textureState[stageIndex][index].Sampler != hostSampler || _rebind) { if (UpdateScale(texture, bindingInfo, index, stage)) { hostTexture = texture?.GetTargetTexture(bindingInfo.Target); } _textureState[stageIndex][index].Texture = hostTexture; _textureState[stageIndex][index].Sampler = hostSampler; _context.Renderer.Pipeline.SetTextureAndSampler(bindingInfo.Binding, hostTexture, hostSampler); } 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); } } }