async def mainloop(): await main_async(canvas) while update_glfw_canvasses(): await asyncio.sleep(0.001) glfw.poll_events() loop.stop() glfw.terminate()
def better_event_loop(max_fps=100): """ A simple event loop that schedules draws. """ td = 1 / max_fps while update_glfw_canvasses(): # Determine next time to draw now = perf_counter() tnext = math.ceil(now / td) * td # Process events until it's time to draw while now < tnext: glfw.wait_events_timeout(tnext - now) now = perf_counter()
def test_glfw_canvas_render(): """Render an orange square ... in a glfw window.""" import glfw from wgpu.gui.glfw import update_glfw_canvasses, WgpuCanvas canvas = WgpuCanvas() # wgpu.utils.get_default_device() adapter = wgpu.request_adapter(canvas=canvas, power_preference="high-performance") device = adapter.request_device() draw_frame1 = _get_draw_function(device, canvas) frame_counter = 0 def draw_frame2(): nonlocal frame_counter frame_counter += 1 draw_frame1() canvas.request_draw(draw_frame2) # Give it a few rounds to start up for i in range(5): glfw.poll_events() update_glfw_canvasses() # There should have been exactly one draw now assert frame_counter == 1 # Ask for a lot of draws for i in range(5): canvas.request_draw() # Process evens for a while for i in range(5): glfw.poll_events() update_glfw_canvasses() # We should have had just one draw assert frame_counter == 2 # Change the canvase size canvas.set_logical_size(300, 200) canvas.set_logical_size(400, 300) for i in range(5): time.sleep(0.01) glfw.poll_events() update_glfw_canvasses() # We should have had just one draw assert frame_counter == 3 # canvas.close() glfw.poll_events()
def render_to_screen( device, vertex_shader, fragment_shader, pipeline_layout, bind_group, *, topology=wgpu.PrimitiveTopology.triangle_strip, ibo=None, vbos=None, vbo_views=None, indirect_buffer=None, color_attachment=None, depth_stencil_state=None, depth_stencil_attachment=None, renderpass_callback=lambda *args: None, ): """Render to a window on screen, for debugging purposes.""" import glfw from wgpu.gui.glfw import WgpuCanvas, update_glfw_canvasses vbos = vbos or [] vbo_views = vbo_views or [] # Setup canvas glfw.init() canvas = WgpuCanvas(title="wgpu test render with GLFW") vshader = device.create_shader_module(code=vertex_shader) fshader = device.create_shader_module(code=fragment_shader) render_pipeline = device.create_render_pipeline( layout=pipeline_layout, vertex_stage={"module": vshader, "entry_point": "main"}, fragment_stage={"module": fshader, "entry_point": "main"}, primitive_topology=topology, rasterization_state={ "front_face": wgpu.FrontFace.ccw, "cull_mode": wgpu.CullMode.none, "depth_bias": 0, "depth_bias_slope_scale": 0.0, "depth_bias_clamp": 0.0, }, color_states=[ { "format": wgpu.TextureFormat.bgra8unorm_srgb, "alpha_blend": ( wgpu.BlendFactor.one, wgpu.BlendFactor.zero, wgpu.BlendOperation.add, ), "color_blend": ( wgpu.BlendFactor.one, wgpu.BlendFactor.zero, wgpu.BlendOperation.add, ), "write_mask": wgpu.ColorWrite.ALL, } ], depth_stencil_state=depth_stencil_state, vertex_state={ "index_format": wgpu.IndexFormat.uint32, "vertex_buffers": vbo_views, }, sample_count=1, sample_mask=0xFFFFFFFF, alpha_to_coverage_enabled=False, ) swap_chain = device.configure_swap_chain( canvas, wgpu.TextureFormat.bgra8unorm_srgb, wgpu.TextureUsage.OUTPUT_ATTACHMENT ) def draw_frame(): with swap_chain as current_texture_view: command_encoder = device.create_command_encoder() ca = color_attachment or { "resolve_target": None, "load_value": (0, 0, 0, 0), # LoadOp.load or color "store_op": wgpu.StoreOp.store, } ca["attachment"] = current_texture_view render_pass = command_encoder.begin_render_pass( color_attachments=[ca], depth_stencil_attachment=depth_stencil_attachment, occlusion_query_set=None, ) render_pass.push_debug_group("foo") render_pass.insert_debug_marker("setting pipeline") render_pass.set_pipeline(render_pipeline) render_pass.insert_debug_marker("setting bind group") render_pass.set_bind_group( 0, bind_group, [], 0, 999999 ) # last 2 elements not used for slot, vbo in enumerate(vbos): render_pass.insert_debug_marker(f"setting vbo {slot}") render_pass.set_vertex_buffer(slot, vbo, 0, vbo.size) render_pass.insert_debug_marker("invoking callback") renderpass_callback(render_pass) render_pass.insert_debug_marker("draw!") if ibo is None: if indirect_buffer is None: render_pass.draw(4, 1, 0, 0) else: render_pass.draw_indirect(indirect_buffer, 0) else: render_pass.set_index_buffer(ibo, 0, ibo.size) if indirect_buffer is None: render_pass.draw_indexed(6, 1, 0, 0, 0) else: render_pass.draw_indexed_indirect(indirect_buffer, 0) render_pass.pop_debug_group() render_pass.end_pass() device.default_queue.submit([command_encoder.finish()]) canvas.request_draw(draw_frame) # Enter main loop while update_glfw_canvasses(): glfw.poll_events() glfw.terminate()
def simple_event_loop(): """ A real simple event loop, but it keeps the CPU busy. """ while update_glfw_canvasses(): glfw.poll_events()
def draw_frame(): with swap_chain as current_texture_view: command_encoder = device.create_command_encoder() render_pass = command_encoder.begin_render_pass( color_attachments=[ { "attachment": current_texture_view, "resolve_target": None, "load_value": (0, 0, 0, 1), # LoadOp.load or color "store_op": wgpu.StoreOp.store, } ], ) render_pass.set_pipeline(render_pipeline) render_pass.set_bind_group( 0, bind_group, [], 0, 999999 ) # last 2 elements not used render_pass.draw(3, 1, 0, 0) render_pass.end_pass() device.default_queue.submit([command_encoder.finish()]) canvas.request_draw(draw_frame) while update_glfw_canvasses(): glfw.poll_events() glfw.terminate()