/// <summary> /// Function to retrieve a render target view. /// </summary> /// <param name="format">Format of the new render target view.</param> /// <param name="bufferFormat">The format of the buffer.</param> /// <param name="firstElement">The first element in the buffer to map to the view.</param> /// <param name="elementCount">The number of elements in the buffer to map to the view.</param> /// <returns>A render target view.</returns> /// <remarks>Use this to create/retrieve a render target view that can bind a portion of the target to the pipeline as a render target. /// <para>The <paramref name="format"/> for the render target view does not have to be the same as the render target backing buffer, and if the format is set to Unknown, then it will /// use the format from the buffer.</para> /// </remarks> /// <exception cref="GorgonLibrary.GorgonException">Thrown when the view could not created or retrieved from the internal cache.</exception> protected GorgonRenderTargetBufferView OnGetRenderTargetView(BufferFormat format, BufferFormat bufferFormat, int firstElement, int elementCount) { // If we pass unknown, use the format from the texture. if (format == BufferFormat.Unknown) { format = bufferFormat; } var info = GorgonBufferFormatInfo.GetInfo(format); if (info.IsTypeless) { throw new GorgonException(GorgonResult.CannotCreate, Resources.GORGFX_VIEW_NO_TYPELESS); } var bufferElementCount = Settings.SizeInBytes / info.SizeInBytes; if ((firstElement < 0) || (firstElement >= bufferElementCount) || (elementCount < 1) || (elementCount >= bufferElementCount)) { throw new GorgonException(GorgonResult.CannotCreate, string.Format(Resources.GORGFX_VIEW_ELEMENT_OUT_OF_RANGE, elementCount, elementCount)); } return((GorgonRenderTargetBufferView)_viewCache.GetRenderTargetView(format, firstElement, elementCount, 0)); }
/// <summary> /// Function to create a list of buffers to use. /// </summary> /// <param name="data">Data to copy/reference.</param> internal unsafe void CreateBuffers(byte *data) { int bufferIndex = 0; var formatInfo = GorgonBufferFormatInfo.GetInfo(_image.Settings.Format); // Format information. // Allocate enough room for the array and mip levels. _buffers = new GorgonImageBuffer[GorgonImageData.GetDepthSliceCount(_image.Settings.Depth, _image.Settings.MipCount) * _image.Settings.ArrayCount]; MipOffsetSize = new Tuple <int, int> [_image.Settings.MipCount * _image.Settings.ArrayCount]; // Offsets for the mip maps. DataBoxes = new DX.DataBox[_image.Settings.ArrayCount * _image.Settings.MipCount]; // Create the data boxes for textures. // Enumerate array indices. (For 1D and 2D only, 3D will always be 1) for (int array = 0; array < _image.Settings.ArrayCount; array++) { int mipWidth = _image.Settings.Width; int mipHeight = _image.Settings.Height; int mipDepth = _image.Settings.Depth; // Enumerate mip map levels. for (int mip = 0; mip < _image.Settings.MipCount; mip++) { int arrayIndex = mip + (array * _image.Settings.MipCount); var pitchInformation = formatInfo.GetPitch(mipWidth, mipHeight, PitchFlags.None); // Get data box for texture upload. DataBoxes[arrayIndex] = new DX.DataBox(new IntPtr(data), pitchInformation.RowPitch, pitchInformation.SlicePitch); // Calculate buffer offset by mip. MipOffsetSize[arrayIndex] = new Tuple <int, int>(bufferIndex, mipDepth); // Enumerate depth slices. for (int depth = 0; depth < mipDepth; depth++) { // Get mip information. _buffers[bufferIndex] = new GorgonImageBuffer(data, pitchInformation, mip, array, depth, mipWidth, mipHeight, mipDepth, _image.Settings.Format); data += pitchInformation.SlicePitch; bufferIndex++; } if (mipWidth > 1) { mipWidth >>= 1; } if (mipHeight > 1) { mipHeight >>= 1; } if (mipDepth > 1) { mipDepth >>= 1; } } } }
/// <summary> /// Function to create the default shader view. /// </summary> protected virtual void OnCreateDefaultShaderView() { // Staging buffers cannot create shader views. if ((Settings.Usage == BufferUsage.Staging) || (Settings.DefaultShaderViewFormat == BufferFormat.Unknown)) { return; } var info = GorgonBufferFormatInfo.GetInfo(Settings.DefaultShaderViewFormat); DefaultShaderView = OnGetShaderView(Settings.DefaultShaderViewFormat, 0, Settings.SizeInBytes / info.SizeInBytes, false); }
/// <summary> /// Initializes a new instance of the <see cref="GorgonInputElement"/> class. /// </summary> /// <param name="context">The context for the element.</param> /// <param name="format">The format and type of the element.</param> /// <param name="offset">The offset of the element within the vertex.</param> /// <param name="index">The index of the element.</param> /// <param name="slot">The vertex buffer slot for the element.</param> /// <param name="instanced">TRUE if using instanced data, FALSE if not.</param> /// <param name="instanceCount">Number of instances to use before moving to the next element.</param> /// <remarks>The slot value must be between 0 and 15 (inclusive). A value outside of this range will cause an exception to be thrown.</remarks> /// <exception cref="System.ArgumentException">Thrown when the <paramref name="format"/> parameter is not supported.</exception> /// <exception cref="System.ArgumentOutOfRangeException">Thrown when the <paramref name="slot"/> parameter is less than 0 or greater than 15.</exception> public GorgonInputElement(string context, BufferFormat format, int offset, int index, int slot, bool instanced, int instanceCount) { if (GorgonBufferFormatInfo.GetInfo(format).BitDepth == 0) { throw new ArgumentException(string.Format(Resources.GORGFX_FORMAT_NOT_SUPPORTED, format), "format"); } if ((slot < 0) || (slot > 15)) { throw new ArgumentOutOfRangeException("slot", string.Format(Resources.GORGFX_VALUE_OUT_OF_RANGE, slot, 16)); } Context = context; Index = index; Format = format; Offset = offset; Size = GorgonBufferFormatInfo.GetInfo(format).SizeInBytes; Slot = slot; Instanced = instanced; InstanceCount = instanceCount; }
/// <summary> /// Function to retrieve a new shader view for the buffer. /// </summary> /// <param name="format">The format of the view.</param> /// <param name="start">Starting element.</param> /// <param name="count">Element count.</param> /// <param name="isRaw">TRUE if using a raw view of the buffer, FALSE if not.</param> /// <returns>A shader view for the buffer.</returns> /// <exception cref="GorgonLibrary.GorgonException">Thrown when the usage for this buffer is set to Staging. /// <para>-or-</para> /// <para>Thrown when the view could not be created.</para> /// </exception> /// <exception cref="System.ArgumentException">Thrown when the <paramref name="start"/> or <paramref name="count"/> parameters are less than 0 or greater than or equal to the /// number of elements in the buffer.</exception> /// <remarks>Use this to create/retrieve additional shader views for the buffer. Multiple views of the same resource can be bound to multiple stages in the pipeline. /// <para>Raw views require that the buffer be created with the <see cref="GorgonLibrary.Graphics.IBufferSettings.AllowRawViews">AllowRawViews</see> property set to TRUE in its settings.</para> /// <para>Raw views can only be used on SM5 video devices or better. </para> /// <para>This function only applies to buffers that have not been created with a Usage of Staging.</para> /// </remarks> protected GorgonBufferShaderView OnGetShaderView(BufferFormat format, int start, int count, bool isRaw) { int elementCount; if (Settings.Usage == BufferUsage.Staging) { throw new GorgonException(GorgonResult.CannotCreate, Resources.GORGFX_VIEW_SRV_NO_STAGING_OR_DYNAMIC); } if (!Settings.AllowShaderViews) { throw new GorgonException(GorgonResult.CannotCreate, string.Format(Resources.GORGFX_VIEW_NO_SUPPORT, "GorgonShaderView")); } // If we're using any other type than structured... if (BufferType != BufferType.Structured) { if (format == BufferFormat.Unknown) { throw new ArgumentException(Resources.GORGFX_VIEW_UNKNOWN_FORMAT, "format"); } // Ensure the size of the data type fits the requested format. var info = GorgonBufferFormatInfo.GetInfo(format); if (info.IsTypeless) { throw new GorgonException(GorgonResult.CannotCreate, Resources.GORGFX_VIEW_NO_TYPELESS); } if (isRaw) { if (Graphics.VideoDevice.SupportedFeatureLevel < DeviceFeatureLevel.SM5) { throw new GorgonException(GorgonResult.CannotCreate, string.Format(Resources.GORGFX_REQUIRES_SM, "SM5")); } if (!Settings.AllowRawViews) { throw new GorgonException(GorgonResult.CannotBind, Resources.GORGFX_BUFFER_NO_RAW_VIEWS); } if (info.Group != BufferFormat.R32) { throw new GorgonException(GorgonResult.CannotBind, Resources.GORGFX_VIEW_RAW_INVALID_FORMAT); } elementCount = SizeInBytes / 4; } else { elementCount = SizeInBytes / info.SizeInBytes; } } else { // We cannot use structured buffers on anything less than a SM5 video device. if (Graphics.VideoDevice.SupportedFeatureLevel < DeviceFeatureLevel.SM5) { throw new GorgonException(GorgonResult.CannotCreate, string.Format(Resources.GORGFX_REQUIRES_SM, "SM5")); } elementCount = Settings.SizeInBytes / Settings.StructureSize; format = BufferFormat.Unknown; isRaw = false; } if (((start + count) > elementCount) || (start < 0) || (count < 1)) { throw new ArgumentException(string.Format(Resources.GORGFX_VIEW_ELEMENT_OUT_OF_RANGE, elementCount, (elementCount - start))); } return(_viewCache.GetBufferView(format, start, count, isRaw)); }
/// <summary> /// Function to retrieve an unordered access view for this buffer. /// </summary> /// <param name="format">Format of the buffer.</param> /// <param name="start">First element to map to the view.</param> /// <param name="count">The number of elements to map to the view.</param> /// <param name="isRaw">TRUE if using a raw view to the buffer, FALSE if not.</param> /// <param name="viewType">The type of view for a structured buffer.</param> /// <returns>An unordered access view for the buffer.</returns> /// <remarks>Use this to create/retrieve an unordered access view that will allow shaders to access the view using multiple threads at the same time. Unlike a Shader View, only one /// unordered access view can be bound to the pipeline at any given time. /// <para>Raw views require that the format be set to R32 (typeless).</para> /// <para>Unordered access views require a video device feature level of SM_5 or better.</para> /// </remarks> /// <exception cref="GorgonLibrary.GorgonException">Thrown when the usage for this buffer is set to Staging or Dynamic. /// <para>-or-</para> /// <para>Thrown when the video device feature level is not SM_5 or better.</para> /// <para>-or-</para> /// <para>Thrown when the resource settings do not allow unordered access views.</para> /// <para>-or-</para> /// <para>Thrown when the view could not be created.</para> /// </exception> /// <exception cref="System.ArgumentException">Thrown when the <paramref name="start"/> or <paramref name="count"/> parameters are less than 0 or greater than or equal to the /// number of elements in the buffer.</exception> protected GorgonBufferUnorderedAccessView OnGetUnorderedAccessView(BufferFormat format, int start, int count, bool isRaw, UnorderedAccessViewType viewType) { int elementCount; if (Graphics.VideoDevice.SupportedFeatureLevel < DeviceFeatureLevel.SM5) { throw new GorgonException(GorgonResult.CannotCreate, string.Format(Resources.GORGFX_REQUIRES_SM, "SM5")); } if (!Settings.AllowUnorderedAccessViews) { throw new GorgonException(GorgonResult.CannotCreate, string.Format(Resources.GORGFX_VIEW_NO_SUPPORT, "GorgonUnorderedAccessView")); } if ((Settings.Usage == BufferUsage.Staging) || (Settings.Usage == BufferUsage.Dynamic)) { throw new GorgonException(GorgonResult.CannotBind, Resources.GORGFX_VIEW_UNORDERED_NO_STAGING_DYNAMIC); } if (BufferType != BufferType.Structured) { if (format == BufferFormat.Unknown) { throw new ArgumentException(Resources.GORGFX_VIEW_UNKNOWN_FORMAT, "format"); } if (Settings.AllowRawViews) { if (format != BufferFormat.R32) { throw new GorgonException(GorgonResult.CannotBind, Resources.GORGFX_VIEW_UNORDERED_RAW_INVALID_FORMAT); } elementCount = SizeInBytes / 4; } else { // Ensure the size of the data type fits the requested format. var info = GorgonBufferFormatInfo.GetInfo(format); elementCount = SizeInBytes / info.SizeInBytes; } } else { isRaw = false; elementCount = SizeInBytes / Settings.StructureSize; format = BufferFormat.Unknown; } if (((start + count) > elementCount) || (start < 0) || (count < 1)) { throw new ArgumentException(string.Format(Resources.GORGFX_VIEW_ELEMENT_OUT_OF_RANGE, elementCount, (elementCount - start))); } if (BufferType == BufferType.Structured) { return((GorgonBufferUnorderedAccessView)_viewCache.GetUnorderedAccessView(format, start, count, 0, viewType, isRaw)); } if (!Graphics.VideoDevice.SupportsUnorderedAccessViewFormat(format)) { throw new GorgonException(GorgonResult.CannotCreate, string.Format(Resources.GORGFX_VIEW_FORMAT_NOT_SUPPORTED, format)); } return((GorgonBufferUnorderedAccessView)_viewCache.GetUnorderedAccessView(format, start, count, 0, viewType, isRaw)); }
/// <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); }