summaryrefslogtreecommitdiff
path: root/servers/visual/rasterizer_rd
diff options
context:
space:
mode:
authorJuan Linietsky <reduzio@gmail.com>2019-07-29 12:59:18 -0300
committerJuan Linietsky <reduzio@gmail.com>2020-02-11 11:53:29 +0100
commitc613ead5fa2361296cf8d9a80d4648492ff4e16f (patch)
tree974356b6840ecf764415d43277ef78ad3c6b6373 /servers/visual/rasterizer_rd
parent4fe3ee1730167b90ec8ae70c871c1dad032981d5 (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.cpp7
-rw-r--r--servers/visual/rasterizer_rd/rasterizer_rd.h4
-rw-r--r--servers/visual/rasterizer_rd/rasterizer_storage_rd.h5
-rw-r--r--servers/visual/rasterizer_rd/shader_rd.cpp198
-rw-r--r--servers/visual/rasterizer_rd/shader_rd.h6
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);