GPU: Shader Builder Filter
This PR introduced some filters to improve the workflow when using shader_builder. Shader builder is used to validate shader compilation during buildtime and can be enabled using `WITH_GPU_BUILDTIME_SHADER_BUILDER`. During backend development shader builder is also handy as you can pin-point it to the shader/backend you're focusing on. Without filters you would insert temporary code to break on a specific shader. * `--gpu-backend` can be used to only check a specific backend. possible values are `vulkan`, `metal` or `opengl`. When argument isn't passed, all backends will be validated. * `--gpu-shader-filter` can be used to only check a subset or indivisual shader. The filter is a name starts with filter. Use `--gpu-shader-filter eevee` to validate all eevee shaders Pull Request: https://projects.blender.org/blender/blender/pulls/115888
This commit is contained in:
parent
fb5d03b5ba
commit
1b99987043
|
@ -16,6 +16,7 @@
|
|||
#include "GPU_init_exit.h"
|
||||
#include "gpu_shader_create_info_private.hh"
|
||||
|
||||
#include "BLI_string_ref.hh"
|
||||
#include "BLI_vector.hh"
|
||||
|
||||
#include "CLG_log.h"
|
||||
|
@ -29,19 +30,29 @@ class ShaderBuilder {
|
|||
GPUContext *gpu_context_ = nullptr;
|
||||
|
||||
public:
|
||||
void init();
|
||||
bool bake_create_infos();
|
||||
void exit();
|
||||
void init_system();
|
||||
bool init_context();
|
||||
bool bake_create_infos(const char *name_starts_with_filter);
|
||||
void exit_context();
|
||||
void exit_system();
|
||||
};
|
||||
|
||||
bool ShaderBuilder::bake_create_infos()
|
||||
bool ShaderBuilder::bake_create_infos(const char *name_starts_with_filter)
|
||||
{
|
||||
return gpu_shader_create_info_compile_all();
|
||||
return gpu_shader_create_info_compile(name_starts_with_filter);
|
||||
}
|
||||
|
||||
void ShaderBuilder::init()
|
||||
void ShaderBuilder::init_system()
|
||||
{
|
||||
CLG_init();
|
||||
ghost_system_ = GHOST_CreateSystemBackground();
|
||||
}
|
||||
|
||||
bool ShaderBuilder::init_context()
|
||||
{
|
||||
BLI_assert(ghost_system_);
|
||||
BLI_assert(ghost_context_ == nullptr);
|
||||
BLI_assert(gpu_context_ == nullptr);
|
||||
|
||||
GHOST_GPUSettings gpuSettings = {0};
|
||||
switch (GPU_backend_type_selection_get()) {
|
||||
|
@ -68,23 +79,33 @@ void ShaderBuilder::init()
|
|||
break;
|
||||
}
|
||||
|
||||
ghost_system_ = GHOST_CreateSystemBackground();
|
||||
ghost_context_ = GHOST_CreateGPUContext(ghost_system_, gpuSettings);
|
||||
if (ghost_context_ == nullptr) {
|
||||
GHOST_DisposeSystem(ghost_system_);
|
||||
return false;
|
||||
}
|
||||
|
||||
GHOST_ActivateGPUContext(ghost_context_);
|
||||
|
||||
gpu_context_ = GPU_context_create(nullptr, ghost_context_);
|
||||
GPU_init();
|
||||
return true;
|
||||
}
|
||||
|
||||
void ShaderBuilder::exit()
|
||||
void ShaderBuilder::exit_context()
|
||||
{
|
||||
BLI_assert(ghost_context_);
|
||||
BLI_assert(gpu_context_);
|
||||
GPU_exit();
|
||||
|
||||
GPU_context_discard(gpu_context_);
|
||||
|
||||
GHOST_DisposeGPUContext(ghost_system_, ghost_context_);
|
||||
GHOST_DisposeSystem(ghost_system_);
|
||||
gpu_context_ = nullptr;
|
||||
ghost_context_ = nullptr;
|
||||
}
|
||||
|
||||
void ShaderBuilder::exit_system()
|
||||
{
|
||||
GHOST_DisposeSystem(ghost_system_);
|
||||
CLG_exit();
|
||||
}
|
||||
|
||||
|
@ -93,13 +114,58 @@ void ShaderBuilder::exit()
|
|||
/** \brief Entry point for the shader_builder. */
|
||||
int main(int argc, const char *argv[])
|
||||
{
|
||||
if (argc < 2) {
|
||||
printf("Usage: %s <data_file_to>\n", argv[0]);
|
||||
std::string gpu_backend_arg;
|
||||
std::string shader_name_starts_with_filter_arg;
|
||||
std::string result_file_arg;
|
||||
|
||||
int arg = 1;
|
||||
while (arg < argc) {
|
||||
if (arg < argc - 2) {
|
||||
blender::StringRefNull argument = argv[arg];
|
||||
if (argument == "--gpu-backend") {
|
||||
gpu_backend_arg = std::string(argv[arg + 1]);
|
||||
arg += 2;
|
||||
}
|
||||
else if (argument == "--gpu-shader-filter") {
|
||||
shader_name_starts_with_filter_arg = std::string(argv[arg + 1]);
|
||||
arg += 2;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (arg == argc - 1) {
|
||||
result_file_arg = argv[arg];
|
||||
arg += 1;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (result_file_arg.empty() || (!ELEM(gpu_backend_arg, "", "vulkan", "metal", "opengl"))) {
|
||||
std::cout << "Usage: " << argv[0];
|
||||
std::cout << " [--gpu-backend ";
|
||||
#ifdef WITH_METAL_BACKEND
|
||||
std::cout << "metal";
|
||||
#endif
|
||||
#ifdef WITH_OPENGL_BACKEND
|
||||
std::cout << "opengl";
|
||||
#endif
|
||||
#ifdef WITH_VULKAN_BACKEND
|
||||
std::cout << ",vulkan";
|
||||
#endif
|
||||
std::cout << "]";
|
||||
std::cout << " [--gpu-shader-filter <shader-name>]";
|
||||
std::cout << " <data_file_out>\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int exit_code = 0;
|
||||
|
||||
blender::gpu::shader_builder::ShaderBuilder builder;
|
||||
builder.init_system();
|
||||
|
||||
struct NamedBackend {
|
||||
std::string name;
|
||||
eGPUBackendType backend;
|
||||
|
@ -107,14 +173,21 @@ int main(int argc, const char *argv[])
|
|||
|
||||
blender::Vector<NamedBackend> backends_to_validate;
|
||||
#ifdef WITH_OPENGL_BACKEND
|
||||
backends_to_validate.append({"OpenGL", GPU_BACKEND_OPENGL});
|
||||
if (ELEM(gpu_backend_arg, "", "opengl")) {
|
||||
backends_to_validate.append({"OpenGL", GPU_BACKEND_OPENGL});
|
||||
}
|
||||
#endif
|
||||
#ifdef WITH_METAL_BACKEND
|
||||
backends_to_validate.append({"Metal", GPU_BACKEND_METAL});
|
||||
if (ELEM(gpu_backend_arg, "", "metal")) {
|
||||
backends_to_validate.append({"Metal", GPU_BACKEND_METAL});
|
||||
}
|
||||
#endif
|
||||
#ifdef WITH_VULKAN_BACKEND
|
||||
backends_to_validate.append({"Vulkan", GPU_BACKEND_VULKAN});
|
||||
if (ELEM(gpu_backend_arg, "", "vulkan")) {
|
||||
backends_to_validate.append({"Vulkan", GPU_BACKEND_VULKAN});
|
||||
}
|
||||
#endif
|
||||
|
||||
for (NamedBackend &backend : backends_to_validate) {
|
||||
GPU_backend_type_selection_set(backend.backend);
|
||||
if (!GPU_backend_supported()) {
|
||||
|
@ -122,18 +195,24 @@ int main(int argc, const char *argv[])
|
|||
backend.name.c_str());
|
||||
continue;
|
||||
}
|
||||
blender::gpu::shader_builder::ShaderBuilder builder;
|
||||
builder.init();
|
||||
if (!builder.bake_create_infos()) {
|
||||
printf("Shader compilation failed for %s backend\n", backend.name.c_str());
|
||||
exit_code = 1;
|
||||
if (builder.init_context()) {
|
||||
if (!builder.bake_create_infos(shader_name_starts_with_filter_arg.c_str())) {
|
||||
printf("Shader compilation failed for %s backend\n", backend.name.c_str());
|
||||
exit_code = 1;
|
||||
}
|
||||
else {
|
||||
printf("%s backend shader compilation succeeded.\n", backend.name.c_str());
|
||||
}
|
||||
builder.exit_context();
|
||||
}
|
||||
else {
|
||||
printf("%s backend shader compilation succeeded.\n", backend.name.c_str());
|
||||
printf("Shader compilation skipped for %s backend. Context could not be created.\n",
|
||||
backend.name.c_str());
|
||||
}
|
||||
builder.exit();
|
||||
}
|
||||
|
||||
builder.exit_system();
|
||||
|
||||
exit(exit_code);
|
||||
return exit_code;
|
||||
}
|
||||
|
|
|
@ -524,7 +524,7 @@ void gpu_shader_create_info_init()
|
|||
}
|
||||
|
||||
/* TEST */
|
||||
// gpu_shader_create_info_compile_all();
|
||||
// gpu_shader_create_info_compile(nullptr);
|
||||
}
|
||||
|
||||
void gpu_shader_create_info_exit()
|
||||
|
@ -540,15 +540,22 @@ void gpu_shader_create_info_exit()
|
|||
delete g_interfaces;
|
||||
}
|
||||
|
||||
bool gpu_shader_create_info_compile_all()
|
||||
bool gpu_shader_create_info_compile(const char *name_starts_with_filter)
|
||||
{
|
||||
using namespace blender::gpu;
|
||||
int success = 0;
|
||||
int skipped_filter = 0;
|
||||
int skipped = 0;
|
||||
int total = 0;
|
||||
for (ShaderCreateInfo *info : g_create_infos->values()) {
|
||||
info->finalize();
|
||||
if (info->do_static_compilation_) {
|
||||
if (name_starts_with_filter &&
|
||||
!info->name_.startswith(blender::StringRefNull(name_starts_with_filter)))
|
||||
{
|
||||
skipped_filter++;
|
||||
continue;
|
||||
}
|
||||
if ((info->metal_backend_only_ && GPU_backend_get_type() != GPU_BACKEND_METAL) ||
|
||||
(GPU_compute_shader_support() == false && info->compute_source_ != nullptr) ||
|
||||
(GPU_geometry_shader_support() == false && info->geometry_source_ != nullptr) ||
|
||||
|
@ -614,6 +621,9 @@ bool gpu_shader_create_info_compile_all()
|
|||
}
|
||||
}
|
||||
printf("Shader Test compilation result: %d / %d passed", success, total);
|
||||
if (skipped_filter > 0) {
|
||||
printf(" (skipped %d when filtering)", skipped_filter);
|
||||
}
|
||||
if (skipped > 0) {
|
||||
printf(" (skipped %d for compatibility reasons)", skipped);
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ extern "C" {
|
|||
void gpu_shader_create_info_init();
|
||||
void gpu_shader_create_info_exit();
|
||||
|
||||
bool gpu_shader_create_info_compile_all();
|
||||
bool gpu_shader_create_info_compile(const char *name_starts_with_filter);
|
||||
|
||||
/** Runtime create infos are not registered in the dictionary and cannot be searched. */
|
||||
const GPUShaderCreateInfo *gpu_shader_create_info_get(const char *info_name);
|
||||
|
|
|
@ -31,7 +31,7 @@ using namespace blender::gpu::shader;
|
|||
|
||||
static void test_shader_compile_statically_defined()
|
||||
{
|
||||
EXPECT_TRUE(gpu_shader_create_info_compile_all());
|
||||
EXPECT_TRUE(gpu_shader_create_info_compile(nullptr));
|
||||
}
|
||||
GPU_TEST(shader_compile_statically_defined)
|
||||
|
||||
|
|
Loading…
Reference in New Issue