diff options
Diffstat (limited to 'source/blender/gpu/intern/gpu_shader.cc')
-rw-r--r-- | source/blender/gpu/intern/gpu_shader.cc | 192 |
1 files changed, 192 insertions, 0 deletions
diff --git a/source/blender/gpu/intern/gpu_shader.cc b/source/blender/gpu/intern/gpu_shader.cc index 3f5a639d2a0..3b41e804fd4 100644 --- a/source/blender/gpu/intern/gpu_shader.cc +++ b/source/blender/gpu/intern/gpu_shader.cc @@ -31,10 +31,32 @@ #include "gpu_backend.hh" #include "gpu_context_private.hh" +#include "gpu_shader_create_info.hh" +#include "gpu_shader_create_info_private.hh" +#include "gpu_shader_dependency_private.h" #include "gpu_shader_private.hh" +#include <string> + extern "C" char datatoc_gpu_shader_colorspace_lib_glsl[]; +namespace blender::gpu { + +std::string Shader::defines_declare(const shader::ShaderCreateInfo &info) const +{ + std::string defines; + for (const auto &def : info.defines_) { + defines += "#define "; + defines += def[0]; + defines += " "; + defines += def[1]; + defines += "\n"; + } + return defines; +} + +} // namespace blender::gpu + using namespace blender; using namespace blender::gpu; @@ -59,6 +81,8 @@ static void standard_defines(Vector<const char *> &sources) BLI_assert(sources.size() == 0); /* Version needs to be first. Exact values will be added by implementation. */ sources.append("version"); + /* Define to identify code usage in shading language. */ + sources.append("#define GPU_SHADER\n"); /* some useful defines to detect GPU type */ if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_ANY, GPU_DRIVER_ANY)) { sources.append("#define GPU_ATI\n"); @@ -225,6 +249,174 @@ GPUShader *GPU_shader_create_compute(const char *computecode, shname); } +GPUShader *GPU_shader_create_from_info(const GPUShaderCreateInfo *_info) +{ + using namespace blender::gpu::shader; + const ShaderCreateInfo &info = *reinterpret_cast<const ShaderCreateInfo *>(_info); + + const_cast<ShaderCreateInfo &>(info).finalize(); + + /* At least a vertex shader and a fragment shader are required, or only a compute shader. */ + if (info.compute_source_.is_empty()) { + if (info.vertex_source_.is_empty()) { + printf("Missing vertex shader in %s.\n", info.name_.c_str()); + } + if (info.fragment_source_.is_empty()) { + printf("Missing fragment shader in %s.\n", info.name_.c_str()); + } + BLI_assert(!info.vertex_source_.is_empty() && !info.fragment_source_.is_empty()); + } + else { + if (!info.vertex_source_.is_empty()) { + printf("Compute shader has vertex_source_ shader attached in %s.\n", info.name_.c_str()); + } + if (!info.geometry_source_.is_empty()) { + printf("Compute shader has geometry_source_ shader attached in %s.\n", info.name_.c_str()); + } + if (!info.fragment_source_.is_empty()) { + printf("Compute shader has fragment_source_ shader attached in %s.\n", info.name_.c_str()); + } + BLI_assert(info.vertex_source_.is_empty() && info.geometry_source_.is_empty() && + info.fragment_source_.is_empty()); + } + + Shader *shader = GPUBackend::get()->shader_alloc(info.name_.c_str()); + + std::string defines = shader->defines_declare(info); + std::string resources = shader->resources_declare(info); + char *shader_shared_utils = nullptr; + + defines += "#define USE_GPU_SHADER_CREATE_INFO\n"; + + Vector<char *> typedefs; + for (auto filename : info.typedef_sources_) { + typedefs.append(gpu_shader_dependency_get_source(filename.c_str())); + } + if (!typedefs.is_empty()) { + shader_shared_utils = gpu_shader_dependency_get_source("gpu_shader_shared_utils.h"); + } + + if (!info.vertex_source_.is_empty()) { + uint32_t builtins = 0; + std::string interface = shader->vertex_interface_declare(info); + char *code = gpu_shader_dependency_get_resolved_source(info.vertex_source_.c_str(), &builtins); + + Vector<const char *> sources; + standard_defines(sources); + sources.append("#define GPU_VERTEX_SHADER\n"); + if (!info.geometry_source_.is_empty()) { + sources.append("#define USE_GEOMETRY_SHADER\n"); + } + sources.append(defines.c_str()); + if (!typedefs.is_empty()) { + sources.append(shader_shared_utils); + } + for (auto *types : typedefs) { + sources.append(types); + } + sources.append(resources.c_str()); + sources.append(interface.c_str()); + sources.append(code); + + shader->vertex_shader_from_glsl(sources); + + free(code); + } + + if (!info.fragment_source_.is_empty()) { + uint32_t builtins = 0; + std::string interface = shader->fragment_interface_declare(info); + char *code = gpu_shader_dependency_get_resolved_source(info.fragment_source_.c_str(), + &builtins); + + Vector<const char *> sources; + standard_defines(sources); + sources.append("#define GPU_FRAGMENT_SHADER\n"); + if (!info.geometry_source_.is_empty()) { + sources.append("#define USE_GEOMETRY_SHADER\n"); + } + sources.append(defines.c_str()); + if (!typedefs.is_empty()) { + sources.append(shader_shared_utils); + } + for (auto *types : typedefs) { + sources.append(types); + } + sources.append(resources.c_str()); + sources.append(interface.c_str()); + sources.append(code); + + shader->fragment_shader_from_glsl(sources); + + free(code); + } + + if (!info.geometry_source_.is_empty()) { + uint32_t builtins = 0; + std::string interface = shader->geometry_interface_declare(info); + std::string layout = shader->geometry_layout_declare(info); + char *code = gpu_shader_dependency_get_resolved_source(info.geometry_source_.c_str(), + &builtins); + + Vector<const char *> sources; + standard_defines(sources); + sources.append("#define GPU_GEOMETRY_SHADER\n"); + sources.append(defines.c_str()); + if (!typedefs.is_empty()) { + sources.append(shader_shared_utils); + } + for (auto *types : typedefs) { + sources.append(types); + } + sources.append(resources.c_str()); + sources.append(layout.c_str()); + sources.append(interface.c_str()); + sources.append(code); + + shader->geometry_shader_from_glsl(sources); + + free(code); + } + + if (!info.compute_source_.is_empty()) { + uint32_t builtins = 0; + char *code = gpu_shader_dependency_get_resolved_source(info.compute_source_.c_str(), + &builtins); + + Vector<const char *> sources; + standard_defines(sources); + sources.append("#define GPU_COMPUTE_SHADER\n"); + sources.append(defines.c_str()); + if (!typedefs.is_empty()) { + sources.append(shader_shared_utils); + } + for (auto *types : typedefs) { + sources.append(types); + } + sources.append(resources.c_str()); + sources.append(code); + + shader->compute_shader_from_glsl(sources); + + free(code); + } + + for (auto *types : typedefs) { + free(types); + } + + if (shader_shared_utils) { + free(shader_shared_utils); + } + + if (!shader->finalize(&info)) { + delete shader; + return nullptr; + } + + return wrap(shader); +} + GPUShader *GPU_shader_create_from_python(const char *vertcode, const char *fragcode, const char *geomcode, |