Пример #1
0
        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);
        }
Пример #2
0
        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);
        }
Пример #3
0
        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;
        }
Пример #4
0
        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);
        }
Пример #5
0
    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, &paramData, 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, &paramData, 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, &paramData, 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();
    }