Moved the shader source compilation code outside RenderingDevice and Vulkan
This commit is contained in:
parent
60c7498cee
commit
4fe3ee1730
14 changed files with 490 additions and 384 deletions
|
@ -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")
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
/*****************/
|
||||
|
|
|
@ -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));
|
||||
|
||||
|
|
12
methods.py
12
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:
|
||||
|
|
68
modules/glslang/SCsub
Normal file
68
modules/glslang/SCsub
Normal file
|
@ -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])
|
||||
|
||||
|
||||
|
5
modules/glslang/config.py
Normal file
5
modules/glslang/config.py
Normal file
|
@ -0,0 +1,5 @@
|
|||
def can_build(env, platform):
|
||||
return True
|
||||
|
||||
def configure(env):
|
||||
pass
|
240
modules/glslang/register_types.cpp
Normal file
240
modules/glslang/register_types.cpp
Normal file
|
@ -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() {
|
||||
|
||||
|
||||
}
|
34
modules/glslang/register_types.h
Normal file
34
modules/glslang/register_types.h
Normal file
|
@ -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();
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
/******************/
|
||||
|
|
Loading…
Reference in a new issue