From 532663a9587bf2df65af37c78c367f27c0a1fb55 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Tue, 23 Oct 2018 17:00:43 +0700 Subject: [PATCH] render calls on the main thread only --- headers/enduro2d/core/_core.hpp | 2 + headers/enduro2d/core/render.hpp | 10 +- samples/sources/sample_02/sample_02.cpp | 4 +- .../core/render_impl/render_opengl.cpp | 121 +++++++++++++++--- 4 files changed, 113 insertions(+), 24 deletions(-) diff --git a/headers/enduro2d/core/_core.hpp b/headers/enduro2d/core/_core.hpp index 2159256e..235d253f 100644 --- a/headers/enduro2d/core/_core.hpp +++ b/headers/enduro2d/core/_core.hpp @@ -21,6 +21,8 @@ namespace e2d class texture; class index_buffer; class vertex_buffer; + class render_target; + class pixel_declaration; class index_declaration; class vertex_declaration; class vfs; diff --git a/headers/enduro2d/core/render.hpp b/headers/enduro2d/core/render.hpp index 2e83012d..6811da16 100644 --- a/headers/enduro2d/core/render.hpp +++ b/headers/enduro2d/core/render.hpp @@ -712,8 +712,12 @@ namespace e2d ~render() noexcept final; shader_ptr create_shader( - input_stream_uptr vertex_stream, - input_stream_uptr fragment_stream); + const str& vertex_source, + const str& fragment_source); + + shader_ptr create_shader( + const input_stream_uptr& vertex_stream, + const input_stream_uptr& fragment_stream); texture_ptr create_texture( const image& image); @@ -753,7 +757,7 @@ namespace e2d render& clear_depth_buffer(f32 value) noexcept; render& clear_stencil_buffer(u8 value) noexcept; render& clear_color_buffer(const color& value) noexcept; - render& set_viewport(u32 x, u32 y, u32 w, u32 h) noexcept; + render& set_viewport(const v2u& pos, const v2u& size) noexcept; render& set_render_target(const render_target_ptr& rt) noexcept; private: class internal_state; diff --git a/samples/sources/sample_02/sample_02.cpp b/samples/sources/sample_02/sample_02.cpp index 6da610ba..2ab0d07d 100644 --- a/samples/sources/sample_02/sample_02.cpp +++ b/samples/sources/sample_02/sample_02.cpp @@ -214,7 +214,7 @@ int e2d_main() { the() .set_render_target(rt) - .set_viewport(0, 0, rt->size().x, rt->size().y) + .set_viewport(v2u::zero(), rt->size()) .clear_depth_buffer(1.f) .clear_stencil_buffer(0) .clear_color_buffer({0.f, 0.4f, 0.f, 1.f}) @@ -228,7 +228,7 @@ int e2d_main() { the() .set_render_target(nullptr) - .set_viewport(0, 0, the().real_size().x, the().real_size().y) + .set_viewport(v2u::zero(), the().real_size()) .clear_depth_buffer(1.f) .clear_stencil_buffer(0) .clear_color_buffer({1.f, 0.4f, 0.f, 1.f}) diff --git a/sources/enduro2d/core/render_impl/render_opengl.cpp b/sources/enduro2d/core/render_impl/render_opengl.cpp index 465c2279..b9633dc2 100644 --- a/sources/enduro2d/core/render_impl/render_opengl.cpp +++ b/sources/enduro2d/core/render_impl/render_opengl.cpp @@ -437,49 +437,78 @@ namespace e2d // render // - render::render(debug& debug, window& window) - : state_(new internal_state(debug, window)) { + render::render(debug& ndebug, window& nwindow) + : state_(new internal_state(ndebug, nwindow)) + { + E2D_ASSERT( + std::this_thread::get_id() == + modules::main_thread()); + if ( glewInit() != GLEW_OK ) { throw bad_render_operation(); } - opengl::gl_trace_info(debug); - opengl::gl_trace_limits(debug); + + opengl::gl_trace_info(ndebug); + opengl::gl_trace_limits(ndebug); + GL_CHECK_CODE(state_->dbg(), glPixelStorei(GL_PACK_ALIGNMENT, 1)); GL_CHECK_CODE(state_->dbg(), glPixelStorei(GL_UNPACK_ALIGNMENT, 1)); } render::~render() noexcept = default; shader_ptr render::create_shader( - input_stream_uptr vertex, - input_stream_uptr fragment) + const str& vertex_source, + const str& fragment_source) { - str vertex_str; - gl_shader_id vs = streams::try_read_tail(vertex_str, vertex) - ? gl_compile_shader(state_->dbg(), vertex_str, GL_VERTEX_SHADER) - : gl_shader_id(state_->dbg()); + E2D_ASSERT( + std::this_thread::get_id() == + modules::main_thread()); + + gl_shader_id vs = gl_compile_shader( + state_->dbg(), vertex_source, GL_VERTEX_SHADER); if ( vs.empty() ) { return nullptr; } - str fragment_str; - gl_shader_id fs = streams::try_read_tail(fragment_str, fragment) - ? gl_compile_shader(state_->dbg(), fragment_str, GL_FRAGMENT_SHADER) - : gl_shader_id(state_->dbg()); + + gl_shader_id fs = gl_compile_shader( + state_->dbg(), fragment_source, GL_FRAGMENT_SHADER); if ( fs.empty() ) { return nullptr; } + gl_program_id ps = gl_link_program( state_->dbg(), std::move(vs), std::move(fs)); if ( ps.empty() ) { return nullptr; } + return std::make_shared( std::make_unique( state_->dbg(), std::move(ps))); } + shader_ptr render::create_shader( + const input_stream_uptr& vertex, + const input_stream_uptr& fragment) + { + E2D_ASSERT( + std::this_thread::get_id() == + modules::main_thread()); + + str vertex_source, fragment_source; + return streams::try_read_tail(vertex_source, vertex) + && streams::try_read_tail(fragment_source, fragment) + ? create_shader(vertex_source, fragment_source) + : nullptr; + } + texture_ptr render::create_texture( const image& image) { + E2D_ASSERT( + std::this_thread::get_id() == + modules::main_thread()); + gl_texture_id id = gl_texture_id::create( state_->dbg(), GL_TEXTURE_2D); if ( id.empty() ) { @@ -487,6 +516,7 @@ namespace e2d "failed to create texture id"); return nullptr; } + const pixel_declaration decl = convert_image_data_format_to_pixel_declaration(image.format()); with_gl_bind_texture(state_->dbg(), id, [this, &id, &image, &decl]() noexcept { @@ -517,6 +547,7 @@ namespace e2d glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); #endif }); + return std::make_shared( std::make_unique( state_->dbg(), std::move(id), image.size(), decl)); @@ -525,6 +556,10 @@ namespace e2d texture_ptr render::create_texture( const input_stream_uptr& image_stream) { + E2D_ASSERT( + std::this_thread::get_id() == + modules::main_thread()); + image image; if ( !images::try_load_image(image, image_stream) ) { return nullptr; @@ -536,6 +571,10 @@ namespace e2d const v2u& size, const pixel_declaration& decl) { + E2D_ASSERT( + std::this_thread::get_id() == + modules::main_thread()); + gl_texture_id id = gl_texture_id::create( state_->dbg(), GL_TEXTURE_2D); if ( id.empty() ) { @@ -543,6 +582,7 @@ namespace e2d "failed to create texture id"); return nullptr; } + with_gl_bind_texture(state_->dbg(), id, [this, &id, &size, &decl]() noexcept { if ( decl.is_compressed() ) { buffer empty_data(decl.bits_per_pixel() * size.x * size.y / 8); @@ -572,6 +612,7 @@ namespace e2d glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); #endif }); + return std::make_shared( std::make_unique( state_->dbg(), std::move(id), size, decl)); @@ -582,12 +623,17 @@ namespace e2d const index_declaration& decl, index_buffer::usage usage) { + E2D_ASSERT( + std::this_thread::get_id() == + modules::main_thread()); E2D_ASSERT(indices.size() % decl.bytes_per_index() == 0); + gl_buffer_id id = gl_compile_index_buffer( state_->dbg(), indices, usage); if ( id.empty() ) { return nullptr; } + return std::make_shared( std::make_unique( state_->dbg(), std::move(id), indices.size(), decl)); @@ -598,12 +644,17 @@ namespace e2d const vertex_declaration& decl, vertex_buffer::usage usage) { + E2D_ASSERT( + std::this_thread::get_id() == + modules::main_thread()); E2D_ASSERT(vertices.size() % decl.bytes_per_vertex() == 0); + gl_buffer_id id = gl_compile_vertex_buffer( state_->dbg(), vertices, usage); if ( id.empty() ) { return nullptr; } + return std::make_shared( std::make_unique( state_->dbg(), std::move(id), vertices.size(), decl)); @@ -615,6 +666,10 @@ namespace e2d const pixel_declaration& depth_decl, render_target::external_texture external_texture) { + E2D_ASSERT( + std::this_thread::get_id() == + modules::main_thread()); + E2D_ASSERT( depth_decl.is_depth() && color_decl.is_color() && @@ -712,6 +767,10 @@ namespace e2d const material& mat, const geometry& geo) { + E2D_ASSERT( + std::this_thread::get_id() == + modules::main_thread()); + draw(mat, geo, property_block()); } @@ -720,6 +779,10 @@ namespace e2d const geometry& geo, const property_block& props) { + E2D_ASSERT( + std::this_thread::get_id() == + modules::main_thread()); + for ( std::size_t i = 0; i < mat.pass_count(); ++i ) { const pass_state& pass = mat.pass(i); const property_block main_props = property_block() @@ -736,6 +799,10 @@ namespace e2d } render& render::clear_depth_buffer(f32 value) noexcept { + E2D_ASSERT( + std::this_thread::get_id() == + modules::main_thread()); + const render_target_ptr& rt = state_->render_target(); if ( !rt || rt->state().depth() || !rt->state().depth_rb().empty() ) { GL_CHECK_CODE(state_->dbg(), glClearDepth( @@ -746,6 +813,10 @@ namespace e2d } render& render::clear_stencil_buffer(u8 value) noexcept { + E2D_ASSERT( + std::this_thread::get_id() == + modules::main_thread()); + const render_target_ptr& rt = state_->render_target(); if ( !rt || rt->state().depth() || !rt->state().depth_rb().empty() ) { GL_CHECK_CODE(state_->dbg(), glClearStencil( @@ -756,6 +827,10 @@ namespace e2d } render& render::clear_color_buffer(const color& value) noexcept { + E2D_ASSERT( + std::this_thread::get_id() == + modules::main_thread()); + const render_target_ptr& rt = state_->render_target(); if ( !rt || rt->state().color() || !rt->state().color_rb().empty() ) { GL_CHECK_CODE(state_->dbg(), glClearColor( @@ -768,16 +843,24 @@ namespace e2d return *this; } - render& render::set_viewport(u32 x, u32 y, u32 w, u32 h) noexcept { + render& render::set_viewport(const v2u& pos, const v2u& size) noexcept { + E2D_ASSERT( + std::this_thread::get_id() == + modules::main_thread()); + GL_CHECK_CODE(state_->dbg(), glViewport( - math::numeric_cast(x), - math::numeric_cast(y), - math::numeric_cast(w), - math::numeric_cast(h))); + math::numeric_cast(pos.x), + math::numeric_cast(pos.y), + math::numeric_cast(size.x), + math::numeric_cast(size.y))); return *this; } render& render::set_render_target(const render_target_ptr& rt) noexcept { + E2D_ASSERT( + std::this_thread::get_id() == + modules::main_thread()); + state_->set_render_target(rt); return *this; }