GPU: Shader: Add support for shader entry points
This works by wrapping the entry point call inside a `main` function. Since resources are still defined in global space, function accessing these are marked with a custom attribute. This custom attribute expands in a `#ifdef` guard for the matching stage. This is a temporary solution and will eventually be lifted once we support SRD. ### TODO - [ ] Implement `[[gpu::vertex/fragment_function]]`. Pull Request: https://projects.blender.org/blender/blender/pulls/139233
This commit is contained in:
committed by
Clément Foucault
parent
dcca2694c5
commit
368a64f386
@@ -212,6 +212,8 @@ class Preprocessor {
|
||||
str = preprocessor_directive_mutation(str);
|
||||
str = swizzle_function_mutation(str);
|
||||
if (language == BLENDER_GLSL) {
|
||||
str = stage_function_mutation(str);
|
||||
str = resource_guard_mutation(str, report_error);
|
||||
str = loop_unroll(str, report_error);
|
||||
str = assert_processing(str, filename);
|
||||
static_strings_parsing(str);
|
||||
@@ -1026,6 +1028,123 @@ class Preprocessor {
|
||||
return str;
|
||||
}
|
||||
|
||||
std::string stage_function_mutation(const std::string &str)
|
||||
{
|
||||
using namespace std;
|
||||
|
||||
if (str.find("_function]]") == string::npos) {
|
||||
return str;
|
||||
}
|
||||
|
||||
vector<pair<string, string>> mutations;
|
||||
|
||||
int64_t line = 1;
|
||||
regex regex_attr(R"(\[\[gpu::(vertex|fragment|compute)_function\]\])");
|
||||
regex_global_search(str, regex_attr, [&](const smatch &match) {
|
||||
string prefix = match.prefix().str();
|
||||
string suffix = match.suffix().str();
|
||||
string attribute = match[0].str();
|
||||
string shader_stage = match[1].str();
|
||||
|
||||
line += line_count(prefix);
|
||||
string signature = suffix.substr(0, suffix.find('{'));
|
||||
string body = '{' +
|
||||
get_content_between_balanced_pair(suffix.substr(signature.size()), '{', '}') +
|
||||
"}\n";
|
||||
|
||||
string function = signature + body;
|
||||
|
||||
string check = "defined(";
|
||||
if (shader_stage == "vertex") {
|
||||
check += "GPU_VERTEX_SHADER";
|
||||
}
|
||||
else if (shader_stage == "fragment") {
|
||||
check += "GPU_FRAGMENT_SHADER";
|
||||
}
|
||||
else if (shader_stage == "compute") {
|
||||
check += "GPU_COMPUTE_SHADER";
|
||||
}
|
||||
check += ")";
|
||||
|
||||
string mutated = guarded_scope_mutation(
|
||||
string(attribute.size(), ' ') + function, line, check);
|
||||
mutations.emplace_back(attribute + function, mutated);
|
||||
});
|
||||
|
||||
string out = str;
|
||||
for (auto mutation : mutations) {
|
||||
replace_all(out, mutation.first, mutation.second);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
std::string resource_guard_mutation(const std::string &str, report_callback report_error)
|
||||
{
|
||||
using namespace std;
|
||||
|
||||
if (str.find("_get(") == string::npos) {
|
||||
return str;
|
||||
}
|
||||
|
||||
vector<pair<string, string>> mutations;
|
||||
|
||||
string prefix_total;
|
||||
regex regex_resource_access(R"(\b(\w+)_get\((\w+)\, \w+\))");
|
||||
regex_global_search(str, regex_resource_access, [&](const smatch &match) {
|
||||
string prefix = prefix_total + match.prefix().str();
|
||||
string suffix = match.suffix().str();
|
||||
string resource_access = match[0].str();
|
||||
string resource_type = match[1].str();
|
||||
string create_info_name = match[2].str();
|
||||
|
||||
prefix_total += match.prefix().str() + resource_access;
|
||||
|
||||
if (resource_type != "specialization_constant" && resource_type != "push_constant" &&
|
||||
resource_type != "interface" && resource_type != "buffer" &&
|
||||
resource_type != "attribute" && resource_type != "sampler" && resource_type != "image")
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
string scope_start = get_content_between_balanced_pair(prefix + '}', '{', '}', true);
|
||||
string scope_end = get_content_between_balanced_pair('{' + suffix, '{', '}');
|
||||
string scope = scope_start.substr(1) + resource_access +
|
||||
scope_end.substr(0, scope_end.rfind('\n') + 1);
|
||||
|
||||
if (scope.find(" return ") != string::npos) {
|
||||
report_error(match,
|
||||
"Return statement with values are not supported inside the same scope as "
|
||||
"resource access function.");
|
||||
return;
|
||||
}
|
||||
|
||||
size_t line_start = 1 + line_count(prefix) - line_count(scope_start) + 1;
|
||||
|
||||
string check = "defined(CREATE_INFO_" + create_info_name + ")";
|
||||
string mutated = guarded_scope_mutation(scope, line_start, check);
|
||||
|
||||
mutations.emplace_back(scope, mutated);
|
||||
});
|
||||
|
||||
string out = str;
|
||||
for (auto mutation : mutations) {
|
||||
replace_all(out, mutation.first, mutation.second);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
std::string guarded_scope_mutation(std::string content, int64_t line_start, std::string check)
|
||||
{
|
||||
int64_t line_end = line_start + line_count(content);
|
||||
std::string guarded_cope;
|
||||
guarded_cope += "#if " + check + "\n";
|
||||
guarded_cope += "#line " + std::to_string(line_start) + "\n";
|
||||
guarded_cope += content;
|
||||
guarded_cope += "#endif\n";
|
||||
guarded_cope += "#line " + std::to_string(line_end) + "\n";
|
||||
return guarded_cope;
|
||||
}
|
||||
|
||||
std::string enum_macro_injection(std::string str)
|
||||
{
|
||||
/**
|
||||
|
||||
@@ -843,6 +843,8 @@ Shader *ShaderCompiler::compile(const shader::ShaderCreateInfo &info, bool is_ba
|
||||
std::string defines = shader->defines_declare(info);
|
||||
std::string resources = shader->resources_declare(info);
|
||||
|
||||
info.resource_guard_defines(defines);
|
||||
|
||||
defines += "#define USE_GPU_SHADER_CREATE_INFO\n";
|
||||
|
||||
Vector<StringRefNull> typedefs;
|
||||
@@ -874,6 +876,12 @@ Shader *ShaderCompiler::compile(const shader::ShaderCreateInfo &info, bool is_ba
|
||||
sources.extend(info.dependencies_generated);
|
||||
sources.append(info.vertex_source_generated);
|
||||
|
||||
if (info.vertex_entry_fn_ != "main") {
|
||||
sources.append("void main() { ");
|
||||
sources.append(info.vertex_entry_fn_);
|
||||
sources.append("(); }\n");
|
||||
}
|
||||
|
||||
shader->vertex_shader_from_glsl(sources);
|
||||
}
|
||||
|
||||
@@ -895,6 +903,12 @@ Shader *ShaderCompiler::compile(const shader::ShaderCreateInfo &info, bool is_ba
|
||||
sources.extend(info.dependencies_generated);
|
||||
sources.append(info.fragment_source_generated);
|
||||
|
||||
if (info.fragment_entry_fn_ != "main") {
|
||||
sources.append("void main() { ");
|
||||
sources.append(info.fragment_entry_fn_);
|
||||
sources.append("(); }\n");
|
||||
}
|
||||
|
||||
shader->fragment_shader_from_glsl(sources);
|
||||
}
|
||||
|
||||
@@ -914,6 +928,12 @@ Shader *ShaderCompiler::compile(const shader::ShaderCreateInfo &info, bool is_ba
|
||||
sources.append(info.geometry_source_generated);
|
||||
sources.extend(code);
|
||||
|
||||
if (info.geometry_entry_fn_ != "main") {
|
||||
sources.append("void main() { ");
|
||||
sources.append(info.geometry_entry_fn_);
|
||||
sources.append("(); }\n");
|
||||
}
|
||||
|
||||
shader->geometry_shader_from_glsl(sources);
|
||||
}
|
||||
|
||||
@@ -932,6 +952,12 @@ Shader *ShaderCompiler::compile(const shader::ShaderCreateInfo &info, bool is_ba
|
||||
sources.extend(info.dependencies_generated);
|
||||
sources.append(info.compute_source_generated);
|
||||
|
||||
if (info.compute_entry_fn_ != "main") {
|
||||
sources.append("void main() { ");
|
||||
sources.append(info.compute_entry_fn_);
|
||||
sources.append("(); }\n");
|
||||
}
|
||||
|
||||
shader->compute_shader_from_glsl(sources);
|
||||
}
|
||||
|
||||
|
||||
@@ -96,6 +96,17 @@ bool ShaderCreateInfo::is_vulkan_compatible() const
|
||||
|
||||
/** \} */
|
||||
|
||||
void ShaderCreateInfo::resource_guard_defines(std::string &defines) const
|
||||
{
|
||||
defines += "#define CREATE_INFO_" + name_ + "\n";
|
||||
for (const auto &info_name : additional_infos_) {
|
||||
const ShaderCreateInfo &info = *reinterpret_cast<const ShaderCreateInfo *>(
|
||||
gpu_shader_create_info_get(info_name.c_str()));
|
||||
|
||||
info.resource_guard_defines(defines);
|
||||
}
|
||||
}
|
||||
|
||||
void ShaderCreateInfo::finalize(const bool recursive)
|
||||
{
|
||||
if (finalized_) {
|
||||
@@ -201,6 +212,23 @@ void ShaderCreateInfo::finalize(const bool recursive)
|
||||
assert_no_overlap(compute_source_.is_empty(), "Compute source already existing");
|
||||
compute_source_ = info.compute_source_;
|
||||
}
|
||||
|
||||
if (info.vertex_entry_fn_ != "main") {
|
||||
assert_no_overlap(vertex_entry_fn_ == "main", "Vertex function already existing");
|
||||
vertex_entry_fn_ = info.vertex_entry_fn_;
|
||||
}
|
||||
if (info.geometry_entry_fn_ != "main") {
|
||||
assert_no_overlap(geometry_entry_fn_ == "main", "Geometry function already existing");
|
||||
geometry_entry_fn_ = info.geometry_entry_fn_;
|
||||
}
|
||||
if (info.fragment_entry_fn_ != "main") {
|
||||
assert_no_overlap(fragment_entry_fn_ == "main", "Fragment function already existing");
|
||||
fragment_entry_fn_ = info.fragment_entry_fn_;
|
||||
}
|
||||
if (info.compute_entry_fn_ != "main") {
|
||||
assert_no_overlap(compute_entry_fn_ == "main", "Compute function already existing");
|
||||
compute_entry_fn_ = info.compute_entry_fn_;
|
||||
}
|
||||
}
|
||||
|
||||
if (!geometry_source_.is_empty() && bool(builtins_ & BuiltinBits::LAYER)) {
|
||||
|
||||
@@ -25,6 +25,12 @@
|
||||
# include <iostream>
|
||||
#endif
|
||||
|
||||
#if defined(GPU_SHADER)
|
||||
# include "gpu_shader_srd_cpp.hh"
|
||||
#else
|
||||
# include "gpu_shader_srd_info.hh"
|
||||
#endif
|
||||
|
||||
/* Force enable `printf` support in release build. */
|
||||
#define GPU_FORCE_ENABLE_SHADER_PRINTF 0
|
||||
|
||||
@@ -117,7 +123,9 @@
|
||||
# define LOCAL_GROUP_SIZE(...) .local_group_size(__VA_ARGS__)
|
||||
|
||||
# define VERTEX_IN(slot, type, name) .vertex_in(slot, Type::type##_t, #name)
|
||||
# define VERTEX_IN_SRD(srd) .shared_resource_descriptor(srd::populate)
|
||||
# define VERTEX_OUT(stage_interface) .vertex_out(stage_interface)
|
||||
# define VERTEX_OUT_SRD(srd) .vertex_out(srd)
|
||||
/* TO REMOVE. */
|
||||
# define GEOMETRY_LAYOUT(...) .geometry_layout(__VA_ARGS__)
|
||||
# define GEOMETRY_OUT(stage_interface) .geometry_out(stage_interface)
|
||||
@@ -126,11 +134,14 @@
|
||||
.subpass_in(slot, Type::type##_t, ImageType::img_type, #name, rog)
|
||||
|
||||
# define FRAGMENT_OUT(slot, type, name) .fragment_out(slot, Type::type##_t, #name)
|
||||
# define FRAGMENT_OUT_SRD(srd) .shared_resource_descriptor(srd::populate)
|
||||
# define FRAGMENT_OUT_DUAL(slot, type, name, blend) \
|
||||
.fragment_out(slot, Type::type##_t, #name, DualBlend::blend)
|
||||
# define FRAGMENT_OUT_ROG(slot, type, name, rog) \
|
||||
.fragment_out(slot, Type::type##_t, #name, DualBlend::NONE, rog)
|
||||
|
||||
# define RESOURCE_SRD(srd) .shared_resource_descriptor(srd::populate)
|
||||
|
||||
# define EARLY_FRAGMENT_TEST(enable) .early_fragment_test(enable)
|
||||
# define DEPTH_WRITE(value) .depth_write(value)
|
||||
|
||||
@@ -168,6 +179,10 @@
|
||||
# define FRAGMENT_SOURCE(filename) .fragment_source(filename)
|
||||
# define COMPUTE_SOURCE(filename) .compute_source(filename)
|
||||
|
||||
# define VERTEX_FUNCTION(function) .vertex_function(function)
|
||||
# define FRAGMENT_FUNCTION(function) .fragment_function(function)
|
||||
# define COMPUTE_FUNCTION(function) .compute_function(function)
|
||||
|
||||
# define DEFINE(name) .define(name)
|
||||
# define DEFINE_VALUE(name, value) .define(name, value)
|
||||
|
||||
@@ -200,7 +215,12 @@
|
||||
namespace gl_VertexShader { \
|
||||
const type name = {}; \
|
||||
}
|
||||
# define VERTEX_IN_SRD(srd) \
|
||||
namespace gl_VertexShader { \
|
||||
using namespace srd; \
|
||||
}
|
||||
# define VERTEX_OUT(stage_interface) using namespace interface::stage_interface;
|
||||
# define VERTEX_OUT_SRD(srd) using namespace interface::srd;
|
||||
/* TO REMOVE. */
|
||||
# define GEOMETRY_LAYOUT(...)
|
||||
# define GEOMETRY_OUT(stage_interface) using namespace interface::stage_interface;
|
||||
@@ -219,6 +239,12 @@
|
||||
namespace gl_FragmentShader { \
|
||||
type name; \
|
||||
}
|
||||
# define FRAGMENT_OUT_SRD(srd) \
|
||||
namespace gl_FragmentShader { \
|
||||
using namespace srd; \
|
||||
}
|
||||
|
||||
# define RESOURCE_SRD(srd) using namespace srd;
|
||||
|
||||
# define EARLY_FRAGMENT_TEST(enable)
|
||||
# define DEPTH_WRITE(value)
|
||||
@@ -247,10 +273,13 @@
|
||||
# define BUILTINS(builtin)
|
||||
|
||||
# define VERTEX_SOURCE(filename)
|
||||
# define GEOMETRY_SOURCE(filename)
|
||||
# define FRAGMENT_SOURCE(filename)
|
||||
# define COMPUTE_SOURCE(filename)
|
||||
|
||||
# define VERTEX_FUNCTION(filename)
|
||||
# define FRAGMENT_FUNCTION(filename)
|
||||
# define COMPUTE_FUNCTION(filename)
|
||||
|
||||
# define DEFINE(name)
|
||||
# define DEFINE_VALUE(name, value)
|
||||
|
||||
@@ -885,6 +914,8 @@ struct ShaderCreateInfo {
|
||||
Vector<StringRefNull> typedef_sources_;
|
||||
|
||||
StringRefNull vertex_source_, geometry_source_, fragment_source_, compute_source_;
|
||||
StringRefNull vertex_entry_fn_ = "main", geometry_entry_fn_ = "main",
|
||||
fragment_entry_fn_ = "main", compute_entry_fn_ = "main";
|
||||
|
||||
Vector<std::array<StringRefNull, 2>> defines_;
|
||||
/**
|
||||
@@ -994,6 +1025,12 @@ struct ShaderCreateInfo {
|
||||
return *(Self *)this;
|
||||
}
|
||||
|
||||
Self &shared_resource_descriptor(void (*fn)(ShaderCreateInfo &))
|
||||
{
|
||||
fn(*this);
|
||||
return *(Self *)this;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
@@ -1175,6 +1212,24 @@ struct ShaderCreateInfo {
|
||||
return *(Self *)this;
|
||||
}
|
||||
|
||||
Self &vertex_function(StringRefNull function_name)
|
||||
{
|
||||
vertex_entry_fn_ = function_name;
|
||||
return *(Self *)this;
|
||||
}
|
||||
|
||||
Self &fragment_function(StringRefNull function_name)
|
||||
{
|
||||
fragment_entry_fn_ = function_name;
|
||||
return *(Self *)this;
|
||||
}
|
||||
|
||||
Self &compute_function(StringRefNull function_name)
|
||||
{
|
||||
compute_entry_fn_ = function_name;
|
||||
return *(Self *)this;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
@@ -1318,6 +1373,8 @@ struct ShaderCreateInfo {
|
||||
* (All statically declared CreateInfos are automatically finalized at startup) */
|
||||
void finalize(const bool recursive = false);
|
||||
|
||||
void resource_guard_defines(std::string &defines) const;
|
||||
|
||||
std::string check_error() const;
|
||||
bool is_vulkan_compatible() const;
|
||||
|
||||
|
||||
59
source/blender/gpu/intern/gpu_shader_srd_cpp.hh
Normal file
59
source/blender/gpu/intern/gpu_shader_srd_cpp.hh
Normal file
@@ -0,0 +1,59 @@
|
||||
/* SPDX-FileCopyrightText: 2021 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup gpu
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#define SRD_STRUCT_BEGIN(srd) \
|
||||
namespace srd { \
|
||||
namespace gl_VertexShader { \
|
||||
} \
|
||||
namespace gl_FragmentShader { \
|
||||
} \
|
||||
namespace gl_ComputeShader { \
|
||||
}
|
||||
#define SRD_STRUCT_END(srd) }
|
||||
|
||||
#define SRD_VERTEX_IN_BEGIN(srd) SRD_STRUCT_BEGIN(srd)
|
||||
#define SRD_VERTEX_IN_END(srd) SRD_STRUCT_END(srd)
|
||||
#define SRD_VERTEX_IN(srd, binding, type, name) const type name = {};
|
||||
|
||||
#define SRD_VERTEX_OUT_BEGIN(srd) GPU_SHADER_INTERFACE_INFO(srd)
|
||||
#define SRD_VERTEX_OUT_END(srd) GPU_SHADER_INTERFACE_END()
|
||||
#define SRD_VERTEX_OUT(srd, qual, type, name) type name = {};
|
||||
|
||||
#define SRD_FRAGMENT_IN_BEGIN(srd) SRD_STRUCT_BEGIN(srd)
|
||||
#define SRD_FRAGMENT_IN_END(srd) SRD_STRUCT_END(srd)
|
||||
#define SRD_FRAGMENT_IN(srd, qual, type, name) const type name = {};
|
||||
#define SRD_FRAGMENT_IN_ROG(srd, slot, type, img_type, name, rog) const type name = {};
|
||||
|
||||
#define SRD_FRAGMENT_OUT_BEGIN(srd) SRD_STRUCT_BEGIN(srd)
|
||||
#define SRD_FRAGMENT_OUT_END(srd) SRD_STRUCT_END(srd)
|
||||
#define SRD_FRAGMENT_OUT(srd, binding, type, name) type name = {};
|
||||
#define SRD_FRAGMENT_OUT_DUAL(srd, slot, type, name, blend) type name = {};
|
||||
#define SRD_FRAGMENT_OUT_ROG(srd, slot, type, name, rog) type name = {};
|
||||
|
||||
#define SRD_RESOURCE_BEGIN(srd) SRD_STRUCT_BEGIN(srd)
|
||||
#define SRD_RESOURCE_END(srd) SRD_STRUCT_END(srd)
|
||||
#define SRD_RESOURCE_SPECIALIZATION_CONSTANT(srd, type, name, default) type name = {};
|
||||
#define SRD_RESOURCE_PUSH_CONSTANT(srd, type, name) type name = {};
|
||||
#define SRD_RESOURCE_PUSH_CONSTANT_ARRAY(srd, type, name, array) type(*name) = {};
|
||||
#define SRD_RESOURCE_SAMPLER(srd, binding, type, name) type name = {};
|
||||
#define SRD_RESOURCE_SAMPLER_FREQ(srd, binding, type, name, freq) type name = {};
|
||||
#define SRD_RESOURCE_IMAGE(srd, binding, format, access, type, name) _##access type name;
|
||||
#define SRD_RESOURCE_IMAGE_FREQ(srd, binding, format, access, type, name, freq) \
|
||||
_##access type name;
|
||||
#define SRD_RESOURCE_STORAGE_BUF(srd, binding, access, type, name, array) type(*name) array = {};
|
||||
#define SRD_RESOURCE_STORAGE_BUF_FREQ(srd, binding, access, type, name, array, freq) \
|
||||
type(*name) array = {};
|
||||
#define SRD_RESOURCE_UNIFORM_BUF(srd, binding, type, name, array) type(*name) array = {};
|
||||
#define SRD_RESOURCE_UNIFORM_BUF_FREQ(srd, binding, type, name, array, freq) \
|
||||
type(*name) array = {};
|
||||
#define SRD_RESOURCE_STRUCT(srd, type, name) type name = {};
|
||||
/* Temporary solution while everything is being ported.
|
||||
* Should be replace by SRD_RESOURCE_STRUCT. */
|
||||
#define SRD_RESOURCE_ADDITIONAL_INFO(srd, type) using namespace type;
|
||||
70
source/blender/gpu/intern/gpu_shader_srd_info.hh
Normal file
70
source/blender/gpu/intern/gpu_shader_srd_info.hh
Normal file
@@ -0,0 +1,70 @@
|
||||
/* SPDX-FileCopyrightText: 2021 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup gpu
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#define SRD_STRUCT_BEGIN(srd) \
|
||||
struct srd { \
|
||||
static void populate(blender::gpu::shader::ShaderCreateInfo &info) \
|
||||
{
|
||||
|
||||
#define SRD_STRUCT_END(srd) \
|
||||
} \
|
||||
} \
|
||||
;
|
||||
|
||||
#define SRD_VERTEX_IN_BEGIN(srd) SRD_STRUCT_BEGIN(srd)
|
||||
#define SRD_VERTEX_IN_END(srd) SRD_STRUCT_END(srd)
|
||||
#define SRD_VERTEX_IN(srd, binding, type, name) info.vertex_in(binding, Type::type##_t, #name);
|
||||
|
||||
#define SRD_VERTEX_OUT_BEGIN(srd) GPU_SHADER_INTERFACE_INFO(srd)
|
||||
#define SRD_VERTEX_OUT_END(srd) GPU_SHADER_INTERFACE_END()
|
||||
#define SRD_VERTEX_OUT(srd, qual, type, name) .qual(Type::type##_t, #name)
|
||||
|
||||
#define SRD_FRAGMENT_IN_BEGIN(srd) SRD_STRUCT_BEGIN(srd)
|
||||
#define SRD_FRAGMENT_IN_END(srd) SRD_STRUCT_END(srd)
|
||||
#define SRD_FRAGMENT_IN(srd, qual, type, name) info.qual(Type::type##_t, #name);
|
||||
#define SRD_FRAGMENT_IN_ROG(srd, slot, type, img_type, name, rog) \
|
||||
info.subpass_in(slot, type, img_type, name, rog)
|
||||
|
||||
#define SRD_FRAGMENT_OUT_BEGIN(srd) SRD_STRUCT_BEGIN(srd)
|
||||
#define SRD_FRAGMENT_OUT_END(srd) SRD_STRUCT_END(srd)
|
||||
#define SRD_FRAGMENT_OUT(srd, binding, type, name) \
|
||||
info.fragment_out(binding, Type::type##_t, #name);
|
||||
#define SRD_FRAGMENT_OUT_DUAL(srd, slot, type, name, blend) \
|
||||
info.fragment_out(slot, Type::type##_t, #name, DualBlend::blend)
|
||||
#define SRD_FRAGMENT_OUT_ROG(srd, slot, type, name, rog) \
|
||||
info.fragment_out(slot, Type::type##_t, #name, DualBlend::NONE, rog)
|
||||
|
||||
#define SRD_RESOURCE_BEGIN(srd) SRD_STRUCT_BEGIN(srd)
|
||||
#define SRD_RESOURCE_END(srd) SRD_STRUCT_END(srd)
|
||||
#define SRD_RESOURCE_SPECIALIZATION_CONSTANT(srd, type, name, default) \
|
||||
info.specialization_constant(Type::type##_t, #name, default);
|
||||
#define SRD_RESOURCE_PUSH_CONSTANT(srd, type, name) info.push_constant(Type::type##_t, #name);
|
||||
#define SRD_RESOURCE_PUSH_CONSTANT_ARRAY(srd, type, name, array) \
|
||||
info.push_constant(Type::type##_t, #name, array);
|
||||
#define SRD_RESOURCE_SAMPLER(srd, binding, type, name) \
|
||||
info.sampler(binding, ImageType::type, #name);
|
||||
#define SRD_RESOURCE_SAMPLER_FREQ(srd, binding, type, name, freq) \
|
||||
info.sampler(binding, ImageType::type, #name, Frequency::freq);
|
||||
#define SRD_RESOURCE_IMAGE(srd, binding, format, access, type, name) \
|
||||
info.image(binding, format, Qualifier::access, ImageReadWriteType::type, #name);
|
||||
#define SRD_RESOURCE_IMAGE_FREQ(srd, binding, format, access, type, name, freq) \
|
||||
info.image(binding, format, Qualifier::access, ImageReadWriteType::type, #name, Frequency::freq);
|
||||
#define SRD_RESOURCE_STORAGE_BUF(srd, binding, access, type, name, array) \
|
||||
info.storage_buf(binding, Qualifier::access, #type, #name #array);
|
||||
#define SRD_RESOURCE_STORAGE_BUF_FREQ(srd, binding, access, type, name, array, freq) \
|
||||
info.storage_buf(binding, Qualifier::access, #type, #name #array, Frequency::freq);
|
||||
#define SRD_RESOURCE_UNIFORM_BUF(srd, binding, type, name, array) \
|
||||
info.uniform_buf(binding, #type, #name #array);
|
||||
#define SRD_RESOURCE_UNIFORM_BUF_FREQ(srd, binding, type, name, array, freq) \
|
||||
info.uniform_buf(binding, #type, #name #array, Frequency::freq);
|
||||
#define SRD_RESOURCE_STRUCT(srd, type, name) type::populate(info);
|
||||
/* Temporary solution while everything is being ported.
|
||||
* Should be replace by SRD_RESOURCE_STRUCT. */
|
||||
#define SRD_RESOURCE_ADDITIONAL_INFO(srd, type) info.additional_info(#type);
|
||||
@@ -1072,6 +1072,21 @@ void groupMemoryBarrier() {}
|
||||
// #define using /* Needed for Stubs. */
|
||||
#define row_major row_major_is_reserved_glsl_keyword_do_not_use
|
||||
|
||||
#ifdef GPU_SHADER_LIBRARY
|
||||
# define GPU_VERTEX_SHADER
|
||||
# define GPU_FRAGMENT_SHADER
|
||||
# define GPU_COMPUTE_SHADER
|
||||
#endif
|
||||
|
||||
/* Resource accessor. */
|
||||
#define specialization_constant_get(create_info, _res) _res
|
||||
#define push_constant_get(create_info, _res) _res
|
||||
#define interface_get(create_info, _res) _res
|
||||
#define attribute_get(create_info, _res) _res
|
||||
#define buffer_get(create_info, _res) _res
|
||||
#define sampler_get(create_info, _res) _res
|
||||
#define image_get(create_info, _res) _res
|
||||
|
||||
#include "GPU_shader_shared_utils.hh"
|
||||
|
||||
#ifdef __GNUC__
|
||||
|
||||
@@ -1228,3 +1228,12 @@ float4x4 __mat4x4(float3x3 a) { return to_float4x4(a); }
|
||||
#define gpu_dfdx(x) dFdx(x)
|
||||
#define gpu_dfdy(x) dFdy(x)
|
||||
#define gpu_fwidth(x) fwidth(x)
|
||||
|
||||
/* Resource accessor. */
|
||||
#define specialization_constant_get(create_info, _res) _res
|
||||
#define push_constant_get(create_info, _res) _res
|
||||
#define interface_get(create_info, _res) _res
|
||||
#define attribute_get(create_info, _res) _res
|
||||
#define buffer_get(create_info, _res) _res
|
||||
#define sampler_get(create_info, _res) _res
|
||||
#define image_get(create_info, _res) _res
|
||||
|
||||
@@ -750,4 +750,151 @@ static void test_preprocess_matrix_constructors()
|
||||
GPU_TEST(preprocess_matrix_constructors);
|
||||
#endif
|
||||
|
||||
static void test_preprocess_stage_attribute()
|
||||
{
|
||||
using namespace shader;
|
||||
using namespace std;
|
||||
|
||||
{
|
||||
string input = R"(
|
||||
[[gpu::vertex_function]] void my_func() {
|
||||
return;
|
||||
}
|
||||
)";
|
||||
string expect = R"(
|
||||
#if defined(GPU_VERTEX_SHADER)
|
||||
#line 2
|
||||
void my_func() {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#line 5
|
||||
)";
|
||||
string error;
|
||||
string output = process_test_string(input, error);
|
||||
EXPECT_EQ(output, expect);
|
||||
EXPECT_EQ(error, "");
|
||||
}
|
||||
}
|
||||
GPU_TEST(preprocess_stage_attribute);
|
||||
|
||||
static void test_preprocess_resource_guard()
|
||||
{
|
||||
using namespace shader;
|
||||
using namespace std;
|
||||
|
||||
{
|
||||
string input = R"(
|
||||
void my_func() {
|
||||
interface_get(draw_resource_id_varying, drw_ResourceID_iface).resource_index;
|
||||
}
|
||||
)";
|
||||
string expect = R"(
|
||||
void my_func() {
|
||||
#if defined(CREATE_INFO_draw_resource_id_varying)
|
||||
#line 3
|
||||
interface_get(draw_resource_id_varying, drw_ResourceID_iface).resource_index;
|
||||
#endif
|
||||
#line 4
|
||||
}
|
||||
)";
|
||||
string error;
|
||||
string output = process_test_string(input, error);
|
||||
EXPECT_EQ(output, expect);
|
||||
EXPECT_EQ(error, "");
|
||||
}
|
||||
{
|
||||
string input = R"(
|
||||
uint my_func() {
|
||||
uint i = 0;
|
||||
i += interface_get(draw_resource_id_varying, drw_ResourceID_iface).resource_index;
|
||||
return i;
|
||||
}
|
||||
)";
|
||||
string expect = R"(
|
||||
uint my_func() {
|
||||
#if defined(CREATE_INFO_draw_resource_id_varying)
|
||||
#line 3
|
||||
uint i = 0;
|
||||
i += interface_get(draw_resource_id_varying, drw_ResourceID_iface).resource_index;
|
||||
return i;
|
||||
#else
|
||||
#line 3
|
||||
return uint(0);
|
||||
#endif
|
||||
#line 6
|
||||
}
|
||||
)";
|
||||
string error;
|
||||
string output = process_test_string(input, error);
|
||||
// EXPECT_EQ(output, expect); /* TODO: Add support. */
|
||||
EXPECT_EQ(error,
|
||||
"Return statement with values are not supported inside the same scope as "
|
||||
"resource access function.");
|
||||
}
|
||||
{
|
||||
string input = R"(
|
||||
uint my_func() {
|
||||
uint i = 0;
|
||||
{
|
||||
i += interface_get(draw_resource_id_varying, drw_ResourceID_iface).resource_index;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
)";
|
||||
string expect = R"(
|
||||
uint my_func() {
|
||||
uint i = 0;
|
||||
{
|
||||
#if defined(CREATE_INFO_draw_resource_id_varying)
|
||||
#line 5
|
||||
i += interface_get(draw_resource_id_varying, drw_ResourceID_iface).resource_index;
|
||||
#endif
|
||||
#line 6
|
||||
}
|
||||
return i;
|
||||
}
|
||||
)";
|
||||
string error;
|
||||
string output = process_test_string(input, error);
|
||||
EXPECT_EQ(output, expect);
|
||||
EXPECT_EQ(error, "");
|
||||
}
|
||||
{
|
||||
string input = R"(
|
||||
uint my_func() {
|
||||
uint i = 0;
|
||||
{
|
||||
i += interface_get(draw_resource_id_varying, drw_ResourceID_iface).resource_index;
|
||||
i += buffer_get(draw_resource_id, resource_id_buf)[0];
|
||||
}
|
||||
return i;
|
||||
}
|
||||
)";
|
||||
string expect = R"(
|
||||
uint my_func() {
|
||||
uint i = 0;
|
||||
{
|
||||
#if defined(CREATE_INFO_draw_resource_id_varying)
|
||||
#line 5
|
||||
#if defined(CREATE_INFO_draw_resource_id)
|
||||
#line 5
|
||||
i += interface_get(draw_resource_id_varying, drw_ResourceID_iface).resource_index;
|
||||
i += buffer_get(draw_resource_id, resource_id_buf)[0];
|
||||
#endif
|
||||
#line 7
|
||||
#endif
|
||||
#line 7
|
||||
}
|
||||
return i;
|
||||
}
|
||||
)";
|
||||
string error;
|
||||
string output = process_test_string(input, error);
|
||||
EXPECT_EQ(output, expect);
|
||||
EXPECT_EQ(error, "");
|
||||
}
|
||||
}
|
||||
GPU_TEST(preprocess_resource_guard);
|
||||
|
||||
} // namespace blender::gpu::tests
|
||||
|
||||
Reference in New Issue
Block a user