/// <summary> /// Initializes a new instance of the <see cref="GorgonTextureLockData"/> class. /// </summary> /// <param name="graphics">The graphics context that owns this lock.</param> /// <param name="texture">The texture that owns this lock.</param> /// <param name="cache">Lock cache that will contain this lock.</param> /// <param name="data">The data returned from the lock.</param> /// <param name="mipLevel">The mip level of the sub resource.</param> /// <param name="arrayIndex">Array index of the sub resource.</param> internal GorgonTextureLockData(GorgonGraphics graphics, GorgonTexture texture, GorgonTextureLockCache cache, DX.DataBox data, int mipLevel, int arrayIndex) : base(mipLevel, arrayIndex, 0) { Graphics = graphics; Texture = texture; _cache = cache; Width = Texture.Settings.Width; Height = Texture.Settings.Height; Depth = Texture.Settings.Depth; // Calculate the current size at the given mip level. for (int mip = 0; mip < mipLevel; ++mip) { if (Width > 1) { Width >>= 1; } if (Height > 1) { Height >>= 1; } if (Depth > 1) { Depth >>= 1; } } PitchInformation = new GorgonFormatPitch(data.RowPitch, data.SlicePitch); Data = new GorgonDataStream(data.DataPointer.ToPointer(), data.SlicePitch); }
/// <summary> /// Function to retrieve the view description for a 2D texture cube. /// </summary> /// <param name="texture">The texture to bind to the view.</param> /// <returns>The shader view description.</returns> /// <exception cref="GorgonException"></exception> private D3D.ShaderResourceViewDescription GetDesc2DCube(GorgonTexture texture) { bool isMultiSampled = ((texture.Settings.Multisampling.Count > 1) || (texture.Settings.Multisampling.Quality > 0)); if (isMultiSampled) { throw new GorgonException(GorgonResult.CannotCreate, Resources.GORGFX_ERR_CANNOT_MULTISAMPLE_CUBE); } int cubeArrayCount = texture.Settings.ArrayCount / 6; return(new D3D.ShaderResourceViewDescription { Format = (Format)Format, Dimension = cubeArrayCount > 1 ? ShaderResourceViewDimension.TextureCubeArray : ShaderResourceViewDimension.TextureCube, TextureCubeArray = { CubeCount = cubeArrayCount, First2DArrayFace = ArrayStart, MipLevels = MipCount, MostDetailedMip = MipStart } }); }
/// <summary> /// Initializes a new instance of the <see cref="GorgonTextureShaderView"/> class. /// </summary> /// <param name="texture">The texture to view.</param> /// <param name="format">The format of the view.</param> /// <param name="firstMipLevel">The first mip level.</param> /// <param name="mipCount">The mip count.</param> /// <param name="arrayIndex">Index of the array.</param> /// <param name="arrayCount">The array count.</param> internal GorgonTextureShaderView(GorgonTexture texture, BufferFormat format, int firstMipLevel, int mipCount, int arrayIndex, int arrayCount) : base(texture, format) { MipStart = firstMipLevel; MipCount = mipCount; ArrayStart = arrayIndex; ArrayCount = arrayCount; IsCube = texture.Settings.ImageType == ImageType.ImageCube; switch (texture.ResourceType) { case ResourceType.Texture1D: _texture1D = (GorgonTexture1D)texture; break; case ResourceType.Texture2D: _texture2D = (GorgonTexture2D)texture; break; case ResourceType.Texture3D: _texture3D = (GorgonTexture3D)texture; break; } }
/// <summary> /// Function to create an array of System.Drawing.Images from a given texture. /// </summary> /// <param name="texture">Texture to evaluate.</param> /// <returns>A list of GDI+ images.</returns> public static Image[] CreateGDIImagesFromTexture(GorgonTexture texture) { using (var data = GorgonImageData.CreateFromTexture(texture)) { return(CreateGDIImagesFromImageData(data)); } }
/// <summary> /// Function called when a texture is switched. /// </summary> /// <param name="texture">Texture to switch to.</param> internal void TextureSwitch(GorgonTexture texture) { // If we have a texture change, and we have the default diffuse shader loaded, then switch to the textured shader. if ((texture != null) && (Graphics.Shaders.PixelShader.Current == DefaultPixelShaderDiffuse)) { Current = DefaultPixelShaderTextured; } // If we have a texture change, and we have the default textured shader loaded, then switch to the diffuse shader. if ((texture == null) && (Graphics.Shaders.PixelShader.Current == DefaultPixelShaderTextured)) { Current = DefaultPixelShaderDiffuse; } }
/// <summary> /// Function to retrieve the view description for a 1D texture. /// </summary> /// <param name="texture">Texture to build a view description for.</param> /// <returns>The shader view description.</returns> private UnorderedAccessViewDescription GetDesc1D(GorgonTexture texture) { return(new UnorderedAccessViewDescription { Format = (Format)Format, Dimension = texture.Settings.ArrayCount > 1 ? UnorderedAccessViewDimension.Texture1DArray : UnorderedAccessViewDimension.Texture1D, Texture1DArray = { MipSlice = MipIndex, ArraySize = ArrayOrDepthCount, FirstArraySlice = ArrayOrDepthStart } }); }
/// <summary> /// Function to retrieve the view description for a 1D texture. /// </summary> /// <param name="texture">Texture to build a view description for.</param> /// <returns>The shader view description.</returns> private D3D.ShaderResourceViewDescription GetDesc1D(GorgonTexture texture) { return(new D3D.ShaderResourceViewDescription { Format = (Format)Format, Dimension = texture.Settings.ArrayCount > 1 ? ShaderResourceViewDimension.Texture1DArray : ShaderResourceViewDimension.Texture1D, Texture1DArray = { MipLevels = MipCount, MostDetailedMip = MipStart, ArraySize = ArrayCount, FirstArraySlice = ArrayStart } }); }
/// <summary> /// Function to copy this texture into a new staging texture. /// </summary> /// <returns> /// The new staging texture. /// </returns> protected override GorgonTexture OnGetStagingTexture() { var settings1D = new GorgonTexture1DSettings { ArrayCount = Settings.ArrayCount, Format = Settings.Format, Width = Settings.Width, MipCount = Settings.MipCount, Usage = BufferUsage.Staging }; GorgonTexture staging = Graphics.Textures.CreateTexture(Name + ".Staging", settings1D); staging.Copy(this); return(staging); }
/// <summary> /// Function to copy this texture into a new staging texture. /// </summary> /// <returns> /// The new staging texture. /// </returns> protected override GorgonTexture OnGetStagingTexture() { var settings3D = new GorgonTexture3DSettings { Format = Settings.Format, Width = Settings.Width, Height = Settings.Height, Depth = Settings.Depth, MipCount = Settings.MipCount, Usage = BufferUsage.Staging }; GorgonTexture staging = Graphics.ImmediateContext.Textures.CreateTexture(Name + ".Staging", settings3D); staging.Copy(this); return(staging); }
/// <summary> /// Function to copy this texture into a new staging texture. /// </summary> /// <returns> /// The new staging texture. /// </returns> protected override GorgonTexture OnGetStagingTexture() { var settings2D = new GorgonTexture2DSettings { ArrayCount = Settings.ArrayCount, Format = Settings.Format, Width = Settings.Width, Height = Settings.Height, IsTextureCube = Settings.IsTextureCube, Multisampling = Settings.Multisampling, MipCount = Settings.MipCount, Usage = BufferUsage.Staging }; GorgonTexture staging = Graphics.ImmediateContext.Textures.CreateTexture(Name + ".Staging", settings2D); staging.Copy(this); return(staging); }
/// <summary> /// Function to retrieve the view description for a 2D texture. /// </summary> /// <param name="texture">Texture to build a view description for.</param> /// <returns>The shader view description.</returns> private D3D.ShaderResourceViewDescription GetDesc2D(GorgonTexture texture) { bool isMultiSampled = ((texture.Settings.Multisampling.Count > 1) || (texture.Settings.Multisampling.Quality > 0)); if (!isMultiSampled) { return(new D3D.ShaderResourceViewDescription { Format = (Format)Format, Dimension = texture.Settings.ArrayCount > 1 ? ShaderResourceViewDimension.Texture2DArray : ShaderResourceViewDimension.Texture2D, Texture2DArray = { MipLevels = MipCount, MostDetailedMip = MipStart, FirstArraySlice = ArrayStart, ArraySize = ArrayCount } }); } return(new D3D.ShaderResourceViewDescription { Format = (Format)Format, Dimension = texture.Settings.ArrayCount > 1 ? ShaderResourceViewDimension.Texture2DMultisampledArray : ShaderResourceViewDimension.Texture2DMultisampled, Texture2DMSArray = { ArraySize = ArrayCount, FirstArraySlice = ArrayStart } }); }
/// <summary> /// Function to resolve a multisampled texture resource into another non-multisampled resource. /// </summary> /// <param name="destination">The texture that will receive the resolved texture.</param> /// <param name="destArrayIndex">[Optional] Index in the array that will receive the resolved texture data.</param> /// <param name="destMipLevel">[Optional] The mip map level that will receive the resolved texture data.</param> /// <param name="srcArrayIndex">[Optional] The array index in the source to resolve.</param> /// <param name="srcMipLevel">[Optional] The source mip level to resolve.</param> /// <param name="resolveFormat">[Optional] A format that will determine how to resolve the multisampled texture into a non-multisampled texture.</param> /// <param name="context">[Optional] A deferred graphics context used to copy the data.</param> /// <exception cref="System.ArgumentNullException">Thrown when the <paramref name="destination"/> parameter is NULL (Nothing in VB.Net).</exception> /// <exception cref="System.ArgumentOutOfRangeException">Thrown when the <paramref name="destArrayIndex"/>, <paramref name="destMipLevel"/>, <paramref name="srcArrayIndex"/>, or the /// <paramref name="srcMipLevel"/> parameters are not within the the range of the array indices or mip levels of the respective textures.</exception> /// <exception cref="System.NotSupportedException">Thrown when the source texture is not multisampled or the destination texture is multisampled or has a non default usage.</exception> /// <exception cref="System.ArgumentException">Thrown when the <paramref name="resolveFormat"/> is not compatible with the formats of the source or destination texture.</exception> /// <remarks>Use this method to resolve a multisampled texture into a non multisampled texture. This is most useful when transferring a multisampled render target pass as an input to /// a secondary pass. /// <para>The <paramref name="resolveFormat"/> parameter is used to determine how to interpret the data in the texture. There are 3 ways this data may be interpreted: /// <list type="number"> /// <item><description>If both textures have a typed format, then the resolve format must be the same as the format of the textures. Both textures must have the same format.</description></item> /// <item><description>If one of the textures have a typeless format and one has a typed format, then the resolve format must be in the same group as the typed format.</description></item> /// <item><description>If the textures both have a typeless format, then the resolve format must be in the same group as the typeless format.</description></item> /// </list> /// Leaving the resolve format as Unknown will automatically use the format of the source texture. /// </para> /// <para>If the <paramref name="context"/> parameter is NULL (Nothing in VB.Net) then the immediate context will be used. If this method is called from multiple threads, then a deferred context should be passed for each thread that is /// accessing the sub resource.</para> /// </remarks> public void ResolveTo(GorgonTexture destination, int destArrayIndex = 0, int destMipLevel = 0, int srcArrayIndex = 0, int srcMipLevel = 0, BufferFormat resolveFormat = BufferFormat.Unknown, GorgonGraphics context = null) { if (resolveFormat == BufferFormat.Unknown) { resolveFormat = Settings.Format; } #if DEBUG if (destination == null) { throw new ArgumentNullException("destination"); } if ((destArrayIndex >= destination.Settings.ArrayCount) && (destArrayIndex < 0)) { throw new ArgumentOutOfRangeException("destArrayIndex", string.Format(Resources.GORGFX_ARG_OUT_OF_RANGE, 0, destination.Settings.ArrayCount)); } if ((destMipLevel < 0) || (destMipLevel >= destination.Settings.MipCount)) { throw new ArgumentOutOfRangeException("destMipLevel", string.Format(Resources.GORGFX_ARG_OUT_OF_RANGE, 0, destination.Settings.MipCount)); } if ((srcArrayIndex >= Settings.ArrayCount) && (srcArrayIndex < 0)) { throw new ArgumentOutOfRangeException("srcArrayIndex", string.Format(Resources.GORGFX_ARG_OUT_OF_RANGE, 0, Settings.ArrayCount)); } if ((srcMipLevel < 0) || (srcMipLevel >= Settings.MipCount)) { throw new ArgumentOutOfRangeException("srcMipLevel", string.Format(Resources.GORGFX_ARG_OUT_OF_RANGE, 0, Settings.MipCount)); } if (Settings.Multisampling.Equals(GorgonMultisampling.NoMultiSampling)) { throw new NotSupportedException(string.Format(Resources.GORGFX_TEXTURE_SRC_NOT_MULTISAMPLED, Name)); } if (destination.Settings.Usage != BufferUsage.Default) { throw new NotSupportedException(string.Format(Resources.GORGFX_TEXTURE_RESOLVE_DEST_NOT_DEFAULT, destination.Name)); } var srcFormatInfo = GorgonBufferFormatInfo.GetInfo(Settings.Format); var destFormatInfo = GorgonBufferFormatInfo.GetInfo(destination.Settings.Format); var resolveFormatInfo = GorgonBufferFormatInfo.GetInfo(resolveFormat); // Ensure that the resource formats and resolve format all match up. if ((!srcFormatInfo.IsTypeless) && (!destFormatInfo.IsTypeless)) { if (Settings.Format != destination.Settings.Format) { throw new ArgumentException(string.Format(Resources.GORGFX_TEXTURE_RESOLVE_FORMATS_NOT_SAME, Settings.Format), "destination"); } if (resolveFormat != Settings.Format) { throw new ArgumentException(string.Format(Resources.GORGFX_TEXTURE_RESOLVE_FORMAT_MUST_BE_UNKNOWN), "resolveFormat"); } } else if ((srcFormatInfo.IsTypeless) && (destFormatInfo.IsTypeless)) { if (Settings.Format != destination.Settings.Format) { throw new ArgumentException(string.Format(Resources.GORGFX_TEXTURE_RESOLVE_FORMATS_NOT_SAME, Settings.Format), "destination"); } if ((resolveFormatInfo.Group != srcFormatInfo.Group) || (resolveFormatInfo.Group != destFormatInfo.Group)) { throw new ArgumentException( string.Format(Resources.GORGFX_TEXTURE_RESOLVE_FORMAT_NOT_SAME_GROUP, Settings.Format), "resolveFormat"); } } else if ((srcFormatInfo.IsTypeless) || (destFormatInfo.IsTypeless)) { if (resolveFormatInfo.IsTypeless) { throw new ArgumentException(string.Format(Resources.GORGFX_TEXTURE_RESOLVE_FORMAT_CANNOT_BE_TYPELESS), "resolveFormat"); } if (srcFormatInfo.Group != destFormatInfo.Group) { throw new ArgumentException( string.Format(Resources.GORGFX_TEXTURE_RESOLVE_SRC_DEST_NOT_SAME_GROUP, Settings.Format, destination.Settings.Format), "destination"); } } #endif int sourceIndex = D3D.Resource.CalculateSubResourceIndex(srcMipLevel, srcArrayIndex, Settings.MipCount); int destIndex = D3D.Resource.CalculateSubResourceIndex(destMipLevel, destArrayIndex, destination.Settings.MipCount); if (context == null) { context = Graphics; } context.Context.ResolveSubresource(D3DResource, sourceIndex, destination.D3DResource, destIndex, (GI.Format)resolveFormat); }
/// <summary> /// Initializes a new instance of the <see cref="GorgonTextureLockCache"/> class. /// </summary> /// <param name="texture">Texture that will be locked.</param> public GorgonTextureLockCache(GorgonTexture texture) { _texture = texture; _locks = new Dictionary <LockCacheKey, GorgonTextureLockData>(); }
/// <summary> /// Function to validate the view settings. /// </summary> private void ValidateViewSettings(GorgonTexture texture) { if (Format == BufferFormat.Unknown) { throw new GorgonException(GorgonResult.CannotCreate, Resources.GORGFX_VIEW_UNKNOWN_FORMAT); } if (FormatInformation.IsTypeless) { throw new GorgonException(GorgonResult.CannotCreate, Resources.GORGFX_VIEW_NO_TYPELESS); } if ((texture.Settings.IsTextureCube) || (texture.Settings.Multisampling.Count > 1) || (texture.Settings.Multisampling.Quality > 0)) { throw new GorgonException(GorgonResult.CannotCreate, Resources.GORGFX_VIEW_UAV_NOT_SUPPORTED); } // 3D textures don't use arrays. if (texture.ResourceType != ResourceType.Texture3D) { if ((ArrayOrDepthCount > texture.Settings.ArrayCount) || (ArrayOrDepthCount + ArrayOrDepthStart > texture.Settings.ArrayCount) || (ArrayOrDepthCount < 1)) { throw new GorgonException(GorgonResult.CannotCreate, string.Format(Resources.GORGFX_VIEW_ARRAY_COUNT_INVALID, texture.Settings.ArrayCount)); } if ((ArrayOrDepthStart >= texture.Settings.ArrayCount) || (ArrayOrDepthStart < 0)) { throw new GorgonException(GorgonResult.CannotCreate, string.Format(Resources.GORGFX_VIEW_ARRAY_START_INVALID, texture.Settings.ArrayCount)); } } else { if ((ArrayOrDepthCount > texture.Settings.Depth) || (ArrayOrDepthCount + ArrayOrDepthStart > texture.Settings.Depth) || (ArrayOrDepthCount < 1)) { throw new GorgonException(GorgonResult.CannotCreate, string.Format(Resources.GORGFX_VIEW_DEPTH_COUNT_INVALID, texture.Settings.Depth)); } if ((ArrayOrDepthStart >= texture.Settings.Depth) || (ArrayOrDepthStart < 0)) { throw new GorgonException(GorgonResult.CannotCreate, string.Format(Resources.GORGFX_VIEW_DEPTH_START_INVALID, texture.Settings.Depth)); } } if ((MipIndex > texture.Settings.MipCount) || (MipIndex < 0)) { throw new GorgonException(GorgonResult.CannotCreate, string.Format(Resources.GORGFX_VIEW_MIP_COUNT_INVALID, texture.Settings.MipCount)); } if ((MipIndex >= texture.Settings.MipCount) || (MipIndex < 0)) { throw new GorgonException(GorgonResult.CannotCreate, string.Format(Resources.GORGFX_VIEW_MIP_START_INVALID, texture.Settings.MipCount)); } }