vlang / v

Simple, fast, safe, compiled language for developing maintainable software. Compiles itself in <1s with zero library dependencies. Supports automatic C => V translation. https://vlang.io
MIT License
35.86k stars 2.17k forks source link

Issue with Sokol and STBI openning images. #22064

Open its-popplewell opened 3 months ago

its-popplewell commented 3 months ago

Describe the bug

See similar -> Issue #16670

I have once again run into issue -- I am just trying to render a square with a texture on it and I am getting an assertion issue: Assertion failed: (_sg.valid), function sg_make_image, file sokol_gfx.h, line 17546. Terminated by signal 6 (SIGABRT).

It seems like my image is loading properly (as I am printing out the result):

stbi.Image{
    width: 640
    height: 360
    nr_channels: 4
    ok: true
    data: 10f436000
    ext: 'png'
}

Reproduction Steps

Here is my code, it is largely adapted from the sokol examples.

// 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
import gg
import stbi

// 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.
#include "@VMODROOT/simple_shader.h" # # It should be generated with `v shader .`

// 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
    // uv
    u f32
    v f32
}

//
//
//

fn create_texture(imgpath string) (gfx.Image, gfx.Sampler) {
    data := stbi.load(imgpath, stbi.LoadParams{}) or {
        println('Failed to load image')
        panic(err)
    }

    println(data)

    mut img_desc := gfx.ImageDesc{
        width: data.width
        height: data.height
        pixel_format: .rgba8
        num_mipmaps: 0
        // wrap_u: .clamp_to_edge
        // wrap_v: .clamp_to_edge
        // min_filter: .linear
        // max_filter: .linear
        // usage: .dynamic
        label: &u8(0)
        d3d11_texture: 0
    }

    //println(tymeof(data.data[0]))

    // comment if .dynamic is enabled
    img_desc.data.subimage[0][0] = gfx.Range{
        ptr: data.data
        size: usize(data.width * data.height * 4)
    }

    println(img_desc)

    sg_img := gfx.make_image(&img_desc)

    //println(sg_img)

    mut smp_desc := gfx.SamplerDesc{
        min_filter: .linear
        mag_filter: .linear
        wrap_u: .clamp_to_edge
        wrap_v: .clamp_to_edge
    }

    sg_smp := gfx.make_sampler(&smp_desc)
    return sg_img, sg_smp
}

fn destroy_texture(sg_img gfx.Image) {
    gfx.destroy_image(sg_img)
}

//
//
//

fn main() {
    mut app := &App{
        width: 800
        height: 400
        pass_action: gfx.create_clear_pass_action(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
    texture         gfx.Image
    sampler         gfx.Sampler
    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 := unsafe { &App(user_data) }
    mut desc := sapp.create_desc()

    app.texture, app.sampler = create_texture('testimg.png')

    gfx.setup(&desc)

    vertices := [
        Vertex_t{-0.5, 0.5, 0.5, 1.0, 1.0, 0.0, 1.0, 0.0, 1.0},
        Vertex_t{0.5, -0.5, 0.5, 1.0, 1.0, 0.0, 1.0, 1.0, 0.0},
        Vertex_t{-0.5, -0.5, 0.5, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0},
        Vertex_t{0.5, 0.5, 0.5, 1.0, 1.0, 0.0, 1.0, 0.0, 1.0},
    ]

    indices := [
        u16(0),
        3,
        1,
        0,
        1,
        2,
    ]

    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)

    mut index_buffer_desc := gfx.BufferDesc{
        label: c'triangle-indices'
    }
    unsafe { vmemset(&index_buffer_desc, 0, int(sizeof(index_buffer_desc))) }

    index_buffer_desc.size = usize(indices.len * int(sizeof(u16)))
    index_buffer_desc.@type = .indexbuffer
    index_buffer_desc.data = gfx.Range{
        ptr: indices.data
        size: index_buffer_desc.size
    }

    app.bind.index_buffer = gfx.make_buffer(&index_buffer_desc)
    app.bind.fs.images[C.SLOT_tex] = app.texture
    app.bind.fs.samplers[C.SLOT_smp] = app.sampler

    shader := gfx.make_shader(C.simple_shader_desc(gfx.query_backend()))

    mut pipeline_desc := gfx.PipelineDesc{}
    unsafe { vmemset(&pipeline_desc, 0, int(sizeof(pipeline_desc))) }

    pipeline_desc.shader = shader
    pipeline_desc.layout.attrs[C.ATTR_vs_position].format = .float3
    pipeline_desc.layout.attrs[C.ATTR_vs_color0].format = .float4
    pipeline_desc.layout.attrs[C.ATTR_vs_texcoord].format = .float2
    pipeline_desc.index_type = .uint16
    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 := unsafe { &App(user_data) }

    pass := sapp.create_default_pass(app.pass_action)
    gfx.begin_pass(&pass)

    gfx.apply_pipeline(app.shader_pipeline)
    gfx.apply_bindings(&app.bind)

    gfx.draw(0, 6, 1)

    gfx.end_pass()
    gfx.commit()
}

and below is my shader code, which is also fairly basic.

// The following defines a vertex shader main function
@vs vs
in vec4 position;
in vec4 color0;
in vec2 texcoord;

out vec4 color;
out vec2 uv;

// You can add more functions here

void main() {
    gl_Position = position;
    color = color0;
    uv = texcoord;
}
@end

// The following defines a fragment shader main function
@fs fs
uniform texture2D tex;
uniform sampler smp;

in vec4 color;
in vec2 uv;
out vec4 frag_color;

// You can add more functions here

void main() {
    //frag_color = color;
    frag_color= texture(sampler2D(tex, smp), uv);
}
@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

There seem to be no resources to help with this and I am completely lost. Any help is appreciated.

Expected Behavior

I would like the code to render triangles with textures on them.

Current Behavior

The program crashes.

Possible Solution

I do not know.

Additional Information/Context

No response

V version

V 0.4.6 c412b9f

Environment details (OS name and version, etc.)

Mac OS -- 14.1.2, running an M1 Processor.

[!NOTE] You can use the 👍 reaction to increase the issue's priority for developers.

Please note that only the 👍 reaction to the issue itself counts as a vote. Other reactions and those to comments will not be taken into account.

phcreery commented 3 weeks ago

I ran into something similar. Interestingly, I was able to solve it by using sgl.Pipeline instead of gfx.Pipeline.