| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409 |
- using System;
- using System.Numerics;
- using System.Runtime.InteropServices;
- using System.Text;
- using ImGuiNET;
- using OpenTK.Windowing.GraphicsLibraryFramework;
- using Veldrid;
- using Veldrid.OpenGL;
- using Veldrid.SPIRV;
- using Veldrid.Vk;
- namespace Pow3r
- {
- internal sealed unsafe partial class Program
- {
- private const string VDVertexShader = @"
- #version 460
- layout (location = 0) in vec2 Position;
- layout (location = 1) in vec2 UV;
- layout (location = 2) in vec4 Color;
- layout (set = 0, binding = 0) uniform ProjMtx {
- mat4 _ProjMtx;
- };
- layout (location = 0) out vec2 Frag_UV;
- layout (location = 1) out vec4 Frag_Color;
- // Converts a color from sRGB gamma to linear light gamma
- vec4 toLinear(vec4 sRGB)
- {
- bvec3 cutoff = lessThan(sRGB.rgb, vec3(0.04045));
- vec3 higher = pow((sRGB.rgb + vec3(0.055))/vec3(1.055), vec3(2.4));
- vec3 lower = sRGB.rgb/vec3(12.92);
- return vec4(mix(higher, lower, cutoff), sRGB.a);
- }
- void main()
- {
- Frag_UV = UV;
- Frag_Color = toLinear(Color);
- gl_Position = _ProjMtx * vec4(Position.xy,0,1);
- }";
- private const string VDFragmentShader = @"
- #version 460
- layout (location = 0) in vec2 Frag_UV;
- layout (location = 1) in vec4 Frag_Color;
- layout (set = 1, binding = 0) uniform texture2D Texture;
- layout (set = 1, binding = 1) uniform sampler TextureSampler;
- layout (location = 0) out vec4 Out_Color;
- void main()
- {
- Out_Color = Frag_Color * texture(sampler2D(Texture, TextureSampler), Frag_UV.st);
- }";
- private VeldridRenderer _vdRenderer = VeldridRenderer.Vulkan;
- private GraphicsDevice _vdGfxDevice;
- private CommandList _vdCommandList;
- private Pipeline _vdPipeline;
- private Shader[] _vdShaders;
- private ResourceSet _vdSetTexture;
- private ResourceSet _vdSetProjMatrix;
- private Texture _vdTexture;
- private Sampler _vdSampler;
- private DeviceBuffer _vdProjMatrixUniformBuffer;
- private int _vdLastWidth;
- private int _vdLastHeight;
- private VdFencedDatum[] _fencedData = Array.Empty<VdFencedDatum>();
- private void InitVeldrid()
- {
- var options = new GraphicsDeviceOptions
- {
- #if DEBUG
- Debug = true,
- #endif
- HasMainSwapchain = true,
- SyncToVerticalBlank = _vsync,
- PreferStandardClipSpaceYDirection = true,
- SwapchainSrgbFormat = true
- };
- GLFW.GetFramebufferSize(_window.WindowPtr, out var w, out var h);
- var hwnd = GLFW.GetWin32Window(_window.WindowPtr);
- var hinstance = GetModuleHandleA(null);
- switch (_vdRenderer)
- {
- case VeldridRenderer.Vulkan:
- _vdGfxDevice = GraphicsDevice.CreateVulkan(
- options,
- VkSurfaceSource.CreateWin32((nint) hinstance, hwnd),
- (uint) w, (uint) h);
- break;
- case VeldridRenderer.D3D11:
- _vdGfxDevice = GraphicsDevice.CreateD3D11(options, hwnd, (uint) w, (uint) h);
- break;
- case VeldridRenderer.OpenGL:
- {
- var platInfo = new OpenGLPlatformInfo(
- (nint) _window.WindowPtr,
- GLFW.GetProcAddress,
- ptr => GLFW.MakeContextCurrent((Window*) ptr),
- () => (nint) GLFW.GetCurrentContext(),
- () => GLFW.MakeContextCurrent(null),
- ptr => GLFW.DestroyWindow((Window*) ptr),
- () => GLFW.SwapBuffers(_window.WindowPtr),
- vsync => GLFW.SwapInterval(vsync ? 1 : 0));
- _vdGfxDevice = GraphicsDevice.CreateOpenGL(options, platInfo, (uint) w, (uint) h);
- break;
- }
- }
- var factory = _vdGfxDevice.ResourceFactory;
- _vdCommandList = factory.CreateCommandList();
- _vdCommandList.Name = "Honk";
- var vtxLayout = new VertexLayoutDescription(
- new VertexElementDescription("Position", VertexElementFormat.Float2,
- VertexElementSemantic.TextureCoordinate),
- new VertexElementDescription("UV", VertexElementFormat.Float2, VertexElementSemantic.TextureCoordinate),
- new VertexElementDescription("Color", VertexElementFormat.Byte4_Norm,
- VertexElementSemantic.TextureCoordinate));
- var vtxShaderDesc = new ShaderDescription(
- ShaderStages.Vertex,
- Encoding.UTF8.GetBytes(VDVertexShader),
- "main");
- var fragShaderDesc = new ShaderDescription(
- ShaderStages.Fragment,
- Encoding.UTF8.GetBytes(VDFragmentShader),
- "main");
- _vdShaders = factory.CreateFromSpirv(vtxShaderDesc, fragShaderDesc);
- _vdShaders[0].Name = "VertexShader";
- _vdShaders[1].Name = "FragmentShader";
- var layoutTexture = factory.CreateResourceLayout(new ResourceLayoutDescription(
- new ResourceLayoutElementDescription(
- "Texture",
- ResourceKind.TextureReadOnly,
- ShaderStages.Fragment),
- new ResourceLayoutElementDescription(
- "TextureSampler",
- ResourceKind.Sampler,
- ShaderStages.Fragment)));
- layoutTexture.Name = "LayoutTexture";
- var layoutProjMatrix = factory.CreateResourceLayout(new ResourceLayoutDescription(
- new ResourceLayoutElementDescription(
- "ProjMtx",
- ResourceKind.UniformBuffer,
- ShaderStages.Vertex)));
- layoutProjMatrix.Name = "LayoutProjMatrix";
- var pipelineDesc = new GraphicsPipelineDescription(
- new BlendStateDescription(
- RgbaFloat.White,
- new BlendAttachmentDescription(
- true,
- BlendFactor.SourceAlpha,
- BlendFactor.InverseSourceAlpha,
- BlendFunction.Add,
- BlendFactor.One,
- BlendFactor.InverseSourceAlpha,
- BlendFunction.Add)
- ),
- DepthStencilStateDescription.Disabled,
- new RasterizerStateDescription(
- FaceCullMode.None,
- PolygonFillMode.Solid,
- FrontFace.Clockwise,
- depthClipEnabled: false,
- scissorTestEnabled: true),
- PrimitiveTopology.TriangleList,
- new ShaderSetDescription(new[] {vtxLayout}, _vdShaders),
- new[] {layoutProjMatrix, layoutTexture},
- new OutputDescription(
- null,
- new OutputAttachmentDescription(PixelFormat.B8_G8_R8_A8_UNorm_SRgb))
- );
- _vdPipeline = factory.CreateGraphicsPipeline(pipelineDesc);
- _vdPipeline.Name = "MainPipeline";
- _vdProjMatrixUniformBuffer = factory.CreateBuffer(new BufferDescription(
- (uint) sizeof(Matrix4x4),
- BufferUsage.Dynamic | BufferUsage.UniformBuffer));
- _vdProjMatrixUniformBuffer.Name = "_vdProjMatrixUniformBuffer";
- _vdSetProjMatrix = factory.CreateResourceSet(new ResourceSetDescription(
- layoutProjMatrix,
- _vdProjMatrixUniformBuffer));
- _vdSetProjMatrix.Name = "_vdSetProjMatrix";
- var io = ImGui.GetIO();
- io.Fonts.GetTexDataAsRGBA32(out byte* pixels, out var width, out var height, out _);
- _vdTexture = factory.CreateTexture(TextureDescription.Texture2D(
- (uint) width, (uint) height,
- mipLevels: 1,
- arrayLayers: 1,
- PixelFormat.R8_G8_B8_A8_UNorm_SRgb,
- TextureUsage.Sampled));
- _vdTexture.Name = "MainTexture";
- _vdSampler = factory.CreateSampler(SamplerDescription.Linear);
- _vdSampler.Name = "MainSampler";
- _vdGfxDevice.UpdateTexture(
- _vdTexture,
- (IntPtr) pixels,
- (uint) (width * height * 4),
- x: 0, y: 0, z: 0,
- (uint) width, (uint) height, depth: 1,
- mipLevel: 0,
- arrayLayer: 0);
- _vdSetTexture = factory.CreateResourceSet(new ResourceSetDescription(
- layoutTexture,
- _vdTexture,
- _vdSampler));
- _vdSetTexture.Name = "SetTexture";
- io.Fonts.SetTexID(0);
- io.Fonts.ClearTexData();
- _vdGfxDevice.ResizeMainWindow((uint) w, (uint) h);
- _vdGfxDevice.SwapBuffers();
- }
- private void RenderVeldrid()
- {
- GLFW.GetFramebufferSize(_window.WindowPtr, out var fbW, out var fbH);
- if (_vdLastWidth != fbW && _vdLastHeight != fbH)
- {
- _vdGfxDevice.ResizeMainWindow((uint) fbW, (uint) fbH);
- _vdLastWidth = fbW;
- _vdLastHeight = fbH;
- }
- _vdCommandList.Begin();
- _vdCommandList.SetFramebuffer(_vdGfxDevice.SwapchainFramebuffer);
- _vdCommandList.SetViewport(0, new Viewport(0, 0, fbW, fbH, 0, 1));
- _vdCommandList.ClearColorTarget(0, RgbaFloat.Black);
- var factory = _vdGfxDevice.ResourceFactory;
- var drawData = ImGui.GetDrawData();
- ref var fencedData = ref GetFreeFencedData();
- ref var vtxBuf = ref fencedData.VertexBuffer;
- ref var idxBuf = ref fencedData.IndexBuffer;
- var byteLenVtx = (uint) (sizeof(ImDrawVert) * drawData.TotalVtxCount);
- if (fencedData.VertexBuffer == null || vtxBuf.SizeInBytes < byteLenVtx)
- {
- vtxBuf?.Dispose();
- vtxBuf = factory.CreateBuffer(new BufferDescription(
- byteLenVtx,
- BufferUsage.VertexBuffer | BufferUsage.Dynamic));
- vtxBuf.Name = "_vdVtxBuffer";
- }
- var byteLenIdx = (uint) (sizeof(ushort) * drawData.TotalIdxCount);
- if (idxBuf == null || idxBuf.SizeInBytes < byteLenIdx)
- {
- idxBuf?.Dispose();
- idxBuf = factory.CreateBuffer(new BufferDescription(
- byteLenIdx,
- BufferUsage.IndexBuffer | BufferUsage.Dynamic));
- idxBuf.Name = "_vdIdxBuffer";
- }
- var vtxOffset = 0;
- var idxOffset = 0;
- var mappedVtxBuf = MappedToSpan(_vdGfxDevice.Map<ImDrawVert>(vtxBuf, MapMode.Write));
- var mappedIdxBuf = MappedToSpan(_vdGfxDevice.Map<ushort>(idxBuf, MapMode.Write));
- var l = drawData.DisplayPos.X;
- var r = drawData.DisplayPos.X + drawData.DisplaySize.X;
- var t = drawData.DisplayPos.Y;
- var b = drawData.DisplayPos.Y + drawData.DisplaySize.Y;
- var matrix = Matrix4x4.CreateOrthographicOffCenter(l, r, b, t, -1, 1);
- var clipOff = drawData.DisplayPos;
- var clipScale = drawData.FramebufferScale;
- _vdCommandList.UpdateBuffer(_vdProjMatrixUniformBuffer, 0, ref matrix);
- _vdCommandList.SetPipeline(_vdPipeline);
- _vdCommandList.SetGraphicsResourceSet(0, _vdSetProjMatrix);
- _vdCommandList.SetGraphicsResourceSet(1, _vdSetTexture);
- _vdCommandList.SetVertexBuffer(0, vtxBuf);
- _vdCommandList.SetIndexBuffer(idxBuf, IndexFormat.UInt16);
- for (var n = 0; n < drawData.CmdListsCount; n++)
- {
- var drawList = drawData.CmdListsRange[n];
- var drawVtx = new Span<ImDrawVert>((void*) drawList.VtxBuffer.Data, drawList.VtxBuffer.Size);
- var drawIdx = new Span<ushort>((void*) drawList.IdxBuffer.Data, drawList.IdxBuffer.Size);
- drawVtx.CopyTo(mappedVtxBuf[vtxOffset..]);
- drawIdx.CopyTo(mappedIdxBuf[idxOffset..]);
- for (var cmdI = 0; cmdI < drawList.CmdBuffer.Size; cmdI++)
- {
- var cmd = drawList.CmdBuffer[cmdI];
- Vector4 clipRect = default;
- clipRect.X = (cmd.ClipRect.X - clipOff.X) * clipScale.X;
- clipRect.Y = (cmd.ClipRect.Y - clipOff.Y) * clipScale.Y;
- clipRect.Z = (cmd.ClipRect.Z - clipOff.X) * clipScale.X;
- clipRect.W = (cmd.ClipRect.W - clipOff.Y) * clipScale.Y;
- _vdCommandList.SetScissorRect(
- 0,
- (uint) clipRect.X,
- (uint) clipRect.Y,
- (uint) (clipRect.Z - clipRect.X),
- (uint) (clipRect.W - clipRect.Y));
- _vdCommandList.DrawIndexed(
- cmd.ElemCount,
- 1,
- (uint) (cmd.IdxOffset + idxOffset),
- (int) (cmd.VtxOffset + vtxOffset),
- 0);
- }
- vtxOffset += drawVtx.Length;
- idxOffset += drawIdx.Length;
- }
- _vdGfxDevice.Unmap(vtxBuf);
- _vdGfxDevice.Unmap(idxBuf);
- _vdCommandList.End();
- _vdGfxDevice.SubmitCommands(_vdCommandList, fencedData.Fence);
- _vdGfxDevice.SwapBuffers();
- }
- private ref VdFencedDatum GetFreeFencedData()
- {
- for (var i = 0; i < _fencedData.Length; i++)
- {
- ref var fenced = ref _fencedData[i];
- if (fenced.Fence.Signaled)
- {
- fenced.Fence.Reset();
- return ref fenced;
- }
- }
- Array.Resize(ref _fencedData, _fencedData.Length + 1);
- ref var slot = ref _fencedData[^1];
- slot = new VdFencedDatum {Fence = _vdGfxDevice.ResourceFactory.CreateFence(false)};
- return ref slot;
- }
- private static Span<T> MappedToSpan<T>(MappedResourceView<T> mapped) where T : struct
- {
- return MemoryMarshal.CreateSpan(ref mapped[0], mapped.Count);
- }
- [DllImport("kernel32.dll")]
- private static extern void* GetModuleHandleA(byte* lpModuleName);
- private struct VdFencedDatum
- {
- public Fence Fence;
- public DeviceBuffer IndexBuffer;
- public DeviceBuffer VertexBuffer;
- }
- private enum VeldridRenderer
- {
- Vulkan,
- D3D11,
- OpenGL
- }
- }
- }
|