Example #1
0
        /// <summary>
        /// Function to create a new texture 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="initialData">[Optional] Initial data used to populate the texture.</param>
        /// <returns>A new <see cref="GorgonTexture2DView"/>.</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="GorgonTexture2DView"/> as a single object that users can use to apply a texture as a shader
        /// resource. This helps simplify creation of a texture 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="GorgonTexture2DView"/> returned, disposal of either one will dispose of the other on your behalf. If
        /// the user created a <see cref="GorgonTexture2DView"/> from the <see cref="GorgonTexture2D.GetShaderResourceView"/> 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>
        /// <para>
        /// If an <paramref name="initialData"/> image is provided, and the width/height/depth is not the same as the values in the <paramref name="info"/> parameter, then the image data will be cropped to
        /// match the values in the <paramref name="info"/> parameter. Things like array count, and mip levels will still be taken from the <paramref name="initialData"/> image parameter.
        /// </para>
        /// </remarks>
        /// <seealso cref="GorgonTexture2D"/>
        public static GorgonTexture2DView CreateTexture(GorgonGraphics graphics, IGorgonTexture2DInfo info, IGorgonImage initialData = null)
        {
            if (graphics == null)
            {
                throw new ArgumentNullException(nameof(graphics));
            }

            if (info == null)
            {
                throw new ArgumentNullException(nameof(info));
            }

            if (initialData != null)
            {
                if ((initialData.Width < info.Width) ||
                    (initialData.Height < info.Height))
                {
                    initialData.Expand(info.Width, info.Height, 1);
                }

                if ((initialData.Width > info.Width) ||
                    (initialData.Height > info.Height))
                {
                    initialData.Crop(new DX.Rectangle(0, 0, info.Width, info.Height), 1);
                }
            }

            var newInfo = new GorgonTexture2DInfo(info)
            {
                Usage   = info.Usage == ResourceUsage.Staging ? ResourceUsage.Default : info.Usage,
                Binding = (info.Binding & TextureBinding.ShaderResource) != TextureBinding.ShaderResource
                                            ? (info.Binding | TextureBinding.ShaderResource)
                                            : info.Binding
            };

            GorgonTexture2D texture = initialData == null
                                          ? new GorgonTexture2D(graphics, newInfo)
                                          : initialData.ToTexture2D(graphics,
                                                                    new GorgonTexture2DLoadOptions
            {
                Usage           = newInfo.Usage,
                Binding         = newInfo.Binding,
                MultisampleInfo = newInfo.MultisampleInfo,
                Name            = newInfo.Name,
                IsTextureCube   = newInfo.IsCubeMap
            });

            GorgonTexture2DView result = texture.GetShaderResourceView();

            result.OwnsResource = true;

            return(result);
        }
Example #2
0
        /// <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 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);
        }
Example #4
0
        /// <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);
        }
        /// <summary>
        /// Function to create a new depth/stencil buffer 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 depth/stencil texture.</param>
        /// <param name="viewFlags">[Optional] Flags used to determine if the depth buffer/stencil can be read by the GPU or not.</param>
        /// <returns>A new <see cref="GorgonDepthStencil2DView"/>.</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="GorgonDepthStencil2DView"/> as a single object that users can use to apply a depth/stencil 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="GorgonDepthStencil2DView"/> returned, disposal of either one will dispose of the other on your behalf.
        /// If the user created a <see cref="GorgonDepthStencil2DView"/> 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>
        /// <para>
        /// To make the texture bindable on the GPU as a shader resource view, set the <see cref="IGorgonTexture2DInfo.Binding"/> to include the <see cref="TextureBinding.ShaderResource"/> flag in the value
        /// and set the <paramref name="viewFlags"/> to <see cref="DepthStencilViewFlags.ReadOnlyDepth"/>, <see cref="DepthStencilViewFlags.ReadOnlyStencil"/> or both.
        /// </para>
        /// </remarks>
        /// <seealso cref="GorgonTexture2D"/>
        public static GorgonDepthStencil2DView CreateDepthStencil(GorgonGraphics graphics, IGorgonTexture2DInfo info, DepthStencilViewFlags viewFlags = DepthStencilViewFlags.None)
        {
            if (graphics == null)
            {
                throw new ArgumentNullException(nameof(graphics));
            }

            if (info == null)
            {
                throw new ArgumentNullException(nameof(info));
            }

            TextureBinding binding = TextureBinding.DepthStencil;

            if ((info.Binding & TextureBinding.ShaderResource) == TextureBinding.ShaderResource)
            {
                if (viewFlags != DepthStencilViewFlags.None)
                {
                    binding |= TextureBinding.ShaderResource;
                }
                else
                {
                    // Do this to notify the user that something is amiss.
                    graphics.Log.Print($"WARNING: Depth Stencil View {info.Name} - Depth/stencil texture has a binding of {TextureBinding.ShaderResource}, but has a view flags of {viewFlags}.  The view will not be bindable to the shader pipeline.",
                                       LoggingLevel.Simple);
                }
            }
            else if (viewFlags != DepthStencilViewFlags.None)
            {
                // Do this to notify the user that something is amiss.
                graphics.Log.Print($"WARNING: Depth Stencil View {info.Name} - Depth/stencil view flag(s) are set to {viewFlags}, but the texture lacks a {TextureBinding.ShaderResource} binding.",
                                   LoggingLevel.Simple);
            }

            var newInfo = new GorgonTexture2DInfo(info)
            {
                // Can't see a reason to use anything other than default for dsvs
                Usage   = ResourceUsage.Default,
                Binding = binding
            };

            BufferFormat depthStencilFormat = newInfo.Format;

            if (((binding & TextureBinding.ShaderResource) == TextureBinding.ShaderResource) &&
                (viewFlags != DepthStencilViewFlags.None))
            {
                switch (newInfo.Format)
                {
                case BufferFormat.R32G8X24_Typeless:
                    depthStencilFormat = BufferFormat.D32_Float_S8X24_UInt;
                    break;

                case BufferFormat.R24G8_Typeless:
                    depthStencilFormat = BufferFormat.D24_UNorm_S8_UInt;
                    break;

                case BufferFormat.R16_Typeless:
                    depthStencilFormat = BufferFormat.D16_UNorm;
                    break;

                case BufferFormat.R32_Typeless:
                    depthStencilFormat = BufferFormat.D32_Float;
                    break;
                }
            }

            var texture = new GorgonTexture2D(graphics, newInfo);
            GorgonDepthStencil2DView result = texture.GetDepthStencilView(depthStencilFormat, flags: viewFlags);

            result.OwnsResource = true;

            return(result);
        }