GPU: Add GL_ARB_clip_control support to the GL backend
This adds support for the extension and always set the clip state value to 0..1 to align with vulkan and metal. Moreover this is needed for the Reverse Z implementation. Note that this is a OpenGL 4.5 feature and is not required to start Blender. So there must still be a fallback path for now. Rel #138898 Pull Request: https://projects.blender.org/blender/blender/pulls/138941
This commit is contained in:
committed by
Clément Foucault
parent
45240026a2
commit
8ac5940e33
@@ -639,6 +639,13 @@ void ShaderModule::material_create_info_amend(GPUMaterial *gpumat, GPUCodegenOut
|
||||
}
|
||||
}
|
||||
|
||||
#if 0 /* Waiting for using DRW_STATE_CLIP_CONTROL_UNIT_RANGE where these are used. */
|
||||
if (geometry_type != MAT_GEOM_WORLD) {
|
||||
/* Allow to use Reverse-Z on OpenGL. Does nothing in other backend. */
|
||||
info.builtins(BuiltinBits::CLIP_CONTROL);
|
||||
}
|
||||
#endif
|
||||
|
||||
std::stringstream global_vars;
|
||||
switch (geometry_type) {
|
||||
case MAT_GEOM_MESH:
|
||||
|
||||
@@ -305,6 +305,13 @@ void StateSet::execute(RecordingState &recording_state) const
|
||||
to_stencil_op(new_state),
|
||||
to_provoking_vertex(new_state));
|
||||
|
||||
if (new_state & DRW_STATE_CLIP_CONTROL_UNIT_RANGE) {
|
||||
GPU_clip_control_unit_range(true);
|
||||
}
|
||||
else {
|
||||
GPU_clip_control_unit_range(false);
|
||||
}
|
||||
|
||||
if (new_state & DRW_STATE_SHADOW_OFFSET) {
|
||||
GPU_shadow_offset(true);
|
||||
}
|
||||
|
||||
@@ -64,6 +64,8 @@ typedef enum {
|
||||
DRW_STATE_LOGIC_INVERT = (10 << 11),
|
||||
DRW_STATE_BLEND_ALPHA_UNDER_PREMUL = (11 << 11),
|
||||
|
||||
/* See GPU_clip_control_unit_range. */
|
||||
DRW_STATE_CLIP_CONTROL_UNIT_RANGE = (1 << 26),
|
||||
DRW_STATE_IN_FRONT_SELECT = (1 << 27),
|
||||
DRW_STATE_SHADOW_OFFSET = (1 << 28),
|
||||
DRW_STATE_CLIP_PLANES = (1 << 29),
|
||||
|
||||
@@ -194,6 +194,11 @@ void GPU_stencil_reference_set(uint reference);
|
||||
void GPU_stencil_write_mask_set(uint write_mask);
|
||||
void GPU_stencil_compare_mask_set(uint compare_mask);
|
||||
|
||||
/* Sets the depth range to be 0..1. Only have effect with the OpenGL backend. Have no effect if
|
||||
* glClipControl is not supported. Shaders used for drawing with this state must use
|
||||
* BuiltinBits::CLIP_CONTROL for their vertex shader to be patched. */
|
||||
void GPU_clip_control_unit_range(bool enable);
|
||||
|
||||
eGPUFaceCullTest GPU_face_culling_get();
|
||||
eGPUBlend GPU_blend_get();
|
||||
eGPUDepthTest GPU_depth_test_get();
|
||||
|
||||
@@ -422,6 +422,10 @@ enum class BuiltinBits {
|
||||
/* Texture atomics requires usage options to alter compilation flag. */
|
||||
TEXTURE_ATOMIC = (1 << 18),
|
||||
|
||||
/* Enable shader patching on GL to remap clip range to 0..1.
|
||||
* Will do nothing if ClipControl is unsupporteds. */
|
||||
CLIP_CONTROL = (1 << 19),
|
||||
|
||||
/* Not a builtin but a flag we use to tag shaders that use the debug features. */
|
||||
USE_PRINTF = (1 << 28),
|
||||
USE_DEBUG_DRAW = (1 << 29),
|
||||
|
||||
@@ -145,6 +145,11 @@ void GPU_state_set(eGPUWriteMask write_mask,
|
||||
state.provoking_vert = uint32_t(provoking_vert);
|
||||
}
|
||||
|
||||
void GPU_clip_control_unit_range(bool enable)
|
||||
{
|
||||
SET_IMMUTABLE_STATE(clip_control, enable);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
@@ -423,6 +428,7 @@ StateManager::StateManager()
|
||||
state.invert_facing = false;
|
||||
state.shadow_bias = false;
|
||||
state.clip_distances = 0;
|
||||
state.clip_control = false;
|
||||
state.polygon_smooth = false;
|
||||
state.line_smooth = false;
|
||||
|
||||
|
||||
@@ -40,6 +40,8 @@ union GPUState {
|
||||
uint32_t logic_op_xor : 1;
|
||||
uint32_t invert_facing : 1;
|
||||
uint32_t shadow_bias : 1;
|
||||
/** Clip range of 0..1 on OpenGL. */
|
||||
uint32_t clip_control : 1;
|
||||
/** Number of clip distances enabled. */
|
||||
/* TODO(fclem): This should be a shader property. */
|
||||
uint32_t clip_distances : 3;
|
||||
|
||||
@@ -413,6 +413,7 @@ static void detect_workarounds()
|
||||
GLContext::multi_bind_support = false;
|
||||
GLContext::multi_bind_image_support = false;
|
||||
/* Turn off OpenGL 4.5 features. */
|
||||
GLContext::clip_control_support = false;
|
||||
GLContext::direct_state_access_support = false;
|
||||
/* Turn off OpenGL 4.6 features. */
|
||||
GLContext::texture_filter_anisotropic_support = false;
|
||||
@@ -612,6 +613,7 @@ GLint GLContext::max_ssbo_binds = 0;
|
||||
|
||||
/** Extensions. */
|
||||
|
||||
bool GLContext::clip_control_support = false;
|
||||
bool GLContext::debug_layer_support = false;
|
||||
bool GLContext::direct_state_access_support = false;
|
||||
bool GLContext::explicit_location_support = false;
|
||||
@@ -710,6 +712,7 @@ void GLBackend::capabilities_init()
|
||||
GLContext::stencil_texturing_support = epoxy_gl_version() >= 43;
|
||||
GLContext::texture_filter_anisotropic_support = epoxy_has_gl_extension(
|
||||
"GL_EXT_texture_filter_anisotropic");
|
||||
GLContext::clip_control_support = epoxy_has_gl_extension("GL_ARB_clip_control");
|
||||
|
||||
/* Disabled until it is proven to work. */
|
||||
GLContext::framebuffer_fetch_support = false;
|
||||
|
||||
@@ -48,6 +48,7 @@ class GLContext : public Context {
|
||||
|
||||
/** Extensions. */
|
||||
|
||||
static bool clip_control_support;
|
||||
static bool debug_layer_support;
|
||||
static bool direct_state_access_support;
|
||||
static bool explicit_location_support;
|
||||
|
||||
@@ -711,6 +711,13 @@ std::string GLShader::vertex_interface_declare(const ShaderCreateInfo &info) con
|
||||
ss << "#define gpu_ViewportIndex gl_ViewportIndex\n";
|
||||
}
|
||||
}
|
||||
if (bool(info.builtins_ & BuiltinBits::CLIP_CONTROL)) {
|
||||
if (GLContext::clip_control_support && !has_geometry_stage) {
|
||||
/* Assume clip range is set to 0..1 and remap the range just like Vulkan and Metal.
|
||||
* If geometry stage is needed, do that remapping inside the geometry shader stage. */
|
||||
post_main += "gl_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n";
|
||||
}
|
||||
}
|
||||
if (bool(info.builtins_ & BuiltinBits::BARYCENTRIC_COORD)) {
|
||||
if (!GLContext::native_barycentric_support) {
|
||||
/* Disabled or unsupported. */
|
||||
@@ -983,6 +990,12 @@ std::string GLShader::workaround_geometry_shader_source_create(
|
||||
ss << " vec3(" << int(i == 0) << ", " << int(i == 1) << ", " << int(i == 2) << ");\n";
|
||||
}
|
||||
ss << " gl_Position = gl_in[" << i << "].gl_Position;\n";
|
||||
if (bool(info.builtins_ & BuiltinBits::CLIP_CONTROL)) {
|
||||
if (GLContext::clip_control_support) {
|
||||
/* Assume clip range is set to 0..1 and remap the range just like Vulkan and Metal. */
|
||||
ss << "gl_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n";
|
||||
}
|
||||
}
|
||||
if (do_layer_output) {
|
||||
ss << " gl_Layer = gpu_Layer[" << i << "];\n";
|
||||
}
|
||||
|
||||
@@ -109,6 +109,9 @@ void GLStateManager::set_state(const GPUState &state)
|
||||
if (changed.shadow_bias != 0) {
|
||||
set_shadow_bias(state.shadow_bias);
|
||||
}
|
||||
if (changed.clip_control != 0) {
|
||||
set_clip_control(state.clip_control);
|
||||
}
|
||||
|
||||
/* TODO: remove. */
|
||||
if (changed.polygon_smooth) {
|
||||
@@ -330,6 +333,19 @@ void GLStateManager::set_shadow_bias(const bool enable)
|
||||
}
|
||||
}
|
||||
|
||||
void GLStateManager::set_clip_control(const bool enable)
|
||||
{
|
||||
if (GLContext::clip_control_support) {
|
||||
if (enable) {
|
||||
/* Match Vulkan and Metal by default. */
|
||||
glClipControl(GL_LOWER_LEFT, GL_ZERO_TO_ONE);
|
||||
}
|
||||
else {
|
||||
glClipControl(GL_LOWER_LEFT, GL_NEGATIVE_ONE_TO_ONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GLStateManager::set_blend(const eGPUBlend value)
|
||||
{
|
||||
/**
|
||||
|
||||
@@ -94,6 +94,7 @@ class GLStateManager : public StateManager {
|
||||
static void set_backface_culling(eGPUFaceCullTest test);
|
||||
static void set_provoking_vert(eGPUProvokingVertex vert);
|
||||
static void set_shadow_bias(bool enable);
|
||||
static void set_clip_control(bool enable);
|
||||
static void set_blend(eGPUBlend value);
|
||||
|
||||
void set_state(const GPUState &state);
|
||||
|
||||
Reference in New Issue
Block a user