Created
December 7, 2014 00:58
-
-
Save thevaber/4a129c64ebdf512c8edf to your computer and use it in GitHub Desktop.
Possible bgfx issue
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
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