Workbench-Next: Workaround lack of texture views support
Extract a mask from the stencil buffer and use that texture instead when texture views are not available. Needed for supporting the Windows ARM software driver. The workaround is isolated on its own class so it's easy to remove once it's no longer needed. Note that while this adds a function to check if texture views are available (`GPU_texture_view_support`), at the moment this always returns true in practice, since OpenGL 4.3 is the minimum supported version. A separate patch will be needed to allow Blender to run using OpenGL 4.2 + extensions. Pull Request: https://projects.blender.org/blender/blender/pulls/111402
This commit is contained in:
@@ -603,6 +603,7 @@ set(GLSL_SRC
|
||||
engines/workbench/shaders/workbench_effect_smaa_frag.glsl
|
||||
engines/workbench/shaders/workbench_effect_smaa_vert.glsl
|
||||
engines/workbench/shaders/workbench_effect_taa_frag.glsl
|
||||
engines/workbench/shaders/workbench_extract_stencil.glsl
|
||||
engines/workbench/shaders/workbench_image_lib.glsl
|
||||
engines/workbench/shaders/workbench_matcap_lib.glsl
|
||||
engines/workbench/shaders/workbench_material_lib.glsl
|
||||
|
||||
@@ -18,3 +18,9 @@ GPU_SHADER_CREATE_INFO(workbench_next_merge_depth)
|
||||
.additional_info("draw_fullscreen")
|
||||
.depth_write(DepthWrite::ANY)
|
||||
.do_static_compilation(true);
|
||||
|
||||
GPU_SHADER_CREATE_INFO(workbench_extract_stencil)
|
||||
.fragment_out(0, Type::UINT, "out_stencil_value")
|
||||
.fragment_source("workbench_extract_stencil.glsl")
|
||||
.additional_info("draw_fullscreen")
|
||||
.do_static_compilation(true);
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
|
||||
void main()
|
||||
{
|
||||
out_stencil_value = 0xFF;
|
||||
}
|
||||
@@ -254,7 +254,7 @@ void AntiAliasingPass::draw(Manager &manager,
|
||||
GPUTexture *color_tx)
|
||||
{
|
||||
auto draw_overlay_depth = [&](GPUTexture *target) {
|
||||
stencil_tx_ = resources.depth_tx.stencil_view();
|
||||
stencil_tx_ = resources.stencil_view.extract(manager, resources.depth_tx);
|
||||
overlay_depth_fb_.ensure(GPU_ATTACHMENT_TEXTURE(target));
|
||||
overlay_depth_fb_.bind();
|
||||
manager.submit(overlay_depth_ps_);
|
||||
|
||||
@@ -190,6 +190,8 @@ void OpaquePass::draw(Manager &manager,
|
||||
|
||||
bool needs_stencil_copy = shadow_pass && !gbuffer_in_front_ps_.is_empty();
|
||||
|
||||
Texture *depth_stencil_tx = nullptr;
|
||||
|
||||
if (needs_stencil_copy) {
|
||||
shadow_depth_stencil_tx.ensure_2d(GPU_DEPTH24_STENCIL8,
|
||||
resolution,
|
||||
@@ -198,22 +200,24 @@ void OpaquePass::draw(Manager &manager,
|
||||
GPU_TEXTURE_USAGE_MIP_SWIZZLE_VIEW);
|
||||
GPU_texture_copy(shadow_depth_stencil_tx, resources.depth_tx);
|
||||
|
||||
deferred_ps_stencil_tx = shadow_depth_stencil_tx.stencil_view();
|
||||
depth_stencil_tx = shadow_depth_stencil_tx.ptr();
|
||||
|
||||
opaque_fb.ensure(GPU_ATTACHMENT_TEXTURE(deferred_ps_stencil_tx));
|
||||
opaque_fb.ensure(GPU_ATTACHMENT_TEXTURE(*depth_stencil_tx));
|
||||
opaque_fb.bind();
|
||||
GPU_framebuffer_clear_stencil(opaque_fb, 0);
|
||||
}
|
||||
else {
|
||||
shadow_depth_stencil_tx.free();
|
||||
deferred_ps_stencil_tx = resources.depth_tx.stencil_view();
|
||||
depth_stencil_tx = resources.depth_tx.ptr();
|
||||
}
|
||||
|
||||
if (shadow_pass) {
|
||||
shadow_pass->draw(
|
||||
manager, view, resources, *deferred_ps_stencil_tx, !gbuffer_in_front_ps_.is_empty());
|
||||
manager, view, resources, **depth_stencil_tx, !gbuffer_in_front_ps_.is_empty());
|
||||
}
|
||||
|
||||
deferred_ps_stencil_tx = resources.stencil_view.extract(manager, *depth_stencil_tx);
|
||||
|
||||
opaque_fb.ensure(GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(resources.color_tx));
|
||||
opaque_fb.bind();
|
||||
manager.submit(deferred_ps_, view);
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
#include "workbench_enums.hh"
|
||||
#include "workbench_shader_shared.h"
|
||||
|
||||
#include "GPU_capabilities.h"
|
||||
|
||||
extern "C" DrawEngineType draw_engine_workbench_next;
|
||||
|
||||
namespace blender::workbench {
|
||||
@@ -137,6 +139,56 @@ class CavityEffect {
|
||||
void load_samples_buf(int ssao_samples);
|
||||
};
|
||||
|
||||
/* Used as a temporary workaround for the lack of texture views support on Windows ARM. */
|
||||
class StencilViewWorkaround {
|
||||
private:
|
||||
Texture stencil_copy_tx_ = "stencil_copy_tx";
|
||||
GPUShader *stencil_copy_sh_ = nullptr;
|
||||
|
||||
public:
|
||||
StencilViewWorkaround()
|
||||
{
|
||||
stencil_copy_sh_ = GPU_shader_create_from_info_name("workbench_extract_stencil");
|
||||
}
|
||||
~StencilViewWorkaround()
|
||||
{
|
||||
DRW_SHADER_FREE_SAFE(stencil_copy_sh_);
|
||||
}
|
||||
|
||||
/** WARNING: Should only be called at render time.
|
||||
* When the workaround path is active,
|
||||
* the returned texture won't stay in sync with the stencil_src,
|
||||
* and will only be valid until the next time this function is called.
|
||||
* Note that the output is a binary mask,
|
||||
* any stencil value that is not 0x00 will be rendered as 0xFF. */
|
||||
GPUTexture *extract(Manager &manager, Texture &stencil_src)
|
||||
{
|
||||
if (GPU_texture_view_support()) {
|
||||
return stencil_src.stencil_view();
|
||||
}
|
||||
|
||||
int2 extent = int2(stencil_src.width(), stencil_src.height());
|
||||
stencil_copy_tx_.ensure_2d(
|
||||
GPU_R8UI, extent, GPU_TEXTURE_USAGE_ATTACHMENT | GPU_TEXTURE_USAGE_SHADER_READ);
|
||||
|
||||
PassSimple ps("Stencil View Workaround");
|
||||
ps.init();
|
||||
ps.clear_color(float4(0));
|
||||
ps.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_STENCIL_NEQUAL);
|
||||
ps.state_stencil(0x00, 0x00, 0xFF);
|
||||
ps.shader_set(stencil_copy_sh_);
|
||||
ps.draw_procedural(GPU_PRIM_TRIS, 1, 3);
|
||||
|
||||
Framebuffer fb;
|
||||
fb.ensure(GPU_ATTACHMENT_TEXTURE(stencil_src), GPU_ATTACHMENT_TEXTURE(stencil_copy_tx_));
|
||||
fb.bind();
|
||||
|
||||
manager.submit(ps);
|
||||
|
||||
return stencil_copy_tx_;
|
||||
}
|
||||
};
|
||||
|
||||
struct SceneResources {
|
||||
static const int jitter_tx_size = 64;
|
||||
|
||||
@@ -158,6 +210,8 @@ struct SceneResources {
|
||||
|
||||
CavityEffect cavity = {};
|
||||
|
||||
StencilViewWorkaround stencil_view;
|
||||
|
||||
void init(const SceneState &scene_state);
|
||||
void load_jitter_tx(int total_samples);
|
||||
};
|
||||
|
||||
@@ -21,8 +21,6 @@ void VolumePass::sync(SceneResources &resources)
|
||||
dummy_shadow_tx_.ensure_3d(GPU_RGBA8, int3(1), GPU_TEXTURE_USAGE_SHADER_READ, float4(1));
|
||||
dummy_volume_tx_.ensure_3d(GPU_RGBA8, int3(1), GPU_TEXTURE_USAGE_SHADER_READ, float4(0));
|
||||
dummy_coba_tx_.ensure_1d(GPU_RGBA8, 1, GPU_TEXTURE_USAGE_SHADER_READ, float4(0));
|
||||
|
||||
stencil_tx_ = resources.depth_tx.stencil_view();
|
||||
}
|
||||
|
||||
void VolumePass::object_sync_volume(Manager &manager,
|
||||
@@ -182,6 +180,9 @@ void VolumePass::draw(Manager &manager, View &view, SceneResources &resources)
|
||||
if (!active_) {
|
||||
return;
|
||||
}
|
||||
|
||||
stencil_tx_ = resources.stencil_view.extract(manager, resources.depth_tx);
|
||||
|
||||
fb_.ensure(GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(resources.color_tx));
|
||||
fb_.bind();
|
||||
manager.submit(ps_, view);
|
||||
|
||||
@@ -53,6 +53,7 @@ bool GPU_shader_storage_buffer_objects_support(void);
|
||||
bool GPU_shader_image_load_store_support(void);
|
||||
bool GPU_shader_draw_parameters_support(void);
|
||||
bool GPU_hdr_support(void);
|
||||
bool GPU_texture_view_support();
|
||||
|
||||
bool GPU_mem_stats_supported(void);
|
||||
void GPU_mem_stats_get(int *totalmem, int *freemem);
|
||||
|
||||
@@ -187,6 +187,11 @@ bool GPU_hdr_support()
|
||||
return GCaps.hdr_viewport_support;
|
||||
}
|
||||
|
||||
bool GPU_texture_view_support()
|
||||
{
|
||||
return GCaps.texture_view_support;
|
||||
}
|
||||
|
||||
int GPU_max_shader_storage_buffer_bindings()
|
||||
{
|
||||
return GCaps.max_shader_storage_buffer_bindings;
|
||||
|
||||
@@ -49,6 +49,7 @@ struct GPUCapabilities {
|
||||
bool shader_draw_parameters_support = false;
|
||||
bool transform_feedback_support = false;
|
||||
bool hdr_viewport_support = false;
|
||||
bool texture_view_support = true;
|
||||
|
||||
/* OpenGL related workarounds. */
|
||||
bool mip_render_workaround = false;
|
||||
|
||||
@@ -563,6 +563,8 @@ void GLBackend::capabilities_init()
|
||||
GCaps.shader_storage_buffer_objects_support = epoxy_has_gl_extension(
|
||||
"GL_ARB_shader_storage_buffer_object");
|
||||
GCaps.transform_feedback_support = true;
|
||||
GCaps.texture_view_support = epoxy_gl_version() >= 43 ||
|
||||
epoxy_has_gl_extension("GL_ARB_texture_view");
|
||||
|
||||
/* GL specific capabilities. */
|
||||
glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, &GCaps.max_texture_3d_size);
|
||||
|
||||
Reference in New Issue
Block a user