/// <summary> /// Function to rent a render target from the factory. /// </summary> /// <param name="targetInfo">The information about the render target to retrieve.</param> /// <param name="name">A unique user defined name for a new render target.</param> /// <param name="clearOnRetrieve">[Optional] <b>true</b> to clear the render target when retrieved, or <b>false</b> to leave the contents as-is.</param> /// <returns>The requested render target.</returns> /// <exception cref="ArgumentNullException">Thrown when the <paramref name="targetInfo"/>, or the <paramref name="name"/> parameter is <b>null</b>.</exception> /// <exception cref="ArgumentException">Thrown when the <paramref name="name"/> parameter is empty.</exception> /// <remarks> /// <para> /// All calls to this method should be paired with a call to the <see cref="Return"/> method. Failure to do so may result in a leak. /// </para> /// <para> /// The optional <paramref name="clearOnRetrieve"/> parameter, if set to <b>true</b>,, will clear the contents of a render target that is being reused /// prior to returning it. In some cases this is not ideal, so setting it to <b>false</b> will preserve the contents. New render targets will always /// be cleared. /// </para> /// <note type="caution"> /// <para> /// For performance reasons, any exceptions thrown from this method will only be thrown when Gorgon is compiled as DEBUG. /// </para> /// </note> /// </remarks> public GorgonRenderTarget2DView Rent(IGorgonTexture2DInfo targetInfo, string name, bool clearOnRetrieve = true) { name.ValidateString(nameof(name)); targetInfo.ValidateObject(nameof(targetInfo)); ExpireTargets(); // Ensure the information is valid. GorgonTexture2DInfo newInfo = _textureInfoAllocator.Allocate(); newInfo.Copy(name, targetInfo); newInfo.Binding = targetInfo.Binding | TextureBinding.RenderTarget | TextureBinding.ShaderResource; newInfo.Usage = ResourceUsage.Default; for (int i = 0; i < _renderTargets.Count; ++i) { GorgonRenderTarget2DView rtv = _renderTargets[i]; GorgonTexture2D target = _renderTargets[i].Texture; if ((!_rented.Contains(rtv)) && (target.Width == newInfo.Width) && (target.Height == newInfo.Height) && (target.MipLevels == newInfo.MipLevels) && (target.ArrayCount == newInfo.ArrayCount) && (target.Format == newInfo.Format) && (target.Binding == newInfo.Binding) && (target.MultisampleInfo.Equals(newInfo.MultisampleInfo)) && (newInfo.IsCubeMap == target.IsCubeMap) && (string.Equals(newInfo.Name, rtv.Texture.Name, StringComparison.OrdinalIgnoreCase))) { if (clearOnRetrieve) { rtv.Clear(GorgonColor.BlackTransparent); } _renderTargets.Remove(rtv); _expiryTime.Remove(rtv); _rented.Add(rtv); return(rtv); } } if (_renderTargets.Count == 0) { _expiryTimer.Reset(); } var newRtv = GorgonRenderTarget2DView.CreateRenderTarget(_graphics, newInfo); // Cache a default shader resource view (the texture holds the cache, we hold a separate one so we can clean it up later). _srvs.Add(newRtv.GetShaderResourceView()); newRtv.OwnerFactory = this; _rented.Add(newRtv); newRtv.Clear(GorgonColor.BlackTransparent); return(newRtv); }
/// <summary> /// Function to return the render target to the factory. /// </summary> /// <param name="rtv">The render target to return.</param> /// <returns><b>true</b> if the target was returned successfully, <b>false</b> if not.</returns> public bool Return(GorgonRenderTarget2DView rtv) { if ((rtv == null) || (rtv.OwnerFactory != this)) { return(false); } if (!_rented.Remove(rtv)) { return(false); } _renderTargets.Add(rtv); return(true); }
/// <summary> /// Function to return the render target to the factory. /// </summary> /// <param name="rtv">The render target to return.</param> /// <returns><b>true</b> if the target was returned successfully, <b>false</b> if not.</returns> public bool Return(GorgonRenderTarget2DView rtv) { ExpireTargets(); if ((rtv == null) || (rtv.OwnerFactory != this)) { return(false); } if (!_rented.Remove(rtv)) { return(false); } _renderTargets.Add(rtv); _expiryTime[rtv] = _expiryTimer.Minutes + (ExpiryTime < 0 ? 0 : ExpiryTime); return(true); }
/// <summary> /// Function to rent a render target from the factory. /// </summary> /// <param name="targetInfo">The information about the render target to retrieve.</param> /// <param name="name">[Optional] A user defined name for a new render target.</param> /// <param name="clearOnRetrieve">[Optional] <b>true</b> to clear the render target when retrieved, or <b>false</b> to leave the contents as-is.</param> /// <returns>The requested render target.</returns> /// <exception cref="ArgumentNullException">Thrown when the <paramref name="targetInfo"/> parameter is <b>null</b>.</exception> /// <remarks> /// <para> /// All calls to this method should be paired with a call to the <see cref="Return"/> method. Failure to do so may result in a leak. /// </para> /// <para> /// The optional <paramref name="clearOnRetrieve"/> parameter, if set to <b>true</b>,, will clear the contents of a render target that is being reused /// prior to returning it. In some cases this is not ideal, so setting it to <b>false</b> will preserve the contents. New render targets will always /// be cleared. /// </para> /// <note type="caution"> /// <para> /// For performance reasons, any exceptions thrown from this method will only be thrown when Gorgon is compiled as DEBUG. /// </para> /// </note> /// </remarks> public GorgonRenderTarget2DView Rent(IGorgonTexture2DInfo targetInfo, string name = null, bool clearOnRetrieve = true) { targetInfo.ValidateObject(nameof(targetInfo)); // Ensure the information is valid. targetInfo = new GorgonTexture2DInfo(targetInfo, string.IsNullOrWhiteSpace(name) ? $"TempTarget_{_srvs.Count}_{targetInfo.Name}" : name) { Binding = targetInfo.Binding | TextureBinding.RenderTarget, Usage = ResourceUsage.Default }; for (int i = 0; i < _renderTargets.Count; ++i) { GorgonRenderTarget2DView rtv = _renderTargets[i]; GorgonTexture2D target = _renderTargets[i].Texture; if ((!_rented.Contains(rtv)) && (target.Width == targetInfo.Width) && (target.Height == targetInfo.Height) && (target.MipLevels == targetInfo.MipLevels) && (target.ArrayCount == targetInfo.ArrayCount) && (target.Format == targetInfo.Format) && (target.Binding == targetInfo.Binding) && (target.MultisampleInfo.Equals(targetInfo.MultisampleInfo)) && (targetInfo.IsCubeMap == target.IsCubeMap)) { if (clearOnRetrieve) { rtv.Clear(GorgonColor.BlackTransparent); } _renderTargets.Remove(rtv); _rented.Add(rtv); return(rtv); } } var newRtv = GorgonRenderTarget2DView.CreateRenderTarget(_graphics, targetInfo); // Cache a default shader resource view (the texture holds the cache, we hold a separate one so we can clean it up later). _srvs.Add(newRtv.GetShaderResourceView()); newRtv.OwnerFactory = this; _rented.Add(newRtv); newRtv.Clear(GorgonColor.BlackTransparent); return(newRtv); }
/// <summary> /// Function to create a new render target that is bindable to the GPU. /// </summary> /// <param name="graphics">The graphics interface to use when creating the target.</param> /// <param name="info">The information about the texture.</param> /// <param name="arrayIndex">[Optional] The index of a texture array to slice the view at.</param> /// <param name="arrayCount">[Optioanl] The number of array indices to view.</param> /// <returns>A new <see cref="GorgonRenderTarget2DView"/>.</returns> /// <exception cref="ArgumentNullException">Thrown when the <paramref name="graphics"/>, or <paramref name="info"/> parameter is <b>null</b>.</exception> /// <remarks> /// <para> /// This is a convenience method that will create a <see cref="GorgonTexture2D"/> and a <see cref="GorgonRenderTarget2DView"/> as a single object that users can use to apply a render target texture. /// This helps simplify creation of a render target by executing some prerequisite steps on behalf of the user. /// </para> /// <para> /// Since the <see cref="GorgonTexture2D"/> created by this method is linked to the <see cref="GorgonRenderTarget2DView"/> returned, disposal of either one will dispose of the other on your behalf. /// If the user created a <see cref="GorgonRenderTarget2DView"/> from the <see cref="GorgonTexture2D.GetRenderTargetView"/> method on the <see cref="GorgonTexture2D"/>, then it's assumed the user /// knows what they are doing and will handle the disposal of the texture and view on their own. /// </para> /// </remarks> /// <seealso cref="GorgonTexture2D"/> public static GorgonRenderTarget2DView CreateRenderTarget(GorgonGraphics graphics, IGorgonTexture2DInfo info, int arrayIndex = 0, int?arrayCount = null) { if (graphics == null) { throw new ArgumentNullException(nameof(graphics)); } if (info == null) { throw new ArgumentNullException(nameof(info)); } TextureBinding binding = TextureBinding.RenderTarget; if ((info.Binding & TextureBinding.ShaderResource) == TextureBinding.ShaderResource) { binding |= TextureBinding.ShaderResource; } if ((info.Binding & TextureBinding.ShaderResource) == TextureBinding.ReadWriteView) { binding |= TextureBinding.ReadWriteView; } var newInfo = new GorgonTexture2DInfo(info) { Usage = ResourceUsage.Default, Binding = binding }; var texture = new GorgonTexture2D(graphics, newInfo); GorgonRenderTarget2DView result = texture.GetRenderTargetView(arrayIndex: arrayIndex, arrayCount: arrayCount ?? 1); result.OwnsResource = true; return(result); }