Workbench Next: Workaround lack of texture views support #111402

Merged
Miguel Pozo merged 2 commits from pragma37/blender:pull-workbench-next-stencil-workaround into main 2023-08-24 15:10:41 +02:00
11 changed files with 87 additions and 7 deletions

View File

@ -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

View File

@ -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);

View File

@ -0,0 +1,5 @@
void main()
{
out_stencil_value = 0xFF;
}

View File

@ -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_);

View File

@ -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);

View File

@ -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);
};

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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);