Segfault when using C3D_DrawArrays()

Discussion in '3DS - Homebrew Development and Emulators' started by StuntHacks, Sep 13, 2017.

  1. StuntHacks
    OP

    StuntHacks Member

    Newcomer
    22
    1
    Jan 19, 2017
    Austria
    Vienna
    Hi,

    I am currently trying to draw a rectangle using Citro3D (I do not want to use some library like sf2d or pp2d) but when I call `C3D_DrawArrays()`, I get a segmentation fault. When I remove this line, the program runs fine, it just doesn't render anything (obviously).

    Here is the code where it crashes:

    Code:
            m3d::Color color(0, 0, 0, 255);
    
            m3d::Vertex* vertices = new Vertex[4];
    
            if (vertices == nullptr) return;
    
            vertices[0].position = (m3d::Vector3f){(float) 10,                       (float) 20,   0.5f};
            vertices[1].position = (m3d::Vector3f){(float) 10 + m_width,     (float) 20,   0.5f};
            vertices[2].position = (m3d::Vector3f){(float) 10,                       (float) 20 + m_height, 0.5f};
            vertices[3].position = (m3d::Vector3f){(float) 10 + m_width,     (float) 20 + m_height, 0.5f};
    
            vertices[0].color = color.getRgba8();
            vertices[1].color = vertices[0].color;
            vertices[2].color = vertices[0].color;
            vertices[3].color = vertices[0].color;
    
            C3D_TexEnv* env = C3D_GetTexEnv(0);
            C3D_TexEnvSrc(env, C3D_Both, GPU_PRIMARY_COLOR, 0, 0);
            C3D_TexEnvOp(env, C3D_Both, 0, 0, 0);
            C3D_TexEnvFunc(env, C3D_Both, GPU_REPLACE);
    
            C3D_AttrInfo* attrInfo = C3D_GetAttrInfo();
            AttrInfo_Init(attrInfo);
            AttrInfo_AddLoader(attrInfo, 0, GPU_FLOAT, 3);
            AttrInfo_AddLoader(attrInfo, 1, GPU_UNSIGNED_BYTE, 4);
    
            C3D_BufInfo* bufInfo = C3D_GetBufInfo();
            BufInfo_Init(bufInfo);
            BufInfo_Add(bufInfo, &vertices, sizeof(m3d::Vertex), 2, 0x10);
            C3D_DrawArrays(GPU_TRIANGLE_STRIP, 0, 4);
    The code I use to start the frame looks like this:
    Code:
            C3D_FrameBegin(C3D_FRAME_SYNCDRAW);
            C3D_FrameDrawOn(m_targetBottom->getRenderTarget());
    Does anybody know what I'm doing wrong?

    ~ StuntHacks
     
  2. Essometer

    Essometer GBAtemp Fan

    Member
    312
    220
    Oct 22, 2010
    Germany
    Enger
    I am not an expert in any way so this is just a guess, but try to replace
    Code:
    BufInfo_Add(bufInfo, &vertices, sizeof(m3d::Vertex), 2, 0x10);
    with
    Code:
    BufInfo_Add(bufInfo, &vertices, sizeof(vertices), 2, 0x10);
    I have no experience with Citro3D, but it looks similar to openGl. Are you sure that the coordinate for your rectangle uses Non Normalized Coordinates?

    One last thing, I think the argument behind the size is the number of vertices, so it should be 4 instead of 2? Like I said, just a guess.
     
    Last edited by Essometer, Sep 13, 2017
  3. StuntHacks
    OP

    StuntHacks Member

    Newcomer
    22
    1
    Jan 19, 2017
    Austria
    Vienna
    I tried both things, even in different combinations, nothing worked sadly...

    But what exactly do you mean by Non Normalized Coordinates? Sorry if this is a noob question, I'm kinda new to Citro3D/Graphical rendering of that kind.
     
  4. Essometer

    Essometer GBAtemp Fan

    Member
    312
    220
    Oct 22, 2010
    Germany
    Enger
    In OpenGL you have a Viewport which is basically the window where thing can be rendered on screen. The
    Viewport uses a 3D coordinate system where 0,0,0 is in the middle of the window and the axis go from 1 to -1.

    Normalized Coordinate mean that the coords you use to specify the point on the screen need to be between 1 and -1.

    Not sure if Citro works this way thou. Also I don't think this would produce a Segfault.

    EDIT: Just looked at the programm example, they use Non Normalized Coordinate as well, probably because the Viewport is
    always the 3DS Display and has always a size of the screen resolution.
     
    Last edited by Essometer, Sep 13, 2017
  5. elhobbs

    elhobbs GBAtemp Advanced Fan

    Member
    811
    299
    Jul 28, 2008
    United States
    Vbo data needs to be in linear (or vram, but linear is easier). You need to use linearAlloc instead new/malloc.
    https://github.com/devkitPro/3ds-examples/blob/master/graphics/gpu/simple_tri/source/main.c
     
  6. StuntHacks
    OP

    StuntHacks Member

    Newcomer
    22
    1
    Jan 19, 2017
    Austria
    Vienna
    I checked, and the coordinates are fine. I now even tried to hardcode them, it still doesn't work... There is still the possibility of immediate rendering mode but that completely ruins running the app in citra.

    — Posts automatically merged - Please don't double post! —

    Okay so I tried doing it like that now:
    Code:
    m3d::Vertex* vertices = linearAlloc(4 * sizeof(m3d::Vertex));
    And now I am getting an `invalid conversion from 'void*' to 'm3d::Vertex*'` error. I am probably just missing something very simple but I really don't get what I'm doing wrong.
     
  7. Essometer

    Essometer GBAtemp Fan

    Member
    312
    220
    Oct 22, 2010
    Germany
    Enger
    Code:
    linearAlloc
    returns a void pointer which you can't assign to a vertex pointer. In the example
    they copy the vertex data with
    Code:
    memcopy
    to the allocated memory.
     
  8. StuntHacks
    OP

    StuntHacks Member

    Newcomer
    22
    1
    Jan 19, 2017
    Austria
    Vienna
    I noticed that as well, probably should have posted that. However, now fixed it to:
    Code:
    m3d::Vertex* vertices = (m3d::Vertex*) linearAlloc(4 * sizeof(m3d::Vertex));
    And yet it still crashes...
     
  9. TarableCode

    TarableCode GBAtemp Regular

    Member
    157
    143
    Mar 2, 2016
    Canada
    In Bufinfo_Add you're passing a pointer to a pointer, try:
    Code:
    BufInfo_Add(bufInfo, vertices, sizeof(m3d::Vertex), 2, 0x10);
    
     
    Coto likes this.
  10. StuntHacks
    OP

    StuntHacks Member

    Newcomer
    22
    1
    Jan 19, 2017
    Austria
    Vienna
    I tried that, it still crashes.

    My current code is the following:
    Code:
            m3d::Color color(255, 0, 0, 255);
    
            m3d::Vertex* vertices = (m3d::Vertex*) linearAlloc(4 * sizeof(m3d::Vertex));
    
            if (vertices == nullptr) return;
    
            vertices[0].position = (m3d::Vector3f){(float) 10,                       (float) 20,   0.5f};
            vertices[1].position = (m3d::Vector3f){(float) 10 + m_width,     (float) 20,   0.5f};
            vertices[2].position = (m3d::Vector3f){(float) 10,                       (float) 20 + m_height, 0.5f};
            vertices[3].position = (m3d::Vector3f){(float) 10 + m_width,     (float) 20 + m_height, 0.5f};
    
            vertices[0].color = color.getRgba8();
            vertices[1].color = vertices[0].color;
            vertices[2].color = vertices[0].color;
            vertices[3].color = vertices[0].color;
    
            C3D_TexEnv* env = C3D_GetTexEnv(0);
            C3D_TexEnvSrc(env, C3D_Both, GPU_PRIMARY_COLOR, 0, 0);
            C3D_TexEnvOp(env, C3D_Both, 0, 0, 0);
            C3D_TexEnvFunc(env, C3D_Both, GPU_REPLACE);
    
            C3D_AttrInfo* attrInfo = C3D_GetAttrInfo();
            AttrInfo_Init(attrInfo);
            AttrInfo_AddLoader(attrInfo, 0, GPU_FLOAT, 3);
            AttrInfo_AddLoader(attrInfo, 1, GPU_UNSIGNED_BYTE, 4);
    
            C3D_BufInfo* bufInfo = C3D_GetBufInfo();
            BufInfo_Init(bufInfo);
            BufInfo_Add(bufInfo, vertices, sizeof(m3d::Vertex), 2, 0x10);
            C3D_SetBufInfo(bufInfo);
            C3D_DrawArrays(GPU_TRIANGLE_STRIP, 0, 3);
     
  11. TarableCode

    TarableCode GBAtemp Regular

    Member
    157
    143
    Mar 2, 2016
    Canada
  12. StuntHacks
    OP

    StuntHacks Member

    Newcomer
    22
    1
    Jan 19, 2017
    Austria
    Vienna
    Well, if I get rid of BufInfo_Init, citra prints a `unknown GetPointer` error. And regardless how I try it, it crashes again and again, each time with a segfault.

    On a sidenote, thanks for your patient help everyone :)
     
  13. TarableCode

    TarableCode GBAtemp Regular

    Member
    157
    143
    Mar 2, 2016
    Canada
    Oh crap sorry, I had BufInfo_Init in my own code and just completely missed it.
    Perhaps you could paste your whole code, it might help to get an idea if the problem lies elsewhere.

    Does it run on hardware?
    It might just be citra being ornery, often times I'd run into that with code that worked on hardware but barfed in an emulator.
     
  14. StuntHacks
    OP

    StuntHacks Member

    Newcomer
    22
    1
    Jan 19, 2017
    Austria
    Vienna
    I just tested it on real hardware. It didn't crash but it looked... weird...
    Warning: Spoilers inside!

    Okay so now the code part:
    The basic of how I am trying to render the rectangle is this: I have a m3d::Screen-object, which renders the screen, and a m3d::Rectangle object, which is a child of the abstract class m3d::Drawable and draws only the rectangle.

    Here is the relevant code of the Screen:
    screen.hpp
    screen.cpp
    rectangle.hpp
    rectangle.cpp
    vertex.hpp
    And finally, the main.cpp:
    main.cpp
     
  15. TarableCode

    TarableCode GBAtemp Regular

    Member
    157
    143
    Mar 2, 2016
    Canada
    Maybe my brain is fuzzy and I'm missing it but I don't see where you load and bind a shader program or create the render targets.
     
  16. StuntHacks
    OP

    StuntHacks Member

    Newcomer
    22
    1
    Jan 19, 2017
    Austria
    Vienna
    I am creating the shader targets in the constructor of the Screen-class, however I am not binding a shader program. Is this required? Most software I have seen online use a file called "shader.shbin" to do that, is that some public file everyone should use or is it just a naming convention and the people have to write it themselves? Because if that's the case, I'm not able to find a file called like that in any repository using that file.

    EDIT: Here the code of my RenderTarget class:
    renderTarget.hpp
    renderTarget.cpp
     
    Last edited by StuntHacks, Sep 13, 2017
  17. TarableCode

    TarableCode GBAtemp Regular

    Member
    157
    143
    Mar 2, 2016
    Canada
    If you have a shader source file named "vshader.v.pica" it will be compiled during the build process and be available within your app using an auto generated header file.
    A good example might be https://github.com/devkitPro/3ds-examples/tree/master/graphics/gpu/gpusprites to take a look at since that's where I started from and it helped me quite a bit.

    Afaik you do need to bind a shader program for anything 3d related to work.
     
  18. StuntHacks
    OP

    StuntHacks Member

    Newcomer
    22
    1
    Jan 19, 2017
    Austria
    Vienna
    Thank you so much, it doesn't crash anymore. However, in citra it doesn't render anything at all and on my 3DS it looks like, well, this (I hardcoded the clear color to white since the last code change, so don't be confused by that):
    Warning: Spoilers inside!
    Those strange line do in fact have the color I hardcoded into the rectangle class, however it doesn't look like a rectangle to me. I'm probably missing something but I don't really get what i'm doing wrong.
     
  19. TarableCode

    TarableCode GBAtemp Regular

    Member
    157
    143
    Mar 2, 2016
    Canada
  20. StuntHacks
    OP

    StuntHacks Member

    Newcomer
    22
    1
    Jan 19, 2017
    Austria
    Vienna
    Please forgive me if I'm just dumb right now but I just don't understand what's going on. Now, I decided I'd just draw a single triangle on the screen. But instead of that, nothing gets drawn, neither on hardware nor in citra.

    Here is the current drawing code:
    Code:
            m3d::Color color(0, 255, 0, 255);
    
            m3d::Vertex* vertices = (m3d::Vertex*) linearAlloc(3 * sizeof(m3d::Vertex));
    
            if (vertices == nullptr) return;
    
            vertices[0].position = (m3d::Vector3f){(float) -0.7, (float) -0.7, 0.5f};
            vertices[1].position = (m3d::Vector3f){(float) -0.7, (float) 0.7, 0.5f};
            vertices[2].position = (m3d::Vector3f){(float) 0.7, (float) 0.5, 0.5f};
    
            vertices[0].color = color.getRgba8();
            vertices[1].color = vertices[0].color;
            vertices[2].color = vertices[0].color;
    
            C3D_TexEnv* env = C3D_GetTexEnv(0);
            C3D_TexEnvSrc(env, C3D_Both, GPU_PRIMARY_COLOR, 0, 0);
            C3D_TexEnvOp(env, C3D_Both, 0, 0, 0);
            C3D_TexEnvFunc(env, C3D_Both, GPU_REPLACE);
    
            C3D_AttrInfo* attrInfo = C3D_GetAttrInfo();
            AttrInfo_Init(attrInfo);
            AttrInfo_AddLoader(attrInfo, 0, GPU_FLOAT, 3);
            AttrInfo_AddLoader(attrInfo, 1, GPU_UNSIGNED_BYTE, 4);
    
            C3D_BufInfo* bufInfo = C3D_GetBufInfo();
            BufInfo_Init(bufInfo);
            BufInfo_Add(bufInfo, vertices, sizeof(m3d::Vertex), 2, 0x10);
            C3D_DrawArrays(GPU_TRIANGLES, 0, 3);