/// <summary> /// Sets 3D texture data, specifying a mipmap level, source box, start index, and number of elements. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="level"></param> /// <param name="left"></param> /// <param name="top"></param> /// <param name="right"></param> /// <param name="bottom"></param> /// <param name="front"></param> /// <param name="back"></param> /// <param name="data"></param> /// <param name="startIndex"></param> /// <param name="elementCount"></param> public void SetData <T>(int level, int left, int top, int right, int bottom, int front, int back, T[] data, int startIndex, int elementCount) where T : struct { if (data == null) { throw new ArgumentNullException("data"); } var elementSizeInByte = Marshal.SizeOf(typeof(T)); var dataHandle = GCHandle.Alloc(data, GCHandleType.Pinned); var dataPtr = (IntPtr)(dataHandle.AddrOfPinnedObject().ToInt64() + startIndex * elementSizeInByte); try { int width = right - left; int height = bottom - top; int depth = back - front; int rowPitch = width * Converter.SizeOf(format); int slicePitch = rowPitch * height; // For 3D texture: Size of 2D image. var box = new DataBox(dataPtr, rowPitch, slicePitch); int subresourceIndex = level; var region = new ResourceRegion(left, top, front, right, bottom, back); lock (device.DeviceContext) { device.DeviceContext.UpdateSubresource(box, tex3D, subresourceIndex, region); } } finally { dataHandle.Free(); } }
/// <summary> /// Sets cube texture data, specifying a cubemap face, mipmap level, source rectangle, start index, and number of elements. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="face"></param> /// <param name="level"></param> /// <param name="rect"></param> /// <param name="data"></param> /// <param name="startIndex"></param> /// <param name="elementCount"></param> public void SetData <T>(CubeFace face, int level, Rectangle?rect, T[] data, int startIndex, int elementCount) where T : struct { if (data == null) { throw new ArgumentNullException("data"); } var elementSizeInByte = Marshal.SizeOf(typeof(T)); var dataHandle = GCHandle.Alloc(data, GCHandleType.Pinned); try { var dataPtr = (IntPtr)(dataHandle.AddrOfPinnedObject().ToInt64() + startIndex * elementSizeInByte); int xOffset, yOffset, width, height; if (rect.HasValue) { xOffset = rect.Value.X; yOffset = rect.Value.Y; width = rect.Value.Width; height = rect.Value.Height; } else { xOffset = 0; yOffset = 0; width = Math.Max(1, this.Width >> level); height = Math.Max(1, this.Height >> level); // For DXT textures the width and height of each level is a multiple of 4. if (format == ColorFormat.Dxt1 || format == ColorFormat.Dxt3 || format == ColorFormat.Dxt5) { width = (width + 3) & ~3; height = (height + 3) & ~3; } } var box = new DataBox(dataPtr, width * Converter.SizeOf(format), 0); int subresourceIndex = (int)face * mipCount + level; var region = new ResourceRegion { Top = yOffset, Front = 0, Back = 1, Bottom = yOffset + height, Left = xOffset, Right = xOffset + width }; lock (device.DeviceContext) { device.DeviceContext.UpdateSubresource(box, texCube, subresourceIndex, region); } } finally { dataHandle.Free(); } }
/// <summary> /// Sets 2D texture data, specifying a mipmap level, source rectangle, start index, and number of elements. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="level"></param> /// <param name="data"></param> /// <param name="startIndex"></param> /// <param name="elementCount"></param> public void SetData <T>(int level, Rectangle?rect, T[] data, int startIndex, int elementCount) where T : struct { var elementSizeInByte = Marshal.SizeOf(typeof(T)); var dataHandle = GCHandle.Alloc(data, GCHandleType.Pinned); // Use try..finally to make sure dataHandle is freed in case of an error try { var startBytes = startIndex * elementSizeInByte; var dataPtr = (IntPtr)(dataHandle.AddrOfPinnedObject().ToInt64() + startBytes); int x, y, w, h; if (rect.HasValue) { x = rect.Value.X; y = rect.Value.Y; w = rect.Value.Width; h = rect.Value.Height; } else { x = 0; y = 0; w = Math.Max(Width >> level, 1); h = Math.Max(Height >> level, 1); // For DXT textures the width and height of each level is a multiple of 4. if (format == ColorFormat.Dxt1 || format == ColorFormat.Dxt3 || format == ColorFormat.Dxt5) { w = (w + 3) & ~3; h = (h + 3) & ~3; } } var box = new SharpDX.DataBox(dataPtr, w * Converter.SizeOf(format), 0); var region = new SharpDX.Direct3D11.ResourceRegion(); region.Top = y; region.Front = 0; region.Back = 1; region.Bottom = y + h; region.Left = x; region.Right = x + w; lock (device.DeviceContext) { device.DeviceContext.UpdateSubresource(box, tex2D, level, region); } } finally { dataHandle.Free(); } }
/// <summary> /// Computes shader resource pitch /// </summary> /// <param name="format"></param> /// <param name="width"></param> /// <returns></returns> public static int GetPitch(ColorFormat format, int width) { Debug.Assert(width > 0, "The width is negative!"); int pitch; switch (format) { case ColorFormat.Dxt1: case ColorFormat.Dxt3: case ColorFormat.Dxt5: Debug.Assert(MathUtil.IsPowerOfTwo(width), "This format must be power of two!"); pitch = ((width + 3) / 4) * Converter.SizeOf(format); break; default: pitch = width * Converter.SizeOf(format); break; } ; return(pitch); }
/// <summary> /// /// </summary> /// <param name="structureStride"></param> /// <param name="structureCount"></param> void Create(GraphicsDevice device, VertexFormat format, int elementsCount, StructuredBufferFlags flags) { Capacity = elementsCount; Stride = Converter.SizeOf(format); Width = elementsCount; Height = 0; Depth = 0; // create staging buffer : var bufferDesc = new BufferDescription { BindFlags = BindFlags.None, Usage = ResourceUsage.Staging, CpuAccessFlags = CpuAccessFlags.Write | CpuAccessFlags.Read, OptionFlags = ResourceOptionFlags.None, SizeInBytes = Capacity * Stride, }; bufferStaging = new Buffer(device.Device, bufferDesc); // create count buffer : bufferDesc = new BufferDescription { BindFlags = BindFlags.None, Usage = ResourceUsage.Staging, CpuAccessFlags = CpuAccessFlags.Write | CpuAccessFlags.Read, OptionFlags = ResourceOptionFlags.None, SizeInBytes = 4, }; bufferCount = new Buffer(device.Device, bufferDesc); // create GPU buffer : bufferDesc = new BufferDescription { BindFlags = BindFlags.UnorderedAccess | BindFlags.ShaderResource, Usage = ResourceUsage.Default, CpuAccessFlags = CpuAccessFlags.None, OptionFlags = ResourceOptionFlags.None, SizeInBytes = Capacity * Stride, }; bufferGpu = new Buffer(device.Device, bufferDesc); var uavFlag = UnorderedAccessViewBufferFlags.None; if (flags == StructuredBufferFlags.None) { uavFlag = UnorderedAccessViewBufferFlags.None; } if (flags == StructuredBufferFlags.Append) { uavFlag = UnorderedAccessViewBufferFlags.Append; } if (flags == StructuredBufferFlags.Counter) { uavFlag = UnorderedAccessViewBufferFlags.Counter; } // create UAV : var uavDesc = new UnorderedAccessViewDescription { Format = Converter.Convert(format), Dimension = UnorderedAccessViewDimension.Buffer, Buffer = new UnorderedAccessViewDescription.BufferResource { ElementCount = Capacity, FirstElement = 0, Flags = uavFlag } }; uav = new UnorderedAccessView(device.Device, BufferGPU, uavDesc); // create SRV : var srvDesc = new ShaderResourceViewDescription { Format = Converter.Convert(format), Buffer = { ElementCount = Capacity, FirstElement = 0 }, Dimension = ShaderResourceViewDimension.Buffer }; SRV = new ShaderResourceView(device.Device, BufferGPU, srvDesc); }