public void ResourceSet_IncompatibleSet_Fails() { DeviceBuffer infoBuffer = RF.CreateBuffer(new BufferDescription(16, BufferUsage.UniformBuffer)); DeviceBuffer orthoBuffer = RF.CreateBuffer(new BufferDescription(64, BufferUsage.UniformBuffer)); ShaderSetDescription shaderSet = new ShaderSetDescription( new VertexLayoutDescription[] { new VertexLayoutDescription( new VertexElementDescription("Position", VertexElementSemantic.Position, VertexElementFormat.Float2), new VertexElementDescription("Color_UInt", VertexElementSemantic.Color, VertexElementFormat.UInt4)) }, new Shader[] { TestShaders.Load(RF, "UIntVertexAttribs", ShaderStages.Vertex, "VS"), TestShaders.Load(RF, "UIntVertexAttribs", ShaderStages.Fragment, "FS") }); ResourceLayout layout = RF.CreateResourceLayout(new ResourceLayoutDescription( new ResourceLayoutElementDescription("InfoBuffer", ResourceKind.UniformBuffer, ShaderStages.Vertex), new ResourceLayoutElementDescription("Ortho", ResourceKind.UniformBuffer, ShaderStages.Vertex))); ResourceLayout layout2 = RF.CreateResourceLayout(new ResourceLayoutDescription( new ResourceLayoutElementDescription("InfoBuffer", ResourceKind.UniformBuffer, ShaderStages.Vertex), new ResourceLayoutElementDescription("Tex", ResourceKind.TextureReadOnly, ShaderStages.Fragment))); ResourceLayout layout3 = RF.CreateResourceLayout(new ResourceLayoutDescription( new ResourceLayoutElementDescription("InfoBuffer", ResourceKind.UniformBuffer, ShaderStages.Vertex))); Texture tex = RF.CreateTexture(TextureDescription.Texture2D(16, 16, 1, 1, PixelFormat.R32_G32_B32_A32_Float, TextureUsage.Sampled)); TextureView texView = RF.CreateTextureView(tex); ResourceSet set = RF.CreateResourceSet(new ResourceSetDescription(layout, infoBuffer, orthoBuffer)); ResourceSet set2 = RF.CreateResourceSet(new ResourceSetDescription(layout2, infoBuffer, texView)); ResourceSet set3 = RF.CreateResourceSet(new ResourceSetDescription(layout3, infoBuffer)); GraphicsPipelineDescription gpd = new GraphicsPipelineDescription( BlendStateDescription.SingleOverrideBlend, DepthStencilStateDescription.Disabled, RasterizerStateDescription.Default, PrimitiveTopology.PointList, shaderSet, layout, new OutputDescription(null, new OutputAttachmentDescription(PixelFormat.B8_G8_R8_A8_UNorm))); Pipeline pipeline = RF.CreateGraphicsPipeline(ref gpd); CommandList cl = RF.CreateCommandList(); cl.Begin(); cl.SetPipeline(pipeline); cl.SetGraphicsResourceSet(0, set); Assert.Throws <VeldridException>(() => cl.SetGraphicsResourceSet(0, set2)); // Wrong type Assert.Throws <VeldridException>(() => cl.SetGraphicsResourceSet(0, set3)); // Wrong count }
public void ResourceSet_InvalidSlot_Fails() { DeviceBuffer infoBuffer = RF.CreateBuffer(new BufferDescription(16, BufferUsage.UniformBuffer)); DeviceBuffer orthoBuffer = RF.CreateBuffer(new BufferDescription(64, BufferUsage.UniformBuffer)); ShaderSetDescription shaderSet = new ShaderSetDescription( new VertexLayoutDescription[] { new VertexLayoutDescription( new VertexElementDescription("Position", VertexElementSemantic.Position, VertexElementFormat.Float2), new VertexElementDescription("Color_UInt", VertexElementSemantic.Color, VertexElementFormat.UInt4)) }, new Shader[] { TestShaders.Load(RF, "UIntVertexAttribs", ShaderStages.Vertex, "VS"), TestShaders.Load(RF, "UIntVertexAttribs", ShaderStages.Fragment, "FS") }); ResourceLayout layout = RF.CreateResourceLayout(new ResourceLayoutDescription( new ResourceLayoutElementDescription("InfoBuffer", ResourceKind.UniformBuffer, ShaderStages.Vertex), new ResourceLayoutElementDescription("Ortho", ResourceKind.UniformBuffer, ShaderStages.Vertex))); ResourceSet set = RF.CreateResourceSet(new ResourceSetDescription(layout, infoBuffer, orthoBuffer)); GraphicsPipelineDescription gpd = new GraphicsPipelineDescription( BlendStateDescription.SingleOverrideBlend, DepthStencilStateDescription.Disabled, RasterizerStateDescription.Default, PrimitiveTopology.PointList, shaderSet, layout, new OutputDescription(null, new OutputAttachmentDescription(PixelFormat.B8_G8_R8_A8_UNorm))); Pipeline pipeline = RF.CreateGraphicsPipeline(ref gpd); CommandList cl = RF.CreateCommandList(); cl.Begin(); cl.SetPipeline(pipeline); Assert.Throws <VeldridException>(() => cl.SetGraphicsResourceSet(1, set)); Assert.Throws <VeldridException>(() => cl.SetGraphicsResourceSet(2, set)); Assert.Throws <VeldridException>(() => cl.SetGraphicsResourceSet(3, set)); }
public void BasicCompute() { if (!GD.Features.ComputeShader) { return; } ResourceLayout layout = RF.CreateResourceLayout(new ResourceLayoutDescription( new ResourceLayoutElementDescription("Params", ResourceKind.UniformBuffer, ShaderStages.Compute), new ResourceLayoutElementDescription("Source", ResourceKind.StructuredBufferReadWrite, ShaderStages.Compute), new ResourceLayoutElementDescription("Destination", ResourceKind.StructuredBufferReadWrite, ShaderStages.Compute))); uint width = 1024; uint height = 1024; DeviceBuffer paramsBuffer = RF.CreateBuffer(new BufferDescription((uint)Unsafe.SizeOf <ComputeTestParams>(), BufferUsage.UniformBuffer)); DeviceBuffer sourceBuffer = RF.CreateBuffer(new BufferDescription(width * height * 4, BufferUsage.StructuredBufferReadWrite, 4)); DeviceBuffer destinationBuffer = RF.CreateBuffer(new BufferDescription(width * height * 4, BufferUsage.StructuredBufferReadWrite, 4)); GD.UpdateBuffer(paramsBuffer, 0, new ComputeTestParams { Width = width, Height = height }); float[] sourceData = new float[width * height]; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { int index = y * (int)width + x; sourceData[index] = index; } } GD.UpdateBuffer(sourceBuffer, 0, sourceData); ResourceSet rs = RF.CreateResourceSet(new ResourceSetDescription(layout, paramsBuffer, sourceBuffer, destinationBuffer)); Pipeline pipeline = RF.CreateComputePipeline(new ComputePipelineDescription( TestShaders.Load(RF, "BasicComputeTest", ShaderStages.Compute, "CS"), layout, 16, 16, 1)); CommandList cl = RF.CreateCommandList(); cl.Begin(); cl.SetPipeline(pipeline); cl.SetComputeResourceSet(0, rs); cl.Dispatch(width / 16, width / 16, 1); cl.End(); GD.SubmitCommands(cl); GD.WaitForIdle(); DeviceBuffer sourceReadback = GetReadback(sourceBuffer); DeviceBuffer destinationReadback = GetReadback(destinationBuffer); MappedResourceView <float> sourceReadView = GD.Map <float>(sourceReadback, MapMode.Read); MappedResourceView <float> destinationReadView = GD.Map <float>(destinationReadback, MapMode.Read); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { int index = y * (int)width + x; Assert.Equal(2 * sourceData[index], sourceReadView[index]); Assert.Equal(sourceData[index], destinationReadView[index]); } } GD.Unmap(sourceReadback); GD.Unmap(destinationReadback); }
public void Points_WithUShortColor() { Texture target = RF.CreateTexture(TextureDescription.Texture2D( 50, 50, 1, 1, PixelFormat.R32_G32_B32_A32_Float, TextureUsage.RenderTarget)); Texture staging = RF.CreateTexture(TextureDescription.Texture2D( 50, 50, 1, 1, PixelFormat.R32_G32_B32_A32_Float, TextureUsage.Staging)); Framebuffer framebuffer = RF.CreateFramebuffer(new FramebufferDescription(null, target)); DeviceBuffer infoBuffer = RF.CreateBuffer(new BufferDescription(16, BufferUsage.UniformBuffer)); DeviceBuffer orthoBuffer = RF.CreateBuffer(new BufferDescription(64, BufferUsage.UniformBuffer)); Matrix4x4 orthoMatrix = Matrix4x4.CreateOrthographicOffCenter( 0, framebuffer.Width, framebuffer.Height, 0, -1, 1); GD.UpdateBuffer(orthoBuffer, 0, ref orthoMatrix); ShaderSetDescription shaderSet = new ShaderSetDescription( new VertexLayoutDescription[] { new VertexLayoutDescription( new VertexElementDescription("Position", VertexElementSemantic.Position, VertexElementFormat.Float2), new VertexElementDescription("Color_UInt", VertexElementSemantic.Color, VertexElementFormat.UShort4)) }, new Shader[] { TestShaders.Load(RF, "U16VertexAttribs", ShaderStages.Vertex, "VS"), TestShaders.Load(RF, "U16VertexAttribs", ShaderStages.Fragment, "FS") }); ResourceLayout layout = RF.CreateResourceLayout(new ResourceLayoutDescription( new ResourceLayoutElementDescription("InfoBuffer", ResourceKind.UniformBuffer, ShaderStages.Vertex), new ResourceLayoutElementDescription("Ortho", ResourceKind.UniformBuffer, ShaderStages.Vertex))); ResourceSet set = RF.CreateResourceSet(new ResourceSetDescription(layout, infoBuffer, orthoBuffer)); GraphicsPipelineDescription gpd = new GraphicsPipelineDescription( BlendStateDescription.SingleOverrideBlend, DepthStencilStateDescription.Disabled, RasterizerStateDescription.Default, PrimitiveTopology.PointList, shaderSet, layout, framebuffer.OutputDescription); Pipeline pipeline = RF.CreateGraphicsPipeline(ref gpd); uint colorNormalizationFactor = 2500; VertexCPU_UShort[] vertices = new VertexCPU_UShort[] { new VertexCPU_UShort { Position = new Vector2(0.5f, 0.5f), R = (ushort)(0.25f * colorNormalizationFactor), G = (ushort)(0.5f * colorNormalizationFactor), B = (ushort)(0.75f * colorNormalizationFactor), }, new VertexCPU_UShort { Position = new Vector2(10.5f, 12.5f), R = (ushort)(0.25f * colorNormalizationFactor), G = (ushort)(0.5f * colorNormalizationFactor), B = (ushort)(0.75f * colorNormalizationFactor), }, new VertexCPU_UShort { Position = new Vector2(25.5f, 35.5f), R = (ushort)(0.75f * colorNormalizationFactor), G = (ushort)(0.5f * colorNormalizationFactor), B = (ushort)(0.25f * colorNormalizationFactor), }, new VertexCPU_UShort { Position = new Vector2(49.5f, 49.5f), R = (ushort)(0.15f * colorNormalizationFactor), G = (ushort)(0.2f * colorNormalizationFactor), B = (ushort)(0.35f * colorNormalizationFactor), }, }; DeviceBuffer vb = RF.CreateBuffer( new BufferDescription((uint)(Unsafe.SizeOf <UIntVertexAttribs.Vertex>() * vertices.Length), BufferUsage.VertexBuffer)); GD.UpdateBuffer(vb, 0, vertices); GD.UpdateBuffer(infoBuffer, 0, new UIntVertexAttribs.Info { ColorNormalizationFactor = colorNormalizationFactor }); CommandList cl = RF.CreateCommandList(); cl.Begin(); cl.SetFramebuffer(framebuffer); cl.SetFullViewports(); cl.SetFullScissorRects(); cl.ClearColorTarget(0, RgbaFloat.Black); cl.SetPipeline(pipeline); cl.SetVertexBuffer(0, vb); cl.SetGraphicsResourceSet(0, set); cl.Draw((uint)vertices.Length); cl.SetFramebuffer(GD.SwapchainFramebuffer); cl.ClearColorTarget(0, RgbaFloat.Red); cl.CopyTexture(target, staging); cl.End(); GD.SubmitCommands(cl); GD.WaitForIdle(); MappedResourceView <RgbaFloat> readView = GD.Map <RgbaFloat>(staging, MapMode.Read); foreach (VertexCPU_UShort vertex in vertices) { uint x = (uint)vertex.Position.X; uint y = (uint)vertex.Position.Y; if (GD.BackendType == GraphicsBackend.OpenGL) { y = framebuffer.Height - y - 1; } RgbaFloat expectedColor = new RgbaFloat( vertex.R / (float)colorNormalizationFactor, vertex.G / (float)colorNormalizationFactor, vertex.B / (float)colorNormalizationFactor, 1); Assert.Equal(expectedColor, readView[x, y], RgbaFloatFuzzyComparer.Instance); } GD.Unmap(staging); }
public unsafe void Points_WithTexture_UpdateUnrelated() { // This is a regression test for the case where a user modifies an unrelated texture // at a time after a ResourceSet containing a texture has been bound. The OpenGL // backend was caching texture state improperly, resulting in wrong textures being sampled. Texture target = RF.CreateTexture(TextureDescription.Texture2D( 50, 50, 1, 1, PixelFormat.R32_G32_B32_A32_Float, TextureUsage.RenderTarget)); Texture staging = RF.CreateTexture(TextureDescription.Texture2D( 50, 50, 1, 1, PixelFormat.R32_G32_B32_A32_Float, TextureUsage.Staging)); Framebuffer framebuffer = RF.CreateFramebuffer(new FramebufferDescription(null, target)); DeviceBuffer orthoBuffer = RF.CreateBuffer(new BufferDescription(64, BufferUsage.UniformBuffer)); Matrix4x4 orthoMatrix = Matrix4x4.CreateOrthographicOffCenter( 0, framebuffer.Width, framebuffer.Height, 0, -1, 1); GD.UpdateBuffer(orthoBuffer, 0, ref orthoMatrix); Texture sampledTexture = RF.CreateTexture( TextureDescription.Texture2D(1, 1, 1, 1, PixelFormat.R32_G32_B32_A32_Float, TextureUsage.Sampled)); TextureView view = RF.CreateTextureView(sampledTexture); RgbaFloat white = RgbaFloat.White; GD.UpdateTexture(sampledTexture, (IntPtr)(&white), (uint)Unsafe.SizeOf <RgbaFloat>(), 0, 0, 0, 1, 1, 1, 0, 0); Texture shouldntBeSampledTexture = RF.CreateTexture( TextureDescription.Texture2D(1, 1, 1, 1, PixelFormat.R32_G32_B32_A32_Float, TextureUsage.Sampled)); ShaderSetDescription shaderSet = new ShaderSetDescription( new VertexLayoutDescription[] { new VertexLayoutDescription( new VertexElementDescription("Position", VertexElementSemantic.Position, VertexElementFormat.Float2)) }, new Shader[] { TestShaders.Load(RF, "TexturedPoints", ShaderStages.Vertex, "VS"), TestShaders.Load(RF, "TexturedPoints", ShaderStages.Fragment, "FS") }); ResourceLayout layout = RF.CreateResourceLayout(new ResourceLayoutDescription( new ResourceLayoutElementDescription("Ortho", ResourceKind.UniformBuffer, ShaderStages.Vertex), new ResourceLayoutElementDescription("Tex", ResourceKind.TextureReadOnly, ShaderStages.Fragment), new ResourceLayoutElementDescription("Smp", ResourceKind.Sampler, ShaderStages.Fragment))); ResourceSet set = RF.CreateResourceSet(new ResourceSetDescription(layout, orthoBuffer, view, GD.PointSampler)); GraphicsPipelineDescription gpd = new GraphicsPipelineDescription( BlendStateDescription.SingleOverrideBlend, DepthStencilStateDescription.Disabled, RasterizerStateDescription.Default, PrimitiveTopology.PointList, shaderSet, layout, framebuffer.OutputDescription); Pipeline pipeline = RF.CreateGraphicsPipeline(ref gpd); Vector2[] vertices = new Vector2[] { new Vector2(0.5f, 0.5f), new Vector2(15.5f, 15.5f), new Vector2(25.5f, 26.5f), new Vector2(3.5f, 25.5f), }; DeviceBuffer vb = RF.CreateBuffer( new BufferDescription((uint)(Unsafe.SizeOf <Vector2>() * vertices.Length), BufferUsage.VertexBuffer)); GD.UpdateBuffer(vb, 0, vertices); CommandList cl = RF.CreateCommandList(); for (int i = 0; i < 2; i++) { cl.Begin(); cl.SetFramebuffer(framebuffer); cl.ClearColorTarget(0, RgbaFloat.Black); cl.SetPipeline(pipeline); cl.SetVertexBuffer(0, vb); cl.SetGraphicsResourceSet(0, set); // Modify an unrelated texture. // This must have no observable effect on the next draw call. RgbaFloat pink = RgbaFloat.Pink; GD.UpdateTexture(shouldntBeSampledTexture, (IntPtr)(&pink), (uint)Unsafe.SizeOf <RgbaFloat>(), 0, 0, 0, 1, 1, 1, 0, 0); cl.Draw((uint)vertices.Length); cl.End(); GD.SubmitCommands(cl); GD.WaitForIdle(); } cl.Begin(); cl.CopyTexture(target, staging); cl.End(); GD.SubmitCommands(cl); GD.WaitForIdle(); MappedResourceView <RgbaFloat> readView = GD.Map <RgbaFloat>(staging, MapMode.Read); foreach (Vector2 vertex in vertices) { uint x = (uint)vertex.X; uint y = (uint)vertex.Y; if (HasInvertedY(GD.BackendType)) { y = framebuffer.Height - y - 1; } Assert.Equal(white, readView[x, y], RgbaFloatFuzzyComparer.Instance); } GD.Unmap(staging); }
public void ComputeGeneratedVertices() { if (!GD.Features.ComputeShader) { return; } uint width = 512; uint height = 512; Texture output = RF.CreateTexture( TextureDescription.Texture2D(width, height, 1, 1, PixelFormat.R32_G32_B32_A32_Float, TextureUsage.RenderTarget)); Framebuffer framebuffer = RF.CreateFramebuffer(new FramebufferDescription(null, output)); uint vertexSize = (uint)Unsafe.SizeOf <ColoredVertex>(); DeviceBuffer buffer = RF.CreateBuffer(new BufferDescription( vertexSize * 4, BufferUsage.StructuredBufferReadWrite, vertexSize)); ResourceLayout computeLayout = RF.CreateResourceLayout(new ResourceLayoutDescription( new ResourceLayoutElementDescription("OutputVertices", ResourceKind.StructuredBufferReadWrite, ShaderStages.Compute))); ResourceSet computeSet = RF.CreateResourceSet(new ResourceSetDescription(computeLayout, buffer)); Pipeline computePipeline = RF.CreateComputePipeline(new ComputePipelineDescription( TestShaders.Load(RF, "ComputeColoredQuadGenerator", ShaderStages.Compute, "CS"), computeLayout, 1, 1, 1)); ResourceLayout graphicsLayout = RF.CreateResourceLayout(new ResourceLayoutDescription( new ResourceLayoutElementDescription("InputVertices", ResourceKind.StructuredBufferReadOnly, ShaderStages.Vertex))); ResourceSet graphicsSet = RF.CreateResourceSet(new ResourceSetDescription(graphicsLayout, buffer)); Pipeline graphicsPipeline = RF.CreateGraphicsPipeline(new GraphicsPipelineDescription( BlendStateDescription.SingleOverrideBlend, DepthStencilStateDescription.Disabled, RasterizerStateDescription.Default, PrimitiveTopology.TriangleStrip, new ShaderSetDescription( Array.Empty <VertexLayoutDescription>(), new[] { TestShaders.Load(RF, "ColoredQuadRenderer", ShaderStages.Vertex, "VS"), TestShaders.Load(RF, "ColoredQuadRenderer", ShaderStages.Fragment, "FS"), }), graphicsLayout, framebuffer.OutputDescription)); CommandList cl = RF.CreateCommandList(); cl.Begin(); cl.SetPipeline(computePipeline); cl.SetComputeResourceSet(0, computeSet); cl.Dispatch(1, 1, 1); cl.SetFramebuffer(framebuffer); cl.ClearColorTarget(0, new RgbaFloat()); cl.SetPipeline(graphicsPipeline); cl.SetGraphicsResourceSet(0, graphicsSet); cl.Draw(4); cl.End(); GD.SubmitCommands(cl); GD.WaitForIdle(); Texture readback = GetReadback(output); MappedResourceView <RgbaFloat> readView = GD.Map <RgbaFloat>(readback, MapMode.Read); for (uint y = 0; y < height; y++) { for (uint x = 0; x < width; x++) { Assert.Equal(RgbaFloat.Red, readView[x, y]); } } GD.Unmap(readback); }