diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index d49ad00502a..c332144dffe 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -602,6 +602,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 diff --git a/source/blender/draw/engines/workbench/shaders/infos/workbench_merge_infront_info.hh b/source/blender/draw/engines/workbench/shaders/infos/workbench_merge_infront_info.hh index 5f7402b68b7..b17edba19fb 100644 --- a/source/blender/draw/engines/workbench/shaders/infos/workbench_merge_infront_info.hh +++ b/source/blender/draw/engines/workbench/shaders/infos/workbench_merge_infront_info.hh @@ -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); diff --git a/source/blender/draw/engines/workbench/shaders/workbench_extract_stencil.glsl b/source/blender/draw/engines/workbench/shaders/workbench_extract_stencil.glsl new file mode 100644 index 00000000000..a6fb3b568c5 --- /dev/null +++ b/source/blender/draw/engines/workbench/shaders/workbench_extract_stencil.glsl @@ -0,0 +1,5 @@ + +void main() +{ + out_stencil_value = 0xFF; +} diff --git a/source/blender/draw/engines/workbench/workbench_effect_antialiasing.cc b/source/blender/draw/engines/workbench/workbench_effect_antialiasing.cc index 671710998a6..5a0c6886a6e 100644 --- a/source/blender/draw/engines/workbench/workbench_effect_antialiasing.cc +++ b/source/blender/draw/engines/workbench/workbench_effect_antialiasing.cc @@ -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_); diff --git a/source/blender/draw/engines/workbench/workbench_mesh_passes.cc b/source/blender/draw/engines/workbench/workbench_mesh_passes.cc index 426d9408cef..a68a97293fc 100644 --- a/source/blender/draw/engines/workbench/workbench_mesh_passes.cc +++ b/source/blender/draw/engines/workbench/workbench_mesh_passes.cc @@ -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); diff --git a/source/blender/draw/engines/workbench/workbench_private.hh b/source/blender/draw/engines/workbench/workbench_private.hh index 03c806a5a1b..c5b86d1e74c 100644 --- a/source/blender/draw/engines/workbench/workbench_private.hh +++ b/source/blender/draw/engines/workbench/workbench_private.hh @@ -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); }; diff --git a/source/blender/draw/engines/workbench/workbench_volume_next.cc b/source/blender/draw/engines/workbench/workbench_volume_next.cc index d8c45e1203c..87b19b27b51 100644 --- a/source/blender/draw/engines/workbench/workbench_volume_next.cc +++ b/source/blender/draw/engines/workbench/workbench_volume_next.cc @@ -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); diff --git a/source/blender/gpu/GPU_capabilities.h b/source/blender/gpu/GPU_capabilities.h index 3273626e603..fbf5fd8f20a 100644 --- a/source/blender/gpu/GPU_capabilities.h +++ b/source/blender/gpu/GPU_capabilities.h @@ -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); diff --git a/source/blender/gpu/intern/gpu_capabilities.cc b/source/blender/gpu/intern/gpu_capabilities.cc index b3556e4dbe2..2597e022f9c 100644 --- a/source/blender/gpu/intern/gpu_capabilities.cc +++ b/source/blender/gpu/intern/gpu_capabilities.cc @@ -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; diff --git a/source/blender/gpu/intern/gpu_capabilities_private.hh b/source/blender/gpu/intern/gpu_capabilities_private.hh index cfad99b0a5a..79f4c8b5225 100644 --- a/source/blender/gpu/intern/gpu_capabilities_private.hh +++ b/source/blender/gpu/intern/gpu_capabilities_private.hh @@ -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; diff --git a/source/blender/gpu/opengl/gl_backend.cc b/source/blender/gpu/opengl/gl_backend.cc index b1c90c6023f..9ff7220b42f 100644 --- a/source/blender/gpu/opengl/gl_backend.cc +++ b/source/blender/gpu/opengl/gl_backend.cc @@ -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);