private void AllocateBuffer(uint vsize, uint isize) { if (_inBuffer) { if (_currentVertexOffset + vsize > _currentVertexBuffer.SizeInBytes || _currentIndexOffset + isize > _currentIndexBuffer.SizeInBytes) { CommitCurrentBuffers(); } } if (_inBuffer) { return; } // Cater for allocations that are larger than the buffer size var vSize = Math.Max(_vertexBufferSize, vsize); var iSize = Math.Max(_indexBufferSize, isize); _currentVertexBuffer = _device.ResourceFactory.CreateBuffer(new BufferDescription(vSize, BufferUsage.Dynamic | BufferUsage.VertexBuffer)); _currentIndexBuffer = _device.ResourceFactory.CreateBuffer(new BufferDescription(iSize, BufferUsage.Dynamic | BufferUsage.IndexBuffer)); _currentVertexMap = _device.Map(_currentVertexBuffer, MapMode.Write); _currentIndexMap = _device.Map(_currentIndexBuffer, MapMode.Write); _currentIndirectArguments = new List <IndirectArgument>(); _inBuffer = true; }
public unsafe void Update_ThenMapRead_Succeeds_R32Float(bool useArrayOverload) { Texture texture = RF.CreateTexture( TextureDescription.Texture2D(1024, 1024, 1, 1, PixelFormat.R32_Float, TextureUsage.Staging)); float[] data = Enumerable.Range(0, 1024 * 1024).Select(i => (float)i).ToArray(); fixed(float *dataPtr = data) { if (useArrayOverload) { GD.UpdateTexture(texture, data, 0, 0, 0, 1024, 1024, 1, 0, 0); } else { GD.UpdateTexture(texture, (IntPtr)dataPtr, 1024 * 1024 * 4, 0, 0, 0, 1024, 1024, 1, 0, 0); } } MappedResource map = GD.Map(texture, MapMode.Read, 0); float * mappedFloatPtr = (float *)map.Data; for (int y = 0; y < 1024; y++) { for (int x = 0; x < 1024; x++) { int index = y * 1024 + x; Assert.Equal(index, mappedFloatPtr[index]); } } }
public unsafe void Update_ThenMapRead_Succeeds_R8_G8_SNorm() { Texture texture = RF.CreateTexture( TextureDescription.Texture2D(8, 8, 1, 1, PixelFormat.R8_G8_SNorm, TextureUsage.Staging)); byte[] data = Enumerable.Range(0, 8 * 8 * 2).Select(i => (byte)i).ToArray(); fixed(byte *dataPtr = data) { GD.UpdateTexture(texture, (IntPtr)dataPtr, 8 * 8 * sizeof(byte) * 2, 0, 0, 0, 8, 8, 1, 0, 0); } MappedResource map = GD.Map(texture, MapMode.Read, 0); byte * mappedBytePtr = (byte *)map.Data; for (int y = 0; y < 8; y++) { for (int x = 0; x < 8; x++) { uint index0 = (uint)(y * map.RowPitch + x * 2); byte value0 = (byte)(y * 8 * 2 + x * 2); Assert.Equal(value0, mappedBytePtr[index0]); uint index1 = (uint)(index0 + 1); byte value1 = (byte)(value0 + 1); Assert.Equal(value1, mappedBytePtr[index1]); } } }
public unsafe void Update_ThenMapRead_SingleMip_Succeeds_R16UNorm(bool useArrayOverload) { Texture texture = RF.CreateTexture( TextureDescription.Texture2D(1024, 1024, 3, 1, PixelFormat.R16_UNorm, TextureUsage.Staging)); ushort[] data = Enumerable.Range(0, 256 * 256).Select(i => (ushort)i).ToArray(); fixed(ushort *dataPtr = data) { if (useArrayOverload) { GD.UpdateTexture(texture, data, 0, 0, 0, 256, 256, 1, 2, 0); } else { GD.UpdateTexture(texture, (IntPtr)dataPtr, 256 * 256 * sizeof(ushort), 0, 0, 0, 256, 256, 1, 2, 0); } } MappedResource map = GD.Map(texture, MapMode.Read, 2); ushort * mappedUShortPtr = (ushort *)map.Data; for (int y = 0; y < 256; y++) { for (int x = 0; x < 256; x++) { uint mapIndex = (uint)(y * (map.RowPitch / sizeof(ushort)) + x); ushort value = (ushort)(y * 256 + x); Assert.Equal(value, mappedUShortPtr[mapIndex]); } } }
public unsafe void Update_ThenCopySingleMip_Succeeds_R16UNorm() { TextureDescription desc = TextureDescription.Texture2D( 1024, 1024, 3, 1, PixelFormat.R16_UNorm, TextureUsage.Staging); Texture src = RF.CreateTexture(desc); Texture dst = RF.CreateTexture(desc); ushort[] data = Enumerable.Range(0, 256 * 256).Select(i => (ushort)i).ToArray(); fixed(ushort *dataPtr = data) { GD.UpdateTexture(src, (IntPtr)dataPtr, 256 * 256 * sizeof(ushort), 0, 0, 0, 256, 256, 1, 2, 0); } CommandList cl = RF.CreateCommandList(); cl.Begin(); cl.CopyTexture(src, dst, 2, 0); cl.End(); GD.SubmitCommands(cl); GD.WaitForIdle(); MappedResource map = GD.Map(dst, MapMode.Read, 2); ushort * mappedFloatPtr = (ushort *)map.Data; for (int y = 0; y < 256; y++) { for (int x = 0; x < 256; x++) { uint mapIndex = (uint)(y * (map.RowPitch / sizeof(ushort)) + x); ushort value = (ushort)(y * 256 + x); Assert.Equal(value, mappedFloatPtr[mapIndex]); } } }
/// <inheritdoc/> public override unsafe void GetData(Span <T> span, int offset, int count) { using MappedResource resource = MapResource(); if (IsPaddingPresent) { ref T spanRef = ref MemoryMarshal.GetReference(span); ref byte resourceRef = ref Unsafe.AsRef <byte>((void *)resource.Pointer);
public void Map_Succeeds_R32_G32_B32_A32_UInt() { Texture texture = RF.CreateTexture( TextureDescription.Texture2D(1024, 1024, 1, 1, PixelFormat.R32_G32_B32_A32_UInt, TextureUsage.Staging)); MappedResource map = GD.Map(texture, MapMode.ReadWrite, 0); GD.Unmap(texture, 0); }
/// <summary> /// Resource to load /// </summary> /// <param name="virtualPath">Requested virtual path</param> /// <param name="resource">Identified resource (i.e. the one to load)</param> /// <returns>Stream that can be returned to the Virtual Path Provider.</returns> /// <remarks>The default implementation uses <c>resource.Assembly.GetManifestResourceStream(resource.FullResourceName)</c></remarks> protected virtual Stream LoadStream(string virtualPath, MappedResource resource) { if (resource == null) { throw new ArgumentNullException("resource"); } var stream = resource.Assembly.GetManifestResourceStream(resource.FullResourceName); return(stream); }
public void Map_DifferentMode_Fails() { if (GD.BackendType == GraphicsBackend.Vulkan) { return; // TODO } Buffer buffer = RF.CreateBuffer(new BufferDescription(1024, BufferUsage.Staging)); MappedResource map = GD.Map(buffer, MapMode.Read); Assert.Throws <VeldridException>(() => GD.Map(buffer, MapMode.Write)); }
/// <summary> /// Resource to load. Will correct the returned views (so that they work as regular non-embedded views) /// </summary> /// <param name="virtualPath">Requested virtual path</param> /// <param name="resource">Identified resource (i.e. the one to load)</param> /// <returns> /// Stream that can be returned to the Virtual Path Provider. /// </returns> protected override Stream LoadStream(string virtualPath, MappedResource resource) { var stream = base.LoadStream(virtualPath, resource); // embedded views need a @inherits instruction if (stream != null && resource.FullResourceName.EndsWith(".cshtml")) { stream = CorrectView(virtualPath, stream); } return stream; }
public void BeginFrame(bool clear = false) { if (clear) { _slots.Clear(); } _map = _gd.Map(_stagingTexture, _mapMode); _textureMapped = true; _firstDirtySlot = uint.MaxValue; _lastDirtySlot = uint.MinValue; }
private unsafe Texture CreateTextureViaStaging(GraphicsDevice gd, ResourceFactory factory) { Texture staging = factory.CreateTexture( TextureDescription.Texture2D(Width, Height, MipLevels, 1, Format, TextureUsage.Staging)); Texture ret = factory.CreateTexture( TextureDescription.Texture2D(Width, Height, MipLevels, 1, Format, TextureUsage.Sampled)); CommandList cl = gd.ResourceFactory.CreateCommandList(); cl.Begin(); for (uint level = 0; level < MipLevels; level++) { Image <Rgba32> image = Images[level]; if (!image.TryGetSinglePixelSpan(out Span <Rgba32> pixelSpan)) { throw new VeldridException("Unable to get image pixelspan."); } fixed(void *pin = &MemoryMarshal.GetReference(pixelSpan)) { MappedResource map = gd.Map(staging, MapMode.Write, level); uint rowWidth = (uint)(image.Width * 4); if (rowWidth == map.RowPitch) { Unsafe.CopyBlock(map.Data.ToPointer(), pin, (uint)(image.Width * image.Height * 4)); } else { for (uint y = 0; y < image.Height; y++) { byte *dstStart = (byte *)map.Data.ToPointer() + y * map.RowPitch; byte *srcStart = (byte *)pin + y * rowWidth; Unsafe.CopyBlock(dstStart, srcStart, rowWidth); } } gd.Unmap(staging, level); cl.CopyTexture( staging, 0, 0, 0, level, 0, ret, 0, 0, 0, level, 0, (uint)image.Width, (uint)image.Height, 1, 1); } } cl.End(); gd.SubmitCommands(cl); staging.Dispose(); cl.Dispose(); return(ret); }
/// <summary> /// Resource to load. Will correct the returned views (so that they work as regular non-embedded views) /// </summary> /// <param name="virtualPath">Requested virtual path</param> /// <param name="resource">Identified resource (i.e. the one to load)</param> /// <returns> /// Stream that can be returned to the Virtual Path Provider. /// </returns> protected override Stream LoadStream(string virtualPath, MappedResource resource) { var stream = base.LoadStream(virtualPath, resource); // embedded views need a @inherits instruction if (stream != null && resource.FullResourceName.EndsWith(".cshtml")) { stream = CorrectView(virtualPath, stream); } return(stream); }
protected unsafe override void UpdateBufferCore(DeviceBuffer buffer, uint bufferOffsetInBytes, IntPtr source, uint sizeInBytes) { D3D11Buffer d3dBuffer = Util.AssertSubtype <DeviceBuffer, D3D11Buffer>(buffer); if (sizeInBytes == 0) { return; } bool useMap = (buffer.Usage & BufferUsage.Dynamic) == BufferUsage.Dynamic || (buffer.Usage & BufferUsage.Staging) == BufferUsage.Staging; if (useMap) { if (bufferOffsetInBytes != 0) { throw new NotImplementedException("bufferOffsetInBytes must be 0 for Dynamic Buffers."); } MappedResource mr = MapCore(buffer, MapMode.Write, 0); if (sizeInBytes < 1024) { Unsafe.CopyBlock(mr.Data.ToPointer(), source.ToPointer(), sizeInBytes); } else { System.Buffer.MemoryCopy(source.ToPointer(), mr.Data.ToPointer(), buffer.SizeInBytes, sizeInBytes); } UnmapCore(buffer, 0); } else { ResourceRegion?subregion = null; if ((d3dBuffer.Buffer.Description.BindFlags & BindFlags.ConstantBuffer) != BindFlags.ConstantBuffer) { // For a shader-constant buffer; set pDstBox to null. It is not possible to use // this method to partially update a shader-constant buffer subregion = new ResourceRegion() { Left = (int)bufferOffsetInBytes, Right = (int)(sizeInBytes + bufferOffsetInBytes), Bottom = 1, Back = 1 }; } lock (_immediateContextLock) { _immediateContext.UpdateSubresource(d3dBuffer.Buffer, 0, subregion, source, 0, 0); } } }
/// <inheritdoc/> public override void SetData(ReadOnlySpan <T> span, int offset, int count) { using Buffer <T> transferBuffer = new Buffer <T>(GraphicsDevice, count, count * ElementSizeInBytes, BufferType.Transfer); using (MappedResource resource = transferBuffer.MapResource()) { MemoryHelper.Copy(span, resource.Pointer, 0, count); } using CommandList copyCommandList = new CommandList(GraphicsDevice, CommandListType.Copy); copyCommandList.CopyBufferRegion(transferBuffer, 0, this, offset * ElementSizeInBytes, count * ElementSizeInBytes); copyCommandList.ExecuteAndWaitForCompletion(); }
public void Map_MultipleTimes_Succeeds() { DeviceBuffer buffer = RF.CreateBuffer(new BufferDescription(1024, BufferUsage.Staging)); MappedResource map = GD.Map(buffer, MapMode.ReadWrite); IntPtr dataPtr = map.Data; map = GD.Map(buffer, MapMode.ReadWrite); Assert.Equal(map.Data, dataPtr); map = GD.Map(buffer, MapMode.ReadWrite); Assert.Equal(map.Data, dataPtr); GD.Unmap(buffer); GD.Unmap(buffer); GD.Unmap(buffer); }
private unsafe Texture CreateTextureViaStaging(GraphicsDevice gd, ResourceFactory factory) { Texture staging = factory.CreateTexture( new TextureDescription(Width, Height, 1, MipLevels, 1, PixelFormat.R8_G8_B8_A8_UNorm, TextureUsage.Staging)); Texture ret = factory.CreateTexture( new TextureDescription(Width, Height, 1, MipLevels, 1, PixelFormat.R8_G8_B8_A8_UNorm, TextureUsage.Sampled)); CommandList cl = gd.ResourceFactory.CreateCommandList(); cl.Begin(); for (uint level = 0; level < MipLevels; level++) { Image <Rgba32> image = Images[level]; fixed(void *pin = &image.DangerousGetPinnableReferenceToPixelBuffer()) { MappedResource map = gd.Map(staging, MapMode.Write, level); uint rowWidth = (uint)(image.Width * 4); if (rowWidth == map.RowPitch) { Unsafe.CopyBlock(map.Data.ToPointer(), pin, (uint)(image.Width * image.Height * 4)); } else { for (uint y = 0; y < image.Height; y++) { byte *dstStart = (byte *)map.Data.ToPointer() + y * map.RowPitch; byte *srcStart = (byte *)pin + y * rowWidth; Unsafe.CopyBlock(dstStart, srcStart, rowWidth); } } gd.Unmap(staging, level); cl.CopyTexture( staging, 0, 0, 0, level, 0, ret, 0, 0, 0, level, 0, (uint)image.Width, (uint)image.Height, 1, 1); } } cl.End(); gd.ExecuteCommands(cl); cl.Dispose(); staging.Dispose(); return(ret); }
private static unsafe void SaveAsPng( RenderContext ctx, Texture texture, Stream dstStream, uint dstWidth, uint dstHeight) { MappedResource map = ctx.GraphicsDevice.Map(texture, MapMode.Read); var span = new ReadOnlySpan <Bgra32>(map.Data.ToPointer(), (int)map.SizeInBytes / 4); Image <Bgra32> image = Image.LoadPixelData(span, (int)texture.Width, (int)texture.Height); ctx.GraphicsDevice.Unmap(texture); if (dstWidth != texture.Width || dstHeight != texture.Height) { image.Mutate(x => x.Resize((int)dstWidth, (int)dstHeight)); } image.SaveAsPng(dstStream); }
public Vk3DMapProxy( FixedStagingBlock block, MappableResource resource, MapMode mode, uint subresource, uint rowPitch, uint depthPitch) { StagingBlock = block; MappedResource = new MappedResource( resource, mode, (IntPtr)block.Data, block.SizeInBytes, subresource, rowPitch, depthPitch); }
private void CopyToBuffer(MappedResource map, uint offset, Array data, uint size) { var handle = GCHandle.Alloc(data, GCHandleType.Pinned); try { var source = handle.AddrOfPinnedObject(); var destination = IntPtr.Add(map.Data, (int)offset); CopyMemory(destination, source, size); } finally { if (handle.IsAllocated) { handle.Free(); } } }
public unsafe void Staging_Map_WriteThenRead() { DeviceBuffer buffer = CreateBuffer(256, BufferUsage.Staging); MappedResource map = GD.Map(buffer, MapMode.Write); byte * dataPtr = (byte *)map.Data.ToPointer(); for (int i = 0; i < map.SizeInBytes; i++) { dataPtr[i] = (byte)i; } GD.Unmap(buffer); map = GD.Map(buffer, MapMode.Read); dataPtr = (byte *)map.Data.ToPointer(); for (int i = 0; i < map.SizeInBytes; i++) { Assert.Equal((byte)i, dataPtr[i]); } }
protected override Texture LoadStaging(Stream stream) { using var wicStream = new WICStream(_wicFactory, stream); using var decoder = new BitmapDecoder(_wicFactory, wicStream, DecodeOptions.CacheOnDemand); using var formatConv = new FormatConverter(_wicFactory); // Do NOT dispose the frame as it might lead to a crash. // Seems like it's owned by the decoder, so hopefully there should be no leaks. BitmapFrameDecode frame = decoder.GetFrame(0); formatConv.Initialize(frame, SharpDX.WIC.PixelFormat.Format32bppRGBA); uint width = (uint)frame.Size.Width; uint height = (uint)frame.Size.Height; Texture stagingTexture = _rf.CreateTexture(TextureDescription.Texture2D( width, height, mipLevels: 1, arrayLayers: 1, PixelFormat.R8_G8_B8_A8_UNorm, TextureUsage.Staging )); MappedResource map = _gd.Map(stagingTexture, MapMode.Write); uint rowWidth = width * 4; if (rowWidth == map.RowPitch) { formatConv.CopyPixels((int)map.RowPitch, map.Data, (int)map.SizeInBytes); } else { for (uint y = 0; y < height; y++) { byte *dstStart = (byte *)map.Data + y * map.RowPitch; formatConv.CopyPixels( new RawBox(x: 0, (int)y, (int)width, height: 1), (int)map.RowPitch, new SharpDX.DataPointer(dstStart, (int)map.RowPitch) ); } } _gd.Unmap(stagingTexture); return(stagingTexture); }
public unsafe void FillWithColorCube(GraphicsDevice d, System.Numerics.Vector4 c) { TextureDescription desc = new TextureDescription(); desc.Width = 1; desc.Height = 1; desc.MipLevels = 1; desc.SampleCount = TextureSampleCount.Count1; desc.ArrayLayers = 6; desc.Depth = 1; desc.Type = TextureType.Texture2D; desc.Usage = TextureUsage.Staging; desc.Format = PixelFormat.R32_G32_B32_A32_Float; _staging = d.ResourceFactory.CreateTexture(desc); float[] col = new float[4]; col[0] = c.X; col[1] = c.Y; col[2] = c.Z; col[3] = c.W; for (uint i = 0; i < 6; i++) { MappedResource map = d.Map(_staging, MapMode.Write, i); fixed(void *data = col) { Unsafe.CopyBlock(map.Data.ToPointer(), data, 16); } } _pool.DescriptorTableDirty = true; Renderer.AddBackgroundUploadTask((gd, cl) => { desc.ArrayLayers = 1; desc.Usage = TextureUsage.Sampled | TextureUsage.Cubemap; _texture = d.ResourceFactory.CreateTexture(desc); cl.CopyTexture(_staging, _texture); Resident = true; _pool.DescriptorTableDirty = true; }); }
/// <inheritdoc /> public unsafe int RegisterTexture(Span <Color> pixels, int width, int height) { var factory = GraphicsDevice.ResourceFactory; Texture staging = factory.CreateTexture( TextureDescription.Texture2D((uint)width, (uint)height, 1, 1, PixelFormat.R8_G8_B8_A8_UNorm, TextureUsage.Staging)); Texture ret = factory.CreateTexture( TextureDescription.Texture2D((uint)width, (uint)height, 1, 1, PixelFormat.R8_G8_B8_A8_UNorm, TextureUsage.Sampled)); CommandList cl = factory.CreateCommandList(); cl.Begin(); MappedResource map = GraphicsDevice.Map(staging, MapMode.Write, 0); if (width == map.RowPitch / 4) { var dst = new Span <Color>(map.Data.ToPointer(), width * height); pixels.CopyTo(dst); } else { for (var y = 0; y < height; y++) { var dst = new Span <Color>(IntPtr.Add(map.Data, y * (int)map.RowPitch).ToPointer(), width); var src = pixels.Slice(y * width, width); src.CopyTo(dst); } } GraphicsDevice.Unmap(staging); cl.CopyTexture(staging, ret); cl.End(); GraphicsDevice.SubmitCommands(cl); GraphicsDevice.DisposeWhenIdle(staging); GraphicsDevice.DisposeWhenIdle(cl); return(Register(ret)); }
/// <summary> /// Creates the indices /// </summary> /// <returns>Amount of indices to draw</returns> private unsafe int GenerateIndices(int verticeCount) { MappedResource indexMap = GraphicsDevice.MapSubresource(TerrainIndexBuffer, 0, MapMode.WriteDiscard); var indexBuffer = (int *)indexMap.DataBox.DataPointer; int index = 0; for (int i = 0; i < verticeCount / 4; i++) { indexBuffer[index++] = i * 4 + 0; indexBuffer[index++] = i * 4 + 1; indexBuffer[index++] = i * 4 + 2; indexBuffer[index++] = i * 4 + 2; indexBuffer[index++] = i * 4 + 3; indexBuffer[index++] = i * 4 + 0; } GraphicsDevice.UnmapSubresource(indexMap); return(index); }
public unsafe void FillWithColor(GraphicsDevice d, System.Drawing.Color c, string name) { TextureDescription desc = new TextureDescription(); desc.Width = 1; desc.Height = 1; desc.MipLevels = 1; desc.SampleCount = TextureSampleCount.Count1; desc.ArrayLayers = 1; desc.Depth = 1; desc.Type = TextureType.Texture2D; desc.Usage = TextureUsage.Staging; desc.Format = PixelFormat.R8_G8_B8_A8_UNorm; _staging = d.ResourceFactory.CreateTexture(desc); byte[] col = new byte[4]; col[0] = c.R; col[1] = c.G; col[2] = c.B; col[3] = c.A; MappedResource map = d.Map(_staging, MapMode.Write, 0); fixed(void *data = col) { Unsafe.CopyBlock(map.Data.ToPointer(), data, 4); } _pool.DescriptorTableDirty = true; Renderer.AddBackgroundUploadTask((gd, cl) => { desc.Usage = TextureUsage.Sampled; _texture = d.ResourceFactory.CreateTexture(desc); _texture.Name = name; cl.CopyTexture(_staging, _texture); Resident = true; _pool.DescriptorTableDirty = true; }); }
/// <summary> /// Maps a subresource so that particle data can be written to the vertex buffer /// </summary> /// <param name="device"></param> /// <returns></returns> public IntPtr MapBuffer(CommandList commandList) { if (IsBufferDirty && requiredQuads > 0) { InitializeIndexBuffer(commandList, requiredQuads * IndicesPerQuad); IsBufferDirty = false; } vertexBuffer = IntPtr.Zero; vertexBufferOrigin = IntPtr.Zero; if (IsBufferDirty) { return(IntPtr.Zero); } mappedVertices = commandList.MapSubresource(ResourceContext.VertexBuffer.Buffer, 0, MapMode.WriteDiscard, false, 0, ResourceContext.VertexCount * vertexStructSize); vertexBuffer = mappedVertices.DataBox.DataPointer; vertexBufferOrigin = mappedVertices.DataBox.DataPointer; return(mappedVertices.DataBox.DataPointer); }
/// <summary> /// Maps a subresource so that particle data can be written to the vertex buffer /// </summary> /// <param name="device"></param> /// <returns></returns> public IntPtr MapBuffer(GraphicsDevice device) { if (bufferIsDirty && requiredQuads > 0) { InitBuffer(device, requiredQuads * verticesPerQuad, requiredQuads * indicesPerQuad); bufferIsDirty = false; } vertexBuffer = IntPtr.Zero; vertexBufferOrigin = IntPtr.Zero; if (bufferIsDirty) { return(IntPtr.Zero); } mappedVertices = device.MapSubresource(resourceContext.VertexBuffer, 0, MapMode.WriteDiscard, false, 0, resourceContext.VertexCount * vertexStructSize); vertexBuffer = mappedVertices.DataBox.DataPointer; vertexBufferOrigin = mappedVertices.DataBox.DataPointer; return(mappedVertices.DataBox.DataPointer); }
public unsafe void UnusualSize() { DeviceBuffer src = RF.CreateBuffer( new BufferDescription(208, BufferUsage.UniformBuffer)); DeviceBuffer dst = RF.CreateBuffer( new BufferDescription(208, BufferUsage.Staging)); byte[] data = Enumerable.Range(0, 208).Select(i => (byte)(i * 150)).ToArray(); GD.UpdateBuffer(src, 0, data); CommandList cl = RF.CreateCommandList(); cl.Begin(); cl.CopyBuffer(src, 0, dst, 0, src.SizeInBytes); cl.End(); GD.SubmitCommands(cl); GD.WaitForIdle(); MappedResource readMap = GD.Map(dst, MapMode.Read); for (int i = 0; i < readMap.SizeInBytes; i++) { Assert.Equal((byte)(i * 150), ((byte *)readMap.Data)[i]); } }
public unsafe void Update_ThenMapRead_Succeeds_R16UNorm() { Texture texture = RF.CreateTexture( TextureDescription.Texture2D(1024, 1024, 1, 1, PixelFormat.R16_UNorm, TextureUsage.Staging)); ushort[] data = Enumerable.Range(0, 1024 * 1024).Select(i => (ushort)i).ToArray(); fixed(ushort *dataPtr = data) { GD.UpdateTexture(texture, (IntPtr)dataPtr, 1024 * 1024 * sizeof(ushort), 0, 0, 0, 1024, 1024, 1, 0, 0); } MappedResource map = GD.Map(texture, MapMode.Read, 0); ushort * mappedUShortPtr = (ushort *)map.Data; for (int y = 0; y < 1024; y++) { for (int x = 0; x < 1024; x++) { ushort index = (ushort)(y * 1024 + x); Assert.Equal(index, mappedUShortPtr[index]); } } }
/// <summary> /// Executes the specified test. /// </summary> /// <param name="generationResult">The generation result.</param> /// <param name="csFunctionName">Name of the cs function.</param> /// <param name="output">The output.</param> public void Execute( ShaderGenerationResult generationResult, string csFunctionName, ITestOutputHelper output) { if (Executed) { output.WriteLine( $"The {Name} tests have already been executed!"); return; } TestSets testSets = TestSets; Mappings mappings = testSets.Mappings; if (ToolChain == null) { /* * Generate the test data and the result set data for the CPU. */ AllocateResults(output); using (new TestTimer(output, $"Running {testSets.TestLoops} iterations on the {Name} backend")) { for (int test = 0; test < testSets.TestLoops; test++) { foreach (MethodMap method in mappings.MethodMaps) { method.ExecuteCPU(TestSets.TestData, Results, test); } } return; } } GeneratedShaderSet set; CompileResult compilationResult; // Compile shader for this backend. using (new TestTimer(output, $"Compiling Compute Shader for {ToolChain.GraphicsBackend}")) { set = generationResult.GetOutput(Backend).Single(); compilationResult = ToolChain.Compile(set.ComputeShaderCode, Stage.Compute, set.ComputeFunction.Name); } if (compilationResult.HasError) { output.WriteLine($"Failed to compile Compute Shader from set \"{set.Name}\"!"); output.WriteLine(compilationResult.ToString()); return; } Assert.NotNull(compilationResult.CompiledOutput); using (GraphicsDevice graphicsDevice = ToolChain.CreateHeadless()) { if (!graphicsDevice.Features.ComputeShader) { output.WriteLine( $"The {ToolChain.GraphicsBackend} backend does not support compute shaders, skipping!"); return; } ResourceFactory factory = graphicsDevice.ResourceFactory; using (DeviceBuffer inOutBuffer = factory.CreateBuffer( new BufferDescription( (uint)mappings.BufferSize, BufferUsage.StructuredBufferReadWrite, (uint)mappings.StructSize))) using (Shader computeShader = factory.CreateShader( new ShaderDescription( ShaderStages.Compute, compilationResult.CompiledOutput, csFunctionName))) using (ResourceLayout inOutStorageLayout = factory.CreateResourceLayout( new ResourceLayoutDescription( new ResourceLayoutElementDescription("InOutBuffer", ResourceKind.StructuredBufferReadWrite, ShaderStages.Compute)))) using (Pipeline computePipeline = factory.CreateComputePipeline(new ComputePipelineDescription( computeShader, new[] { inOutStorageLayout }, 1, 1, 1))) using (ResourceSet computeResourceSet = factory.CreateResourceSet( new ResourceSetDescription(inOutStorageLayout, inOutBuffer))) using (CommandList commandList = factory.CreateCommandList()) { // Ensure the headless graphics device is the backend we expect. Assert.Equal(ToolChain.GraphicsBackend, graphicsDevice.BackendType); output.WriteLine($"Created compute pipeline for {Name} backend."); // Allocate the results buffer AllocateResults(output); using (new TestTimer(output, $"Running {testSets.TestLoops} iterations on the {Name} backend")) { // Loop for each test for (int test = 0; test < testSets.TestLoops; test++) { // Update parameter buffer graphicsDevice.UpdateBuffer( inOutBuffer, 0, // Get the portion of test data for the current test loop Marshal.UnsafeAddrOfPinnedArrayElement(testSets.TestData, mappings.BufferSize * test), (uint)mappings.BufferSize); graphicsDevice.WaitForIdle(); // Execute compute shaders commandList.Begin(); commandList.SetPipeline(computePipeline); commandList.SetComputeResourceSet(0, computeResourceSet); commandList.Dispatch((uint)mappings.Methods, 1, 1); commandList.End(); graphicsDevice.SubmitCommands(commandList); graphicsDevice.WaitForIdle(); // Read back parameters using a staging buffer using (DeviceBuffer stagingBuffer = factory.CreateBuffer( new BufferDescription(inOutBuffer.SizeInBytes, BufferUsage.Staging))) { commandList.Begin(); commandList.CopyBuffer(inOutBuffer, 0, stagingBuffer, 0, stagingBuffer.SizeInBytes); commandList.End(); graphicsDevice.SubmitCommands(commandList); graphicsDevice.WaitForIdle(); // Read back test results MappedResource map = graphicsDevice.Map(stagingBuffer, MapMode.Read); mappings.SetResults(map.Data, Results, test); graphicsDevice.Unmap(stagingBuffer); } } } } } }
/// <summary> /// Resource to load /// </summary> /// <param name="virtualPath">Requested virtual path</param> /// <param name="resource">Identified resource (i.e. the one to load)</param> /// <returns>Stream that can be returned to the Virtual Path Provider.</returns> /// <remarks>The default implementation uses <c>resource.Assembly.GetManifestResourceStream(resource.FullResourceName)</c></remarks> protected virtual Stream LoadStream(string virtualPath, MappedResource resource) { if (resource == null) throw new ArgumentNullException("resource"); var stream = resource.Assembly.GetManifestResourceStream(resource.FullResourceName); return stream; }