From 41b9b2988a6c9cc86940c68b7e572344836aed1e Mon Sep 17 00:00:00 2001 From: Larpon Date: Thu, 27 Jan 2022 20:16:00 +0100 Subject: [PATCH] examples: add port of simple triangle sokol sample (#13298) --- cmd/tools/modules/testing/common.v | 1 + examples/sokol/simple_shader_glsl/.gitignore | 1 + .../simple_shader_glsl/simple_shader.glsl | 36 ++++ .../sokol/simple_shader_glsl/simple_shader.v | 156 ++++++++++++++++++ examples/sokol/simple_shader_glsl/v.mod | 0 vlib/sokol/gfx/gfx_structs.c.v | 13 +- vlib/sokol/sapp/sapp.c.v | 19 +++ vlib/sokol/sapp/sapp_funcs.c.v | 9 + 8 files changed, 227 insertions(+), 8 deletions(-) create mode 100644 examples/sokol/simple_shader_glsl/.gitignore create mode 100644 examples/sokol/simple_shader_glsl/simple_shader.glsl create mode 100644 examples/sokol/simple_shader_glsl/simple_shader.v create mode 100644 examples/sokol/simple_shader_glsl/v.mod diff --git a/cmd/tools/modules/testing/common.v b/cmd/tools/modules/testing/common.v index 08badc1db..d11b8c982 100644 --- a/cmd/tools/modules/testing/common.v +++ b/cmd/tools/modules/testing/common.v @@ -167,6 +167,7 @@ pub fn new_test_session(_vargs string, will_compile bool) TestSession { if testing.github_job != 'sokol-shaders-can-be-compiled' { // These examples need .h files that are produced from the supplied .glsl files, // using by the shader compiler tools in https://github.com/floooh/sokol-tools-bin/archive/pre-feb2021-api-changes.tar.gz + skip_files << 'examples/sokol/simple_shader_glsl/simple_shader.v' skip_files << 'examples/sokol/02_cubes_glsl/cube_glsl.v' skip_files << 'examples/sokol/03_march_tracing_glsl/rt_glsl.v' skip_files << 'examples/sokol/04_multi_shader_glsl/rt_glsl.v' diff --git a/examples/sokol/simple_shader_glsl/.gitignore b/examples/sokol/simple_shader_glsl/.gitignore new file mode 100644 index 000000000..1fe4fe6f3 --- /dev/null +++ b/examples/sokol/simple_shader_glsl/.gitignore @@ -0,0 +1 @@ +simple_shader.h diff --git a/examples/sokol/simple_shader_glsl/simple_shader.glsl b/examples/sokol/simple_shader_glsl/simple_shader.glsl new file mode 100644 index 000000000..20aa0433b --- /dev/null +++ b/examples/sokol/simple_shader_glsl/simple_shader.glsl @@ -0,0 +1,36 @@ +// The following defines a vertex shader main function +@vs vs +in vec4 position; +in vec4 color0; + +out vec4 color; + +// You can add more functions here + +void main() { + gl_Position = position; + color = color0; +} +@end + +// The following defines a fragment shader main function +@fs fs +in vec4 color; +out vec4 frag_color; + +// You can add more functions here + +void main() { + frag_color = color; +} +@end + +// The value after `@program` and before `vs fs` decide a part of the name +// of the C function you need to define in V. The value entered is suffixed `_shader_desc` +// in the generated C code. Thus the name for this becomes: `simple_shader_desc`. +// In V it's signature then need to be defined as: +// `fn C.simple_shader_desc(gfx.Backend) &gfx.ShaderDesc`. See `simple_shader.v` for the define. +// +// Running `v shader -v .` in this dir will also show you brief information +// about how to use the compiled shader. +@program simple vs fs diff --git a/examples/sokol/simple_shader_glsl/simple_shader.v b/examples/sokol/simple_shader_glsl/simple_shader.v new file mode 100644 index 000000000..4fd8fb0fd --- /dev/null +++ b/examples/sokol/simple_shader_glsl/simple_shader.v @@ -0,0 +1,156 @@ +// Copyright(C) 2022 Lars Pontoppidan. All rights reserved. +// Use of this source code is governed by an MIT license file distributed with this software package +module main + +// Example shader triangle adapted to V from https://github.com/floooh/sokol-samples/blob/1f2ad36/sapp/triangle-sapp.c +import sokol.sapp +import sokol.gfx + +// Use `v shader` or `sokol-shdc` to generate the necessary `.h` file +// Using `v shader -v .` in this directory will show some additional +// info - and what you should include to make things work. +#flag -I @VMODROOT/. +#include "simple_shader.h" + +// simple_shader_desc is a C function declaration defined by +// the `@program` entry in the `simple_shader.glsl` shader file. +// When the shader is compiled this function name is generated +// by the shader compiler for easier inclusion of universal shader code +// in C (and V) code. +fn C.simple_shader_desc(gfx.Backend) &gfx.ShaderDesc + +// Vertex_t makes it possible to model vertex buffer data +// for use with the shader system +struct Vertex_t { + // Position + x f32 + y f32 + z f32 + // Color + r f32 + g f32 + b f32 + a f32 +} + +fn main() { + mut app := &App{ + width: 800 + height: 400 + pass_action: gfx.create_clear_pass(0.0, 0.0, 0.0, 1.0) // This will create a black color as a default pass (window background color) + } + app.run() +} + +struct App { + pass_action gfx.PassAction +mut: + width int + height int + shader_pipeline gfx.Pipeline + bind gfx.Bindings +} + +fn (mut a App) run() { + title := 'V Simple Shader Example' + desc := sapp.Desc{ + width: a.width + height: a.height + user_data: a + init_userdata_cb: init + frame_userdata_cb: frame + window_title: title.str + html5_canvas_name: title.str + cleanup_userdata_cb: cleanup + sample_count: 4 // Enables MSAA (Multisample anti-aliasing) x4 on rendered output, this can be omitted. + } + sapp.run(&desc) +} + +fn init(user_data voidptr) { + mut app := &App(user_data) + mut desc := sapp.create_desc() + + gfx.setup(&desc) + + // `vertices` defines a vertex buffer with 3 vertices + // with 3 position fields XYZ and 4 color components RGBA - + // for drawing a multi-colored triangle. + // + // C code: + // float vertices[] = { + // // Positions // Colors + // 0.0, 0.5, 0.5, 1.0, 0.0, 0.0, 1.0, + // 0.5, -0.5, 0.5, 0.0, 1.0, 0.0, 1.0, + // -0.5, -0.5, 0.5, 0.0, 0.0, 1.0, 1.0 + // }; + // + // Array entries in the following V code is the equivalent + // of the C code entry described above: + vertices := [ + Vertex_t{0.0, 0.5, 0.5, 1.0, 0.0, 0.0, 1.0}, + Vertex_t{0.5, -0.5, 0.5, 0.0, 1.0, 0.0, 1.0}, + Vertex_t{-0.5, -0.5, 0.5, 0.0, 0.0, 1.0, 1.0}, + ] + + // Create a vertex buffer with the 3 vertices defined above. + mut vertex_buffer_desc := gfx.BufferDesc{ + label: c'triangle-vertices' + } + unsafe { vmemset(&vertex_buffer_desc, 0, int(sizeof(vertex_buffer_desc))) } + + vertex_buffer_desc.size = usize(vertices.len * int(sizeof(Vertex_t))) + vertex_buffer_desc.data = gfx.Range{ + ptr: vertices.data + size: vertex_buffer_desc.size + } + + app.bind.vertex_buffers[0] = gfx.make_buffer(&vertex_buffer_desc) + + // Create shader from the code-generated sg_shader_desc (gfx.ShaderDesc in V). + // Note the function `C.simple_shader_desc()` (also defined above) - this is + // the function that returns the compiled shader code/desciption we have + // written in `simple_shader.glsl` and compiled with `v shader .` (`sokol-shdc`). + shader := gfx.make_shader(C.simple_shader_desc(gfx.query_backend())) + + // Create a pipeline object (default render states are fine for triangle) + mut pipeline_desc := gfx.PipelineDesc{} + // This will zero the memory used to store the pipeline in. + unsafe { vmemset(&pipeline_desc, 0, int(sizeof(pipeline_desc))) } + + // Populate the essential struct fields + pipeline_desc.shader = shader + // The vertex shader (`simple_shader.glsl`) takes 2 inputs: + // ```glsl + // in vec4 position; + // in vec4 color0; + // ``` + // Also note the naming of the C.ATTR_* used as indicies. + // They are the prefixed versions of the names of the input variables in the shader code. + // If they change in the shader code they will also change here. + pipeline_desc.layout.attrs[C.ATTR_vs_position].format = .float3 // x,y,z as f32 + pipeline_desc.layout.attrs[C.ATTR_vs_color0].format = .float4 // r, g, b, a as f32 + // The .label is optional but can aid debugging sokol shader related issues + // When things get complex - and you get tired :) + pipeline_desc.label = c'triangle-pipeline' + + app.shader_pipeline = gfx.make_pipeline(&pipeline_desc) +} + +fn cleanup(user_data voidptr) { + gfx.shutdown() +} + +fn frame(user_data voidptr) { + mut app := &App(user_data) + + gfx.begin_default_pass(&app.pass_action, sapp.width(), sapp.height()) + + gfx.apply_pipeline(app.shader_pipeline) + gfx.apply_bindings(&app.bind) + + gfx.draw(0, 3, 1) + + gfx.end_pass() + gfx.commit() +} diff --git a/examples/sokol/simple_shader_glsl/v.mod b/examples/sokol/simple_shader_glsl/v.mod new file mode 100644 index 000000000..e69de29bb diff --git a/vlib/sokol/gfx/gfx_structs.c.v b/vlib/sokol/gfx/gfx_structs.c.v index fb23a0033..b3ac95ce0 100644 --- a/vlib/sokol/gfx/gfx_structs.c.v +++ b/vlib/sokol/gfx/gfx_structs.c.v @@ -1,6 +1,7 @@ module gfx struct C.sg_desc { +pub mut: _start_canary u32 buffer_pool_size int image_pool_size int @@ -30,18 +31,14 @@ struct C.sg_desc { pub type Desc = C.sg_desc struct C.sg_context_desc { - /* - sg_pixel_format color_format; - sg_pixel_format depth_format; - int sample_count; - sg_wgpu_context_desc wgpu; - */ +pub mut: + color_format PixelFormat + depth_format PixelFormat sample_count int gl GLContextDesc metal MetalContextDesc d3d11 D3D11ContextDesc - color_format PixelFormat - depth_format PixelFormat + // TODO C.sg_wgpu_context_desc wgpu; } pub type ContextDesc = C.sg_context_desc diff --git a/vlib/sokol/sapp/sapp.c.v b/vlib/sokol/sapp/sapp.c.v index 17053237d..5302181ab 100644 --- a/vlib/sokol/sapp/sapp.c.v +++ b/vlib/sokol/sapp/sapp.c.v @@ -20,6 +20,7 @@ pub fn create_desc() gfx.Desc { render_target_view_cb: d3d11_get_render_target_view depth_stencil_view_cb: d3d11_get_depth_stencil_view } + return gfx.Desc{ context: gfx.ContextDesc{ metal: metal_desc @@ -48,6 +49,24 @@ pub fn height() int { return C.sapp_height() } +// color_format gets default framebuffer color pixel format +[inline] +pub fn color_format() int { + return C.sapp_color_format() +} + +// depth_format gets default framebuffer depth pixel format +[inline] +pub fn depth_format() int { + return C.sapp_depth_format() +} + +// sample_count gets default framebuffer sample count +[inline] +pub fn sample_count() int { + return C.sapp_sample_count() +} + // returns true when high_dpi was requested and actually running in a high-dpi scenario [inline] pub fn high_dpi() bool { diff --git a/vlib/sokol/sapp/sapp_funcs.c.v b/vlib/sokol/sapp/sapp_funcs.c.v index 4baa40c8d..6f8b45e7f 100644 --- a/vlib/sokol/sapp/sapp_funcs.c.v +++ b/vlib/sokol/sapp/sapp_funcs.c.v @@ -11,6 +11,15 @@ fn C.sapp_widthf() f32 fn C.sapp_height() int fn C.sapp_heightf() f32 +// get default framebuffer color pixel format +fn C.sapp_color_format() int + +// get default framebuffer depth pixel format +fn C.sapp_depth_format() int + +// get default framebuffer sample count +fn C.sapp_sample_count() int + // returns true when high_dpi was requested and actually running in a high-dpi scenario fn C.sapp_high_dpi() bool -- 2.30.2