static VertexLayout ReadVertexLayout(MemoryReader reader) { var layout = new VertexLayout(); layout.Begin(); var attributeCount = reader.Read <byte>(); var stride = reader.Read <ushort>(); for (int i = 0; i < attributeCount; i++) { var e = reader.Read <VertexElement>(); var usage = attributeUsageMap[e.Attrib]; layout.Add(usage, e.Count, attributeTypeMap[e.AttribType], e.Normalized != 0, e.AsInt != 0); if (layout.GetOffset(usage) != e.Offset) { throw new InvalidOperationException("Invalid mesh data; vertex attribute offset mismatch."); } } layout.End(); if (layout.Stride != stride) { throw new InvalidOperationException("Invalid mesh data; vertex layout stride mismatch."); } return(layout); }
public static VertexLayout ReadVertexLayout(this UnmanagedMemoryAccessor reader, ref int index) { var layout = new VertexLayout(); layout.Begin(); var attributeCount = reader.ReadByte(ref index); var stride = reader.ReadUInt16(ref index); for (int i = 0; i < attributeCount; i++) { var offset = reader.ReadUInt16(ref index); var attrib = reader.ReadUInt16(ref index); var count = reader.ReadByte(ref index); var attribType = reader.ReadUInt16(ref index); var normalized = reader.ReadBool(ref index); var asInt = reader.ReadBool(ref index); var usage = attributeUsageMap[attrib]; layout.Add(usage, count, attributeTypeMap[attribType], normalized, asInt); if (layout.GetOffset(usage) != offset) { throw new InvalidOperationException("Invalid mesh data; vertex attribute offset mismatch."); } } layout.End(); if (layout.Stride != stride) { throw new InvalidOperationException("Invalid mesh data; vertex layout stride mismatch."); } return(layout); }
public void InitRenderer(MTKView view, IMTLDevice device) { #if BGFX var platformData = new PlatformData(); platformData.WindowHandle = view.Handle; platformData.Context = device.Handle; Bgfx.Bgfx.SetPlatformData(platformData); var settings = new InitSettings(); settings.Backend = RendererBackend.Metal; settings.Width = (int)view.Bounds.Width; settings.Height = (int)view.Bounds.Height; settings.ResetFlags = ResetFlags.Vsync; settings.PlatformData = platformData; //settings.limits.maxEncoders = 128; Bgfx.Bgfx.ManuallyRenderFrame(); Bgfx.Bgfx.Init(settings); var vertexLayout = new VertexLayout(); vertexLayout.Begin(RendererBackend.Metal); vertexLayout.Add(VertexAttributeUsage.Position, 3, VertexAttributeType.Float); vertexLayout.Add(VertexAttributeUsage.Color0, 4, VertexAttributeType.UInt8, true); vertexLayout.End(); var vertexBuffer = new VertexBuffer(MemoryBlock.FromArray(Data.cubeVertices), vertexLayout); var indexBuffer = new IndexBuffer(MemoryBlock.FromArray(Data.cubeTriList)); var vertexShader = LoadShader("vs_cubes.bin"); var fragmentShader = LoadShader("fs_cubes.bin"); var program = new Program(vertexShader, fragmentShader); _vertexBuffer = vertexBuffer; _indexBuffer = indexBuffer; _program = program; Bgfx.Bgfx.Touch(0); #endif view.Delegate = this; }
private void InitGraphics() { var io = ImGui.GetIO(); io.DisplaySize = new System.Numerics.Vector2(Engine.Canvas.Width, Engine.Canvas.Height); m_imgui_program = Engine.Content.Get <ShaderProgram>("imgui_shader"); m_imgui_tex_program = Engine.Content.Get <ShaderProgram>("imgui_shader_image"); m_vertex_layout = new VertexLayout(); m_vertex_layout.Begin(); m_vertex_layout.Add(Attrib.Position, AttribType.Float, 2, false, false); m_vertex_layout.Add(Attrib.TexCoord0, AttribType.Float, 2, false, false); m_vertex_layout.Add(Attrib.Color0, AttribType.Uint8, 4, true, false); m_vertex_layout.End(); m_fonts.Add("default", io.Fonts.AddFontDefault()); unsafe { io.Fonts.GetTexDataAsRGBA32(out IntPtr data, out var width, out var height, out var bytes_per_pixel); m_font_atlas = Texture2D.Create(data, width, height, bytes_per_pixel); m_textures.Add((IntPtr)m_font_atlas.GetHashCode(), m_font_atlas); } m_font_atlas_tex_id = (IntPtr)m_font_atlas.GetHashCode(); io.Fonts.SetTexID(m_font_atlas_tex_id); m_canvas_view = Engine.Canvas.CreateView(Color.Transparent); m_vertex_stream = new VertexStream(VertexStreamMode.Stream); m_vertex_stream.SetVertexLayout(m_vertex_layout); }
static unsafe void RunCompute(Sample sample, bool indirectSupported) { // build vertex layouts var quadLayout = new VertexLayout(); quadLayout.Begin() .Add(VertexAttributeUsage.Position, 2, VertexAttributeType.Float) .End(); var computeLayout = new VertexLayout(); computeLayout.Begin() .Add(VertexAttributeUsage.TexCoord0, 4, VertexAttributeType.Float) .End(); // static quad data var vb = new VertexBuffer(MemoryBlock.FromArray(QuadVertices), quadLayout); var ib = new IndexBuffer(MemoryBlock.FromArray(QuadIndices)); // create compute buffers var currPositionBuffer0 = new DynamicVertexBuffer(1 << 15, computeLayout, BufferFlags.ComputeReadWrite); var currPositionBuffer1 = new DynamicVertexBuffer(1 << 15, computeLayout, BufferFlags.ComputeReadWrite); var prevPositionBuffer0 = new DynamicVertexBuffer(1 << 15, computeLayout, BufferFlags.ComputeReadWrite); var prevPositionBuffer1 = new DynamicVertexBuffer(1 << 15, computeLayout, BufferFlags.ComputeReadWrite); // load shaders var particleProgram = ResourceLoader.LoadProgram("vs_particle", "fs_particle"); var initInstancesProgram = ResourceLoader.LoadProgram("cs_init_instances"); var updateInstancesProgram = ResourceLoader.LoadProgram("cs_update_instances"); // indirect rendering support var indirectProgram = SharpBgfx.Program.Invalid; var indirectBuffer = IndirectBuffer.Invalid; bool useIndirect = false; if (indirectSupported) { indirectProgram = ResourceLoader.LoadProgram("cs_indirect"); indirectBuffer = new IndirectBuffer(2); useIndirect = true; } // setup params uniforms var paramData = new ParamsData { TimeStep = 0.0157f, DispatchSize = 32, Gravity = 0.109f, Damping = 0.25f, ParticleIntensity = 0.64f, ParticleSize = 0.279f, BaseSeed = 57, ParticlePower = 3.5f, InitialSpeed = 3.2f, InitialShape = 1, MaxAccel = 100.0f }; // have the compute shader run initialization var u_params = new Uniform("u_params", UniformType.Vector4, 3); Bgfx.SetUniform(u_params, ¶mData, 3); Bgfx.SetComputeBuffer(0, prevPositionBuffer0, ComputeBufferAccess.Write); Bgfx.SetComputeBuffer(1, currPositionBuffer0, ComputeBufferAccess.Write); Bgfx.Dispatch(0, initInstancesProgram, MaxParticleCount / ThreadGroupUpdateSize); // start the frame clock var clock = new Clock(); clock.Start(); // main loop while (sample.ProcessEvents(ResetFlags.Vsync)) { // tick the clock var elapsed = clock.Frame(); var time = clock.TotalTime(); // write some debug text Bgfx.DebugTextClear(); Bgfx.DebugTextWrite(0, 1, DebugColor.White, DebugColor.Blue, "SharpBgfx/Samples/24-NBody"); Bgfx.DebugTextWrite(0, 2, DebugColor.White, DebugColor.Cyan, "Description: N-body simulation with compute shaders using buffers."); Bgfx.DebugTextWrite(0, 3, DebugColor.White, DebugColor.Cyan, "Frame: {0:F3} ms", elapsed * 1000); // fill the indirect buffer if we're using it if (useIndirect) { Bgfx.SetUniform(u_params, ¶mData, 3); Bgfx.SetComputeBuffer(0, indirectBuffer, ComputeBufferAccess.Write); Bgfx.Dispatch(0, indirectProgram); } // update particle positions Bgfx.SetComputeBuffer(0, prevPositionBuffer0, ComputeBufferAccess.Read); Bgfx.SetComputeBuffer(1, currPositionBuffer0, ComputeBufferAccess.Read); Bgfx.SetComputeBuffer(2, prevPositionBuffer1, ComputeBufferAccess.Write); Bgfx.SetComputeBuffer(3, currPositionBuffer1, ComputeBufferAccess.Write); Bgfx.SetUniform(u_params, ¶mData, 3); if (useIndirect) { Bgfx.Dispatch(0, updateInstancesProgram, indirectBuffer, 1); } else { Bgfx.Dispatch(0, updateInstancesProgram, paramData.DispatchSize); } // ping-pong the buffers for next frame Swap(ref currPositionBuffer0, ref currPositionBuffer1); Swap(ref prevPositionBuffer0, ref prevPositionBuffer1); // view transforms for particle rendering var viewMatrix = Matrix4x4.CreateLookAt(new Vector3(0.0f, 0.0f, -45.0f), -Vector3.UnitZ, Vector3.UnitY); var projMatrix = Matrix4x4.CreatePerspectiveFieldOfView((float)Math.PI / 4, (float)sample.WindowWidth / sample.WindowHeight, 0.1f, 10000.0f); Bgfx.SetViewTransform(0, &viewMatrix.M11, &projMatrix.M11); Bgfx.SetViewRect(0, 0, 0, sample.WindowWidth, sample.WindowHeight); // draw the particles Bgfx.SetVertexBuffer(vb); Bgfx.SetIndexBuffer(ib); Bgfx.SetInstanceDataBuffer(currPositionBuffer0, 0, paramData.DispatchSize * ThreadGroupUpdateSize); Bgfx.SetRenderState(RenderState.ColorWrite | RenderState.BlendAdd | RenderState.DepthTestAlways); if (useIndirect) { Bgfx.Submit(0, particleProgram, indirectBuffer); } else { Bgfx.Submit(0, particleProgram); } // done with frame Bgfx.Frame(); } // cleanup if (indirectSupported) { indirectProgram.Dispose(); indirectBuffer.Dispose(); } u_params.Dispose(); currPositionBuffer0.Dispose(); currPositionBuffer1.Dispose(); prevPositionBuffer0.Dispose(); prevPositionBuffer1.Dispose(); updateInstancesProgram.Dispose(); initInstancesProgram.Dispose(); particleProgram.Dispose(); ib.Dispose(); vb.Dispose(); }