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 <BasicComputeTestParams>(), 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 BasicComputeTestParams { 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.LoadCompute(RF, "BasicComputeTest"), 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 FillBuffer_WithOffsets(uint srcSetMultiple, uint srcBindingMultiple, uint dstSetMultiple, uint dstBindingMultiple, bool combinedLayout) { if (!GD.Features.ComputeShader) { return; } Debug.Assert((GD.StructuredBufferMinOffsetAlignment % sizeof(uint)) == 0); uint valueCount = 512; uint dataSize = valueCount * sizeof(uint); uint totalSrcAlignment = GD.StructuredBufferMinOffsetAlignment * (srcSetMultiple + srcBindingMultiple); uint totalDstAlignment = GD.StructuredBufferMinOffsetAlignment * (dstSetMultiple + dstBindingMultiple); DeviceBuffer copySrc = RF.CreateBuffer( new BufferDescription(totalSrcAlignment + dataSize, BufferUsage.StructuredBufferReadOnly, sizeof(uint))); DeviceBuffer copyDst = RF.CreateBuffer( new BufferDescription(totalDstAlignment + dataSize, BufferUsage.StructuredBufferReadWrite, sizeof(uint))); ResourceLayout[] layouts; ResourceSet[] sets; DeviceBufferRange srcRange = new DeviceBufferRange(copySrc, srcSetMultiple * GD.StructuredBufferMinOffsetAlignment, dataSize); DeviceBufferRange dstRange = new DeviceBufferRange(copyDst, dstSetMultiple * GD.StructuredBufferMinOffsetAlignment, dataSize); if (combinedLayout) { layouts = new[] { RF.CreateResourceLayout(new ResourceLayoutDescription( new ResourceLayoutElementDescription( "CopySrc", ResourceKind.StructuredBufferReadOnly, ShaderStages.Compute, ResourceLayoutElementOptions.DynamicBinding), new ResourceLayoutElementDescription( "CopyDst", ResourceKind.StructuredBufferReadWrite, ShaderStages.Compute, ResourceLayoutElementOptions.DynamicBinding))) }; sets = new[] { RF.CreateResourceSet(new ResourceSetDescription(layouts[0], srcRange, dstRange)) }; } else { layouts = new[] { RF.CreateResourceLayout(new ResourceLayoutDescription( new ResourceLayoutElementDescription( "CopySrc", ResourceKind.StructuredBufferReadOnly, ShaderStages.Compute, ResourceLayoutElementOptions.DynamicBinding))), RF.CreateResourceLayout(new ResourceLayoutDescription( new ResourceLayoutElementDescription( "CopyDst", ResourceKind.StructuredBufferReadWrite, ShaderStages.Compute, ResourceLayoutElementOptions.DynamicBinding))) }; sets = new[] { RF.CreateResourceSet(new ResourceSetDescription(layouts[0], srcRange)), RF.CreateResourceSet(new ResourceSetDescription(layouts[1], dstRange)), }; } Pipeline pipeline = RF.CreateComputePipeline(new ComputePipelineDescription( TestShaders.LoadCompute(RF, combinedLayout ? "FillBuffer" : "FillBuffer_SeparateLayout"), layouts, 1, 1, 1)); uint[] srcData = Enumerable.Range(0, (int)copySrc.SizeInBytes / sizeof(uint)).Select(i => (uint)i).ToArray(); GD.UpdateBuffer(copySrc, 0, srcData); CommandList cl = RF.CreateCommandList(); cl.Begin(); cl.SetPipeline(pipeline); if (combinedLayout) { uint[] offsets = new[] { srcBindingMultiple *GD.StructuredBufferMinOffsetAlignment, dstBindingMultiple *GD.StructuredBufferMinOffsetAlignment }; cl.SetComputeResourceSet(0, sets[0], offsets); } else { uint offset = srcBindingMultiple * GD.StructuredBufferMinOffsetAlignment; cl.SetComputeResourceSet(0, sets[0], 1, ref offset); offset = dstBindingMultiple * GD.StructuredBufferMinOffsetAlignment; cl.SetComputeResourceSet(1, sets[1], 1, ref offset); } cl.Dispatch(512, 1, 1); cl.End(); GD.SubmitCommands(cl); GD.WaitForIdle(); DeviceBuffer readback = GetReadback(copyDst); MappedResourceView <uint> readView = GD.Map <uint>(readback, MapMode.Read); for (uint i = 0; i < valueCount; i++) { uint srcIndex = totalSrcAlignment / sizeof(uint) + i; uint expected = srcData[(int)srcIndex]; uint dstIndex = totalDstAlignment / sizeof(uint) + i; uint actual = readView[dstIndex]; Assert.Equal(expected, actual); } GD.Unmap(readback); }
protected override void Draw(float delta) { if (InputTracker.GetKeyDown(Key.F1)) { _lightFromCamera = !_lightFromCamera; } // Begin() must be called before commands can be issued. _commandList.Begin(); // Update per-frame resources. MappedResourceView <Matrix4x4> writeMap = GraphicsDevice.Map <Matrix4x4>(_cameraProjViewBuffer, MapMode.Write); writeMap[0] = _camera.ViewMatrix; writeMap[1] = _camera.ProjectionMatrix; GraphicsDevice.Unmap(_cameraProjViewBuffer); if (_lightFromCamera) { GraphicsDevice.UpdateBuffer(_lightInfoBuffer, 0, new LightInfo(_camera.Forward, _camera.Position)); } else { GraphicsDevice.UpdateBuffer(_lightInfoBuffer, 0, new LightInfo(_lightDir, _camera.Position)); } _localRotation += delta * ((float)Math.PI * 2 / 9); _globalRotation += -delta * ((float)Math.PI * 2 / 240); GraphicsDevice.UpdateBuffer(_rotationInfoBuffer, 0, new Vector4(_localRotation, _globalRotation, 0, 0)); Matrix4x4.Invert(_camera.ProjectionMatrix, out Matrix4x4 inverseProjection); Matrix4x4.Invert(_camera.ViewMatrix, out Matrix4x4 inverseView); GraphicsDevice.UpdateBuffer(_viewInfoBuffer, 0, new InvCameraInfo( inverseProjection, inverseView)); // We want to render directly to the output window. _commandList.SetFramebuffer(MainSwapchain.Framebuffer); _commandList.ClearColorTarget(0, RgbaFloat.White); _commandList.ClearDepthStencil(1f); //// First, draw the background starfield. _commandList.SetPipeline(_starfieldPipeline); _commandList.SetGraphicsResourceSet(0, _viewInfoSet); _commandList.Draw(4); // Next, draw our orbiting rocks with instanced drawing. _commandList.SetPipeline(_instancePipeline); // Set uniforms _commandList.SetGraphicsResourceSet(0, _sharedResourceSet); // Always after SetPipeline _commandList.SetGraphicsResourceSet(1, _instanceTextureSet); _commandList.SetVertexBuffer(0, _rockModel.VertexBuffer); _commandList.SetIndexBuffer(_rockModel.IndexBuffer, _rockModel.IndexFormat); _commandList.SetVertexBuffer(1, _instanceVB); // Issue a Draw command for two instances with 4 indices. _commandList.DrawIndexed( indexCount: _rockModel.IndexCount, instanceCount: _instanceCount, indexStart: 0, vertexOffset: 0, instanceStart: 0); // Next, we draw our central planet. _commandList.SetPipeline(_planetPipeline); _commandList.SetGraphicsResourceSet(1, _planetTextureSet); _commandList.SetVertexBuffer(0, _planetModel.VertexBuffer); _commandList.SetIndexBuffer(_planetModel.IndexBuffer, _planetModel.IndexFormat); // The planet is drawn with regular indexed drawing -- not instanced. _commandList.DrawIndexed(_planetModel.IndexCount); // End() must be called before commands can be submitted for execution. _commandList.End(); GraphicsDevice.SubmitCommands(_commandList); // Once commands have been submitted, the rendered image can be presented to the application window. GraphicsDevice.SwapBuffers(MainSwapchain); }
public static unsafe Texture CreateArrayTexture <T>(GraphicsDevice gd, TextureUsage usage, IReadOnlyTexture <T> texture) where T : unmanaged { if (gd == null) { throw new ArgumentNullException(nameof(gd)); } if (texture == null) { throw new ArgumentNullException(nameof(texture)); } var pixelFormat = GetFormat(typeof(T)); bool mip = (usage & TextureUsage.GenerateMipmaps) != 0; uint mipLevels = mip ? MipLevelCount(texture.Width, texture.Height) : 1; using Texture staging = gd.ResourceFactory.CreateTexture(new TextureDescription( (uint)texture.Width, (uint)texture.Height, 1, mipLevels, (uint)texture.ArrayLayers, pixelFormat, TextureUsage.Staging, TextureType.Texture2D)); staging.Name = "T_" + texture.Name + "_Staging"; for (int layer = 0; layer < texture.ArrayLayers; layer++) { var mapped = gd.Map(staging, MapMode.Write, (uint)layer * mipLevels); try { var span = new Span <T>(mapped.Data.ToPointer(), (int)mapped.SizeInBytes / sizeof(T)); int pitch = (int)(mapped.RowPitch / sizeof(T)); var source = texture.GetLayerBuffer(layer); var dest = new ImageBuffer <T>(texture.Width, texture.Height, pitch, span); BlitUtil.BlitDirect(source, dest); //gd.UpdateTexture( // staging, (IntPtr) texDataPtr, (uint) (buffer.Buffer.Length * Unsafe.SizeOf<T>()), // 0, 0, 0, // (uint) texture.Width, (uint) texture.Height, 1, // 0, (uint) layer); } finally { gd.Unmap(staging, (uint)layer * mipLevels); } } Texture veldridTexture = gd.ResourceFactory.CreateTexture(new TextureDescription( (uint)texture.Width, (uint)texture.Height, 1, mipLevels, (uint)texture.ArrayLayers, pixelFormat, usage, TextureType.Texture2D)); veldridTexture.Name = "T_" + texture.Name; using CommandList cl = gd.ResourceFactory.CreateCommandList(); cl.Begin(); cl.CopyTexture(staging, veldridTexture); if (mip) { cl.GenerateMipmaps(veldridTexture); } cl.End(); gd.SubmitCommands(cl); return(veldridTexture); }
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, true)); 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.LoadCompute(RF, "ComputeColoredQuadGenerator"), 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>(), TestShaders.LoadVertexFragment(RF, "ColoredQuadRenderer")), 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); }
static void Main(string[] args) { _useOculus = true; if (!VRContext.IsOculusSupported()) { _useOculus = false; if (!VRContext.IsOpenVRSupported()) { Console.WriteLine("This sample requires an Oculus or OpenVR-capable headset."); return; } } Sdl2Window window = VeldridStartup.CreateWindow( new WindowCreateInfo( Sdl2Native.SDL_WINDOWPOS_CENTERED, Sdl2Native.SDL_WINDOWPOS_CENTERED, 1280, 720, WindowState.Normal, "Veldrid.VirtualReality Sample")); VRContextOptions options = new VRContextOptions { EyeFramebufferSampleCount = TextureSampleCount.Count4 }; VRContext vrContext = _useOculus ? VRContext.CreateOculus(options) : VRContext.CreateOpenVR(options); GraphicsBackend backend = GraphicsBackend.Direct3D11; bool debug = false; #if DEBUG debug = true; #endif GraphicsDeviceOptions gdo = new GraphicsDeviceOptions(debug, null, false, ResourceBindingModel.Improved, true, true, true); if (backend == GraphicsBackend.Vulkan) { // Oculus runtime causes validation errors. gdo.Debug = false; } (GraphicsDevice gd, Swapchain sc) = CreateDeviceAndSwapchain(window, vrContext, backend, gdo); window.Resized += () => sc.Resize((uint)window.Width, (uint)window.Height); vrContext.Initialize(gd); ImGuiRenderer igr = new ImGuiRenderer(gd, sc.Framebuffer.OutputDescription, window.Width, window.Height, ColorSpaceHandling.Linear); window.Resized += () => igr.WindowResized(window.Width, window.Height); AssimpMesh mesh = new AssimpMesh( gd, vrContext.LeftEyeFramebuffer.OutputDescription, Path.Combine(AppContext.BaseDirectory, "cat", "cat.obj"), Path.Combine(AppContext.BaseDirectory, "cat", "cat_diff.png")); Skybox skybox = new Skybox( Image.Load(Path.Combine(AppContext.BaseDirectory, "skybox", "miramar_ft.png")), Image.Load(Path.Combine(AppContext.BaseDirectory, "skybox", "miramar_bk.png")), Image.Load(Path.Combine(AppContext.BaseDirectory, "skybox", "miramar_lf.png")), Image.Load(Path.Combine(AppContext.BaseDirectory, "skybox", "miramar_rt.png")), Image.Load(Path.Combine(AppContext.BaseDirectory, "skybox", "miramar_up.png")), Image.Load(Path.Combine(AppContext.BaseDirectory, "skybox", "miramar_dn.png"))); skybox.CreateDeviceObjects(gd, vrContext.LeftEyeFramebuffer.OutputDescription); CommandList windowCL = gd.ResourceFactory.CreateCommandList(); CommandList eyesCL = gd.ResourceFactory.CreateCommandList(); MirrorTextureEyeSource eyeSource = MirrorTextureEyeSource.BothEyes; Stopwatch sw = Stopwatch.StartNew(); double lastFrameTime = sw.Elapsed.TotalSeconds; while (window.Exists) { double newFrameTime = sw.Elapsed.TotalSeconds; double deltaSeconds = newFrameTime - lastFrameTime; lastFrameTime = newFrameTime; InputSnapshot snapshot = window.PumpEvents(); if (!window.Exists) { break; } InputTracker.UpdateFrameInput(snapshot); HandleInputs(deltaSeconds); igr.Update(1f / 60f, snapshot); if (ImGui.BeginMainMenuBar()) { if (ImGui.BeginMenu("Settings")) { if (ImGui.BeginMenu("Mirror Texture")) { if (ImGui.MenuItem("Both Eyes", null, eyeSource == MirrorTextureEyeSource.BothEyes)) { eyeSource = MirrorTextureEyeSource.BothEyes; } if (ImGui.MenuItem("Left Eye", null, eyeSource == MirrorTextureEyeSource.LeftEye)) { eyeSource = MirrorTextureEyeSource.LeftEye; } if (ImGui.MenuItem("Right Eye", null, eyeSource == MirrorTextureEyeSource.RightEye)) { eyeSource = MirrorTextureEyeSource.RightEye; } ImGui.EndMenu(); } if (ImGui.BeginMenu("VR API")) { if (ImGui.MenuItem("Oculus", null, _useOculus) && !_useOculus) { _useOculus = true; _switchVRContext = true; } if (ImGui.MenuItem("OpenVR", null, !_useOculus) && _useOculus) { _useOculus = false; _switchVRContext = true; } ImGui.EndMenu(); } ImGui.EndMenu(); } ImGui.EndMainMenuBar(); } windowCL.Begin(); windowCL.SetFramebuffer(sc.Framebuffer); windowCL.ClearColorTarget(0, new RgbaFloat(0f, 0f, 0.2f, 1f)); vrContext.RenderMirrorTexture(windowCL, sc.Framebuffer, eyeSource); igr.Render(gd, windowCL); windowCL.End(); gd.SubmitCommands(windowCL); gd.SwapBuffers(sc); HmdPoseState poses = vrContext.WaitForPoses(); // Render Eyes eyesCL.Begin(); eyesCL.PushDebugGroup("Left Eye"); Matrix4x4 leftView = poses.CreateView(VREye.Left, _userPosition, -Vector3.UnitZ, Vector3.UnitY); RenderEye(eyesCL, vrContext.LeftEyeFramebuffer, mesh, skybox, poses.LeftEyeProjection, leftView); eyesCL.PopDebugGroup(); eyesCL.PushDebugGroup("Right Eye"); Matrix4x4 rightView = poses.CreateView(VREye.Right, _userPosition, -Vector3.UnitZ, Vector3.UnitY); RenderEye(eyesCL, vrContext.RightEyeFramebuffer, mesh, skybox, poses.RightEyeProjection, rightView); eyesCL.PopDebugGroup(); eyesCL.End(); gd.SubmitCommands(eyesCL); vrContext.SubmitFrame(); if (_switchVRContext) { _switchVRContext = false; vrContext.Dispose(); vrContext = _useOculus ? VRContext.CreateOculus() : VRContext.CreateOpenVR(); vrContext.Initialize(gd); } } vrContext.Dispose(); gd.Dispose(); }
static int Main(string[] args) { if (args.Length != 2) { Console.WriteLine($"ImageTint <image-path> <out>: Tints the image at <image-path> and saves it to <out>."); return(1); } string inPath = args[0]; string outPath = args[1]; // This demo uses WindowState.Hidden to avoid popping up an unnecessary window to the user. VeldridStartup.CreateWindowAndGraphicsDevice( new WindowCreateInfo { WindowInitialState = WindowState.Hidden, }, new GraphicsDeviceOptions(), out Sdl2Window window, out GraphicsDevice gd); DisposeCollectorResourceFactory factory = new DisposeCollectorResourceFactory(gd.ResourceFactory); ImageSharpTexture inputImage = new ImageSharpTexture(inPath, false); Texture inputTexture = inputImage.CreateDeviceTexture(gd, factory); TextureView view = factory.CreateTextureView(inputTexture); Texture output = factory.CreateTexture(TextureDescription.Texture2D( inputImage.Width, inputImage.Height, 1, 1, PixelFormat.R8_G8_B8_A8_UNorm, TextureUsage.RenderTarget)); Framebuffer framebuffer = factory.CreateFramebuffer(new FramebufferDescription(null, output)); DeviceBuffer vertexBuffer = factory.CreateBuffer(new BufferDescription(64, BufferUsage.VertexBuffer)); Vector4[] quadVerts = { new Vector4(-1, 1, 0, 0), new Vector4(1, 1, 1, 0), new Vector4(-1, -1, 0, 1), new Vector4(1, -1, 1, 1), }; gd.UpdateBuffer(vertexBuffer, 0, quadVerts); ShaderSetDescription shaderSet = new ShaderSetDescription( new[] { new VertexLayoutDescription( new VertexElementDescription("Position", VertexElementSemantic.Position, VertexElementFormat.Float2), new VertexElementDescription("TextureCoordinates", VertexElementSemantic.TextureCoordinate, VertexElementFormat.Float2)) }, new[] { SampleApplication.LoadShader(factory, "TintShader", ShaderStages.Vertex, "VS"), SampleApplication.LoadShader(factory, "TintShader", ShaderStages.Fragment, "FS") }); ResourceLayout layout = factory.CreateResourceLayout(new ResourceLayoutDescription( new ResourceLayoutElementDescription("Input", ResourceKind.TextureReadOnly, ShaderStages.Fragment), new ResourceLayoutElementDescription("Sampler", ResourceKind.Sampler, ShaderStages.Fragment), new ResourceLayoutElementDescription("Tint", ResourceKind.UniformBuffer, ShaderStages.Fragment))); Pipeline pipeline = factory.CreateGraphicsPipeline(new GraphicsPipelineDescription( BlendStateDescription.SingleOverrideBlend, DepthStencilStateDescription.Disabled, RasterizerStateDescription.Default, PrimitiveTopology.TriangleStrip, shaderSet, layout, framebuffer.OutputDescription)); DeviceBuffer tintInfoBuffer = factory.CreateBuffer(new BufferDescription(16, BufferUsage.UniformBuffer)); gd.UpdateBuffer( tintInfoBuffer, 0, new TintInfo( new Vector3(1f, 0.2f, 0.1f), // Change this to modify the tint color. 0.25f)); ResourceSet resourceSet = factory.CreateResourceSet( new ResourceSetDescription(layout, view, gd.PointSampler, tintInfoBuffer)); // RenderTarget textures are not CPU-visible, so to get our tinted image back, we need to first copy it into // a "staging Texture", which is a Texture that is CPU-visible (it can be Mapped). Texture stage = factory.CreateTexture(TextureDescription.Texture2D( inputImage.Width, inputImage.Height, 1, 1, PixelFormat.R8_G8_B8_A8_UNorm, TextureUsage.Staging)); CommandList cl = factory.CreateCommandList(); cl.Begin(); cl.SetFramebuffer(framebuffer); cl.SetFullViewports(); cl.SetVertexBuffer(0, vertexBuffer); cl.SetPipeline(pipeline); cl.SetGraphicsResourceSet(0, resourceSet); cl.Draw(4, 1, 0, 0); cl.CopyTexture( output, 0, 0, 0, 0, 0, stage, 0, 0, 0, 0, 0, stage.Width, stage.Height, 1, 1); cl.End(); gd.SubmitCommands(cl); gd.WaitForIdle(); // When a texture is mapped into a CPU-visible region, it is often not laid out linearly. // Instead, it is laid out as a series of rows, which are all spaced out evenly by a "row pitch". // This spacing is provided in MappedResource.RowPitch. // It is also possible to obtain a "structured view" of a mapped data region, which is what is done below. // With a structured view, you can read individual elements from the region. // The code below simply iterates over the two-dimensional region and places each texel into a linear buffer. // ImageSharp requires the pixel data be contained in a linear buffer. MappedResourceView <Rgba32> map = gd.Map <Rgba32>(stage, MapMode.Read); // Rgba32 is synonymous with PixelFormat.R8_G8_B8_A8_UNorm. Rgba32[] pixelData = new Rgba32[stage.Width * stage.Height]; for (int y = 0; y < stage.Height; y++) { for (int x = 0; x < stage.Width; x++) { int index = (int)(y * stage.Width + x); pixelData[index] = map[x, y]; } } gd.Unmap(stage); // Resources should be Unmapped when the region is no longer used. Image <Rgba32> outputImage = Image.LoadPixelData(pixelData, (int)stage.Width, (int)stage.Height); outputImage.Save(outPath); factory.DisposeCollector.DisposeAll(); gd.Dispose(); window.Close(); return(0); }
public void Points_WithFloat16Color() { 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.TextureCoordinate, VertexElementFormat.Float2), new VertexElementDescription("Color_Half", VertexElementSemantic.TextureCoordinate, VertexElementFormat.Half4)) }, TestShaders.LoadVertexFragment(RF, "F16VertexAttribs")); ResourceLayout layout = RF.CreateResourceLayout(new ResourceLayoutDescription( new ResourceLayoutElementDescription("InfoBuffer", ResourceKind.UniformBuffer, ShaderStages.Vertex), new ResourceLayoutElementDescription("OrthoBuffer", 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; const ushort f16_375 = 0x5DDC; // 375.0 const ushort f16_500 = 0x5FD0; // 500.0 const ushort f16_625 = 0x60E2; // 625.0 const ushort f16_875 = 0x62D6; // 875.0 const ushort f16_1250 = 0x64E2; // 1250.0 const ushort f16_1875 = 0x6753; // 1875.0 VertexCPU_UShort[] vertices = new VertexCPU_UShort[] { new VertexCPU_UShort { Position = new Vector2(0.5f, 0.5f), R = f16_625, G = f16_1250, B = f16_1875, }, new VertexCPU_UShort { Position = new Vector2(10.5f, 12.5f), R = f16_625, G = f16_1250, B = f16_1875, }, new VertexCPU_UShort { Position = new Vector2(25.5f, 35.5f), R = f16_1875, G = f16_1250, B = f16_625, }, new VertexCPU_UShort { Position = new Vector2(49.5f, 49.5f), R = f16_375, G = f16_500, B = f16_875, }, }; RgbaFloat[] expectedColors = new[] { new RgbaFloat( 625.0f / colorNormalizationFactor, 1250.0f / colorNormalizationFactor, 1875.0f / colorNormalizationFactor, 1), new RgbaFloat( 625.0f / colorNormalizationFactor, 1250.0f / colorNormalizationFactor, 1875.0f / colorNormalizationFactor, 1), new RgbaFloat( 1875.0f / colorNormalizationFactor, 1250.0f / colorNormalizationFactor, 625.0f / colorNormalizationFactor, 1), new RgbaFloat( 375.0f / colorNormalizationFactor, 500.0f / colorNormalizationFactor, 875.0f / colorNormalizationFactor, 1), }; DeviceBuffer vb = RF.CreateBuffer( new BufferDescription((uint)(Unsafe.SizeOf <UIntVertexAttribsVertex>() * vertices.Length), BufferUsage.VertexBuffer)); GD.UpdateBuffer(vb, 0, vertices); GD.UpdateBuffer(infoBuffer, 0, new UIntVertexAttribsInfo { 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.CopyTexture(target, staging); cl.End(); GD.SubmitCommands(cl); GD.WaitForIdle(); MappedResourceView <RgbaFloat> readView = GD.Map <RgbaFloat>(staging, MapMode.Read); for (int i = 0; i < vertices.Length; i++) { VertexCPU_UShort vertex = vertices[i]; uint x = (uint)vertex.Position.X; uint y = (uint)vertex.Position.Y; if (!GD.IsUvOriginTopLeft || GD.IsClipSpaceYInverted) { y = framebuffer.Height - y - 1; } RgbaFloat expectedColor = expectedColors[i]; Assert.Equal(expectedColor, readView[x, y], RgbaFloatFuzzyComparer.Instance); } GD.Unmap(staging); }
// TODO: Cleanup public Texture CreateDeviceTexture(GraphicsDevice gd, ResourceFactory rf, TextureUsage usage) { if (gd == null) { throw new ArgumentNullException(nameof(gd)); } if (rf == null) { throw new ArgumentNullException(nameof(rf)); } using var _ = PerfTracker.FrameEvent("6.1.2.1 Rebuild MultiTextures"); if (IsMetadataDirty) { RebuildLayers(); } var palette = PaletteManager.Palette.GetCompletePalette(); using var staging = rf.CreateTexture(new TextureDescription(Width, Height, Depth, MipLevels, ArrayLayers, Format.ToVeldrid(), TextureUsage.Staging, Type)); staging.Name = "T_" + Name + "_Staging"; Span <uint> toBuffer = stackalloc uint[(int)(Width * Height)]; foreach (var lsi in LogicalSubImages) { //if (!rebuildAll && !lsi.IsPaletteAnimated) // TODO: Requires caching a single Texture and then modifying it // continue; for (int i = 0; i < lsi.Frames; i++) { toBuffer.Fill(lsi.IsAlphaTested ? 0 : 0xff000000); Rebuild(lsi, i, toBuffer, palette); uint destinationLayer = (uint)LayerLookup[new LayerKey(lsi.Id, i)]; unsafe { fixed(uint *toBufferPtr = toBuffer) { gd.UpdateTexture( staging, (IntPtr)toBufferPtr, Width * Height * sizeof(uint), 0, 0, 0, Width, Height, 1, 0, destinationLayer); } } } } /* TODO: Mipmap * for (uint level = 1; level < MipLevels; level++) * { * } //*/ var texture = rf.CreateTexture(new TextureDescription(Width, Height, Depth, MipLevels, ArrayLayers, Format.ToVeldrid(), usage, Type)); texture.Name = "T_" + Name; using (CommandList cl = rf.CreateCommandList()) { cl.Begin(); cl.CopyTexture(staging, texture); cl.End(); gd.SubmitCommands(cl); } IsDirty = false; return(texture); }
[STAThread] // Needed for ASIOOutput.StartDriver method static void Main(string[] args) { // Create window, GraphicsDevice, and all resources necessary for the demo. VeldridStartup.CreateWindowAndGraphicsDevice( new WindowCreateInfo(50, 50, 3600, 2000, WindowState.Normal, "Vector Engine Editor"), new GraphicsDeviceOptions(true, null, true), out _window, out _gd); _gd.MainSwapchain.SyncToVerticalBlank = false; _window.Resized += () => { _gd.MainSwapchain.Resize((uint)_window.Width, (uint)_window.Height); _controller.WindowResized(_window.Width, _window.Height); }; _cl = _gd.ResourceFactory.CreateCommandList(); _controller = new ImGuiController(_gd, _gd.MainSwapchain.Framebuffer.OutputDescription, _window.Width, _window.Height); string assetsPath = HostHelper.AssetsPath; FileLoader.Init(assetsPath); FileLoader.LoadAllComponentGroups(); if (_showEditor) { HostHelper.StopGame(true); } else { HostHelper.PlayGame(true); } // Main application loop while (_window.Exists) { GameLoop.Tick(); InputSnapshot snapshot = _window.PumpEvents(); if (!_window.Exists) { break; } foreach (var keypress in snapshot.KeyEvents) { if (keypress.Key == Key.E && keypress.Down && keypress.Modifiers == ModifierKeys.Control) { _showEditor = !_showEditor; } if (keypress.Key == Key.S && keypress.Down && keypress.Modifiers == ModifierKeys.Control) { HostHelper.SaveScene(); } if (keypress.Key == Key.D && keypress.Down && keypress.Modifiers == ModifierKeys.Control) { HostHelper.Duplicate(); } } if (_showEditor) { if (EditorCamera == null) { foreach (var component in EntityAdmin.Instance.Components) { if (component.Entity.Name == EmptyScene.EDITOR_CAM_ENTITY_NAME) { EditorCamera = component.Entity; break; } } } if (midi == null) { midi = new MIDI(); midi.SetupWatchersAndPorts(); while (!midi.SetupComplete) { Thread.Sleep(1); } } IMidiMessage midiMessage; while (midi.MidiMessageQueue.TryDequeue(out midiMessage)) { MidiState.UpdateState(midiMessage); } // TODO: figure out why LastFrameTime makes ImGui run stupid fast... (for things like key repeats) _controller.Update(GameTime.LastFrameTime / 10f, snapshot); // Feed the input events to our ImGui controller, which passes them through to ImGui. EditorUI.SubmitUI(EntityAdmin.Instance); _cl.Begin(); _cl.SetFramebuffer(_gd.MainSwapchain.Framebuffer); _cl.ClearColorTarget(0, new RgbaFloat(ClearColor.X, ClearColor.Y, ClearColor.Z, 1f)); _controller.Render(_gd, _cl); _cl.End(); _gd.SubmitCommands(_cl); _gd.SwapBuffers(_gd.MainSwapchain); } } if (!HostHelper.PlayingGame) { HostHelper.SaveScene(); } // Clean up Veldrid resources _gd.WaitForIdle(); _controller.Dispose(); _cl.Dispose(); _gd.Dispose(); }
public void ComputeShader3dTexture() { // Just a dumb compute shader that fills a 3D texture with the same value from a uniform multiplied by the depth. string shaderText = @" #version 450 layout(set = 0, binding = 0, rgba32f) uniform image3D TextureToFill; layout(set = 0, binding = 1) uniform FillValueBuffer { float FillValue; float Padding1; float Padding2; float Padding3; }; layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in; void main() { ivec3 textureCoordinate = ivec3(gl_GlobalInvocationID.xyz); float dataToStore = FillValue * (textureCoordinate.z + 1); imageStore(TextureToFill, textureCoordinate, vec4(dataToStore)); } "; const float FillValue = 42.42f; const uint OutputTextureSize = 32; using Shader computeShader = RF.CreateFromSpirv(new ShaderDescription( ShaderStages.Compute, Encoding.ASCII.GetBytes(shaderText), "main")); using ResourceLayout computeLayout = RF.CreateResourceLayout(new ResourceLayoutDescription( new ResourceLayoutElementDescription("TextureToFill", ResourceKind.TextureReadWrite, ShaderStages.Compute), new ResourceLayoutElementDescription("FillValueBuffer", ResourceKind.UniformBuffer, ShaderStages.Compute))); using Pipeline computePipeline = RF.CreateComputePipeline(new ComputePipelineDescription( computeShader, computeLayout, 16, 16, 1)); using DeviceBuffer fillValueBuffer = RF.CreateBuffer(new BufferDescription((uint)Marshal.SizeOf <FillValueStruct>(), BufferUsage.UniformBuffer)); // Create our output texture. using Texture computeTargetTexture = RF.CreateTexture(TextureDescription.Texture3D( OutputTextureSize, OutputTextureSize, OutputTextureSize, 1, PixelFormat.R32_G32_B32_A32_Float, TextureUsage.Sampled | TextureUsage.Storage)); using TextureView computeTargetTextureView = RF.CreateTextureView(computeTargetTexture); using ResourceSet computeResourceSet = RF.CreateResourceSet(new ResourceSetDescription( computeLayout, computeTargetTextureView, fillValueBuffer)); using CommandList cl = RF.CreateCommandList(); cl.Begin(); cl.UpdateBuffer(fillValueBuffer, 0, new FillValueStruct(FillValue)); // Use the compute shader to fill the texture. cl.SetPipeline(computePipeline); cl.SetComputeResourceSet(0, computeResourceSet); const uint GroupDivisorXY = 16; cl.Dispatch(OutputTextureSize / GroupDivisorXY, OutputTextureSize / GroupDivisorXY, OutputTextureSize); cl.End(); GD.SubmitCommands(cl); GD.WaitForIdle(); // Read back from our texture and make sure it has been properly filled. for (uint depth = 0; depth < computeTargetTexture.Depth; depth++) { RgbaFloat expectedFillValue = new RgbaFloat(new System.Numerics.Vector4(FillValue * (depth + 1))); int notFilledCount = CountTexelsNotFilledAtDepth(GD, computeTargetTexture, expectedFillValue, depth); Assert.Equal(0, notFilledCount); } }
public static void EndDraw() { // End() must be called before commands can be submitted for execution. CommandList.End(); Device.SubmitCommands(CommandList); }
protected override void Draw(float deltaSeconds, long ticks) { if (Death && CurDeathWaitTicks == DeathWaitTicks) { PrevTicks = ticks; } if (Death) { CurDeathWaitTicks--; if (CurDeathWaitTicks <= 0) { CurDeathWaitTicks = -1; Death = false; PrevTicks = ticks; ticks = 0; } else { ticks = PrevTicks; } } else { ticks -= PrevTicks; } CommandList.Begin(); CommandList.SetFramebuffer(GraphicsDevice.SwapchainFramebuffer); CommandList.UpdateBuffer(ProjectionBuffer, 0, Matrix4x4.CreateOrthographicOffCenter( 0, GraphicsDevice.SwapchainFramebuffer.Width, GraphicsDevice.SwapchainFramebuffer.Height, 0, -1, 1 )); CommandList.UpdateBuffer(ViewBuffer, 0, Matrix4x4.CreateTranslation(Vector3.Zero)); if (PlayerJumping >= 0) { CurPlayerVertPos += PlayerVelocity; PlayerVelocity += EnergyLoss; PlayerJumping++; } if (PlayerJumping > NumJumpCycles) { CurPlayerVertPos = 320; PlayerJumping = -1; PlayerVelocity = StartingPlayerVelocity; } CommandList.UpdateBuffer(WorldBuffer, 0, Matrix4x4.CreateTranslation(new Vector3(PlayerX, CurPlayerVertPos, 0))); CommandList.ClearColorTarget(0, RgbaFloat.White); CommandList.ClearDepthStencil(1f); CommandList.SetPipeline(Pipeline); CommandList.SetVertexBuffer(0, VertexBuffer); CommandList.SetIndexBuffer(IndexBuffer, IndexFormat.UInt16); CommandList.SetGraphicsResourceSet(0, ProjViewSet); CommandList.SetGraphicsResourceSet(1, MainAvatarTextureSet); CommandList.DrawIndexed(6, 1, 0, 0, 0); var xCoord = (0 - (ticks * SpeedFactor) % 2000); CommandList.UpdateBuffer(WorldBuffer, 0, Matrix4x4.CreateTranslation(new Vector3(xCoord, 150, 0))); CommandList.DrawIndexed(6, 1, 12, 0, 0); xCoord = 2000 - ((ticks * SpeedFactor) % 2000); CommandList.UpdateBuffer(WorldBuffer, 0, Matrix4x4.CreateTranslation(new Vector3(xCoord, 150, 0))); CommandList.DrawIndexed(6, 1, 12, 0, 0); for (var i = 0; i < CactusPlacements.Length; i++) { var cactusPlacement = CactusPlacements[i]; var actualCactusPlacement = cactusPlacement - ((ticks * SpeedFactor) % 3650); if (actualCactusPlacement > 0 && actualCactusPlacement < 190 && CurPlayerVertPos > 200 && !Death) { Death = true; CurDeathWaitTicks = DeathWaitTicks; break; } CommandList.UpdateBuffer(WorldBuffer, 0, Matrix4x4.CreateTranslation(new Vector3(actualCactusPlacement, 300, 0))); CommandList.DrawIndexed(6, 1, IndexStartMap[CactusTypes[i % CactusTypes.Length]], 0, 0); } CommandList.End(); if (!Death) { GraphicsDevice.SubmitCommands(CommandList); } GraphicsDevice.SwapBuffers(); GraphicsDevice.WaitForIdle(); }
private void RenderAllSingleThread(GraphicsDevice gd, CommandList cl, SceneContext sc) { float depthClear = gd.IsDepthRangeZeroToOne ? 0f : 1f; Matrix4x4 cameraProj = Camera.ProjectionMatrix; Vector4 nearLimitCS = Vector4.Transform(new Vector3(0, 0, -_nearCascadeLimit), cameraProj); Vector4 midLimitCS = Vector4.Transform(new Vector3(0, 0, -_midCascadeLimit), cameraProj); Vector4 farLimitCS = Vector4.Transform(new Vector3(0, 0, -_farCascadeLimit), cameraProj); cl.UpdateBuffer(sc.DepthLimitsBuffer, 0, new DepthCascadeLimits { NearLimit = nearLimitCS.Z, MidLimit = midLimitCS.Z, FarLimit = farLimitCS.Z }); cl.UpdateBuffer(sc.LightInfoBuffer, 0, sc.DirectionalLight.GetInfo()); Vector3 lightPos = sc.DirectionalLight.Transform.Position - sc.DirectionalLight.Direction * 1000f; // Near Matrix4x4 viewProj0 = UpdateDirectionalLightMatrices( gd, sc, Camera.NearDistance, _nearCascadeLimit, sc.ShadowMapTexture.Width, out BoundingFrustum lightFrustum); cl.UpdateBuffer(sc.LightViewProjectionBuffer0, 0, ref viewProj0); cl.SetFramebuffer(sc.NearShadowMapFramebuffer); cl.SetFullViewports(); cl.ClearDepthStencil(depthClear); Render(gd, cl, sc, RenderPasses.ShadowMapNear, lightFrustum, lightPos, _renderQueues[0], _cullableStage[0], _renderableStage[0], null, false); // Mid Matrix4x4 viewProj1 = UpdateDirectionalLightMatrices( gd, sc, _nearCascadeLimit, _midCascadeLimit, sc.ShadowMapTexture.Width, out lightFrustum); cl.UpdateBuffer(sc.LightViewProjectionBuffer1, 0, ref viewProj1); cl.SetFramebuffer(sc.MidShadowMapFramebuffer); cl.SetFullViewports(); cl.ClearDepthStencil(depthClear); Render(gd, cl, sc, RenderPasses.ShadowMapMid, lightFrustum, lightPos, _renderQueues[0], _cullableStage[0], _renderableStage[0], null, false); // Far Matrix4x4 viewProj2 = UpdateDirectionalLightMatrices( gd, sc, _midCascadeLimit, _farCascadeLimit, sc.ShadowMapTexture.Width, out lightFrustum); cl.UpdateBuffer(sc.LightViewProjectionBuffer2, 0, ref viewProj2); cl.SetFramebuffer(sc.FarShadowMapFramebuffer); cl.SetFullViewports(); cl.ClearDepthStencil(depthClear); Render(gd, cl, sc, RenderPasses.ShadowMapFar, lightFrustum, lightPos, _renderQueues[0], _cullableStage[0], _renderableStage[0], null, false); // Reflections cl.SetFramebuffer(sc.ReflectionFramebuffer); float fbWidth = sc.ReflectionFramebuffer.Width; float fbHeight = sc.ReflectionFramebuffer.Height; cl.SetViewport(0, new Viewport(0, 0, fbWidth, fbHeight, 0, 1)); cl.SetFullViewports(); cl.SetFullScissorRects(); cl.ClearColorTarget(0, RgbaFloat.Black); cl.ClearDepthStencil(depthClear); // Render reflected scene. Matrix4x4 planeReflectionMatrix = Matrix4x4.CreateReflection(MirrorMesh.Plane); CameraInfo camInfo = new CameraInfo(); camInfo.CameraLookDirection = Vector3.Normalize(Vector3.Reflect(_camera.LookDirection, MirrorMesh.Plane.Normal)); camInfo.CameraPosition_WorldSpace = Vector3.Transform(_camera.Position, planeReflectionMatrix); cl.UpdateBuffer(sc.CameraInfoBuffer, 0, ref camInfo); Matrix4x4 view = sc.Camera.ViewMatrix; view = planeReflectionMatrix * view; cl.UpdateBuffer(sc.ViewMatrixBuffer, 0, view); Matrix4x4 projection = _camera.ProjectionMatrix; cl.UpdateBuffer(sc.ReflectionViewProjBuffer, 0, view * projection); BoundingFrustum cameraFrustum = new BoundingFrustum(view * projection); Render(gd, cl, sc, RenderPasses.ReflectionMap, cameraFrustum, _camera.Position, _renderQueues[0], _cullableStage[0], _renderableStage[0], null, false); cl.GenerateMipmaps(sc.ReflectionColorTexture); // Main scene cl.SetFramebuffer(sc.MainSceneFramebuffer); fbWidth = sc.MainSceneFramebuffer.Width; fbHeight = sc.MainSceneFramebuffer.Height; cl.SetViewport(0, new Viewport(0, 0, fbWidth, fbHeight, 0, 1)); cl.SetFullViewports(); cl.SetFullScissorRects(); cl.ClearDepthStencil(depthClear); sc.UpdateCameraBuffers(cl); // Re-set because reflection step changed it. cameraFrustum = new BoundingFrustum(_camera.ViewMatrix * _camera.ProjectionMatrix); Render(gd, cl, sc, RenderPasses.Standard, cameraFrustum, _camera.Position, _renderQueues[0], _cullableStage[0], _renderableStage[0], null, false); Render(gd, cl, sc, RenderPasses.AlphaBlend, cameraFrustum, _camera.Position, _renderQueues[0], _cullableStage[0], _renderableStage[0], null, false); Render(gd, cl, sc, RenderPasses.Overlay, cameraFrustum, _camera.Position, _renderQueues[0], _cullableStage[0], _renderableStage[0], null, false); if (sc.MainSceneColorTexture.SampleCount != TextureSampleCount.Count1) { cl.ResolveTexture(sc.MainSceneColorTexture, sc.MainSceneResolvedColorTexture); } cl.SetFramebuffer(sc.DuplicatorFramebuffer); fbWidth = sc.DuplicatorFramebuffer.Width; fbHeight = sc.DuplicatorFramebuffer.Height; cl.SetFullViewports(); Render(gd, cl, sc, RenderPasses.Duplicator, new BoundingFrustum(), _camera.Position, _renderQueues[0], _cullableStage[0], _renderableStage[0], null, false); cl.SetFramebuffer(gd.SwapchainFramebuffer); fbWidth = gd.SwapchainFramebuffer.Width; fbHeight = gd.SwapchainFramebuffer.Height; cl.SetFullViewports(); Render(gd, cl, sc, RenderPasses.SwapchainOutput, new BoundingFrustum(), _camera.Position, _renderQueues[0], _cullableStage[0], _renderableStage[0], null, false); cl.End(); _resourceUpdateCL.Begin(); foreach (Renderable renderable in _allPerFrameRenderablesSet) { renderable.UpdatePerFrameResources(gd, _resourceUpdateCL, sc); } _resourceUpdateCL.End(); gd.SubmitCommands(_resourceUpdateCL); gd.SubmitCommands(cl); }
public static unsafe Texture LoadTexture( GraphicsDevice gd, ResourceFactory factory, string assetPath, PixelFormat format) { KtxFile tex2D; using (FileStream fs = File.OpenRead(assetPath)) { tex2D = KtxFile.Load(fs, false); } uint width = tex2D.Header.PixelWidth; uint height = tex2D.Header.PixelHeight; if (height == 0) { height = width; } uint mipLevels = tex2D.Header.NumberOfMipmapLevels; Texture ret = factory.CreateTexture(TextureDescription.Texture2D( width, height, mipLevels, 1, format, TextureUsage.Sampled)); Texture stagingTex = factory.CreateTexture(TextureDescription.Texture2D( width, height, mipLevels, 1, format, TextureUsage.Staging)); // Copy texture data into staging buffer for (uint level = 0; level < mipLevels; level++) { KtxMipmap mipmap = tex2D.Faces[0].Mipmaps[level]; byte[] pixelData = mipmap.Data; fixed(byte *pixelDataPtr = &pixelData[0]) { gd.UpdateTexture(stagingTex, (IntPtr)pixelDataPtr, (uint)pixelData.Length, 0, 0, 0, mipmap.Width, mipmap.Height, 1, level, 0); } } CommandList copyCL = factory.CreateCommandList(); copyCL.Begin(); for (uint level = 0; level < mipLevels; level++) { uint levelWidth = tex2D.Faces[0].Mipmaps[level].Width; uint levelHeight = tex2D.Faces[0].Mipmaps[level].Height; copyCL.CopyTexture(stagingTex, 0, 0, 0, level, 0, ret, 0, 0, 0, level, 0, levelWidth, levelHeight, 1, 1); } copyCL.End(); gd.SubmitCommands(copyCL); gd.DisposeWhenIdle(copyCL); gd.DisposeWhenIdle(stagingTex); return(ret); }
public void Points_WithUIntColor() { 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.TextureCoordinate, VertexElementFormat.Float2), new VertexElementDescription("Color_UInt", VertexElementSemantic.TextureCoordinate, VertexElementFormat.UInt4)) }, TestShaders.LoadVertexFragment(RF, "UIntVertexAttribs")); 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; UIntVertexAttribsVertex[] vertices = new UIntVertexAttribsVertex[] { new UIntVertexAttribsVertex { Position = new Vector2(0.5f, 0.5f), Color_Int = new UInt4 { X = (uint)(0.25f * colorNormalizationFactor), Y = (uint)(0.5f * colorNormalizationFactor), Z = (uint)(0.75f * colorNormalizationFactor), } }, new UIntVertexAttribsVertex { Position = new Vector2(10.5f, 12.5f), Color_Int = new UInt4 { X = (uint)(0.25f * colorNormalizationFactor), Y = (uint)(0.5f * colorNormalizationFactor), Z = (uint)(0.75f * colorNormalizationFactor), } }, new UIntVertexAttribsVertex { Position = new Vector2(25.5f, 35.5f), Color_Int = new UInt4 { X = (uint)(0.75f * colorNormalizationFactor), Y = (uint)(0.5f * colorNormalizationFactor), Z = (uint)(0.25f * colorNormalizationFactor), } }, new UIntVertexAttribsVertex { Position = new Vector2(49.5f, 49.5f), Color_Int = new UInt4 { X = (uint)(0.15f * colorNormalizationFactor), Y = (uint)(0.25f * colorNormalizationFactor), Z = (uint)(0.35f * colorNormalizationFactor), } }, }; DeviceBuffer vb = RF.CreateBuffer( new BufferDescription((uint)(Unsafe.SizeOf <UIntVertexAttribsVertex>() * vertices.Length), BufferUsage.VertexBuffer)); GD.UpdateBuffer(vb, 0, vertices); GD.UpdateBuffer(infoBuffer, 0, new UIntVertexAttribsInfo { 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.CopyTexture(target, staging); cl.End(); GD.SubmitCommands(cl); GD.WaitForIdle(); MappedResourceView <RgbaFloat> readView = GD.Map <RgbaFloat>(staging, MapMode.Read); foreach (UIntVertexAttribsVertex vertex in vertices) { uint x = (uint)vertex.Position.X; uint y = (uint)vertex.Position.Y; if (!GD.IsUvOriginTopLeft || GD.IsClipSpaceYInverted) { y = framebuffer.Height - y - 1; } RgbaFloat expectedColor = new RgbaFloat( vertex.Color_Int.X / (float)colorNormalizationFactor, vertex.Color_Int.Y / (float)colorNormalizationFactor, vertex.Color_Int.Z / (float)colorNormalizationFactor, 1); Assert.Equal(expectedColor, readView[x, y], RgbaFloatFuzzyComparer.Instance); } GD.Unmap(staging); }
private void RenderAllMultiThreaded(GraphicsDevice gd, CommandList cl, SceneContext sc) { Matrix4x4 cameraProj = Camera.ProjectionMatrix; Vector4 nearLimitCS = Vector4.Transform(new Vector3(0, 0, -_nearCascadeLimit), cameraProj); Vector4 midLimitCS = Vector4.Transform(new Vector3(0, 0, -_midCascadeLimit), cameraProj); Vector4 farLimitCS = Vector4.Transform(new Vector3(0, 0, -_farCascadeLimit), cameraProj); _resourceUpdateCL.Begin(); CommandList[] cls = new CommandList[5]; for (int i = 0; i < cls.Length; i++) { cls[i] = gd.ResourceFactory.CreateCommandList(); cls[i].Begin(); } _resourceUpdateCL.UpdateBuffer(sc.DepthLimitsBuffer, 0, new DepthCascadeLimits { NearLimit = nearLimitCS.Z, MidLimit = midLimitCS.Z, FarLimit = farLimitCS.Z }); _resourceUpdateCL.UpdateBuffer(sc.LightInfoBuffer, 0, sc.DirectionalLight.GetInfo()); _allPerFrameRenderablesSet.Clear(); _tasks[0] = Task.Run(() => { // Near Matrix4x4 viewProj0 = UpdateDirectionalLightMatrices( sc, Camera.NearDistance, _nearCascadeLimit, sc.ShadowMapTexture.Width, out BoundingFrustum lightFrustum0); cls[1].UpdateBuffer(sc.LightViewProjectionBuffer0, 0, ref viewProj0); cls[1].SetFramebuffer(sc.NearShadowMapFramebuffer); cls[1].SetViewport(0, new Viewport(0, 0, sc.ShadowMapTexture.Width, sc.ShadowMapTexture.Height, 0, 1)); cls[1].SetScissorRect(0, 0, 0, sc.ShadowMapTexture.Width, sc.ShadowMapTexture.Height); cls[1].ClearDepthStencil(1f); Render(gd, cls[1], sc, RenderPasses.ShadowMapNear, lightFrustum0, _renderQueues[0], _cullableStage[0], _renderableStage[0], null, true); }); _tasks[1] = Task.Run(() => { // Mid Matrix4x4 viewProj1 = UpdateDirectionalLightMatrices( sc, _nearCascadeLimit, _midCascadeLimit, sc.ShadowMapTexture.Width, out var lightFrustum1); cls[2].UpdateBuffer(sc.LightViewProjectionBuffer1, 0, ref viewProj1); cls[2].SetFramebuffer(sc.MidShadowMapFramebuffer); cls[2].SetViewport(0, new Viewport(0, 0, sc.ShadowMapTexture.Width, sc.ShadowMapTexture.Height, 0, 1)); cls[2].SetScissorRect(0, 0, 0, sc.ShadowMapTexture.Width, sc.ShadowMapTexture.Height); cls[2].ClearDepthStencil(1f); Render(gd, cls[2], sc, RenderPasses.ShadowMapMid, lightFrustum1, _renderQueues[1], _cullableStage[1], _renderableStage[1], null, true); }); _tasks[2] = Task.Run(() => { // Far Matrix4x4 viewProj2 = UpdateDirectionalLightMatrices( sc, _midCascadeLimit, _farCascadeLimit, sc.ShadowMapTexture.Width, out var lightFrustum2); cls[3].UpdateBuffer(sc.LightViewProjectionBuffer2, 0, ref viewProj2); cls[3].SetFramebuffer(sc.FarShadowMapFramebuffer); cls[3].SetViewport(0, new Viewport(0, 0, sc.ShadowMapTexture.Width, sc.ShadowMapTexture.Height, 0, 1)); cls[3].SetScissorRect(0, 0, 0, sc.ShadowMapTexture.Width, sc.ShadowMapTexture.Height); cls[3].ClearDepthStencil(1f); Render(gd, cls[3], sc, RenderPasses.ShadowMapFar, lightFrustum2, _renderQueues[2], _cullableStage[2], _renderableStage[2], null, true); }); _tasks[3] = Task.Run(() => { // Reflections cls[4].SetFramebuffer(sc.ReflectionFramebuffer); float scWidth = sc.ReflectionFramebuffer.Width; float scHeight = sc.ReflectionFramebuffer.Height; cls[4].SetViewport(0, new Viewport(0, 0, scWidth, scHeight, 0, 1)); cls[4].SetFullViewports(); cls[4].SetFullScissorRects(); cls[4].ClearColorTarget(0, RgbaFloat.Black); cls[4].ClearDepthStencil(1f); // Render reflected scene. Matrix4x4 planeReflectionMatrix = Matrix4x4.CreateReflection(MirrorMesh.Plane); CameraInfo camInfo = new CameraInfo(); camInfo.CameraLookDirection = Vector3.Normalize(Vector3.Reflect(_camera.LookDirection, MirrorMesh.Plane.Normal)); camInfo.CameraPosition_WorldSpace = Vector3.Transform(_camera.Position, planeReflectionMatrix); cls[4].UpdateBuffer(sc.CameraInfoBuffer, 0, ref camInfo); Matrix4x4 view = sc.Camera.ViewMatrix; view = planeReflectionMatrix * view; cls[4].UpdateBuffer(sc.ViewMatrixBuffer, 0, view); Matrix4x4 projection = _camera.ProjectionMatrix; cls[4].UpdateBuffer(sc.ReflectionViewProjBuffer, 0, view * projection); BoundingFrustum cameraFrustum = new BoundingFrustum(view * projection); Render(gd, cls[4], sc, RenderPasses.ReflectionMap, cameraFrustum, _renderQueues[3], _cullableStage[3], _renderableStage[3], null, true); cl.GenerateMipmaps(sc.ReflectionColorTexture); // Main scene cls[4].SetFramebuffer(sc.MainSceneFramebuffer); scWidth = sc.MainSceneFramebuffer.Width; scHeight = sc.MainSceneFramebuffer.Height; cls[4].SetViewport(0, new Viewport(0, 0, scWidth, scHeight, 0, 1)); cls[4].SetScissorRect(0, 0, 0, (uint)scWidth, (uint)scHeight); cls[4].ClearColorTarget(0, RgbaFloat.Black); cls[4].ClearDepthStencil(1f); sc.UpdateCameraBuffers(cls[4]); cameraFrustum = new BoundingFrustum(_camera.ViewMatrix * _camera.ProjectionMatrix); Render(gd, cls[4], sc, RenderPasses.Standard, cameraFrustum, _renderQueues[3], _cullableStage[3], _renderableStage[3], null, true); Render(gd, cls[4], sc, RenderPasses.AlphaBlend, cameraFrustum, _renderQueues[3], _cullableStage[3], _renderableStage[3], null, true); Render(gd, cls[4], sc, RenderPasses.Overlay, cameraFrustum, _renderQueues[3], _cullableStage[3], _renderableStage[3], null, true); }); Task.WaitAll(_tasks); foreach (Renderable renderable in _allPerFrameRenderablesSet) { renderable.UpdatePerFrameResources(gd, _resourceUpdateCL, sc); } _resourceUpdateCL.End(); gd.SubmitCommands(_resourceUpdateCL); for (int i = 0; i < cls.Length; i++) { cls[i].End(); gd.SubmitCommands(cls[i]); cls[i].Dispose(); } if (sc.MainSceneColorTexture.SampleCount != TextureSampleCount.Count1) { cl.ResolveTexture(sc.MainSceneColorTexture, sc.MainSceneResolvedColorTexture); } cl.SetFramebuffer(sc.DuplicatorFramebuffer); uint fbWidth = sc.DuplicatorFramebuffer.Width; uint fbHeight = sc.DuplicatorFramebuffer.Height; cl.SetViewport(0, new Viewport(0, 0, fbWidth, fbHeight, 0, 1)); cl.SetViewport(1, new Viewport(0, 0, fbWidth, fbHeight, 0, 1)); cl.SetScissorRect(0, 0, 0, fbWidth, fbHeight); cl.SetScissorRect(1, 0, 0, fbWidth, fbHeight); Render(gd, cl, sc, RenderPasses.Duplicator, new BoundingFrustum(), _renderQueues[0], _cullableStage[0], _renderableStage[0], null, false); cl.SetFramebuffer(gd.SwapchainFramebuffer); fbWidth = gd.SwapchainFramebuffer.Width; fbHeight = gd.SwapchainFramebuffer.Height; cl.SetViewport(0, new Viewport(0, 0, fbWidth, fbHeight, 0, 1)); cl.SetScissorRect(0, 0, 0, fbWidth, fbHeight); Render(gd, cl, sc, RenderPasses.SwapchainOutput, new BoundingFrustum(), _renderQueues[0], _cullableStage[0], _renderableStage[0], null, false); cl.End(); gd.SubmitCommands(cl); }
public unsafe void Points_WithTexture_UpdateUnrelated(bool useTextureView) { // 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)); 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.TextureCoordinate, VertexElementFormat.Float2)) }, TestShaders.LoadVertexFragment(RF, "TexturedPoints")); 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; if (useTextureView) { TextureView view = RF.CreateTextureView(sampledTexture); set = RF.CreateResourceSet(new ResourceSetDescription(layout, orthoBuffer, view, GD.PointSampler)); } else { set = RF.CreateResourceSet(new ResourceSetDescription(layout, orthoBuffer, sampledTexture, 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 (!GD.IsUvOriginTopLeft || GD.IsClipSpaceYInverted) { y = framebuffer.Height - y - 1; } Assert.Equal(white, readView[x, y], RgbaFloatFuzzyComparer.Instance); } GD.Unmap(staging); }
public override void Operate() { _commands.Begin(); _commands.SetFramebuffer(_framebuffer); _commands.ClearColorTarget(0, RgbaFloat.Black); _commands.ClearDepthStencil(1f); var renderables = World.Where(CanOperateOn) .GroupBy(entity => { var mesh = entity.GetComponent <MeshData>(); return( entity.GetComponent <Material>(), mesh.FrontFace, mesh.PrimitiveTopology, entity.GetComponent <IResourceSet>().ResourceLayout, mesh.VertexBuffer.LayoutDescription ); }); foreach (var renderable in renderables) { var material = renderable.Key.Item1; if (!_pipelines.ContainsKey(material)) { var frontFace = renderable.Key.FrontFace; var primitiveTopology = renderable.Key.PrimitiveTopology; var resourceLayout = renderable.Key.ResourceLayout; var vertexLayout = renderable.Key.LayoutDescription; var pipeline = CreatePipeline(material, frontFace, primitiveTopology, resourceLayout, vertexLayout); _pipelines.Add(material, pipeline); } _commands.SetPipeline(_pipelines[material]); var meshesWithUniforms = renderable.Select(entity => ( entity.GetComponent <MeshData>().VertexBuffer, entity.GetComponent <IResourceSet>().ResourceSet )); foreach (var meshAndUniforms in meshesWithUniforms) { var mesh = meshAndUniforms.VertexBuffer; _commands.SetVertexBuffer(0, mesh.Vertices); _commands.SetIndexBuffer(mesh.Indices.DeviceBuffer, IndexFormat.UInt16); _commands.SetGraphicsResourceSet(0, meshAndUniforms.ResourceSet); _commands.DrawIndexed( indexCount: (uint)mesh.Indices.Count, instanceCount: 1, // TODO: Group renderables by MeshData and figure out instance uniforms indexStart: 0, vertexOffset: 0, instanceStart: 0 ); } } _commands.End(); _submitCommands(_commands); }
public void ComputeGeneratedTexture() { if (!GD.Features.ComputeShader) { return; } uint width = 4; uint height = 1; TextureDescription texDesc = TextureDescription.Texture2D( width, height, 1, 1, PixelFormat.R32_G32_B32_A32_Float, TextureUsage.Sampled | TextureUsage.Storage); Texture computeOutput = RF.CreateTexture(texDesc); texDesc.Usage = TextureUsage.RenderTarget; Texture finalOutput = RF.CreateTexture(texDesc); Framebuffer framebuffer = RF.CreateFramebuffer(new FramebufferDescription(null, finalOutput)); ResourceLayout computeLayout = RF.CreateResourceLayout(new ResourceLayoutDescription( new ResourceLayoutElementDescription("ComputeOutput", ResourceKind.TextureReadWrite, ShaderStages.Compute))); ResourceSet computeSet = RF.CreateResourceSet(new ResourceSetDescription(computeLayout, computeOutput)); Pipeline computePipeline = RF.CreateComputePipeline(new ComputePipelineDescription( TestShaders.LoadCompute(RF, "ComputeTextureGenerator"), computeLayout, 4, 1, 1)); ResourceLayout graphicsLayout = RF.CreateResourceLayout(new ResourceLayoutDescription( new ResourceLayoutElementDescription("Input", ResourceKind.TextureReadOnly, ShaderStages.Fragment), new ResourceLayoutElementDescription("InputSampler", ResourceKind.Sampler, ShaderStages.Fragment))); ResourceSet graphicsSet = RF.CreateResourceSet(new ResourceSetDescription(graphicsLayout, computeOutput, GD.PointSampler)); Pipeline graphicsPipeline = RF.CreateGraphicsPipeline(new GraphicsPipelineDescription( BlendStateDescription.SingleOverrideBlend, DepthStencilStateDescription.Disabled, RasterizerStateDescription.CullNone, PrimitiveTopology.TriangleStrip, new ShaderSetDescription( Array.Empty <VertexLayoutDescription>(), TestShaders.LoadVertexFragment(RF, "FullScreenBlit")), 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(finalOutput); MappedResourceView <RgbaFloat> readView = GD.Map <RgbaFloat>(readback, MapMode.Read); Assert.Equal(RgbaFloat.Red, readView[0, 0]); Assert.Equal(RgbaFloat.Green, readView[1, 0]); Assert.Equal(RgbaFloat.Blue, readView[2, 0]); Assert.Equal(RgbaFloat.White, readView[3, 0]); GD.Unmap(readback); }
public void Execute(RenderContext context) { RenderedObjectsOpaque = 0; RenderedObjectsTransparent = 0; EnsureIntermediateFramebuffer(context.GraphicsDevice, context.RenderTarget); _renderList.Clear(); context.Scene3D?.BuildRenderList( _renderList, context.Scene3D.Camera, context.GameTime); BuildingRenderList?.Invoke(this, new BuildingRenderListEventArgs( _renderList, context.Scene3D?.Camera, context.GameTime)); _commandList.Begin(); if (context.Scene3D != null) { _commandList.PushDebugGroup("3D Scene"); Render3DScene(_commandList, context.Scene3D, context); _commandList.PopDebugGroup(); } else { _commandList.SetFramebuffer(_intermediateFramebuffer); _commandList.ClearColorTarget(0, ClearColor); } // GUI and camera-dependent 2D elements { _commandList.PushDebugGroup("2D Scene"); _drawingContext.Begin( _commandList, _loadContext.StandardGraphicsResources.LinearClampSampler, new SizeF(context.RenderTarget.Width, context.RenderTarget.Height)); context.Scene3D?.Render(_drawingContext); context.Scene2D?.Render(_drawingContext); _shadowMapRenderer.DrawDebugOverlay( context.Scene3D, _drawingContext); Rendering2D?.Invoke(this, new Rendering2DEventArgs(_drawingContext)); _drawingContext.End(); _commandList.PopDebugGroup(); } _commandList.End(); context.GraphicsDevice.SubmitCommands(_commandList); _textureCopier.Execute( _intermediateTexture, context.RenderTarget); }
private void Draw() { Debug.Assert(_window.Exists); int width = _window.Width; int height = _window.Height; int x = _window.X; int y = _window.Y; if (_windowResized) { _windowResized = false; CFG.Current.GFX_Display_Width = width; CFG.Current.GFX_Display_Height = height; _gd.ResizeMainWindow((uint)width, (uint)height); //_scene.Camera.WindowResized(width, height); _resizeHandled?.Invoke(width, height); CommandList cl = _gd.ResourceFactory.CreateCommandList(); cl.Begin(); //_sc.RecreateWindowSizedResources(_gd, cl); RecreateWindowFramebuffers(cl); ImguiRenderer.WindowResized(width, height); MSBEditor.EditorResized(_window, _gd); ModelEditor.EditorResized(_window, _gd); cl.End(); _gd.SubmitCommands(cl); cl.Dispose(); } if (_windowMoved) { _windowMoved = false; CFG.Current.GFX_Display_X = x; CFG.Current.GFX_Display_Y = y; } if (_newSampleCount != null) { //_sc.MainSceneSampleCount = _newSampleCount.Value; _newSampleCount = null; //DestroyAllObjects(); //CreateAllObjects(); } //_frameCommands.Begin(); //CommonMaterials.FlushAll(_frameCommands); //_scene.RenderAllStages(_gd, _frameCommands, _sc); //CommandList cl2 = _gd.ResourceFactory.CreateCommandList(); MainWindowCommandList.Begin(); //cl2.SetFramebuffer(_gd.SwapchainFramebuffer); MainWindowCommandList.SetFramebuffer(_gd.SwapchainFramebuffer); MainWindowCommandList.ClearColorTarget(0, new RgbaFloat(0.176f, 0.176f, 0.188f, 1.0f)); float depthClear = _gd.IsDepthRangeZeroToOne ? 1f : 0f; MainWindowCommandList.ClearDepthStencil(0.0f); MainWindowCommandList.SetFullViewport(0); //MainWindowCommandList.End(); //_gd.SubmitCommands(MainWindowCommandList); //_gd.WaitForIdle(); if (_msbEditorFocused) { MSBEditor.Draw(_gd, MainWindowCommandList); } if (_modelEditorFocused) { ModelEditor.Draw(_gd, MainWindowCommandList); } var fence = Scene.Renderer.Frame(MainWindowCommandList, false); //GuiCommandList.Begin(); //GuiCommandList.SetFramebuffer(_gd.SwapchainFramebuffer); MainWindowCommandList.SetFullViewport(0); MainWindowCommandList.SetFullScissorRects(); ImguiRenderer.Render(_gd, MainWindowCommandList); //GuiCommandList.End(); MainWindowCommandList.End(); _gd.SubmitCommands(MainWindowCommandList, fence); Scene.Renderer.SubmitPostDrawCommandLists(); //Scene.SceneRenderPipeline.TestUpdateView(_gd, MainWindowCommandList, TestWorldView.CameraTransform.CameraViewMatrix); _gd.SwapBuffers(); }
public void Points_WithUShortNormColor() { 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); ShaderSetDescription shaderSet = new ShaderSetDescription( new VertexLayoutDescription[] { new VertexLayoutDescription( new VertexElementDescription("Position", VertexElementSemantic.Position, VertexElementFormat.Float2), new VertexElementDescription("Color", VertexElementSemantic.Color, VertexElementFormat.UShort4_Norm)) }, new Shader[] { TestShaders.Load(RF, "U16NormVertexAttribs", ShaderStages.Vertex, "VS"), TestShaders.Load(RF, "U16NormVertexAttribs", ShaderStages.Fragment, "FS") }); ResourceLayout layout = RF.CreateResourceLayout(new ResourceLayoutDescription( new ResourceLayoutElementDescription("Ortho", ResourceKind.UniformBuffer, ShaderStages.Vertex))); ResourceSet set = RF.CreateResourceSet(new ResourceSetDescription(layout, orthoBuffer)); GraphicsPipelineDescription gpd = new GraphicsPipelineDescription( BlendStateDescription.SingleOverrideBlend, DepthStencilStateDescription.Disabled, RasterizerStateDescription.Default, PrimitiveTopology.PointList, shaderSet, layout, framebuffer.OutputDescription); Pipeline pipeline = RF.CreateGraphicsPipeline(ref gpd); VertexCPU_UShortNorm[] vertices = new VertexCPU_UShortNorm[] { new VertexCPU_UShortNorm { Position = new Vector2(0.5f, 0.5f), R = UShortNorm(0.25f), G = UShortNorm(0.5f), B = UShortNorm(0.75f), }, new VertexCPU_UShortNorm { Position = new Vector2(10.5f, 12.5f), R = UShortNorm(0.25f), G = UShortNorm(0.5f), B = UShortNorm(0.75f), }, new VertexCPU_UShortNorm { Position = new Vector2(25.5f, 35.5f), R = UShortNorm(0.75f), G = UShortNorm(0.5f), B = UShortNorm(0.25f), }, new VertexCPU_UShortNorm { Position = new Vector2(49.5f, 49.5f), R = UShortNorm(0.15f), G = UShortNorm(0.25f), B = UShortNorm(0.35f), }, }; DeviceBuffer vb = RF.CreateBuffer( new BufferDescription((uint)(Unsafe.SizeOf <VertexCPU_UShortNorm>() * vertices.Length), BufferUsage.VertexBuffer)); GD.UpdateBuffer(vb, 0, vertices); 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.CopyTexture(target, staging); cl.End(); GD.SubmitCommands(cl); GD.WaitForIdle(); MappedResourceView <RgbaFloat> readView = GD.Map <RgbaFloat>(staging, MapMode.Read); foreach (VertexCPU_UShortNorm vertex in vertices) { uint x = (uint)vertex.Position.X; uint y = (uint)vertex.Position.Y; if (!GD.IsUvOriginTopLeft) { y = framebuffer.Height - y - 1; } RgbaFloat expectedColor = new RgbaFloat( vertex.R / (float)ushort.MaxValue, vertex.G / (float)ushort.MaxValue, vertex.B / (float)ushort.MaxValue, 1); Assert.Equal(expectedColor, readView[x, y], RgbaFloatFuzzyComparer.Instance); } GD.Unmap(staging); }
public unsafe void Copy_Compressed_Array(bool separateLayerCopies) { PixelFormat format = PixelFormat.BC3_UNorm; if (!GD.GetPixelFormatSupport(format, TextureType.Texture2D, TextureUsage.Sampled)) { return; } TextureDescription texDesc = TextureDescription.Texture2D( 16, 16, 1, 4, format, TextureUsage.Sampled); Texture copySrc = RF.CreateTexture(texDesc); texDesc.Usage = TextureUsage.Staging; Texture copyDst = RF.CreateTexture(texDesc); for (uint layer = 0; layer < copySrc.ArrayLayers; layer++) { int byteCount = 16 * 16; byte[] data = Enumerable.Range(0, byteCount).Select(i => (byte)(i + layer)).ToArray(); GD.UpdateTexture( copySrc, data, 0, 0, 0, 16, 16, 1, 0, layer); } CommandList copyCL = RF.CreateCommandList(); copyCL.Begin(); if (separateLayerCopies) { for (uint layer = 0; layer < copySrc.ArrayLayers; layer++) { copyCL.CopyTexture(copySrc, 0, 0, 0, 0, layer, copyDst, 0, 0, 0, 0, layer, 16, 16, 1, 1); } } else { copyCL.CopyTexture(copySrc, 0, 0, 0, 0, 0, copyDst, 0, 0, 0, 0, 0, 16, 16, 1, copySrc.ArrayLayers); } copyCL.End(); Fence fence = RF.CreateFence(false); GD.SubmitCommands(copyCL, fence); GD.WaitForFence(fence); for (uint layer = 0; layer < copyDst.ArrayLayers; layer++) { MappedResource map = GD.Map(copyDst, MapMode.Read, layer); byte * basePtr = (byte *)map.Data; int index = 0; uint rowSize = 64; uint numRows = 4; for (uint row = 0; row < numRows; row++) { byte *rowBase = basePtr + (row * map.RowPitch); for (uint x = 0; x < rowSize; x++) { Assert.Equal((byte)(index + layer), rowBase[x]); index += 1; } } GD.Unmap(copyDst, layer); } }
public byte[] VboToPng(float[] vbo, int trianglesCount, bool flipHorizontal = false) { Logger.AddLog("VeldridRender.VboToPng"); CheckThread(); try { uint size = (uint)vbo.Length * 4; if (size % 16 != 0) { size += 16 - size % 16; } DeviceBuffer vertexBuffer = resourceFactory.CreateBuffer(new BufferDescription(size, BufferUsage.VertexBuffer)); graphicsDevice.UpdateBuffer(vertexBuffer, 0, vbo); graphicsDevice.WaitForIdle(); CommandList cl = resourceFactory.CreateCommandList(); cl.Begin(); cl.SetFramebuffer(_offscreenFB); cl.ClearColorTarget(0, background); cl.SetFullViewport(0); //cl.UpdateBuffer(vertexBuffer, 0, vbo); cl.SetVertexBuffer(0, vertexBuffer); cl.SetPipeline(_pipeline); cl.SetGraphicsResourceSet(0, _uniformsResourceSet); cl.SetGraphicsResourceSet(1, _textureSet); cl.Draw((uint)(trianglesCount * 3)); //transfer GPU drawing to CPU readable one cl.CopyTexture(_offscreenFB.ColorTargets[0].Target, _offscreenReadOut); cl.End(); graphicsDevice.SubmitCommands(cl); //Thread.Sleep(5); graphicsDevice.WaitForIdle(); //Thread.Sleep(5); MappedResourceView <byte> view = graphicsDevice.Map <byte>(_offscreenReadOut, MapMode.Read); byte[] tmp = new byte[view.SizeInBytes]; Marshal.Copy(view.MappedResource.Data, tmp, 0, (int)view.SizeInBytes); graphicsDevice.Unmap(_offscreenReadOut); return(Helpers.ImageProcessing.Rgba32ToPng( new ProcessImage { Load = tmp, Width = (int)_offscreenReadOut.Width, Height = (int)_offscreenReadOut.Height, Type = ProcessImageType.RGBA32 }, flipHorizontal, FlipVertical) .Load); } catch (Exception ex) { Logger.AddLog(ex); } return(null); }