GPUShader: Add optionnal single shader stage interface for in and out
This makes optionnal the use of a different interface for the geometry shader stage output. When the vertex and geometry interface instance name matches, a `_in` and `_out` suffix is added to the end of the instance name. This makes it easier to have optional geometry shader stages. # Conflicts: # source/blender/gpu/intern/gpu_shader_create_info.hh
This commit is contained in:
@@ -380,7 +380,12 @@ struct ShaderCreateInfo {
|
||||
return *(Self *)this;
|
||||
}
|
||||
|
||||
/* Only needed if geometry shader is enabled. */
|
||||
/**
|
||||
* Only needed if geometry shader is enabled.
|
||||
* IMPORTANT: Input and output instance name will have respectively "_in" and "_out" suffix
|
||||
* appended in the geometry shader IF AND ONLY IF the vertex_out interface instance name matches
|
||||
* the geometry_out interface instance name.
|
||||
*/
|
||||
Self &geometry_out(StageInterfaceInfo &interface)
|
||||
{
|
||||
geometry_out_interfaces_.append(&interface);
|
||||
|
||||
@@ -492,16 +492,34 @@ std::string GLShader::geometry_layout_declare(const ShaderCreateInfo &info) cons
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
static StageInterfaceInfo *find_interface_by_name(const Vector<StageInterfaceInfo *> &ifaces,
|
||||
const StringRefNull &name)
|
||||
{
|
||||
for (auto iface : ifaces) {
|
||||
if (iface->name == name) {
|
||||
return iface;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::string GLShader::geometry_interface_declare(const ShaderCreateInfo &info) const
|
||||
{
|
||||
|
||||
std::stringstream ss;
|
||||
ss << "\n/* Interfaces. */\n";
|
||||
for (const StageInterfaceInfo *iface : info.vertex_out_interfaces_) {
|
||||
print_interface(ss, "in", *iface, "[]");
|
||||
bool has_matching_output_iface = find_interface_by_name(info.geometry_out_interfaces_,
|
||||
iface->instance_name) != nullptr;
|
||||
const char *suffix = (has_matching_output_iface) ? "_in[]" : "[]";
|
||||
print_interface(ss, "in", *iface, suffix);
|
||||
}
|
||||
ss << "\n";
|
||||
for (const StageInterfaceInfo *iface : info.geometry_out_interfaces_) {
|
||||
print_interface(ss, "out", *iface);
|
||||
bool has_matching_input_iface = find_interface_by_name(info.vertex_out_interfaces_,
|
||||
iface->instance_name) != nullptr;
|
||||
const char *suffix = (has_matching_input_iface) ? "_out" : "";
|
||||
print_interface(ss, "out", *iface, suffix);
|
||||
}
|
||||
ss << "\n";
|
||||
return ss.str();
|
||||
@@ -532,7 +550,7 @@ std::string GLShader::compute_layout_declare(const ShaderCreateInfo &info) const
|
||||
static char *glsl_patch_default_get()
|
||||
{
|
||||
/** Used for shader patching. Init once. */
|
||||
static char patch[512] = "\0";
|
||||
static char patch[700] = "\0";
|
||||
if (patch[0] != '\0') {
|
||||
return patch;
|
||||
}
|
||||
@@ -559,6 +577,11 @@ static char *glsl_patch_default_get()
|
||||
if (GLContext::shader_draw_parameters_support) {
|
||||
STR_CONCAT(patch, slen, "#extension GL_ARB_shader_draw_parameters : enable\n");
|
||||
STR_CONCAT(patch, slen, "#define GPU_ARB_shader_draw_parameters\n");
|
||||
STR_CONCAT(patch, slen, "#define gpu_BaseInstance gl_BaseInstanceARB\n");
|
||||
}
|
||||
else {
|
||||
/* Fallback: Emulate base instance using a uniform. */
|
||||
STR_CONCAT(patch, slen, "uniform int gpu_BaseInstance\n");
|
||||
}
|
||||
if (GLContext::geometry_shader_invocations) {
|
||||
STR_CONCAT(patch, slen, "#extension GL_ARB_gpu_shader5 : enable\n");
|
||||
@@ -569,6 +592,9 @@ static char *glsl_patch_default_get()
|
||||
STR_CONCAT(patch, slen, "#define GPU_ARB_texture_cube_map_array\n");
|
||||
}
|
||||
|
||||
/* Vulkan GLSL compat. */
|
||||
STR_CONCAT(patch, slen, "#define gpu_InstanceIndex (gl_InstanceID + gpu_BaseInstance)\n");
|
||||
|
||||
/* Derivative sign can change depending on implementation. */
|
||||
STR_CONCATF(patch, slen, "#define DFDX_SIGN %1.1f\n", GLContext::derivative_signs[0]);
|
||||
STR_CONCATF(patch, slen, "#define DFDY_SIGN %1.1f\n", GLContext::derivative_signs[1]);
|
||||
|
||||
@@ -440,6 +440,14 @@ GLShaderInterface::GLShaderInterface(GLuint program, const shader::ShaderCreateI
|
||||
}
|
||||
}
|
||||
|
||||
/* Compatibility uniforms. */
|
||||
if (!GLContext::shader_draw_parameters_support) {
|
||||
input->location = glGetUniformLocation(program, "gpu_BaseInstance");
|
||||
copy_input_name(input, "gpu_BaseInstance", name_buffer_, name_buffer_offset);
|
||||
input->binding = -1;
|
||||
input++;
|
||||
}
|
||||
|
||||
/* Builtin Uniforms */
|
||||
for (int32_t u_int = 0; u_int < GPU_NUM_UNIFORMS; u_int++) {
|
||||
GPUUniformBuiltin u = static_cast<GPUUniformBuiltin>(u_int);
|
||||
|
||||
Reference in New Issue
Block a user