summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJuan Linietsky <juan@godotengine.org>2019-07-28 19:58:32 -0300
committerJuan Linietsky <reduzio@gmail.com>2020-02-11 11:53:29 +0100
commit4fe3ee1730167b90ec8ae70c871c1dad032981d5 (patch)
tree98b9f82d3a4defc1560245e40c0ba7b3a674fa81
parent60c7498cee169b2cd652045ec19bb526d76f9d61 (diff)
Moved the shader source compilation code outside RenderingDevice and Vulkan
-rw-r--r--drivers/vulkan/SCsub58
-rw-r--r--drivers/vulkan/rendering_device_vulkan.cpp283
-rw-r--r--drivers/vulkan/rendering_device_vulkan.h7
-rw-r--r--main/main.cpp2
-rw-r--r--methods.py12
-rw-r--r--modules/glslang/SCsub68
-rw-r--r--modules/glslang/config.py5
-rw-r--r--modules/glslang/register_types.cpp240
-rw-r--r--modules/glslang/register_types.h34
-rw-r--r--modules/register_module_types.h1
-rw-r--r--servers/visual/rasterizer_rd/rasterizer_rd.cpp16
-rw-r--r--servers/visual/rasterizer_rd/shader_rd.cpp65
-rw-r--r--servers/visual/rendering_device.cpp31
-rw-r--r--servers/visual/rendering_device.h52
14 files changed, 490 insertions, 384 deletions
diff --git a/drivers/vulkan/SCsub b/drivers/vulkan/SCsub
index 8ecfd47a0a..2251181704 100644
--- a/drivers/vulkan/SCsub
+++ b/drivers/vulkan/SCsub
@@ -4,63 +4,5 @@ Import('env')
env.add_source_files(env.drivers_sources,"*.cpp")
-# Thirdparty source files
-# Not unbundled so far since not widespread as shared library
-thirdparty_dir = "#thirdparty/glslang/"
-thirdparty_sources = [
-"glslang/MachineIndependent/RemoveTree.cpp",
-"glslang/MachineIndependent/ParseHelper.cpp",
-"glslang/MachineIndependent/iomapper.cpp",
-"glslang/MachineIndependent/propagateNoContraction.cpp",
-"glslang/MachineIndependent/Intermediate.cpp",
-"glslang/MachineIndependent/linkValidate.cpp",
-"glslang/MachineIndependent/attribute.cpp",
-"glslang/MachineIndependent/Scan.cpp",
-"glslang/MachineIndependent/Initialize.cpp",
-"glslang/MachineIndependent/Constant.cpp",
-"glslang/MachineIndependent/reflection.cpp",
-"glslang/MachineIndependent/limits.cpp",
-"glslang/MachineIndependent/preprocessor/PpScanner.cpp",
-"glslang/MachineIndependent/preprocessor/PpTokens.cpp",
-"glslang/MachineIndependent/preprocessor/PpAtom.cpp",
-"glslang/MachineIndependent/preprocessor/PpContext.cpp",
-"glslang/MachineIndependent/preprocessor/Pp.cpp",
-"glslang/MachineIndependent/InfoSink.cpp",
-"glslang/MachineIndependent/intermOut.cpp",
-"glslang/MachineIndependent/SymbolTable.cpp",
-"glslang/MachineIndependent/glslang_tab.cpp",
-"glslang/MachineIndependent/pch.cpp",
-"glslang/MachineIndependent/Versions.cpp",
-"glslang/MachineIndependent/ShaderLang.cpp",
-"glslang/MachineIndependent/parseConst.cpp",
-"glslang/MachineIndependent/PoolAlloc.cpp",
-"glslang/MachineIndependent/ParseContextBase.cpp",
-"glslang/MachineIndependent/IntermTraverse.cpp",
-"glslang/GenericCodeGen/Link.cpp",
-"glslang/GenericCodeGen/CodeGen.cpp",
-"OGLCompilersDLL/InitializeDll.cpp",
-"SPIRV/InReadableOrder.cpp",
-"SPIRV/GlslangToSpv.cpp",
-"SPIRV/SpvBuilder.cpp",
-"SPIRV/SpvTools.cpp",
-"SPIRV/disassemble.cpp",
-"SPIRV/doc.cpp",
-"SPIRV/SPVRemapper.cpp",
-"SPIRV/SpvPostProcess.cpp",
-"SPIRV/Logger.cpp"
-]
-
-if (env["platform"]=="windows"):
- thirdparty_sources.append("glslang/OSDependent/Windows/ossource.cpp")
-else:
- thirdparty_sources.append("glslang/OSDependent/Unix/ossource.cpp")
-
-thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources]
-
-env_thirdparty = env.Clone()
-#env_thirdparty.disable_warnings()
-env_thirdparty.add_source_files(env.drivers_sources, thirdparty_sources)
-
-env.Prepend(CPPPATH=[thirdparty_dir])
#SConscript("shaders/SCsub")
diff --git a/drivers/vulkan/rendering_device_vulkan.cpp b/drivers/vulkan/rendering_device_vulkan.cpp
index 7f4ebd5134..f6154a3cbd 100644
--- a/drivers/vulkan/rendering_device_vulkan.cpp
+++ b/drivers/vulkan/rendering_device_vulkan.cpp
@@ -3,8 +3,6 @@
#include "core/os/file_access.h"
#include "core/project_settings.h"
#include "drivers/vulkan/vulkan_context.h"
-#include "thirdparty/glslang/SPIRV/GlslangToSpv.h"
-#include "thirdparty/glslang/glslang/Include/Types.h"
#include "thirdparty/spirv-reflect/spirv_reflect.h"
void RenderingDeviceVulkan::_add_dependency(RID p_id, RID p_depends_on) {
@@ -3212,103 +3210,6 @@ RID RenderingDeviceVulkan::index_array_create(RID p_index_buffer, uint32_t p_ind
/**** SHADER ****/
/****************/
-static const TBuiltInResource default_builtin_resource = {
- .maxLights = 32,
- .maxClipPlanes = 6,
- .maxTextureUnits = 32,
- .maxTextureCoords = 32,
- .maxVertexAttribs = 64,
- .maxVertexUniformComponents = 4096,
- .maxVaryingFloats = 64,
- .maxVertexTextureImageUnits = 32,
- .maxCombinedTextureImageUnits = 80,
- .maxTextureImageUnits = 32,
- .maxFragmentUniformComponents = 4096,
- .maxDrawBuffers = 32,
- .maxVertexUniformVectors = 128,
- .maxVaryingVectors = 8,
- .maxFragmentUniformVectors = 16,
- .maxVertexOutputVectors = 16,
- .maxFragmentInputVectors = 15,
- .minProgramTexelOffset = -8,
- .maxProgramTexelOffset = 7,
- .maxClipDistances = 8,
- .maxComputeWorkGroupCountX = 65535,
- .maxComputeWorkGroupCountY = 65535,
- .maxComputeWorkGroupCountZ = 65535,
- .maxComputeWorkGroupSizeX = 1024,
- .maxComputeWorkGroupSizeY = 1024,
- .maxComputeWorkGroupSizeZ = 64,
- .maxComputeUniformComponents = 1024,
- .maxComputeTextureImageUnits = 16,
- .maxComputeImageUniforms = 8,
- .maxComputeAtomicCounters = 8,
- .maxComputeAtomicCounterBuffers = 1,
- .maxVaryingComponents = 60,
- .maxVertexOutputComponents = 64,
- .maxGeometryInputComponents = 64,
- .maxGeometryOutputComponents = 128,
- .maxFragmentInputComponents = 128,
- .maxImageUnits = 8,
- .maxCombinedImageUnitsAndFragmentOutputs = 8,
- .maxCombinedShaderOutputResources = 8,
- .maxImageSamples = 0,
- .maxVertexImageUniforms = 0,
- .maxTessControlImageUniforms = 0,
- .maxTessEvaluationImageUniforms = 0,
- .maxGeometryImageUniforms = 0,
- .maxFragmentImageUniforms = 8,
- .maxCombinedImageUniforms = 8,
- .maxGeometryTextureImageUnits = 16,
- .maxGeometryOutputVertices = 256,
- .maxGeometryTotalOutputComponents = 1024,
- .maxGeometryUniformComponents = 1024,
- .maxGeometryVaryingComponents = 64,
- .maxTessControlInputComponents = 128,
- .maxTessControlOutputComponents = 128,
- .maxTessControlTextureImageUnits = 16,
- .maxTessControlUniformComponents = 1024,
- .maxTessControlTotalOutputComponents = 4096,
- .maxTessEvaluationInputComponents = 128,
- .maxTessEvaluationOutputComponents = 128,
- .maxTessEvaluationTextureImageUnits = 16,
- .maxTessEvaluationUniformComponents = 1024,
- .maxTessPatchComponents = 120,
- .maxPatchVertices = 32,
- .maxTessGenLevel = 64,
- .maxViewports = 16,
- .maxVertexAtomicCounters = 0,
- .maxTessControlAtomicCounters = 0,
- .maxTessEvaluationAtomicCounters = 0,
- .maxGeometryAtomicCounters = 0,
- .maxFragmentAtomicCounters = 8,
- .maxCombinedAtomicCounters = 8,
- .maxAtomicCounterBindings = 1,
- .maxVertexAtomicCounterBuffers = 0,
- .maxTessControlAtomicCounterBuffers = 0,
- .maxTessEvaluationAtomicCounterBuffers = 0,
- .maxGeometryAtomicCounterBuffers = 0,
- .maxFragmentAtomicCounterBuffers = 1,
- .maxCombinedAtomicCounterBuffers = 1,
- .maxAtomicCounterBufferSize = 16384,
- .maxTransformFeedbackBuffers = 4,
- .maxTransformFeedbackInterleavedComponents = 64,
- .maxCullDistances = 8,
- .maxCombinedClipAndCullDistances = 8,
- .maxSamples = 4,
- .limits = {
- .nonInductiveForLoops = 1,
- .whileLoops = 1,
- .doWhileLoops = 1,
- .generalUniformIndexing = 1,
- .generalAttributeMatrixVectorIndexing = 1,
- .generalVaryingIndexing = 1,
- .generalSamplerIndexing = 1,
- .generalVariableIndexing = 1,
- .generalConstantMatrixVectorIndexing = 1,
- }
-};
-
static const char *shader_stage_names[RenderingDevice::SHADER_STAGE_MAX] = {
"Vertex",
"Fragment",
@@ -3347,7 +3248,7 @@ String RenderingDeviceVulkan::_shader_uniform_debug(RID p_shader, int p_set) {
}
return ret;
}
-
+#if 0
bool RenderingDeviceVulkan::_uniform_add_binding(Vector<Vector<VkDescriptorSetLayoutBinding> > &bindings, Vector<Vector<UniformInfo> > &uniform_infos, const glslang::TObjectReflection &reflection, RenderingDevice::ShaderStage p_stage, Shader::PushConstant &push_constant, String *r_error) {
VkDescriptorSetLayoutBinding layout_binding;
@@ -3543,30 +3444,12 @@ bool RenderingDeviceVulkan::_uniform_add_binding(Vector<Vector<VkDescriptorSetLa
return true;
}
+#endif
-RID RenderingDeviceVulkan::shader_create_from_source(const Vector<ShaderStageSource> &p_stages, String *r_error, ShaderStage *r_error_stage, bool p_allow_cache) {
+RID RenderingDeviceVulkan::shader_create(const Vector<ShaderStageData> &p_stages) {
_THREAD_SAFE_METHOD_
- // initialize in case it's not initialized. This is done once per thread
- // and it's safe to call multiple times
- glslang::InitializeProcess();
- EShLanguage stages[SHADER_STAGE_MAX] = {
- EShLangVertex,
- EShLangFragment,
- EShLangTessControl,
- EShLangTessEvaluation,
- EShLangCompute
- };
-
- int ClientInputSemanticsVersion = 100; // maps to, say, #define VULKAN 100
- glslang::EShTargetClientVersion VulkanClientVersion = glslang::EShTargetVulkan_1_0;
- glslang::EShTargetLanguageVersion TargetVersion = glslang::EShTargetSpv_1_0;
-
- Vector<std::vector<unsigned int> > spirv_code;
-
- glslang::TShader::ForbidIncluder includer;
-
//descriptor layouts
Vector<Vector<VkDescriptorSetLayoutBinding> > set_bindings;
Vector<Vector<UniformInfo> > uniform_info;
@@ -3581,148 +3464,13 @@ RID RenderingDeviceVulkan::shader_create_from_source(const Vector<ShaderStageSou
for (int i = 0; i < p_stages.size(); i++) {
- if (stages_processed & (1 << p_stages[i].shader_stage)) {
- if (r_error) {
- (*r_error) = "Stage " + String(shader_stage_names[p_stages[i].shader_stage]) + " submitted more than once.";
- }
- return RID();
- }
- glslang::TShader shader(stages[p_stages[i].shader_stage]);
- CharString cs = p_stages[i].shader_source.utf8();
- const char *cs_strings = cs.get_data();
- shader.setStrings(&cs_strings, 1);
- shader.setEnvInput(glslang::EShSourceGlsl, stages[p_stages[i].shader_stage], glslang::EShClientVulkan, ClientInputSemanticsVersion);
- shader.setEnvClient(glslang::EShClientVulkan, VulkanClientVersion);
- shader.setEnvTarget(glslang::EShTargetSpv, TargetVersion);
-
- EShMessages messages = (EShMessages)(EShMsgSpvRules | EShMsgVulkanRules);
- const int DefaultVersion = 100;
- std::string pre_processed_code;
-
- //preprocess
- if (!shader.preprocess(&default_builtin_resource, DefaultVersion, ENoProfile, false, false, messages, &pre_processed_code, includer)) {
-
- if (r_error) {
- (*r_error) = "Failed pre-processing on shader stage: " + String(shader_stage_names[p_stages[i].shader_stage]) + "\n";
- (*r_error) += shader.getInfoLog();
- (*r_error) += "\n";
- (*r_error) += shader.getInfoDebugLog();
- }
-
- if (r_error_stage) {
- *r_error_stage = p_stages[i].shader_stage;
- }
-
- return RID();
- }
- //set back..
- cs_strings = pre_processed_code.c_str();
- shader.setStrings(&cs_strings, 1);
-
- //parse
- if (!shader.parse(&default_builtin_resource, DefaultVersion, false, messages)) {
- if (r_error) {
- (*r_error) = "Failed parsing on shader stage: " + String(shader_stage_names[p_stages[i].shader_stage]) + "\n";
- (*r_error) += shader.getInfoLog();
- (*r_error) += "\n";
- (*r_error) += shader.getInfoDebugLog();
- }
- if (r_error_stage) {
- *r_error_stage = p_stages[i].shader_stage;
- }
-
- return RID();
- }
-
- //link
- glslang::TProgram program;
- program.addShader(&shader);
-
- if (!program.link(messages)) {
- if (r_error) {
- (*r_error) = "Failed linking on shader stage: " + String(shader_stage_names[p_stages[i].shader_stage]) + "\n";
- (*r_error) += program.getInfoLog();
- (*r_error) += "\n";
- (*r_error) += program.getInfoDebugLog();
- }
- if (r_error_stage) {
- *r_error_stage = p_stages[i].shader_stage;
- }
-
- return RID();
- }
-
-#if 0
- //obtain bindings for descriptor layout
- program.mapIO();
- program.buildReflection(EShReflectionAllBlockVariables);
- //program.dumpReflection();
-
- for (int j = 0; j < program.getNumUniformBlocks(); j++) {
- const glslang::TObjectReflection &reflection = program.getUniformBlock(j);
- if (reflection.getType()->getBasicType() == glslang::EbtBlock && reflection.getType()->getQualifier().storage == glslang::EvqUniform && reflection.getType()->getQualifier().layoutPushConstant) {
- uint32_t len = reflection.size;
- if (push_constant_debug.push_constant_size != 0 && push_constant_debug.push_constant_size != len) {
- print_line("eep");
- }
-
- push_constant_debug.push_constant_size = len;
- push_constant_debug.push_constants_vk_stage |= shader_stage_masks[p_stages[i].shader_stage];
- //print_line("Debug stage " + String(shader_stage_names[p_stages[i].shader_stage]) + " push constant size: " + itos(push_constant_debug.push_constant_size));
- }
- }
-
-
- for (int j = 0; j < program.getNumUniformVariables(); j++) {
- if (!_uniform_add_binding(bindings, uniform_info, program.getUniform(j), p_stages[i].shader_stage, push_constant, r_error)) {
- return RID();
- }
- }
-
- for (int j = 0; j < program.getNumUniformBlocks(); j++) {
- if (!_uniform_add_binding(bindings, uniform_info, program.getUniformBlock(j), p_stages[i].shader_stage, push_constant, r_error)) {
- return RID();
- }
- }
-
- for (int j = 0; j < program.getNumBufferVariables(); j++) {
- if (!_uniform_add_binding(bindings, uniform_info, program.getBufferVariable(j), p_stages[i].shader_stage, push_constant, r_error)) {
- return RID();
- }
- }
-
- for (int j = 0; j < program.getNumBufferBlocks(); j++) {
- if (!_uniform_add_binding(bindings, uniform_info, program.getBufferBlock(j), p_stages[i].shader_stage, push_constant, r_error)) {
- return RID();
- }
- }
-
- if (p_stages[i].shader_stage == SHADER_STAGE_VERTEX) {
- for (int j = 0; j < program.getNumPipeInputs(); j++) {
- if (program.getPipeInput(i).getType()->getQualifier().hasLocation()) {
- int location = program.getPipeInput(i).getType()->getQualifier().layoutLocation;
-
- if (vertex_input_locations.find(location) == -1) {
- vertex_input_locations.push_back(location);
- }
- }
- }
- }
-
- if (p_stages[i].shader_stage == SHADER_STAGE_FRAGMENT) {
-
- fragment_outputs = program.getNumPipeOutputs();
- }
-
-#endif
- std::vector<uint32_t> SpirV;
- spv::SpvBuildLogger logger;
- glslang::SpvOptions spvOptions;
- glslang::GlslangToSpv(*program.getIntermediate(stages[p_stages[i].shader_stage]), SpirV, &logger, &spvOptions);
+ ERR_FAIL_COND_V_MSG(stages_processed & (1 << p_stages[i].shader_stage), RID(),
+ "Stage " + String(shader_stage_names[p_stages[i].shader_stage]) + " submitted more than once.");
{
SpvReflectShaderModule module;
- SpvReflectResult result = spvReflectCreateShaderModule(SpirV.size() * sizeof(uint32_t), &SpirV[0], &module);
+ PoolVector<uint8_t>::Read spirv = p_stages[i].spir_v.read();
+ SpvReflectResult result = spvReflectCreateShaderModule(p_stages[i].spir_v.size(), spirv.ptr(), &module);
ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, RID(),
"Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_stages[i].shader_stage]) + "' failed parsing shader.");
@@ -3941,8 +3689,6 @@ RID RenderingDeviceVulkan::shader_create_from_source(const Vector<ShaderStageSou
spvReflectDestroyShaderModule(&module);
}
- spirv_code.push_back(SpirV);
-
stages_processed |= (1 << p_stages[i].shader_stage);
}
@@ -3962,8 +3708,10 @@ RID RenderingDeviceVulkan::shader_create_from_source(const Vector<ShaderStageSou
shader_module_create_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
shader_module_create_info.pNext = NULL;
shader_module_create_info.flags = 0;
- shader_module_create_info.codeSize = spirv_code[i].size() * sizeof(uint32_t);
- shader_module_create_info.pCode = &spirv_code[i][0];
+ shader_module_create_info.codeSize = p_stages[i].spir_v.size();
+ PoolVector<uint8_t>::Read r = p_stages[i].spir_v.read();
+
+ shader_module_create_info.pCode = (const uint32_t *)r.ptr();
VkShaderModule module;
VkResult res = vkCreateShaderModule(device, &shader_module_create_info, NULL, &module);
@@ -4087,14 +3835,7 @@ RID RenderingDeviceVulkan::shader_create_from_source(const Vector<ShaderStageSou
vkDestroyDescriptorSetLayout(device, shader.sets[i].descriptor_set_layout, NULL);
}
- if (r_error) {
- *r_error = error_text;
- }
- if (r_error_stage) {
- *r_error_stage = SHADER_STAGE_MAX;
- }
-
- return RID();
+ ERR_FAIL_V_MSG(RID(), error_text);
}
return shader_owner.make_rid(shader);
diff --git a/drivers/vulkan/rendering_device_vulkan.h b/drivers/vulkan/rendering_device_vulkan.h
index 2420e62aab..5b3b7a5f47 100644
--- a/drivers/vulkan/rendering_device_vulkan.h
+++ b/drivers/vulkan/rendering_device_vulkan.h
@@ -5,7 +5,7 @@
#include "core/os/thread_safe.h"
#include "core/rid_owner.h"
#include "servers/visual/rendering_device.h"
-#include "thirdparty/glslang/glslang/Public/ShaderLang.h"
+
#ifdef DEBUG_ENABLED
#define _DEBUG
#endif
@@ -494,7 +494,6 @@ class RenderingDeviceVulkan : public RenderingDevice {
};
String _shader_uniform_debug(RID p_shader, int p_set = -1);
- bool _uniform_add_binding(Vector<Vector<VkDescriptorSetLayoutBinding> > &bindings, Vector<Vector<UniformInfo> > &uniform_infos, const glslang::TObjectReflection &reflection, RenderingDevice::ShaderStage p_stage, Shader::PushConstant &push_constant, String *r_error);
RID_Owner<Shader> shader_owner;
@@ -608,7 +607,7 @@ class RenderingDeviceVulkan : public RenderingDevice {
// was not supplied as intended.
struct RenderPipeline {
- //Cached values for validation
+ //Cached values for validation
#ifdef DEBUG_ENABLED
struct Validation {
FramebufferFormatID framebuffer_format;
@@ -853,7 +852,7 @@ public:
/**** SHADER ****/
/****************/
- virtual RID shader_create_from_source(const Vector<ShaderStageSource> &p_stages, String *r_error = NULL, ShaderStage *r_error_stage = NULL, bool p_allow_cache = true);
+ virtual RID shader_create(const Vector<ShaderStageData> &p_stages);
virtual Vector<int> shader_get_vertex_input_locations_used(RID p_shader);
/*****************/
diff --git a/main/main.cpp b/main/main.cpp
index d1b1c1198e..b401cd4233 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -1207,6 +1207,8 @@ error:
Error Main::setup2(Thread::ID p_main_tid_override) {
+ preregister_module_types();
+
// Print engine name and version
print_line(String(VERSION_NAME) + " v" + get_full_version_string() + " - " + String(VERSION_WEBSITE));
diff --git a/methods.py b/methods.py
index a1d101af18..f6c9e939c6 100644
--- a/methods.py
+++ b/methods.py
@@ -137,6 +137,7 @@ def detect_modules():
includes_cpp = ""
register_cpp = ""
unregister_cpp = ""
+ preregister_cpp = ""
files = glob.glob("modules/*")
files.sort() # so register_module_types does not change that often, and also plugins are registered in alphabetic order
@@ -154,6 +155,11 @@ def detect_modules():
register_cpp += '#ifdef MODULE_' + x.upper() + '_ENABLED\n'
register_cpp += '\tregister_' + x + '_types();\n'
register_cpp += '#endif\n'
+ preregister_cpp += '#ifdef MODULE_' + x.upper() + '_ENABLED\n'
+ preregister_cpp += '#ifdef MODULE_' + x.upper() + '_HAS_PREREGISTER\n'
+ preregister_cpp += '\tpreregister_' + x + '_types();\n'
+ preregister_cpp += '#endif\n'
+ preregister_cpp += '#endif\n'
unregister_cpp += '#ifdef MODULE_' + x.upper() + '_ENABLED\n'
unregister_cpp += '\tunregister_' + x + '_types();\n'
unregister_cpp += '#endif\n'
@@ -168,6 +174,10 @@ def detect_modules():
%s
+void preregister_module_types() {
+%s
+}
+
void register_module_types() {
%s
}
@@ -175,7 +185,7 @@ void register_module_types() {
void unregister_module_types() {
%s
}
-""" % (includes_cpp, register_cpp, unregister_cpp)
+""" % (includes_cpp, preregister_cpp, register_cpp, unregister_cpp)
# NOTE: It is safe to generate this file here, since this is still executed serially
with open("modules/register_module_types.gen.cpp", "w") as f:
diff --git a/modules/glslang/SCsub b/modules/glslang/SCsub
new file mode 100644
index 0000000000..484036dc94
--- /dev/null
+++ b/modules/glslang/SCsub
@@ -0,0 +1,68 @@
+#!/usr/bin/env python
+
+Import('env')
+Import('env_modules')
+
+env_glslang = env_modules.Clone()
+
+# Thirdparty source files
+# Not unbundled so far since not widespread as shared library
+thirdparty_dir = "#thirdparty/glslang/"
+thirdparty_sources = [
+"glslang/MachineIndependent/RemoveTree.cpp",
+"glslang/MachineIndependent/ParseHelper.cpp",
+"glslang/MachineIndependent/iomapper.cpp",
+"glslang/MachineIndependent/propagateNoContraction.cpp",
+"glslang/MachineIndependent/Intermediate.cpp",
+"glslang/MachineIndependent/linkValidate.cpp",
+"glslang/MachineIndependent/attribute.cpp",
+"glslang/MachineIndependent/Scan.cpp",
+"glslang/MachineIndependent/Initialize.cpp",
+"glslang/MachineIndependent/Constant.cpp",
+"glslang/MachineIndependent/reflection.cpp",
+"glslang/MachineIndependent/limits.cpp",
+"glslang/MachineIndependent/preprocessor/PpScanner.cpp",
+"glslang/MachineIndependent/preprocessor/PpTokens.cpp",
+"glslang/MachineIndependent/preprocessor/PpAtom.cpp",
+"glslang/MachineIndependent/preprocessor/PpContext.cpp",
+"glslang/MachineIndependent/preprocessor/Pp.cpp",
+"glslang/MachineIndependent/InfoSink.cpp",
+"glslang/MachineIndependent/intermOut.cpp",
+"glslang/MachineIndependent/SymbolTable.cpp",
+"glslang/MachineIndependent/glslang_tab.cpp",
+"glslang/MachineIndependent/pch.cpp",
+"glslang/MachineIndependent/Versions.cpp",
+"glslang/MachineIndependent/ShaderLang.cpp",
+"glslang/MachineIndependent/parseConst.cpp",
+"glslang/MachineIndependent/PoolAlloc.cpp",
+"glslang/MachineIndependent/ParseContextBase.cpp",
+"glslang/MachineIndependent/IntermTraverse.cpp",
+"glslang/GenericCodeGen/Link.cpp",
+"glslang/GenericCodeGen/CodeGen.cpp",
+"OGLCompilersDLL/InitializeDll.cpp",
+"SPIRV/InReadableOrder.cpp",
+"SPIRV/GlslangToSpv.cpp",
+"SPIRV/SpvBuilder.cpp",
+"SPIRV/SpvTools.cpp",
+"SPIRV/disassemble.cpp",
+"SPIRV/doc.cpp",
+"SPIRV/SPVRemapper.cpp",
+"SPIRV/SpvPostProcess.cpp",
+"SPIRV/Logger.cpp"
+]
+
+if (env["platform"]=="windows"):
+ thirdparty_sources.append("glslang/OSDependent/Windows/ossource.cpp")
+else:
+ thirdparty_sources.append("glslang/OSDependent/Unix/ossource.cpp")
+
+thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources]
+
+
+env_glslang.add_source_files(env.modules_sources, thirdparty_sources)
+# Godot's own source files
+env_glslang.add_source_files(env.modules_sources, "*.cpp")
+env.Prepend(CPPPATH=[thirdparty_dir])
+
+
+
diff --git a/modules/glslang/config.py b/modules/glslang/config.py
new file mode 100644
index 0000000000..1c8cd12a2d
--- /dev/null
+++ b/modules/glslang/config.py
@@ -0,0 +1,5 @@
+def can_build(env, platform):
+ return True
+
+def configure(env):
+ pass
diff --git a/modules/glslang/register_types.cpp b/modules/glslang/register_types.cpp
new file mode 100644
index 0000000000..ef159e743d
--- /dev/null
+++ b/modules/glslang/register_types.cpp
@@ -0,0 +1,240 @@
+/*************************************************************************/
+/* register_types.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "register_types.h"
+#include "servers/visual/rendering_device.h"
+
+#include "thirdparty/glslang/SPIRV/GlslangToSpv.h"
+#include "thirdparty/glslang/glslang/Include/Types.h"
+#include "thirdparty/glslang/glslang/Public/ShaderLang.h"
+
+static const TBuiltInResource default_builtin_resource = {
+ .maxLights = 32,
+ .maxClipPlanes = 6,
+ .maxTextureUnits = 32,
+ .maxTextureCoords = 32,
+ .maxVertexAttribs = 64,
+ .maxVertexUniformComponents = 4096,
+ .maxVaryingFloats = 64,
+ .maxVertexTextureImageUnits = 32,
+ .maxCombinedTextureImageUnits = 80,
+ .maxTextureImageUnits = 32,
+ .maxFragmentUniformComponents = 4096,
+ .maxDrawBuffers = 32,
+ .maxVertexUniformVectors = 128,
+ .maxVaryingVectors = 8,
+ .maxFragmentUniformVectors = 16,
+ .maxVertexOutputVectors = 16,
+ .maxFragmentInputVectors = 15,
+ .minProgramTexelOffset = -8,
+ .maxProgramTexelOffset = 7,
+ .maxClipDistances = 8,
+ .maxComputeWorkGroupCountX = 65535,
+ .maxComputeWorkGroupCountY = 65535,
+ .maxComputeWorkGroupCountZ = 65535,
+ .maxComputeWorkGroupSizeX = 1024,
+ .maxComputeWorkGroupSizeY = 1024,
+ .maxComputeWorkGroupSizeZ = 64,
+ .maxComputeUniformComponents = 1024,
+ .maxComputeTextureImageUnits = 16,
+ .maxComputeImageUniforms = 8,
+ .maxComputeAtomicCounters = 8,
+ .maxComputeAtomicCounterBuffers = 1,
+ .maxVaryingComponents = 60,
+ .maxVertexOutputComponents = 64,
+ .maxGeometryInputComponents = 64,
+ .maxGeometryOutputComponents = 128,
+ .maxFragmentInputComponents = 128,
+ .maxImageUnits = 8,
+ .maxCombinedImageUnitsAndFragmentOutputs = 8,
+ .maxCombinedShaderOutputResources = 8,
+ .maxImageSamples = 0,
+ .maxVertexImageUniforms = 0,
+ .maxTessControlImageUniforms = 0,
+ .maxTessEvaluationImageUniforms = 0,
+ .maxGeometryImageUniforms = 0,
+ .maxFragmentImageUniforms = 8,
+ .maxCombinedImageUniforms = 8,
+ .maxGeometryTextureImageUnits = 16,
+ .maxGeometryOutputVertices = 256,
+ .maxGeometryTotalOutputComponents = 1024,
+ .maxGeometryUniformComponents = 1024,
+ .maxGeometryVaryingComponents = 64,
+ .maxTessControlInputComponents = 128,
+ .maxTessControlOutputComponents = 128,
+ .maxTessControlTextureImageUnits = 16,
+ .maxTessControlUniformComponents = 1024,
+ .maxTessControlTotalOutputComponents = 4096,
+ .maxTessEvaluationInputComponents = 128,
+ .maxTessEvaluationOutputComponents = 128,
+ .maxTessEvaluationTextureImageUnits = 16,
+ .maxTessEvaluationUniformComponents = 1024,
+ .maxTessPatchComponents = 120,
+ .maxPatchVertices = 32,
+ .maxTessGenLevel = 64,
+ .maxViewports = 16,
+ .maxVertexAtomicCounters = 0,
+ .maxTessControlAtomicCounters = 0,
+ .maxTessEvaluationAtomicCounters = 0,
+ .maxGeometryAtomicCounters = 0,
+ .maxFragmentAtomicCounters = 8,
+ .maxCombinedAtomicCounters = 8,
+ .maxAtomicCounterBindings = 1,
+ .maxVertexAtomicCounterBuffers = 0,
+ .maxTessControlAtomicCounterBuffers = 0,
+ .maxTessEvaluationAtomicCounterBuffers = 0,
+ .maxGeometryAtomicCounterBuffers = 0,
+ .maxFragmentAtomicCounterBuffers = 1,
+ .maxCombinedAtomicCounterBuffers = 1,
+ .maxAtomicCounterBufferSize = 16384,
+ .maxTransformFeedbackBuffers = 4,
+ .maxTransformFeedbackInterleavedComponents = 64,
+ .maxCullDistances = 8,
+ .maxCombinedClipAndCullDistances = 8,
+ .maxSamples = 4,
+ .limits = {
+ .nonInductiveForLoops = 1,
+ .whileLoops = 1,
+ .doWhileLoops = 1,
+ .generalUniformIndexing = 1,
+ .generalAttributeMatrixVectorIndexing = 1,
+ .generalVaryingIndexing = 1,
+ .generalSamplerIndexing = 1,
+ .generalVariableIndexing = 1,
+ .generalConstantMatrixVectorIndexing = 1,
+ }
+};
+
+
+
+static PoolVector<uint8_t> _compile_shader_glsl(RenderingDevice::ShaderStage p_stage, const String &p_source_code, RenderingDevice::ShaderLanguage p_language, String *r_error) {
+
+ PoolVector<uint8_t> ret;
+
+ ERR_FAIL_COND_V(p_language==RenderingDevice::SHADER_LANGUAGE_HLSL,ret);
+
+ // initialize in case it's not initialized. This is done once per thread
+ // and it's safe to call multiple times
+ glslang::InitializeProcess();
+ EShLanguage stages[RenderingDevice::SHADER_STAGE_MAX] = {
+ EShLangVertex,
+ EShLangFragment,
+ EShLangTessControl,
+ EShLangTessEvaluation,
+ EShLangCompute
+ };
+
+ int ClientInputSemanticsVersion = 100; // maps to, say, #define VULKAN 100
+
+ glslang::EShTargetClientVersion VulkanClientVersion = glslang::EShTargetVulkan_1_0;
+ glslang::EShTargetLanguageVersion TargetVersion = glslang::EShTargetSpv_1_0;
+ glslang::TShader::ForbidIncluder includer;
+
+ glslang::TShader shader(stages[p_stage]);
+ CharString cs = p_source_code.ascii();
+ const char *cs_strings = cs.get_data();
+
+ shader.setStrings(&cs_strings, 1);
+ shader.setEnvInput(glslang::EShSourceGlsl, stages[p_stage], glslang::EShClientVulkan, ClientInputSemanticsVersion);
+ shader.setEnvClient(glslang::EShClientVulkan, VulkanClientVersion);
+ shader.setEnvTarget(glslang::EShTargetSpv, TargetVersion);
+
+ EShMessages messages = (EShMessages)(EShMsgSpvRules | EShMsgVulkanRules);
+ const int DefaultVersion = 100;
+ std::string pre_processed_code;
+
+ //preprocess
+ if (!shader.preprocess(&default_builtin_resource, DefaultVersion, ENoProfile, false, false, messages, &pre_processed_code, includer)) {
+
+ if (r_error) {
+ (*r_error) = "Failed pre-process:\n";
+ (*r_error) += shader.getInfoLog();
+ (*r_error) += "\n";
+ (*r_error) += shader.getInfoDebugLog();
+ }
+
+ return ret;
+ }
+ //set back..
+ cs_strings = pre_processed_code.c_str();
+ shader.setStrings(&cs_strings, 1);
+
+ //parse
+ if (!shader.parse(&default_builtin_resource, DefaultVersion, false, messages)) {
+ if (r_error) {
+ (*r_error) = "Failed parse:\n";
+ (*r_error) += shader.getInfoLog();
+ (*r_error) += "\n";
+ (*r_error) += shader.getInfoDebugLog();
+ }
+ return ret;
+ }
+
+ //link
+ glslang::TProgram program;
+ program.addShader(&shader);
+
+ if (!program.link(messages)) {
+ if (r_error) {
+ (*r_error) = "Failed link:\n";
+ (*r_error) += program.getInfoLog();
+ (*r_error) += "\n";
+ (*r_error) += program.getInfoDebugLog();
+ }
+
+ return ret;
+ }
+
+
+ std::vector<uint32_t> SpirV;
+ spv::SpvBuildLogger logger;
+ glslang::SpvOptions spvOptions;
+ glslang::GlslangToSpv(*program.getIntermediate(stages[p_stage]), SpirV, &logger, &spvOptions);
+
+
+ ret.resize(SpirV.size() * sizeof(uint32_t));
+ {
+ PoolVector<uint8_t>::Write w = ret.write();
+ copymem(w.ptr(),&SpirV[0],SpirV.size()*sizeof(uint32_t));
+ }
+
+ return ret;
+}
+
+void preregister_glslang_types() {
+ RenderingDevice::shader_set_compile_function(_compile_shader_glsl);
+}
+
+void register_glslang_types() {
+}
+void unregister_glslang_types() {
+
+
+}
diff --git a/modules/glslang/register_types.h b/modules/glslang/register_types.h
new file mode 100644
index 0000000000..83bfaf8d93
--- /dev/null
+++ b/modules/glslang/register_types.h
@@ -0,0 +1,34 @@
+/*************************************************************************/
+/* register_types.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#define MODULE_GLSLANG_HAS_PREREGISTER
+void preregister_glslang_types();
+void register_glslang_types();
+void unregister_glslang_types();
diff --git a/modules/register_module_types.h b/modules/register_module_types.h
index b410457201..acd9fc7c97 100644
--- a/modules/register_module_types.h
+++ b/modules/register_module_types.h
@@ -31,6 +31,7 @@
#ifndef REGISTER_MODULE_TYPES_H
#define REGISTER_MODULE_TYPES_H
+void preregister_module_types();
void register_module_types();
void unregister_module_types();
diff --git a/servers/visual/rasterizer_rd/rasterizer_rd.cpp b/servers/visual/rasterizer_rd/rasterizer_rd.cpp
index d1c7549409..9be7a6e3f7 100644
--- a/servers/visual/rasterizer_rd/rasterizer_rd.cpp
+++ b/servers/visual/rasterizer_rd/rasterizer_rd.cpp
@@ -61,9 +61,9 @@ void RasterizerRD::end_frame(bool p_swap_buffers) {
void RasterizerRD::initialize() {
{ //create framebuffer copy shader
- RenderingDevice::ShaderStageSource vert;
+ RenderingDevice::ShaderStageData vert;
vert.shader_stage = RenderingDevice::SHADER_STAGE_VERTEX;
- vert.shader_source =
+ vert.spir_v = RenderingDevice::get_singleton()->shader_compile_from_source(RenderingDevice::SHADER_STAGE_VERTEX,
"#version 450\n"
"layout(push_constant, binding = 0, std140) uniform Pos { vec4 dst_rect; } pos;\n"
"layout(location =0) out vec2 uv;\n"
@@ -72,22 +72,22 @@ void RasterizerRD::initialize() {
" uv = base_arr[gl_VertexIndex];\n"
" vec2 vtx = pos.dst_rect.xy+uv*pos.dst_rect.zw;\n"
" gl_Position = vec4(vtx * 2.0 - 1.0,0.0,1.0);\n"
- "}\n";
+ "}\n");
- RenderingDevice::ShaderStageSource frag;
+ RenderingDevice::ShaderStageData frag;
frag.shader_stage = RenderingDevice::SHADER_STAGE_FRAGMENT;
- frag.shader_source =
+ 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"
"layout (binding = 0) uniform sampler2D src_rt;\n"
- "void main() { color=texture(src_rt,uv); }\n";
+ "void main() { color=texture(src_rt,uv); }\n");
- Vector<RenderingDevice::ShaderStageSource> source;
+ Vector<RenderingDevice::ShaderStageData> source;
source.push_back(vert);
source.push_back(frag);
String error;
- copy_viewports_rd_shader = RD::get_singleton()->shader_create_from_source(source, &error);
+ copy_viewports_rd_shader = RD::get_singleton()->shader_create(source);
if (!copy_viewports_rd_shader.is_valid()) {
print_line("failed compilation: " + error);
} else {
diff --git a/servers/visual/rasterizer_rd/shader_rd.cpp b/servers/visual/rasterizer_rd/shader_rd.cpp
index d4b3db60ac..945fc25cab 100644
--- a/servers/visual/rasterizer_rd/shader_rd.cpp
+++ b/servers/visual/rasterizer_rd/shader_rd.cpp
@@ -171,7 +171,12 @@ void ShaderRD::_compile_version(Version *p_version) {
for (int i = 0; i < variant_defines.size(); i++) {
- Vector<RD::ShaderStageSource> stages;
+ Vector<RD::ShaderStageData> stages;
+
+ String error;
+ String current_source;
+ RD::ShaderStage current_stage = RD::SHADER_STAGE_VERTEX;
+ bool build_ok=true;
{
//vertex stage
@@ -201,15 +206,21 @@ void ShaderRD::_compile_version(Version *p_version) {
builder.append(vertex_code3.get_data()); //fourth of vertex
- RD::ShaderStageSource stage;
- stage.shader_source = builder.as_string();
- stage.shader_stage = RD::SHADER_STAGE_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 {
- stages.push_back(stage);
+ stage.shader_stage = RD::SHADER_STAGE_VERTEX;
+ stages.push_back(stage);
+ }
}
- {
+ if (build_ok){
//fragment stage
+ current_stage =RD::SHADER_STAGE_FRAGMENT;
StringBuilder builder;
@@ -240,29 +251,26 @@ void ShaderRD::_compile_version(Version *p_version) {
builder.append(fragment_code4.get_data()); //fourth part of fragment
- RD::ShaderStageSource stage;
- stage.shader_source = builder.as_string();
- stage.shader_stage = RD::SHADER_STAGE_FRAGMENT;
-#if 0
- if (stage.shader_stage == RD::SHADER_STAGE_FRAGMENT && p_version->uniforms.length()) {
- print_line(stage.shader_source.get_with_code_lines());
+ 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 {
+
+ stage.shader_stage = RD::SHADER_STAGE_FRAGMENT;
+ stages.push_back(stage);
}
-#endif
- stages.push_back(stage);
+
}
- String error;
- RD::ShaderStage error_stage;
- RID shader = RD::get_singleton()->shader_create_from_source(stages, &error, &error_stage);
- if (shader.is_null() && error != String()) {
- ERR_PRINT("Error compiling shader, variant #" + itos(i) + " (" + variant_defines[i].get_data() + ").");
+ 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);
#ifdef DEBUG_ENABLED
- if (error_stage < RD::SHADER_STAGE_MAX) {
- ERR_PRINT("code:\n" + stages[error_stage].shader_source.get_with_code_lines());
- }
+ ERR_PRINT("code:\n" + current_source.get_with_code_lines());
#endif
//clear versions if they exist
for (int j = 0; j < i; j++) {
@@ -274,6 +282,19 @@ void ShaderRD::_compile_version(Version *p_version) {
return;
}
+ RID shader = RD::get_singleton()->shader_create(stages);
+
+ if (shader.is_null()) {
+ //clear versions if they exist
+ for (int j = 0; j < i; j++) {
+ RD::get_singleton()->free(p_version->variants[j]);
+ }
+
+ memdelete_arr(p_version->variants);
+ p_version->variants = NULL;
+ return;
+ }
+
p_version->variants[i] = shader;
}
diff --git a/servers/visual/rendering_device.cpp b/servers/visual/rendering_device.cpp
index eaecc76b55..55707acc8c 100644
--- a/servers/visual/rendering_device.cpp
+++ b/servers/visual/rendering_device.cpp
@@ -1,13 +1,38 @@
#include "rendering_device.h"
-
-RenderingDevice *RenderingDevice::singleton=NULL;
+RenderingDevice *RenderingDevice::singleton = NULL;
RenderingDevice *RenderingDevice::get_singleton() {
return singleton;
}
+RenderingDevice::ShaderCompileFunction RenderingDevice::compile_function = NULL;
+RenderingDevice::ShaderCacheFunction RenderingDevice::cache_function = NULL;
+
+void RenderingDevice::shader_set_compile_function(ShaderCompileFunction p_function) {
+ compile_function = p_function;
+}
+void RenderingDevice::shader_set_cache_function(ShaderCacheFunction p_function) {
+ cache_function = p_function;
+}
+
+PoolVector<uint8_t> RenderingDevice::shader_compile_from_source(ShaderStage p_stage, const String &p_source_code, ShaderLanguage p_language, String *r_error, bool p_allow_cache) {
+ if (p_allow_cache && cache_function) {
+ PoolVector<uint8_t> cache = cache_function(p_stage, p_source_code, p_language);
+ if (cache.size()) {
+ return cache;
+ }
+ }
+
+ ERR_FAIL_COND_V(!compile_function, PoolVector<uint8_t>());
+
+ return compile_function(p_stage, p_source_code, p_language, r_error);
+}
+
RenderingDevice::RenderingDevice() {
- singleton=this;
+ ShaderCompileFunction compile_function;
+ ShaderCacheFunction cache_function;
+
+ singleton = this;
}
diff --git a/servers/visual/rendering_device.h b/servers/visual/rendering_device.h
index fed2b0e79d..4f32673dc7 100644
--- a/servers/visual/rendering_device.h
+++ b/servers/visual/rendering_device.h
@@ -5,6 +5,32 @@
class RenderingDevice : public Object {
GDCLASS(RenderingDevice, Object)
+public:
+ enum ShaderStage {
+ SHADER_STAGE_VERTEX,
+ SHADER_STAGE_FRAGMENT,
+ SHADER_STAGE_TESSELATION_CONTROL,
+ SHADER_STAGE_TESSELATION_EVALUATION,
+ SHADER_STAGE_COMPUTE,
+ SHADER_STAGE_MAX,
+ SHADER_STAGE_VERTEX_BIT = (1 << SHADER_STAGE_VERTEX),
+ SHADER_STAGE_FRAGMENT_BIT = (1 << SHADER_STAGE_FRAGMENT),
+ SHADER_STAGE_TESSELATION_CONTROL_BIT = (1 << SHADER_STAGE_TESSELATION_CONTROL),
+ SHADER_STAGE_TESSELATION_EVALUATION_BIT = (1 << SHADER_STAGE_TESSELATION_EVALUATION),
+ SHADER_STAGE_COMPUTE_BIT = (1 << SHADER_STAGE_COMPUTE),
+ };
+
+ enum ShaderLanguage {
+ SHADER_LANGUAGE_GLSL,
+ SHADER_LANGUAGE_HLSL
+ };
+
+ typedef PoolVector<uint8_t> (*ShaderCompileFunction)(ShaderStage p_stage, const String &p_source_code, ShaderLanguage p_language, String *r_error);
+ typedef PoolVector<uint8_t> (*ShaderCacheFunction)(ShaderStage p_stage, const String &p_source_code, ShaderLanguage p_language);
+
+private:
+ static ShaderCompileFunction compile_function;
+ static ShaderCacheFunction cache_function;
static RenderingDevice *singleton;
@@ -497,29 +523,21 @@ public:
/**** SHADER ****/
/****************/
- enum ShaderStage {
- SHADER_STAGE_VERTEX,
- SHADER_STAGE_FRAGMENT,
- SHADER_STAGE_TESSELATION_CONTROL,
- SHADER_STAGE_TESSELATION_EVALUATION,
- SHADER_STAGE_COMPUTE,
- SHADER_STAGE_MAX,
- SHADER_STAGE_VERTEX_BIT = (1 << SHADER_STAGE_VERTEX),
- SHADER_STAGE_FRAGMENT_BIT = (1 << SHADER_STAGE_FRAGMENT),
- SHADER_STAGE_TESSELATION_CONTROL_BIT = (1 << SHADER_STAGE_TESSELATION_CONTROL),
- SHADER_STAGE_TESSELATION_EVALUATION_BIT = (1 << SHADER_STAGE_TESSELATION_EVALUATION),
- SHADER_STAGE_COMPUTE_BIT = (1 << SHADER_STAGE_COMPUTE),
- };
+ virtual PoolVector<uint8_t> shader_compile_from_source(ShaderStage p_stage, const String &p_source_code, ShaderLanguage p_language = SHADER_LANGUAGE_GLSL, String *r_error = NULL, bool p_allow_cache = true);
- struct ShaderStageSource {
+ static void shader_set_compile_function(ShaderCompileFunction p_function);
+ static void shader_set_cache_function(ShaderCacheFunction p_function);
+
+ struct ShaderStageData {
ShaderStage shader_stage;
- String shader_source;
- ShaderStageSource() {
+ PoolVector<uint8_t> spir_v;
+
+ ShaderStageData() {
shader_stage = SHADER_STAGE_VERTEX;
}
};
- virtual RID shader_create_from_source(const Vector<ShaderStageSource> &p_stages, String *r_error = NULL, ShaderStage *r_error_stage = NULL, bool p_allow_cache = true) = 0;
+ virtual RID shader_create(const Vector<ShaderStageData> &p_stages) = 0;
virtual Vector<int> shader_get_vertex_input_locations_used(RID p_shader) = 0;
/******************/