Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/gpu/intern/gpu_shader_create_info.cc')
-rw-r--r--source/blender/gpu/intern/gpu_shader_create_info.cc164
1 files changed, 141 insertions, 23 deletions
diff --git a/source/blender/gpu/intern/gpu_shader_create_info.cc b/source/blender/gpu/intern/gpu_shader_create_info.cc
index b8ae6bc3868..fe0304828c2 100644
--- a/source/blender/gpu/intern/gpu_shader_create_info.cc
+++ b/source/blender/gpu/intern/gpu_shader_create_info.cc
@@ -27,11 +27,15 @@
#include "BLI_set.hh"
#include "BLI_string_ref.hh"
+#include "GPU_capabilities.h"
+#include "GPU_platform.h"
#include "GPU_shader.h"
#include "GPU_texture.h"
#include "gpu_shader_create_info.hh"
#include "gpu_shader_create_info_private.hh"
+#include "gpu_shader_dependency_private.h"
+#include "gpu_shader_private.hh"
#undef GPU_SHADER_INTERFACE_INFO
#undef GPU_SHADER_CREATE_INFO
@@ -51,6 +55,8 @@ void ShaderCreateInfo::finalize()
}
finalized_ = true;
+ Set<StringRefNull> deps_merged;
+
for (auto &info_name : additional_infos_) {
const ShaderCreateInfo &info = *reinterpret_cast<const ShaderCreateInfo *>(
gpu_shader_create_info_get(info_name.c_str()));
@@ -70,42 +76,81 @@ void ShaderCreateInfo::finalize()
batch_resources_.extend(info.batch_resources_);
pass_resources_.extend(info.pass_resources_);
- typedef_sources_.extend(info.typedef_sources_);
+ typedef_sources_.extend_non_duplicates(info.typedef_sources_);
validate(info);
- if (info.local_group_size_[0] != 0) {
- BLI_assert(local_group_size_[0] == 0);
- for (int i = 0; i < 3; i++) {
- local_group_size_[i] = info.local_group_size_[i];
+ auto assert_no_overlap = [&](const bool test, const StringRefNull error) {
+ if (!test) {
+ std::cout << name_ << ": Validation failed while merging " << info.name_ << " : ";
+ std::cout << error << std::endl;
+ BLI_assert(0);
}
+ };
+
+ if (!deps_merged.add(info.name_)) {
+ assert_no_overlap(false, "additional info already merged via another info");
+ }
+
+ if (info.compute_layout_.local_size_x != -1) {
+ assert_no_overlap(compute_layout_.local_size_x == -1, "Compute layout already defined");
+ compute_layout_ = info.compute_layout_;
}
+
if (!info.vertex_source_.is_empty()) {
- BLI_assert(vertex_source_.is_empty());
+ assert_no_overlap(vertex_source_.is_empty(), "Vertex source already existing");
vertex_source_ = info.vertex_source_;
}
if (!info.geometry_source_.is_empty()) {
- BLI_assert(geometry_source_.is_empty());
+ assert_no_overlap(geometry_source_.is_empty(), "Geometry source already existing");
geometry_source_ = info.geometry_source_;
geometry_layout_ = info.geometry_layout_;
}
if (!info.fragment_source_.is_empty()) {
- BLI_assert(fragment_source_.is_empty());
+ assert_no_overlap(fragment_source_.is_empty(), "Fragment source already existing");
fragment_source_ = info.fragment_source_;
}
if (!info.compute_source_.is_empty()) {
- BLI_assert(compute_source_.is_empty());
+ assert_no_overlap(compute_source_.is_empty(), "Compute source already existing");
compute_source_ = info.compute_source_;
}
do_static_compilation_ = do_static_compilation_ || info.do_static_compilation_;
}
+
+ if (auto_resource_location_) {
+ int images = 0, samplers = 0, ubos = 0, ssbos = 0;
+
+ auto set_resource_slot = [&](Resource &res) {
+ switch (res.bind_type) {
+ case Resource::BindType::UNIFORM_BUFFER:
+ res.slot = ubos++;
+ break;
+ case Resource::BindType::STORAGE_BUFFER:
+ res.slot = ssbos++;
+ break;
+ case Resource::BindType::SAMPLER:
+ res.slot = samplers++;
+ break;
+ case Resource::BindType::IMAGE:
+ res.slot = images++;
+ break;
+ }
+ };
+
+ for (auto &res : batch_resources_) {
+ set_resource_slot(res);
+ }
+ for (auto &res : pass_resources_) {
+ set_resource_slot(res);
+ }
+ }
}
void ShaderCreateInfo::validate(const ShaderCreateInfo &other_info)
{
- {
- /* Check same bindpoints usage in OGL. */
+ if (!auto_resource_location_) {
+ /* Check same bind-points usage in OGL. */
Set<int> images, samplers, ubos, ssbos;
auto register_resource = [&](const Resource &res) -> bool {
@@ -124,26 +169,26 @@ void ShaderCreateInfo::validate(const ShaderCreateInfo &other_info)
};
auto print_error_msg = [&](const Resource &res) {
- std::cerr << name_ << ": Validation failed : Overlapping ";
+ std::cout << name_ << ": Validation failed : Overlapping ";
switch (res.bind_type) {
case Resource::BindType::UNIFORM_BUFFER:
- std::cerr << "Uniform Buffer " << res.uniformbuf.name;
+ std::cout << "Uniform Buffer " << res.uniformbuf.name;
break;
case Resource::BindType::STORAGE_BUFFER:
- std::cerr << "Storage Buffer " << res.storagebuf.name;
+ std::cout << "Storage Buffer " << res.storagebuf.name;
break;
case Resource::BindType::SAMPLER:
- std::cerr << "Sampler " << res.sampler.name;
+ std::cout << "Sampler " << res.sampler.name;
break;
case Resource::BindType::IMAGE:
- std::cerr << "Image " << res.image.name;
+ std::cout << "Image " << res.image.name;
break;
default:
- std::cerr << "Unknown Type";
+ std::cout << "Unknown Type";
break;
}
- std::cerr << " (" << res.slot << ") while merging " << other_info.name_ << std::endl;
+ std::cout << " (" << res.slot << ") while merging " << other_info.name_ << std::endl;
};
for (auto &res : batch_resources_) {
@@ -159,7 +204,7 @@ void ShaderCreateInfo::validate(const ShaderCreateInfo &other_info)
}
}
{
- /* TODO(fclem) Push constant validation. */
+ /* TODO(@fclem): Push constant validation. */
}
}
@@ -194,6 +239,22 @@ void gpu_shader_create_info_init()
# include "gpu_shader_baked.hh"
#endif
+ /* WORKAROUND: Replace draw_mesh info with the legacy one for systems that have problems with UBO
+ * indexing. */
+ if (GPU_type_matches(GPU_DEVICE_INTEL | GPU_DEVICE_INTEL_UHD, GPU_OS_ANY, GPU_DRIVER_ANY) ||
+ GPU_type_matches(GPU_DEVICE_ANY, GPU_OS_MAC, GPU_DRIVER_ANY) || GPU_crappy_amd_driver()) {
+ draw_modelmat = draw_modelmat_legacy;
+ }
+
+ for (ShaderCreateInfo *info : g_create_infos->values()) {
+ if (info->do_static_compilation_) {
+ info->builtins_ |= gpu_shader_dependency_get_builtins(info->vertex_source_);
+ info->builtins_ |= gpu_shader_dependency_get_builtins(info->fragment_source_);
+ info->builtins_ |= gpu_shader_dependency_get_builtins(info->geometry_source_);
+ info->builtins_ |= gpu_shader_dependency_get_builtins(info->compute_source_);
+ }
+ }
+
/* TEST */
// gpu_shader_create_info_compile_all();
}
@@ -213,25 +274,82 @@ void gpu_shader_create_info_exit()
bool gpu_shader_create_info_compile_all()
{
+ using namespace blender::gpu;
+ int success = 0;
+ int total = 0;
for (ShaderCreateInfo *info : g_create_infos->values()) {
if (info->do_static_compilation_) {
- // printf("Compiling %s: ... \n", info->name_.c_str());
+ total++;
GPUShader *shader = GPU_shader_create_from_info(
reinterpret_cast<const GPUShaderCreateInfo *>(info));
if (shader == nullptr) {
printf("Compilation %s Failed\n", info->name_.c_str());
- return false;
+ }
+ else {
+ success++;
+
+#if 0 /* TODO(fclem): This is too verbose for now. Make it a cmake option. */
+ /* Test if any resource is optimized out and print a warning if that's the case. */
+ /* TODO(fclem): Limit this to OpenGL backend. */
+ const ShaderInterface *interface = unwrap(shader)->interface;
+
+ blender::Vector<ShaderCreateInfo::Resource> all_resources;
+ all_resources.extend(info->pass_resources_);
+ all_resources.extend(info->batch_resources_);
+
+ for (ShaderCreateInfo::Resource &res : all_resources) {
+ blender::StringRefNull name = "";
+ const ShaderInput *input = nullptr;
+
+ switch (res.bind_type) {
+ case ShaderCreateInfo::Resource::BindType::UNIFORM_BUFFER:
+ input = interface->ubo_get(res.slot);
+ name = res.uniformbuf.name;
+ break;
+ case ShaderCreateInfo::Resource::BindType::STORAGE_BUFFER:
+ input = interface->ssbo_get(res.slot);
+ name = res.storagebuf.name;
+ break;
+ case ShaderCreateInfo::Resource::BindType::SAMPLER:
+ input = interface->texture_get(res.slot);
+ name = res.sampler.name;
+ break;
+ case ShaderCreateInfo::Resource::BindType::IMAGE:
+ input = interface->texture_get(res.slot);
+ name = res.image.name;
+ break;
+ }
+
+ if (input == nullptr) {
+ std::cout << "Error: " << info->name_;
+ std::cout << ": Resource « " << name << " » not found in the shader interface\n";
+ }
+ else if (input->location == -1) {
+ std::cout << "Warning: " << info->name_;
+ std::cout << ": Resource « " << name << " » is optimized out\n";
+ }
+ }
+#endif
}
GPU_shader_free(shader);
- // printf("Success\n");
}
}
- return true;
+ printf("===============================\n");
+ printf("Shader Test compilation result: \n");
+ printf("%d Total\n", total);
+ printf("%d Passed\n", success);
+ printf("%d Failed\n", total - success);
+ printf("===============================\n");
+ return success == total;
}
/* Runtime create infos are not registered in the dictionary and cannot be searched. */
const GPUShaderCreateInfo *gpu_shader_create_info_get(const char *info_name)
{
+ if (g_create_infos->contains(info_name) == false) {
+ printf("Error: Cannot find shader create info named \"%s\"\n", info_name);
+ return nullptr;
+ }
ShaderCreateInfo *info = g_create_infos->lookup(info_name);
return reinterpret_cast<const GPUShaderCreateInfo *>(info);
}