diff options
author | Juan Linietsky <reduzio@gmail.com> | 2019-07-29 12:59:18 -0300 |
---|---|---|
committer | Juan Linietsky <reduzio@gmail.com> | 2020-02-11 11:53:29 +0100 |
commit | c613ead5fa2361296cf8d9a80d4648492ff4e16f (patch) | |
tree | 974356b6840ecf764415d43277ef78ad3c6b6373 /servers/visual/rasterizer_rd | |
parent | 4fe3ee1730167b90ec8ae70c871c1dad032981d5 (diff) |
Added a spinlock template as well as a thread work pool class.
Also, optimized shader compilation to happen on threads.
Diffstat (limited to 'servers/visual/rasterizer_rd')
-rw-r--r-- | servers/visual/rasterizer_rd/rasterizer_rd.cpp | 7 | ||||
-rw-r--r-- | servers/visual/rasterizer_rd/rasterizer_rd.h | 4 | ||||
-rw-r--r-- | servers/visual/rasterizer_rd/rasterizer_storage_rd.h | 5 | ||||
-rw-r--r-- | servers/visual/rasterizer_rd/shader_rd.cpp | 198 | ||||
-rw-r--r-- | servers/visual/rasterizer_rd/shader_rd.h | 6 |
5 files changed, 125 insertions, 95 deletions
diff --git a/servers/visual/rasterizer_rd/rasterizer_rd.cpp b/servers/visual/rasterizer_rd/rasterizer_rd.cpp index 9be7a6e3f7..8a77d9a71e 100644 --- a/servers/visual/rasterizer_rd/rasterizer_rd.cpp +++ b/servers/visual/rasterizer_rd/rasterizer_rd.cpp @@ -76,7 +76,7 @@ void RasterizerRD::initialize() { RenderingDevice::ShaderStageData frag; frag.shader_stage = RenderingDevice::SHADER_STAGE_FRAGMENT; - frag.spir_v =RenderingDevice::get_singleton()->shader_compile_from_source(RenderingDevice::SHADER_STAGE_FRAGMENT, + frag.spir_v = RenderingDevice::get_singleton()->shader_compile_from_source(RenderingDevice::SHADER_STAGE_FRAGMENT, "#version 450\n" "layout (location = 0) in vec2 uv;\n" "layout (location = 0) out vec4 color;\n" @@ -120,8 +120,12 @@ void RasterizerRD::initialize() { } } +ThreadWorkPool RasterizerRD::thread_work_pool; + void RasterizerRD::finalize() { + thread_work_pool.finish(); + memdelete(scene); memdelete(canvas); memdelete(storage); @@ -133,6 +137,7 @@ void RasterizerRD::finalize() { } RasterizerRD::RasterizerRD() { + thread_work_pool.init(); time = 0; storage = memnew(RasterizerStorageRD); canvas = memnew(RasterizerCanvasRD(storage)); diff --git a/servers/visual/rasterizer_rd/rasterizer_rd.h b/servers/visual/rasterizer_rd/rasterizer_rd.h index 749d5c23ad..f5ee7ddc76 100644 --- a/servers/visual/rasterizer_rd/rasterizer_rd.h +++ b/servers/visual/rasterizer_rd/rasterizer_rd.h @@ -2,10 +2,12 @@ #define RASTERIZER_RD_H #include "core/os/os.h" +#include "core/thread_work_pool.h" #include "servers/visual/rasterizer.h" #include "servers/visual/rasterizer_rd/rasterizer_canvas_rd.h" #include "servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.h" #include "servers/visual/rasterizer_rd/rasterizer_storage_rd.h" + class RasterizerRD : public Rasterizer { protected: RasterizerCanvasRD *canvas; @@ -51,6 +53,8 @@ public: virtual bool is_low_end() const { return true; } + static ThreadWorkPool thread_work_pool; + RasterizerRD(); ~RasterizerRD() {} }; diff --git a/servers/visual/rasterizer_rd/rasterizer_storage_rd.h b/servers/visual/rasterizer_rd/rasterizer_storage_rd.h index c2f60c08b3..c05d9a41f6 100644 --- a/servers/visual/rasterizer_rd/rasterizer_storage_rd.h +++ b/servers/visual/rasterizer_rd/rasterizer_storage_rd.h @@ -4,8 +4,8 @@ #include "core/rid_owner.h" #include "servers/visual/rasterizer.h" #include "servers/visual/rasterizer_rd/effects_rd.h" -#include "servers/visual/rendering_device.h" #include "servers/visual/rasterizer_rd/shader_compiler_rd.h" +#include "servers/visual/rendering_device.h" class RasterizerStorageRD : public RasterizerStorage { public: @@ -109,7 +109,8 @@ private: } }; - mutable RID_Owner<Texture> texture_owner; + //textures can be created from threads, so this RID_Owner is thread safe + mutable RID_Owner<Texture, true> texture_owner; Ref<Image> _validate_texture_format(const Ref<Image> &p_image, TextureToRDFormat &r_format); diff --git a/servers/visual/rasterizer_rd/shader_rd.cpp b/servers/visual/rasterizer_rd/shader_rd.cpp index 945fc25cab..58596f6a72 100644 --- a/servers/visual/rasterizer_rd/shader_rd.cpp +++ b/servers/visual/rasterizer_rd/shader_rd.cpp @@ -30,6 +30,7 @@ #include "shader_rd.h" #include "core/string_builder.h" +#include "rasterizer_rd.h" #include "servers/visual/rendering_device.h" void ShaderRD::setup(const char *p_vertex_code, const char *p_fragment_code, const char *p_name) { @@ -160,142 +161,157 @@ void ShaderRD::_clear_version(Version *p_version) { p_version->variants = NULL; } } -void ShaderRD::_compile_version(Version *p_version) { - _clear_version(p_version); +void ShaderRD::_compile_variant(uint32_t p_variant, Version *p_version) { - p_version->valid = false; - p_version->dirty = false; + Vector<RD::ShaderStageData> stages; - p_version->variants = memnew_arr(RID, variant_defines.size()); + String error; + String current_source; + RD::ShaderStage current_stage = RD::SHADER_STAGE_VERTEX; + bool build_ok = true; - for (int i = 0; i < variant_defines.size(); i++) { + { + //vertex stage - Vector<RD::ShaderStageData> stages; + StringBuilder builder; - String error; - String current_source; - RD::ShaderStage current_stage = RD::SHADER_STAGE_VERTEX; - bool build_ok=true; + builder.append(vertex_codev.get_data()); // version info (if exists) + builder.append("\n"); //make sure defines begin at newline + builder.append(general_defines.get_data()); + builder.append(variant_defines[p_variant].get_data()); - { - //vertex stage + for (int j = 0; j < p_version->custom_defines.size(); j++) { + builder.append(p_version->custom_defines[j].get_data()); + } - StringBuilder builder; + builder.append(vertex_code0.get_data()); //first part of vertex - builder.append(vertex_codev.get_data()); // version info (if exists) - builder.append("\n"); //make sure defines begin at newline - builder.append(general_defines.get_data()); - builder.append(variant_defines[i].get_data()); + builder.append(p_version->uniforms.get_data()); //uniforms (same for vertex and fragment) - for (int j = 0; j < p_version->custom_defines.size(); j++) { - builder.append(p_version->custom_defines[j].get_data()); - } + builder.append(vertex_code1.get_data()); //second part of vertex - builder.append(vertex_code0.get_data()); //first part of vertex + builder.append(p_version->vertex_globals.get_data()); // vertex globals - builder.append(p_version->uniforms.get_data()); //uniforms (same for vertex and fragment) + builder.append(vertex_code2.get_data()); //third part of vertex - builder.append(vertex_code1.get_data()); //second part of vertex + builder.append(p_version->vertex_code.get_data()); // code - builder.append(p_version->vertex_globals.get_data()); // vertex globals + builder.append(vertex_code3.get_data()); //fourth of vertex - builder.append(vertex_code2.get_data()); //third part of vertex + current_source = builder.as_string(); + RD::ShaderStageData stage; + stage.spir_v = RD::get_singleton()->shader_compile_from_source(RD::SHADER_STAGE_VERTEX, current_source, RD::SHADER_LANGUAGE_GLSL, &error); + if (stage.spir_v.size() == 0) { + build_ok = false; + } else { - builder.append(p_version->vertex_code.get_data()); // code + stage.shader_stage = RD::SHADER_STAGE_VERTEX; + stages.push_back(stage); + } + } - builder.append(vertex_code3.get_data()); //fourth of vertex + if (build_ok) { + //fragment stage + current_stage = RD::SHADER_STAGE_FRAGMENT; - current_source = builder.as_string(); - RD::ShaderStageData stage; - stage.spir_v = RD::get_singleton()->shader_compile_from_source(RD::SHADER_STAGE_VERTEX,current_source,RD::SHADER_LANGUAGE_GLSL,&error); - if (stage.spir_v.size()==0) { - build_ok=false; - } else { + StringBuilder builder; - stage.shader_stage = RD::SHADER_STAGE_VERTEX; - stages.push_back(stage); - } + builder.append(fragment_codev.get_data()); // version info (if exists) + builder.append("\n"); //make sure defines begin at newline + + builder.append(general_defines.get_data()); + builder.append(variant_defines[p_variant].get_data()); + for (int j = 0; j < p_version->custom_defines.size(); j++) { + builder.append(p_version->custom_defines[j].get_data()); } - if (build_ok){ - //fragment stage - current_stage =RD::SHADER_STAGE_FRAGMENT; + builder.append(fragment_code0.get_data()); //first part of fragment - StringBuilder builder; + builder.append(p_version->uniforms.get_data()); //uniforms (same for fragment and fragment) - builder.append(fragment_codev.get_data()); // version info (if exists) - builder.append("\n"); //make sure defines begin at newline + builder.append(fragment_code1.get_data()); //first part of fragment - builder.append(general_defines.get_data()); - builder.append(variant_defines[i].get_data()); - for (int j = 0; j < p_version->custom_defines.size(); j++) { - builder.append(p_version->custom_defines[j].get_data()); - } + builder.append(p_version->fragment_globals.get_data()); // fragment globals - builder.append(fragment_code0.get_data()); //first part of fragment + builder.append(fragment_code2.get_data()); //third part of fragment - builder.append(p_version->uniforms.get_data()); //uniforms (same for fragment and fragment) + builder.append(p_version->fragment_light.get_data()); // fragment light - builder.append(fragment_code1.get_data()); //first part of fragment + builder.append(fragment_code3.get_data()); //fourth part of fragment - builder.append(p_version->fragment_globals.get_data()); // fragment globals + builder.append(p_version->fragment_code.get_data()); // fragment code - builder.append(fragment_code2.get_data()); //third part of fragment + builder.append(fragment_code4.get_data()); //fourth part of fragment - builder.append(p_version->fragment_light.get_data()); // fragment light + current_source = builder.as_string(); + RD::ShaderStageData stage; + stage.spir_v = RD::get_singleton()->shader_compile_from_source(RD::SHADER_STAGE_FRAGMENT, current_source, RD::SHADER_LANGUAGE_GLSL, &error); + if (stage.spir_v.size() == 0) { + build_ok = false; + } else { - builder.append(fragment_code3.get_data()); //fourth part of fragment + stage.shader_stage = RD::SHADER_STAGE_FRAGMENT; + stages.push_back(stage); + } + } - builder.append(p_version->fragment_code.get_data()); // fragment code + if (!build_ok) { + variant_set_mutex.lock(); //properly print the errors + ERR_PRINT("Error compiling " + String(current_stage == RD::SHADER_STAGE_VERTEX ? "Vertex" : "Fragment") + " shader, variant #" + itos(p_variant) + " (" + variant_defines[p_variant].get_data() + ")."); + ERR_PRINT(error); - builder.append(fragment_code4.get_data()); //fourth part of fragment +#ifdef DEBUG_ENABLED + ERR_PRINT("code:\n" + current_source.get_with_code_lines()); +#endif - current_source = builder.as_string(); - RD::ShaderStageData stage; - stage.spir_v = RD::get_singleton()->shader_compile_from_source(RD::SHADER_STAGE_FRAGMENT,current_source,RD::SHADER_LANGUAGE_GLSL,&error); - if (stage.spir_v.size()==0) { - build_ok=false; - } else { + variant_set_mutex.unlock(); + return; + } - stage.shader_stage = RD::SHADER_STAGE_FRAGMENT; - stages.push_back(stage); - } + RID shader = RD::get_singleton()->shader_create(stages); - } + variant_set_mutex.lock(); + p_version->variants[p_variant] = shader; + variant_set_mutex.unlock(); +} +void ShaderRD::_compile_version(Version *p_version) { - if (!build_ok) { - ERR_PRINT("Error compiling " + String(current_stage == RD::SHADER_STAGE_VERTEX ? "Vertex" : "Fragment") + " shader, variant #" + itos(i) + " (" + variant_defines[i].get_data() + ")."); - ERR_PRINT(error); + _clear_version(p_version); -#ifdef DEBUG_ENABLED - ERR_PRINT("code:\n" + current_source.get_with_code_lines()); -#endif - //clear versions if they exist - for (int j = 0; j < i; j++) { - RD::get_singleton()->free(p_version->variants[j]); - } + p_version->valid = false; + p_version->dirty = false; - memdelete_arr(p_version->variants); - p_version->variants = NULL; - return; - } + p_version->variants = memnew_arr(RID, variant_defines.size()); +#if 1 - RID shader = RD::get_singleton()->shader_create(stages); + RasterizerRD::thread_work_pool.do_work(variant_defines.size(), this, &ShaderRD::_compile_variant, p_version); +#else + for (int i = 0; i < variant_defines.size(); i++) { - if (shader.is_null()) { - //clear versions if they exist - for (int j = 0; j < i; j++) { - RD::get_singleton()->free(p_version->variants[j]); - } + _compile_variant(i, p_version); + } +#endif - memdelete_arr(p_version->variants); - p_version->variants = NULL; - return; + bool all_valid = true; + for (int i = 0; i < variant_defines.size(); i++) { + if (p_version->variants[i].is_null()) { + all_valid = false; + break; } + } - p_version->variants[i] = shader; + if (!all_valid) { + //clear versions if they exist + for (int i = 0; i < variant_defines.size(); i++) { + if (!p_version->variants[i].is_null()) { + RD::get_singleton()->free(p_version->variants[i]); + } + } + memdelete_arr(p_version->variants); + p_version->variants = NULL; + return; } p_version->valid = true; diff --git a/servers/visual/rasterizer_rd/shader_rd.h b/servers/visual/rasterizer_rd/shader_rd.h index 558675935d..81169343d6 100644 --- a/servers/visual/rasterizer_rd/shader_rd.h +++ b/servers/visual/rasterizer_rd/shader_rd.h @@ -36,7 +36,7 @@ #include "core/rid_owner.h" #include "core/variant.h" #include <stdio.h> - +#include <mutex> /** @author Juan Linietsky <reduzio@gmail.com> */ @@ -67,6 +67,10 @@ class ShaderRD { bool initialize_needed; }; + std::mutex variant_set_mutex; + + void _compile_variant(uint32_t p_variant, Version *p_version); + void _clear_version(Version *p_version); void _compile_version(Version *p_version); |