From 4fe3ee1730167b90ec8ae70c871c1dad032981d5 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Sun, 28 Jul 2019 19:58:32 -0300 Subject: [PATCH] Moved the shader source compilation code outside RenderingDevice and Vulkan --- drivers/vulkan/SCsub | 58 ---- drivers/vulkan/rendering_device_vulkan.cpp | 283 +----------------- drivers/vulkan/rendering_device_vulkan.h | 7 +- main/main.cpp | 2 + methods.py | 12 +- modules/glslang/SCsub | 68 +++++ modules/glslang/config.py | 5 + modules/glslang/register_types.cpp | 240 +++++++++++++++ modules/glslang/register_types.h | 34 +++ modules/register_module_types.h | 1 + .../visual/rasterizer_rd/rasterizer_rd.cpp | 16 +- servers/visual/rasterizer_rd/shader_rd.cpp | 65 ++-- servers/visual/rendering_device.cpp | 31 +- servers/visual/rendering_device.h | 52 ++-- 14 files changed, 490 insertions(+), 384 deletions(-) create mode 100644 modules/glslang/SCsub create mode 100644 modules/glslang/config.py create mode 100644 modules/glslang/register_types.cpp create mode 100644 modules/glslang/register_types.h diff --git a/drivers/vulkan/SCsub b/drivers/vulkan/SCsub index 8ecfd47a0ad..2251181704c 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 7f4ebd51343..f6154a3cbd3 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 > &bindings, Vector > &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 &p_stages, String *r_error, ShaderStage *r_error_stage, bool p_allow_cache) { +RID RenderingDeviceVulkan::shader_create(const Vector &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 > spirv_code; - - glslang::TShader::ForbidIncluder includer; - //descriptor layouts Vector > set_bindings; Vector > uniform_info; @@ -3581,148 +3464,13 @@ RID RenderingDeviceVulkan::shader_create_from_source(const VectorgetBasicType() == 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 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::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::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 > &bindings, Vector > &uniform_infos, const glslang::TObjectReflection &reflection, RenderingDevice::ShaderStage p_stage, Shader::PushConstant &push_constant, String *r_error); RID_Owner 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 &p_stages, String *r_error = NULL, ShaderStage *r_error_stage = NULL, bool p_allow_cache = true); + virtual RID shader_create(const Vector &p_stages); virtual Vector shader_get_vertex_input_locations_used(RID p_shader); /*****************/ diff --git a/main/main.cpp b/main/main.cpp index d1b1c1198e1..b401cd42333 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 a1d101af188..f6c9e939c6a 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 00000000000..484036dc944 --- /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 00000000000..1c8cd12a2dc --- /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 00000000000..ef159e743de --- /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 _compile_shader_glsl(RenderingDevice::ShaderStage p_stage, const String &p_source_code, RenderingDevice::ShaderLanguage p_language, String *r_error) { + + PoolVector 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 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::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 00000000000..83bfaf8d93f --- /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 b4104572018..acd9fc7c974 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 d1c75494095..9be7a6e3f70 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 source; + Vector 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 d4b3db60ac3..945fc25cab6 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 stages; + Vector 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 eaecc76b558..55707acc8cf 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 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 cache = cache_function(p_stage, p_source_code, p_language); + if (cache.size()) { + return cache; + } + } + + ERR_FAIL_COND_V(!compile_function, PoolVector()); + + 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 fed2b0e79dd..4f32673dc78 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 (*ShaderCompileFunction)(ShaderStage p_stage, const String &p_source_code, ShaderLanguage p_language, String *r_error); + typedef PoolVector (*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 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 spir_v; + + ShaderStageData() { shader_stage = SHADER_STAGE_VERTEX; } }; - virtual RID shader_create_from_source(const Vector &p_stages, String *r_error = NULL, ShaderStage *r_error_stage = NULL, bool p_allow_cache = true) = 0; + virtual RID shader_create(const Vector &p_stages) = 0; virtual Vector shader_get_vertex_input_locations_used(RID p_shader) = 0; /******************/