Skip to content

Instantly share code, notes, and snippets.

@thevaber
Created December 7, 2014 00:58
Show Gist options
  • Save thevaber/4a129c64ebdf512c8edf to your computer and use it in GitHub Desktop.
Save thevaber/4a129c64ebdf512c8edf to your computer and use it in GitHub Desktop.
Possible bgfx issue
/*
bgfx transient buffer issue
If in one (or more; slightly different behavior, see comments in main loop) frames a draw call is
submitted which uses a transient vertex buffer (even with one vertex and zeroed state), and in
subsequent frames different draw call with transient buffer is made using the same shader program
but different vertex type (vertex decl), it does not get rendered correctly - vertex data seems
to be corrupted (wrong vertex positions, colors,...; possibly not visible at all if the wrong
positions are out of view bounds I think). Only the first draw call in each frame gets corrupted
in such way.
This is a rather minimal repro code using SDL2 (embedded shaders for OpenGL renderer).
Correct image is a triangle with red, green and blue colors (clockwise) roughly in center of the window
*/
#include <SDL2/SDL.h>
#include <bgfx.h>
#include <bgfxplatform.h>
#include <bx/fpumath.h>
/*
varying.def.sc:
vec4 v_color0 : COLOR0 = vec4(1.0, 0.0, 0.0, 1.0);
vec3 a_position : POSITION;
vec4 a_color0 : COLOR0;
*/
/*
vertex shader:
$input a_position, a_color0
$output v_color0
#include "bgfx_shader.sh"
void main()
{
gl_Position = mul(u_modelViewProj, vec4(a_position, 1.0) );
v_color0 = a_color0;
}
*/
static const uint8_t vs_bin[325] =
{
0x56, 0x53, 0x48, 0x03, 0xa4, 0x8b, 0xef, 0x49, 0x01, 0x00, 0x0f, 0x75, 0x5f, 0x6d, 0x6f, 0x64, // VSH....I...u_mod
0x65, 0x6c, 0x56, 0x69, 0x65, 0x77, 0x50, 0x72, 0x6f, 0x6a, 0x09, 0x01, 0x00, 0x00, 0x01, 0x00, // elViewProj......
0x20, 0x01, 0x00, 0x00, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x68, 0x69, // ...attribute hi
0x67, 0x68, 0x70, 0x20, 0x76, 0x65, 0x63, 0x34, 0x20, 0x61, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, // ghp vec4 a_color
0x30, 0x3b, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x68, 0x69, 0x67, // 0;.attribute hig
0x68, 0x70, 0x20, 0x76, 0x65, 0x63, 0x33, 0x20, 0x61, 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, // hp vec3 a_positi
0x6f, 0x6e, 0x3b, 0x0a, 0x76, 0x61, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x68, 0x69, 0x67, 0x68, // on;.varying high
0x70, 0x20, 0x76, 0x65, 0x63, 0x34, 0x20, 0x76, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x30, 0x3b, // p vec4 v_color0;
0x0a, 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x68, 0x69, 0x67, 0x68, 0x70, 0x20, 0x6d, // .uniform highp m
0x61, 0x74, 0x34, 0x20, 0x75, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x56, 0x69, 0x65, 0x77, 0x50, // at4 u_modelViewP
0x72, 0x6f, 0x6a, 0x3b, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x20, 0x28, // roj;.void main (
0x29, 0x0a, 0x7b, 0x0a, 0x20, 0x20, 0x68, 0x69, 0x67, 0x68, 0x70, 0x20, 0x76, 0x65, 0x63, 0x34, // ).{. highp vec4
0x20, 0x74, 0x6d, 0x70, 0x76, 0x61, 0x72, 0x5f, 0x31, 0x3b, 0x0a, 0x20, 0x20, 0x74, 0x6d, 0x70, // tmpvar_1;. tmp
0x76, 0x61, 0x72, 0x5f, 0x31, 0x2e, 0x77, 0x20, 0x3d, 0x20, 0x31, 0x2e, 0x30, 0x3b, 0x0a, 0x20, // var_1.w = 1.0;.
0x20, 0x74, 0x6d, 0x70, 0x76, 0x61, 0x72, 0x5f, 0x31, 0x2e, 0x78, 0x79, 0x7a, 0x20, 0x3d, 0x20, // tmpvar_1.xyz =
0x61, 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3b, 0x0a, 0x20, 0x20, 0x67, 0x6c, // a_position;. gl
0x5f, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x28, 0x75, 0x5f, 0x6d, // _Position = (u_m
0x6f, 0x64, 0x65, 0x6c, 0x56, 0x69, 0x65, 0x77, 0x50, 0x72, 0x6f, 0x6a, 0x20, 0x2a, 0x20, 0x74, // odelViewProj * t
0x6d, 0x70, 0x76, 0x61, 0x72, 0x5f, 0x31, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x76, 0x5f, 0x63, 0x6f, // mpvar_1);. v_co
0x6c, 0x6f, 0x72, 0x30, 0x20, 0x3d, 0x20, 0x61, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x30, 0x3b, // lor0 = a_color0;
0x0a, 0x7d, 0x0a, 0x0a, 0x00, // .}...
};
/*
fragment shader:
$input v_color0
#include "bgfx_shader.sh"
void main()
{
gl_FragColor = v_color0;
}
*/
static const uint8_t fs_bin[89] =
{
0x46, 0x53, 0x48, 0x03, 0xa4, 0x8b, 0xef, 0x49, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x76, 0x61, // FSH....I..J...va
0x72, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x68, 0x69, 0x67, 0x68, 0x70, 0x20, 0x76, 0x65, 0x63, 0x34, // rying highp vec4
0x20, 0x76, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x30, 0x3b, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, // v_color0;.void
0x6d, 0x61, 0x69, 0x6e, 0x20, 0x28, 0x29, 0x0a, 0x7b, 0x0a, 0x20, 0x20, 0x67, 0x6c, 0x5f, 0x46, // main ().{. gl_F
0x72, 0x61, 0x67, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x76, 0x5f, 0x63, 0x6f, 0x6c, // ragColor = v_col
0x6f, 0x72, 0x30, 0x3b, 0x0a, 0x7d, 0x0a, 0x0a, 0x00, // or0;.}...
};
struct vertex_t {
float x, y, z;
uint32_t abgr;
static void init() {
decl.begin().add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float).add(bgfx::Attrib::Color0, 4, bgfx::AttribType::Uint8, true).end();
}
static bgfx::VertexDecl decl;
};
bgfx::VertexDecl vertex_t::decl;
struct vertex_with_uv_t {
float x, y, z;
uint32_t abgr;
float u, v;
static void init() {
decl.begin().add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float).add(bgfx::Attrib::Color0, 4, bgfx::AttribType::Uint8, true).add(bgfx::Attrib::TexCoord0, 2, bgfx::AttribType::Float).end();
}
static bgfx::VertexDecl decl;
};
bgfx::VertexDecl vertex_with_uv_t::decl;
int main(int argc, char** argv) {
const int res_x = 1280, res_y = 1024;
SDL_Init(SDL_INIT_VIDEO);
SDL_Window* window = SDL_CreateWindow("test", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, res_x, res_y, SDL_WINDOW_SHOWN);
bgfx::sdlSetWindow(window);
bgfx::init(bgfx::RendererType::OpenGL);
bgfx::reset(res_x, res_y);
bgfx::ShaderHandle vsh = bgfx::createShader(bgfx::makeRef(vs_bin, sizeof(vs_bin)));
bgfx::ShaderHandle fsh = bgfx::createShader(bgfx::makeRef(fs_bin, sizeof(fs_bin)));
bgfx::ProgramHandle program = bgfx::createProgram(vsh, fsh, true);
vertex_t::init();
vertex_with_uv_t::init();
float view[16];
bx::mtxIdentity( view );
float proj[16];
bx::mtxOrtho(proj, 0.0f, 300.0f, 300.0f, 0.0f, -100.0f, 100.0f);
for (int i = 0; i < 2; i++) {
bgfx::setViewTransform(i, view, proj);
bgfx::setViewRect(i, 0, 0, res_x, res_y);
}
int frame_num = 0;
while(1) {
frame_num++;
SDL_Event event;
while (SDL_PollEvent(&event)) {}
// frame_num <= 1 (ie. single frame) flickers between correct and incorrect display (on other test machine, the incorrect triangle doesn't display at all, so it flickers between correct and blank; possibly just the corrupted vertex data being out of view)
// frame_num <= 2 (ie. two frames) only displays incorrect
// frame_num == 0 (never true) displays only correct
// frame_num == 3 (and numbers greater than 3) displays only correct
if (frame_num <= 1)
{
bgfx::setViewClear(0, BGFX_CLEAR_COLOR_BIT, 0x222222ff);
bgfx::setViewClear(1, BGFX_CLEAR_NONE);
typedef vertex_t vertex_type;
if (bgfx::checkAvailTransientVertexBuffer(3, vertex_t::decl)) {
// Vertex count or primitive type doesn't seem to matter, anything seems to trigger the bug
vertex_type v = {0};
if (bgfx::checkAvailTransientVertexBuffer(1, vertex_type::decl)) {
bgfx::TransientVertexBuffer transient_buffer;
bgfx::allocTransientVertexBuffer(&transient_buffer, 1, vertex_type::decl);
memcpy(transient_buffer.data, &v, 1 * sizeof(vertex_type));
bgfx::setProgram(program);
bgfx::setState(BGFX_STATE_RGB_WRITE | BGFX_STATE_PT_POINTS); // (zero state also triggers it)
bgfx::setVertexBuffer(&transient_buffer);
bgfx::submit(0);
}
}
} else {
for ( int i = 0; i < 1; i++ ) { // Change to i < 2 to see that only the first draw call gets corrupted
bgfx::setViewClear( 0, BGFX_CLEAR_NONE );
bgfx::setViewClear( 1, BGFX_CLEAR_COLOR_BIT, 0x222222ff );
typedef vertex_with_uv_t vertex_type;
vertex_type v[3];
v[0].x = 100;
v[0].y = 100;
v[0].z = 0;
v[0].u = 0.0f;
v[0].v = 0.0f;
v[0].abgr = 0xff0000ff;
v[1].x = 200;
v[1].y = 100;
v[1].z = 0;
v[1].u = 0.0f;
v[1].v = 0.0f;
v[1].abgr = 0xff00ff00;
v[2].x = 200;
v[2].y = 200;
v[2].z = 0;
v[2].u = 0.0f;
v[2].v = 0.0f;
v[2].abgr = 0xffff0000;
if ( bgfx::checkAvailTransientVertexBuffer( 3, vertex_type::decl ) ) {
bgfx::TransientVertexBuffer transient_buffer;
bgfx::allocTransientVertexBuffer( &transient_buffer, 3, vertex_type::decl );
memcpy( transient_buffer.data, v, 3 * sizeof( vertex_type ) );
bgfx::setProgram( program );
bgfx::setState( BGFX_STATE_RGB_WRITE );
bgfx::setVertexBuffer( &transient_buffer );
bgfx::submit( 1 );
}
}
}
bgfx::frame();
}
bgfx::shutdown();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment