Workbench: Share shader cache across instances
Improve instance creation performance by sharing compiled shaders across instances. (See #114990) Pull Request: https://projects.blender.org/blender/blender/pulls/118062
This commit is contained in:
@@ -111,12 +111,6 @@ static void setup_taa_weights(const float2 offset, float r_weights[9], float &r_
|
||||
|
||||
AntiAliasingPass::AntiAliasingPass()
|
||||
{
|
||||
taa_accumulation_sh_ = GPU_shader_create_from_info_name("workbench_taa");
|
||||
smaa_edge_detect_sh_ = GPU_shader_create_from_info_name("workbench_smaa_stage_0");
|
||||
smaa_aa_weight_sh_ = GPU_shader_create_from_info_name("workbench_smaa_stage_1");
|
||||
smaa_resolve_sh_ = GPU_shader_create_from_info_name("workbench_smaa_stage_2");
|
||||
overlay_depth_sh_ = GPU_shader_create_from_info_name("workbench_overlay_depth");
|
||||
|
||||
smaa_search_tx_.ensure_2d(
|
||||
GPU_R8, {SEARCHTEX_WIDTH, SEARCHTEX_HEIGHT}, GPU_TEXTURE_USAGE_SHADER_READ);
|
||||
GPU_texture_update(smaa_search_tx_, GPU_DATA_UBYTE, searchTexBytes);
|
||||
@@ -127,15 +121,6 @@ AntiAliasingPass::AntiAliasingPass()
|
||||
GPU_texture_filter_mode(smaa_area_tx_, true);
|
||||
}
|
||||
|
||||
AntiAliasingPass::~AntiAliasingPass()
|
||||
{
|
||||
DRW_SHADER_FREE_SAFE(taa_accumulation_sh_);
|
||||
DRW_SHADER_FREE_SAFE(smaa_edge_detect_sh_);
|
||||
DRW_SHADER_FREE_SAFE(smaa_aa_weight_sh_);
|
||||
DRW_SHADER_FREE_SAFE(smaa_resolve_sh_);
|
||||
DRW_SHADER_FREE_SAFE(overlay_depth_sh_);
|
||||
}
|
||||
|
||||
void AntiAliasingPass::init(const SceneState &scene_state)
|
||||
{
|
||||
enabled_ = scene_state.draw_aa;
|
||||
@@ -147,7 +132,7 @@ void AntiAliasingPass::sync(const SceneState &scene_state, SceneResources &resou
|
||||
overlay_depth_ps_.state_set(DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS |
|
||||
DRW_STATE_STENCIL_EQUAL);
|
||||
overlay_depth_ps_.state_stencil(0x00, 0xFF, uint8_t(StencilBits::OBJECT_IN_FRONT));
|
||||
overlay_depth_ps_.shader_set(overlay_depth_sh_);
|
||||
overlay_depth_ps_.shader_set(ShaderCache::get().overlay_depth.get());
|
||||
overlay_depth_ps_.draw_procedural(GPU_PRIM_TRIS, 1, 3);
|
||||
|
||||
if (!enabled_) {
|
||||
@@ -171,14 +156,14 @@ void AntiAliasingPass::sync(const SceneState &scene_state, SceneResources &resou
|
||||
taa_accumulation_ps_.state_set(scene_state.sample == 0 ?
|
||||
DRW_STATE_WRITE_COLOR :
|
||||
DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ADD_FULL);
|
||||
taa_accumulation_ps_.shader_set(taa_accumulation_sh_);
|
||||
taa_accumulation_ps_.shader_set(ShaderCache::get().taa_accumulation.get());
|
||||
taa_accumulation_ps_.bind_texture("colorBuffer", &resources.color_tx);
|
||||
taa_accumulation_ps_.push_constant("samplesWeights", weights_, 9);
|
||||
taa_accumulation_ps_.draw_procedural(GPU_PRIM_TRIS, 1, 3);
|
||||
|
||||
smaa_edge_detect_ps_.init();
|
||||
smaa_edge_detect_ps_.state_set(DRW_STATE_WRITE_COLOR);
|
||||
smaa_edge_detect_ps_.shader_set(smaa_edge_detect_sh_);
|
||||
smaa_edge_detect_ps_.shader_set(ShaderCache::get().smaa_edge_detect.get());
|
||||
smaa_edge_detect_ps_.bind_texture("colorTex", &taa_accumulation_tx_);
|
||||
smaa_edge_detect_ps_.push_constant("viewportMetrics", &smaa_viewport_metrics_, 1);
|
||||
smaa_edge_detect_ps_.clear_color(float4(0.0f));
|
||||
@@ -186,7 +171,7 @@ void AntiAliasingPass::sync(const SceneState &scene_state, SceneResources &resou
|
||||
|
||||
smaa_aa_weight_ps_.init();
|
||||
smaa_aa_weight_ps_.state_set(DRW_STATE_WRITE_COLOR);
|
||||
smaa_aa_weight_ps_.shader_set(smaa_aa_weight_sh_);
|
||||
smaa_aa_weight_ps_.shader_set(ShaderCache::get().smaa_aa_weight.get());
|
||||
smaa_aa_weight_ps_.bind_texture("edgesTex", &smaa_edge_tx_);
|
||||
smaa_aa_weight_ps_.bind_texture("areaTex", smaa_area_tx_);
|
||||
smaa_aa_weight_ps_.bind_texture("searchTex", smaa_search_tx_);
|
||||
@@ -196,7 +181,7 @@ void AntiAliasingPass::sync(const SceneState &scene_state, SceneResources &resou
|
||||
|
||||
smaa_resolve_ps_.init();
|
||||
smaa_resolve_ps_.state_set(DRW_STATE_WRITE_COLOR);
|
||||
smaa_resolve_ps_.shader_set(smaa_resolve_sh_);
|
||||
smaa_resolve_ps_.shader_set(ShaderCache::get().smaa_resolve.get());
|
||||
smaa_resolve_ps_.bind_texture("blendTex", &smaa_weight_tx_);
|
||||
smaa_resolve_ps_.bind_texture("colorTex", &taa_accumulation_tx_);
|
||||
smaa_resolve_ps_.push_constant("viewportMetrics", &smaa_viewport_metrics_, 1);
|
||||
|
||||
@@ -55,15 +55,6 @@ static void square_to_circle(float x, float y, float &r, float &T)
|
||||
}
|
||||
}
|
||||
|
||||
DofPass::~DofPass()
|
||||
{
|
||||
DRW_SHADER_FREE_SAFE(prepare_sh_);
|
||||
DRW_SHADER_FREE_SAFE(downsample_sh_);
|
||||
DRW_SHADER_FREE_SAFE(blur1_sh_);
|
||||
DRW_SHADER_FREE_SAFE(blur2_sh_);
|
||||
DRW_SHADER_FREE_SAFE(resolve_sh_);
|
||||
}
|
||||
|
||||
void DofPass::setup_samples()
|
||||
{
|
||||
float4 *sample = samples_buf_.begin();
|
||||
@@ -111,14 +102,6 @@ void DofPass::init(const SceneState &scene_state)
|
||||
return;
|
||||
}
|
||||
|
||||
if (prepare_sh_ == nullptr) {
|
||||
prepare_sh_ = GPU_shader_create_from_info_name("workbench_effect_dof_prepare");
|
||||
downsample_sh_ = GPU_shader_create_from_info_name("workbench_effect_dof_downsample");
|
||||
blur1_sh_ = GPU_shader_create_from_info_name("workbench_effect_dof_blur1");
|
||||
blur2_sh_ = GPU_shader_create_from_info_name("workbench_effect_dof_blur2");
|
||||
resolve_sh_ = GPU_shader_create_from_info_name("workbench_effect_dof_resolve");
|
||||
}
|
||||
|
||||
offset_ = scene_state.sample / float(scene_state.samples_len);
|
||||
|
||||
int2 half_res = scene_state.resolution / 2;
|
||||
@@ -180,7 +163,7 @@ void DofPass::sync(SceneResources &resources)
|
||||
|
||||
down_ps_.init();
|
||||
down_ps_.state_set(DRW_STATE_WRITE_COLOR);
|
||||
down_ps_.shader_set(prepare_sh_);
|
||||
down_ps_.shader_set(ShaderCache::get().dof_prepare.get());
|
||||
down_ps_.bind_texture("sceneColorTex", &resources.color_tx);
|
||||
down_ps_.bind_texture("sceneDepthTex", &resources.depth_tx);
|
||||
down_ps_.push_constant("invertedViewportSize", float2(DRW_viewport_invert_size_get()));
|
||||
@@ -190,14 +173,14 @@ void DofPass::sync(SceneResources &resources)
|
||||
|
||||
down2_ps_.init();
|
||||
down2_ps_.state_set(DRW_STATE_WRITE_COLOR);
|
||||
down2_ps_.shader_set(downsample_sh_);
|
||||
down2_ps_.shader_set(ShaderCache::get().dof_downsample.get());
|
||||
down2_ps_.bind_texture("sceneColorTex", &source_tx_, sampler_state);
|
||||
down2_ps_.bind_texture("inputCocTex", &coc_halfres_tx_, sampler_state);
|
||||
down2_ps_.draw_procedural(GPU_PRIM_TRIS, 1, 3);
|
||||
|
||||
blur_ps_.init();
|
||||
blur_ps_.state_set(DRW_STATE_WRITE_COLOR);
|
||||
blur_ps_.shader_set(blur1_sh_);
|
||||
blur_ps_.shader_set(ShaderCache::get().dof_blur1.get());
|
||||
blur_ps_.bind_ubo("samples", samples_buf_);
|
||||
blur_ps_.bind_texture("noiseTex", resources.jitter_tx);
|
||||
blur_ps_.bind_texture("inputCocTex", &coc_halfres_tx_, sampler_state);
|
||||
@@ -208,7 +191,7 @@ void DofPass::sync(SceneResources &resources)
|
||||
|
||||
blur2_ps_.init();
|
||||
blur2_ps_.state_set(DRW_STATE_WRITE_COLOR);
|
||||
blur2_ps_.shader_set(blur2_sh_);
|
||||
blur2_ps_.shader_set(ShaderCache::get().dof_blur2.get());
|
||||
blur2_ps_.bind_texture("inputCocTex", &coc_halfres_tx_, sampler_state);
|
||||
blur2_ps_.bind_texture("blurTex", &blur_tx_);
|
||||
blur2_ps_.push_constant("invertedViewportSize", float2(DRW_viewport_invert_size_get()));
|
||||
@@ -216,7 +199,7 @@ void DofPass::sync(SceneResources &resources)
|
||||
|
||||
resolve_ps_.init();
|
||||
resolve_ps_.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_CUSTOM);
|
||||
resolve_ps_.shader_set(resolve_sh_);
|
||||
resolve_ps_.shader_set(ShaderCache::get().dof_resolve.get());
|
||||
resolve_ps_.bind_texture("halfResColorTex", &source_tx_, sampler_state);
|
||||
resolve_ps_.bind_texture("sceneDepthTex", &resources.depth_tx);
|
||||
resolve_ps_.push_constant("invertedViewportSize", float2(DRW_viewport_invert_size_get()));
|
||||
|
||||
@@ -14,21 +14,12 @@
|
||||
|
||||
namespace blender::workbench {
|
||||
|
||||
OutlinePass::~OutlinePass()
|
||||
{
|
||||
DRW_SHADER_FREE_SAFE(sh_);
|
||||
}
|
||||
|
||||
void OutlinePass::init(const SceneState &scene_state)
|
||||
{
|
||||
enabled_ = scene_state.draw_outline;
|
||||
if (!enabled_) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (sh_ == nullptr) {
|
||||
sh_ = GPU_shader_create_from_info_name("workbench_effect_outline");
|
||||
}
|
||||
}
|
||||
|
||||
void OutlinePass::sync(SceneResources &resources)
|
||||
@@ -39,7 +30,7 @@ void OutlinePass::sync(SceneResources &resources)
|
||||
|
||||
ps_.init();
|
||||
ps_.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ALPHA_PREMUL);
|
||||
ps_.shader_set(sh_);
|
||||
ps_.shader_set(ShaderCache::get().outline.get());
|
||||
ps_.bind_ubo("world_data", resources.world_buf);
|
||||
ps_.bind_texture("objectIdBuffer", &resources.object_id_tx);
|
||||
ps_.draw_procedural(GPU_PRIM_TRIS, 1, 3);
|
||||
|
||||
@@ -593,6 +593,11 @@ static void workbench_instance_free(void *instance)
|
||||
delete reinterpret_cast<workbench::Instance *>(instance);
|
||||
}
|
||||
|
||||
static void workbench_engine_free()
|
||||
{
|
||||
workbench::ShaderCache::release();
|
||||
}
|
||||
|
||||
static void workbench_view_update(void *vedata)
|
||||
{
|
||||
WORKBENCH_Data *ved = reinterpret_cast<WORKBENCH_Data *>(vedata);
|
||||
@@ -806,7 +811,7 @@ DrawEngineType draw_engine_workbench = {
|
||||
/*idname*/ N_("Workbench"),
|
||||
/*vedata_size*/ &workbench_data_size,
|
||||
/*engine_init*/ &workbench_engine_init,
|
||||
/*engine_free*/ nullptr,
|
||||
/*engine_free*/ &workbench_engine_free,
|
||||
/*instance_free*/ &workbench_instance_free,
|
||||
/*cache_init*/ &workbench_cache_init,
|
||||
/*cache_populate*/ &workbench_cache_populate,
|
||||
|
||||
@@ -45,9 +45,8 @@ static inline eGeometryType geometry_type_from_object(Object *ob)
|
||||
enum class ePipelineType {
|
||||
OPAQUE = 0,
|
||||
TRANSPARENT,
|
||||
SHADOW,
|
||||
};
|
||||
static constexpr int pipeline_type_len = static_cast<int>(ePipelineType::SHADOW) + 1;
|
||||
static constexpr int pipeline_type_len = static_cast<int>(ePipelineType::TRANSPARENT) + 1;
|
||||
|
||||
enum class eLightingType {
|
||||
FLAT = 0,
|
||||
|
||||
@@ -32,10 +32,7 @@ void MeshPass::init_pass(SceneResources &resources, DRWState state, int clip_pla
|
||||
}
|
||||
}
|
||||
|
||||
void MeshPass::init_subpasses(ePipelineType pipeline,
|
||||
eLightingType lighting,
|
||||
bool clip,
|
||||
ShaderCache &shaders)
|
||||
void MeshPass::init_subpasses(ePipelineType pipeline, eLightingType lighting, bool clip)
|
||||
{
|
||||
texture_subpass_map_.clear();
|
||||
|
||||
@@ -49,9 +46,9 @@ void MeshPass::init_subpasses(ePipelineType pipeline,
|
||||
pass_names[geom][shader] = std::string(get_name(geom_type)) +
|
||||
std::string(get_name(shader_type));
|
||||
}
|
||||
GPUShader *sh = shaders.prepass_shader_get(pipeline, geom_type, shader_type, lighting, clip);
|
||||
PassMain::Sub *pass = &sub(pass_names[geom][shader].c_str());
|
||||
pass->shader_set(sh);
|
||||
pass->shader_set(
|
||||
ShaderCache::get().prepass_get(geom_type, pipeline, lighting, shader_type, clip));
|
||||
passes_[geom][shader] = pass;
|
||||
}
|
||||
}
|
||||
@@ -115,23 +112,20 @@ void OpaquePass::sync(const SceneState &scene_state, SceneResources &resources)
|
||||
DRWState in_front_state = state | DRW_STATE_STENCIL_ALWAYS;
|
||||
gbuffer_in_front_ps_.init_pass(resources, in_front_state, scene_state.clip_planes.size());
|
||||
gbuffer_in_front_ps_.state_stencil(uint8_t(StencilBits::OBJECT_IN_FRONT), 0xFF, 0x00);
|
||||
gbuffer_in_front_ps_.init_subpasses(
|
||||
ePipelineType::OPAQUE, scene_state.lighting_type, clip, resources.shader_cache);
|
||||
gbuffer_in_front_ps_.init_subpasses(ePipelineType::OPAQUE, scene_state.lighting_type, clip);
|
||||
|
||||
state |= DRW_STATE_STENCIL_NEQUAL;
|
||||
gbuffer_ps_.init_pass(resources, state, scene_state.clip_planes.size());
|
||||
gbuffer_ps_.state_stencil(
|
||||
uint8_t(StencilBits::OBJECT), 0xFF, uint8_t(StencilBits::OBJECT_IN_FRONT));
|
||||
gbuffer_ps_.init_subpasses(
|
||||
ePipelineType::OPAQUE, scene_state.lighting_type, clip, resources.shader_cache);
|
||||
gbuffer_ps_.init_subpasses(ePipelineType::OPAQUE, scene_state.lighting_type, clip);
|
||||
|
||||
deferred_ps_.init();
|
||||
deferred_ps_.state_set(DRW_STATE_WRITE_COLOR);
|
||||
deferred_ps_.shader_set(resources.shader_cache.resolve_shader_get(ePipelineType::OPAQUE,
|
||||
scene_state.lighting_type,
|
||||
scene_state.draw_cavity,
|
||||
scene_state.draw_curvature,
|
||||
scene_state.draw_shadows));
|
||||
deferred_ps_.shader_set(ShaderCache::get().resolve_get(scene_state.lighting_type,
|
||||
scene_state.draw_cavity,
|
||||
scene_state.draw_curvature,
|
||||
scene_state.draw_shadows));
|
||||
deferred_ps_.push_constant("forceShadowing", false);
|
||||
deferred_ps_.bind_ubo(WB_WORLD_SLOT, resources.world_buf);
|
||||
deferred_ps_.bind_texture(WB_MATCAP_SLOT, resources.matcap_tx);
|
||||
@@ -229,11 +223,6 @@ bool OpaquePass::is_empty() const
|
||||
/** \name TransparentPass
|
||||
* \{ */
|
||||
|
||||
TransparentPass::~TransparentPass()
|
||||
{
|
||||
DRW_SHADER_FREE_SAFE(resolve_sh_);
|
||||
}
|
||||
|
||||
void TransparentPass::sync(const SceneState &scene_state, SceneResources &resources)
|
||||
{
|
||||
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND_OIT |
|
||||
@@ -246,20 +235,16 @@ void TransparentPass::sync(const SceneState &scene_state, SceneResources &resour
|
||||
accumulation_ps_.state_stencil(
|
||||
uint8_t(StencilBits::OBJECT), 0xFF, uint8_t(StencilBits::OBJECT_IN_FRONT));
|
||||
accumulation_ps_.clear_color(float4(0.0f, 0.0f, 0.0f, 1.0f));
|
||||
accumulation_ps_.init_subpasses(
|
||||
ePipelineType::TRANSPARENT, scene_state.lighting_type, clip, resources.shader_cache);
|
||||
accumulation_ps_.init_subpasses(ePipelineType::TRANSPARENT, scene_state.lighting_type, clip);
|
||||
|
||||
accumulation_in_front_ps_.init_pass(resources, state, scene_state.clip_planes.size());
|
||||
accumulation_in_front_ps_.clear_color(float4(0.0f, 0.0f, 0.0f, 1.0f));
|
||||
accumulation_in_front_ps_.init_subpasses(
|
||||
ePipelineType::TRANSPARENT, scene_state.lighting_type, clip, resources.shader_cache);
|
||||
ePipelineType::TRANSPARENT, scene_state.lighting_type, clip);
|
||||
|
||||
if (resolve_sh_ == nullptr) {
|
||||
resolve_sh_ = GPU_shader_create_from_info_name("workbench_transparent_resolve");
|
||||
}
|
||||
resolve_ps_.init();
|
||||
resolve_ps_.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ALPHA);
|
||||
resolve_ps_.shader_set(resolve_sh_);
|
||||
resolve_ps_.shader_set(ShaderCache::get().transparent_resolve.get());
|
||||
resolve_ps_.bind_texture("transparentAccum", &accumulation_tx);
|
||||
resolve_ps_.bind_texture("transparentRevealage", &reveal_tx);
|
||||
resolve_ps_.draw_procedural(GPU_PRIM_TRIS, 1, 3);
|
||||
@@ -314,11 +299,6 @@ bool TransparentPass::is_empty() const
|
||||
/** \name TransparentDepthPass
|
||||
* \{ */
|
||||
|
||||
TransparentDepthPass::~TransparentDepthPass()
|
||||
{
|
||||
DRW_SHADER_FREE_SAFE(merge_sh_);
|
||||
}
|
||||
|
||||
void TransparentDepthPass::sync(const SceneState &scene_state, SceneResources &resources)
|
||||
{
|
||||
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL |
|
||||
@@ -329,14 +309,10 @@ void TransparentDepthPass::sync(const SceneState &scene_state, SceneResources &r
|
||||
DRWState in_front_state = state | DRW_STATE_STENCIL_ALWAYS;
|
||||
in_front_ps_.init_pass(resources, in_front_state, scene_state.clip_planes.size());
|
||||
in_front_ps_.state_stencil(uint8_t(StencilBits::OBJECT_IN_FRONT), 0xFF, 0x00);
|
||||
in_front_ps_.init_subpasses(
|
||||
ePipelineType::OPAQUE, eLightingType::FLAT, clip, resources.shader_cache);
|
||||
in_front_ps_.init_subpasses(ePipelineType::OPAQUE, eLightingType::FLAT, clip);
|
||||
|
||||
if (merge_sh_ == nullptr) {
|
||||
merge_sh_ = GPU_shader_create_from_info_name("workbench_merge_depth");
|
||||
}
|
||||
merge_ps_.init();
|
||||
merge_ps_.shader_set(merge_sh_);
|
||||
merge_ps_.shader_set(ShaderCache::get().merge_depth.get());
|
||||
merge_ps_.state_set(DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_WRITE_STENCIL |
|
||||
DRW_STATE_STENCIL_EQUAL);
|
||||
merge_ps_.state_stencil(
|
||||
@@ -348,8 +324,7 @@ void TransparentDepthPass::sync(const SceneState &scene_state, SceneResources &r
|
||||
main_ps_.init_pass(resources, state, scene_state.clip_planes.size());
|
||||
main_ps_.state_stencil(
|
||||
uint8_t(StencilBits::OBJECT), 0xFF, uint8_t(StencilBits::OBJECT_IN_FRONT));
|
||||
main_ps_.init_subpasses(
|
||||
ePipelineType::OPAQUE, eLightingType::FLAT, clip, resources.shader_cache);
|
||||
main_ps_.init_subpasses(ePipelineType::OPAQUE, eLightingType::FLAT, clip);
|
||||
}
|
||||
|
||||
void TransparentDepthPass::draw(Manager &manager, View &view, SceneResources &resources)
|
||||
|
||||
@@ -19,28 +19,107 @@ namespace blender::workbench {
|
||||
|
||||
using namespace draw;
|
||||
|
||||
class ShaderCache {
|
||||
public:
|
||||
~ShaderCache();
|
||||
|
||||
GPUShader *prepass_shader_get(ePipelineType pipeline_type,
|
||||
eGeometryType geometry_type,
|
||||
eShaderType shader_type,
|
||||
eLightingType lighting_type,
|
||||
bool clip);
|
||||
|
||||
GPUShader *resolve_shader_get(ePipelineType pipeline_type,
|
||||
eLightingType lighting_type,
|
||||
bool cavity = false,
|
||||
bool curvature = false,
|
||||
bool shadow = false);
|
||||
|
||||
class StaticShader : NonCopyable {
|
||||
private:
|
||||
/* TODO(fclem): We might want to change to a Map since most shader will never be compiled. */
|
||||
GPUShader *prepass_shader_cache_[pipeline_type_len][geometry_type_len][shader_type_len]
|
||||
[lighting_type_len][2 /*clip*/] = {{{{{nullptr}}}}};
|
||||
GPUShader *resolve_shader_cache_[pipeline_type_len][lighting_type_len][2 /*cavity*/]
|
||||
[2 /*curvature*/][2 /*shadow*/] = {{{{{nullptr}}}}};
|
||||
std::string info_name_;
|
||||
GPUShader *shader_ = nullptr;
|
||||
|
||||
public:
|
||||
StaticShader(std::string info_name) : info_name_(info_name) {}
|
||||
|
||||
StaticShader() = default;
|
||||
StaticShader(StaticShader &&other) = default;
|
||||
StaticShader &operator=(StaticShader &&other) = default;
|
||||
|
||||
~StaticShader()
|
||||
{
|
||||
DRW_SHADER_FREE_SAFE(shader_);
|
||||
}
|
||||
|
||||
GPUShader *get()
|
||||
{
|
||||
if (!shader_) {
|
||||
BLI_assert(!info_name_.empty());
|
||||
shader_ = GPU_shader_create_from_info_name(info_name_.c_str());
|
||||
}
|
||||
return shader_;
|
||||
}
|
||||
};
|
||||
|
||||
class ShaderCache {
|
||||
private:
|
||||
static ShaderCache *static_cache;
|
||||
|
||||
StaticShader prepass_[geometry_type_len][pipeline_type_len][lighting_type_len][shader_type_len]
|
||||
[2 /*clip*/];
|
||||
StaticShader resolve_[lighting_type_len][2 /*cavity*/][2 /*curvature*/][2 /*shadow*/];
|
||||
|
||||
StaticShader shadow_[2 /*depth_pass*/][2 /*manifold*/][2 /*cap*/];
|
||||
|
||||
StaticShader volume_[2 /*smoke*/][3 /*interpolation*/][2 /*slice*/][2 /*coba*/];
|
||||
|
||||
public:
|
||||
static ShaderCache &get();
|
||||
static void release();
|
||||
|
||||
ShaderCache();
|
||||
|
||||
GPUShader *prepass_get(eGeometryType geometry_type,
|
||||
ePipelineType pipeline_type,
|
||||
eLightingType lighting_type,
|
||||
eShaderType shader_type,
|
||||
bool clip)
|
||||
{
|
||||
return prepass_[int(geometry_type)][int(pipeline_type)][int(lighting_type)][int(shader_type)]
|
||||
[clip]
|
||||
.get();
|
||||
}
|
||||
|
||||
GPUShader *resolve_get(eLightingType lighting_type,
|
||||
bool cavity = false,
|
||||
bool curvature = false,
|
||||
bool shadow = false)
|
||||
{
|
||||
return resolve_[int(lighting_type)][cavity][curvature][shadow].get();
|
||||
}
|
||||
|
||||
GPUShader *shadow_get(bool depth_pass, bool manifold, bool cap = false)
|
||||
{
|
||||
return shadow_[depth_pass][manifold][cap].get();
|
||||
}
|
||||
|
||||
GPUShader *volume_get(bool smoke, int interpolation, bool coba, bool slice)
|
||||
{
|
||||
return volume_[smoke][interpolation][coba][slice].get();
|
||||
}
|
||||
|
||||
StaticShader extract_stencil = {"workbench_extract_stencil"};
|
||||
|
||||
/* Transparency */
|
||||
StaticShader transparent_resolve = {"workbench_transparent_resolve"};
|
||||
StaticShader merge_depth = {"workbench_merge_depth"};
|
||||
|
||||
/* ShadowView */
|
||||
StaticShader shadow_visibility_dynamic = {
|
||||
"workbench_shadow_visibility_compute_dynamic_pass_type"};
|
||||
StaticShader shadow_visibility_static = {"workbench_shadow_visibility_compute_static_pass_type"};
|
||||
|
||||
/* Outline */
|
||||
StaticShader outline = {"workbench_effect_outline"};
|
||||
|
||||
/* Dof */
|
||||
StaticShader dof_prepare = {"workbench_effect_dof_prepare"};
|
||||
StaticShader dof_downsample = {"workbench_effect_dof_downsample"};
|
||||
StaticShader dof_blur1 = {"workbench_effect_dof_blur1"};
|
||||
StaticShader dof_blur2 = {"workbench_effect_dof_blur2"};
|
||||
StaticShader dof_resolve = {"workbench_effect_dof_resolve"};
|
||||
|
||||
/* AA */
|
||||
StaticShader taa_accumulation = {"workbench_taa"};
|
||||
StaticShader smaa_edge_detect = {"workbench_smaa_stage_0"};
|
||||
StaticShader smaa_aa_weight = {"workbench_smaa_stage_1"};
|
||||
StaticShader smaa_resolve = {"workbench_smaa_stage_2"};
|
||||
StaticShader overlay_depth = {"workbench_overlay_depth"};
|
||||
};
|
||||
|
||||
struct Material {
|
||||
@@ -145,18 +224,8 @@ class CavityEffect {
|
||||
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,
|
||||
@@ -178,7 +247,7 @@ class StencilViewWorkaround {
|
||||
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.shader_set(ShaderCache::get().extract_stencil.get());
|
||||
ps.draw_procedural(GPU_PRIM_TRIS, 1, 3);
|
||||
|
||||
Framebuffer fb;
|
||||
@@ -194,8 +263,6 @@ class StencilViewWorkaround {
|
||||
struct SceneResources {
|
||||
static const int jitter_tx_size = 64;
|
||||
|
||||
ShaderCache shader_cache = {};
|
||||
|
||||
StringRefNull current_matcap = {};
|
||||
Texture matcap_tx = "matcap_tx";
|
||||
|
||||
@@ -239,10 +306,7 @@ class MeshPass : public PassMain {
|
||||
bool is_empty() const;
|
||||
|
||||
void init_pass(SceneResources &resources, DRWState state, int clip_planes);
|
||||
void init_subpasses(ePipelineType pipeline,
|
||||
eLightingType lighting,
|
||||
bool clip,
|
||||
ShaderCache &shaders);
|
||||
void init_subpasses(ePipelineType pipeline, eLightingType lighting, bool clip);
|
||||
|
||||
PassMain::Sub &get_subpass(eGeometryType geometry_type,
|
||||
::Image *image = nullptr,
|
||||
@@ -283,9 +347,6 @@ class OpaquePass {
|
||||
};
|
||||
|
||||
class TransparentPass {
|
||||
private:
|
||||
GPUShader *resolve_sh_ = nullptr;
|
||||
|
||||
public:
|
||||
TextureFromPool accumulation_tx = {"accumulation_accumulation_tx"};
|
||||
TextureFromPool reveal_tx = {"accumulation_reveal_tx"};
|
||||
@@ -296,17 +357,12 @@ class TransparentPass {
|
||||
PassSimple resolve_ps_ = {"Transparent.Resolve"};
|
||||
Framebuffer resolve_fb = {};
|
||||
|
||||
~TransparentPass();
|
||||
|
||||
void sync(const SceneState &scene_state, SceneResources &resources);
|
||||
void draw(Manager &manager, View &view, SceneResources &resources, int2 resolution);
|
||||
bool is_empty() const;
|
||||
};
|
||||
|
||||
class TransparentDepthPass {
|
||||
private:
|
||||
GPUShader *merge_sh_ = nullptr;
|
||||
|
||||
public:
|
||||
MeshPass main_ps_ = {"TransparentDepth.Main"};
|
||||
Framebuffer main_fb = {"TransparentDepth.Main"};
|
||||
@@ -315,13 +371,13 @@ class TransparentDepthPass {
|
||||
PassSimple merge_ps_ = {"TransparentDepth.Merge"};
|
||||
Framebuffer merge_fb = {"TransparentDepth.Merge"};
|
||||
|
||||
~TransparentDepthPass();
|
||||
|
||||
void sync(const SceneState &scene_state, SceneResources &resources);
|
||||
void draw(Manager &manager, View &view, SceneResources &resources);
|
||||
bool is_empty() const;
|
||||
};
|
||||
|
||||
#define DEBUG_SHADOW_VOLUME 0
|
||||
|
||||
class ShadowPass {
|
||||
private:
|
||||
enum PassType { PASS = 0, FAIL, FORCED_FAIL, MAX };
|
||||
@@ -335,12 +391,8 @@ class ShadowPass {
|
||||
VisibilityBuf pass_visibility_buf_ = {};
|
||||
VisibilityBuf fail_visibility_buf_ = {};
|
||||
|
||||
GPUShader *dynamic_pass_type_shader_;
|
||||
GPUShader *static_pass_type_shader_;
|
||||
|
||||
public:
|
||||
ShadowView();
|
||||
~ShadowView();
|
||||
ShadowView() : View("ShadowPass.View"){};
|
||||
|
||||
void setup(View &view, float3 light_direction, bool force_fail_method);
|
||||
bool debug_object_culling(Object *ob);
|
||||
@@ -368,16 +420,10 @@ class ShadowPass {
|
||||
PassMain::Sub *passes_[PassType::MAX][2][2] = {{{nullptr}}};
|
||||
PassMain::Sub *&get_pass_ptr(PassType type, bool manifold, bool cap = false);
|
||||
|
||||
/* [Is Pass Technique][Is Manifold][Is Cap] */
|
||||
GPUShader *shaders_[2][2][2] = {{{nullptr}}};
|
||||
GPUShader *get_shader(bool depth_pass, bool manifold, bool cap = false);
|
||||
|
||||
TextureFromPool depth_tx_ = {};
|
||||
Framebuffer fb_ = {};
|
||||
|
||||
public:
|
||||
~ShadowPass();
|
||||
|
||||
void init(const SceneState &scene_state, SceneResources &resources);
|
||||
void update();
|
||||
void sync();
|
||||
@@ -407,11 +453,7 @@ class VolumePass {
|
||||
|
||||
GPUTexture *stencil_tx_ = nullptr;
|
||||
|
||||
GPUShader *shaders_[2 /*slice*/][2 /*coba*/][3 /*interpolation*/][2 /*smoke*/];
|
||||
|
||||
public:
|
||||
~VolumePass();
|
||||
|
||||
void sync(SceneResources &resources);
|
||||
|
||||
void object_sync_volume(Manager &manager,
|
||||
@@ -429,8 +471,6 @@ class VolumePass {
|
||||
void draw(Manager &manager, View &view, SceneResources &resources);
|
||||
|
||||
private:
|
||||
GPUShader *get_shader(bool slice, bool coba, int interpolation, bool smoke);
|
||||
|
||||
void draw_slice_ps(Manager &manager,
|
||||
PassMain::Sub &ps,
|
||||
ObjectRef &ob_ref,
|
||||
@@ -450,12 +490,9 @@ class OutlinePass {
|
||||
bool enabled_ = false;
|
||||
|
||||
PassSimple ps_ = PassSimple("Workbench.Outline");
|
||||
GPUShader *sh_ = nullptr;
|
||||
Framebuffer fb_ = Framebuffer("Workbench.Outline");
|
||||
|
||||
public:
|
||||
~OutlinePass();
|
||||
|
||||
void init(const SceneState &scene_state);
|
||||
void sync(SceneResources &resources);
|
||||
void draw(Manager &manager, SceneResources &resources);
|
||||
@@ -481,12 +518,6 @@ class DofPass {
|
||||
Framebuffer blur2_fb_ = {};
|
||||
Framebuffer resolve_fb_ = {};
|
||||
|
||||
GPUShader *prepare_sh_ = nullptr;
|
||||
GPUShader *downsample_sh_ = nullptr;
|
||||
GPUShader *blur1_sh_ = nullptr;
|
||||
GPUShader *blur2_sh_ = nullptr;
|
||||
GPUShader *resolve_sh_ = nullptr;
|
||||
|
||||
PassSimple down_ps_ = {"Workbench.DoF.DownSample"};
|
||||
PassSimple down2_ps_ = {"Workbench.DoF.DownSample2"};
|
||||
PassSimple blur_ps_ = {"Workbench.DoF.Blur"};
|
||||
@@ -503,8 +534,6 @@ class DofPass {
|
||||
float ratio_ = 0;
|
||||
|
||||
public:
|
||||
~DofPass();
|
||||
|
||||
void init(const SceneState &scene_state);
|
||||
void sync(SceneResources &resources);
|
||||
void draw(Manager &manager, View &view, SceneResources &resources, int2 resolution);
|
||||
@@ -542,12 +571,6 @@ class AntiAliasingPass {
|
||||
float4 smaa_viewport_metrics_ = float4(0);
|
||||
float smaa_mix_factor_ = 0;
|
||||
|
||||
GPUShader *taa_accumulation_sh_ = nullptr;
|
||||
GPUShader *smaa_edge_detect_sh_ = nullptr;
|
||||
GPUShader *smaa_aa_weight_sh_ = nullptr;
|
||||
GPUShader *smaa_resolve_sh_ = nullptr;
|
||||
GPUShader *overlay_depth_sh_ = nullptr;
|
||||
|
||||
PassSimple taa_accumulation_ps_ = {"TAA.Accumulation"};
|
||||
PassSimple smaa_edge_detect_ps_ = {"SMAA.EdgeDetect"};
|
||||
PassSimple smaa_aa_weight_ps_ = {"SMAA.BlendWeights"};
|
||||
@@ -556,7 +579,6 @@ class AntiAliasingPass {
|
||||
|
||||
public:
|
||||
AntiAliasingPass();
|
||||
~AntiAliasingPass();
|
||||
|
||||
void init(const SceneState &scene_state);
|
||||
void sync(const SceneState &scene_state, SceneResources &resources);
|
||||
|
||||
@@ -6,132 +6,92 @@
|
||||
|
||||
namespace blender::workbench {
|
||||
|
||||
ShaderCache::~ShaderCache()
|
||||
ShaderCache *ShaderCache::static_cache = nullptr;
|
||||
|
||||
ShaderCache &ShaderCache::get()
|
||||
{
|
||||
for (auto i : IndexRange(pipeline_type_len)) {
|
||||
for (auto j : IndexRange(geometry_type_len)) {
|
||||
for (auto k : IndexRange(shader_type_len)) {
|
||||
for (auto l : IndexRange(lighting_type_len)) {
|
||||
for (auto m : IndexRange(2) /*clip*/) {
|
||||
DRW_SHADER_FREE_SAFE(prepass_shader_cache_[i][j][k][l][m]);
|
||||
if (!ShaderCache::static_cache) {
|
||||
ShaderCache::static_cache = new ShaderCache();
|
||||
}
|
||||
return *ShaderCache::static_cache;
|
||||
}
|
||||
|
||||
void ShaderCache::release()
|
||||
{
|
||||
if (ShaderCache::static_cache) {
|
||||
delete ShaderCache::static_cache;
|
||||
ShaderCache::static_cache = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
ShaderCache::ShaderCache()
|
||||
{
|
||||
std::string geometries[] = {"_mesh", "_curves", "_ptcloud"};
|
||||
std::string pipelines[] = {"_opaque", "_transparent"};
|
||||
std::string lightings[] = {"_flat", "_studio", "_matcap"};
|
||||
std::string shaders[] = {"_material", "_texture"};
|
||||
std::string clip[] = {"_no_clip", "_clip"};
|
||||
static_assert(std::size(geometries) == geometry_type_len);
|
||||
static_assert(std::size(pipelines) == pipeline_type_len);
|
||||
static_assert(std::size(lightings) == lighting_type_len);
|
||||
static_assert(std::size(shaders) == shader_type_len);
|
||||
|
||||
for (auto g : IndexRange(geometry_type_len)) {
|
||||
for (auto p : IndexRange(pipeline_type_len)) {
|
||||
for (auto l : IndexRange(lighting_type_len)) {
|
||||
for (auto s : IndexRange(shader_type_len)) {
|
||||
for (auto c : IndexRange(2) /*clip*/) {
|
||||
prepass_[g][p][l][s][c] = {"workbench_prepass" + geometries[g] + pipelines[p] +
|
||||
lightings[l] + shaders[s] + clip[c]};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (auto i : IndexRange(pipeline_type_len)) {
|
||||
for (auto j : IndexRange(lighting_type_len)) {
|
||||
for (auto k : IndexRange(2) /*cavity*/) {
|
||||
for (auto l : IndexRange(2) /*curvature*/) {
|
||||
for (auto m : IndexRange(2) /*shadow*/) {
|
||||
DRW_SHADER_FREE_SAFE(resolve_shader_cache_[i][j][k][l][m]);
|
||||
}
|
||||
|
||||
std::string cavity[] = {"_no_cavity", "_cavity"};
|
||||
std::string curvature[] = {"_no_curvature", "_curvature"};
|
||||
std::string shadow[] = {"_no_shadow", "_shadow"};
|
||||
|
||||
for (auto l : IndexRange(lighting_type_len)) {
|
||||
for (auto ca : IndexRange(2) /*cavity*/) {
|
||||
for (auto cu : IndexRange(2) /*curvature*/) {
|
||||
for (auto s : IndexRange(2) /*shadow*/) {
|
||||
resolve_[l][ca][cu][s] = {"workbench_resolve_opaque" + lightings[l] + cavity[ca] +
|
||||
curvature[cu] + shadow[s]};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GPUShader *ShaderCache::prepass_shader_get(ePipelineType pipeline_type,
|
||||
eGeometryType geometry_type,
|
||||
eShaderType shader_type,
|
||||
eLightingType lighting_type,
|
||||
bool clip)
|
||||
{
|
||||
GPUShader *&shader_ptr = prepass_shader_cache_[int(pipeline_type)][int(geometry_type)][int(
|
||||
shader_type)][int(lighting_type)][clip ? 1 : 0];
|
||||
std::string pass[] = {"_fail", "_pass"};
|
||||
std::string manifold[] = {"_no_manifold", "_manifold"};
|
||||
std::string caps[] = {"_no_caps", "_caps"};
|
||||
|
||||
if (shader_ptr != nullptr) {
|
||||
return shader_ptr;
|
||||
for (auto p : IndexRange(2) /*pass*/) {
|
||||
for (auto m : IndexRange(2) /*manifold*/) {
|
||||
for (auto c : IndexRange(2) /*caps*/) {
|
||||
shadow_[p][m][c] = {"workbench_shadow" + pass[p] + manifold[m] + caps[c] +
|
||||
(DEBUG_SHADOW_VOLUME ? "_debug" : "")};
|
||||
}
|
||||
}
|
||||
}
|
||||
std::string info_name = "workbench_prepass_";
|
||||
switch (geometry_type) {
|
||||
case eGeometryType::MESH:
|
||||
info_name += "mesh_";
|
||||
break;
|
||||
case eGeometryType::CURVES:
|
||||
info_name += "curves_";
|
||||
break;
|
||||
case eGeometryType::POINTCLOUD:
|
||||
info_name += "ptcloud_";
|
||||
break;
|
||||
}
|
||||
switch (pipeline_type) {
|
||||
case ePipelineType::OPAQUE:
|
||||
info_name += "opaque_";
|
||||
break;
|
||||
case ePipelineType::TRANSPARENT:
|
||||
info_name += "transparent_";
|
||||
break;
|
||||
case ePipelineType::SHADOW:
|
||||
info_name += "shadow_";
|
||||
break;
|
||||
}
|
||||
switch (lighting_type) {
|
||||
case eLightingType::FLAT:
|
||||
info_name += "flat_";
|
||||
break;
|
||||
case eLightingType::STUDIO:
|
||||
info_name += "studio_";
|
||||
break;
|
||||
case eLightingType::MATCAP:
|
||||
info_name += "matcap_";
|
||||
break;
|
||||
}
|
||||
switch (shader_type) {
|
||||
case eShaderType::MATERIAL:
|
||||
info_name += "material";
|
||||
break;
|
||||
case eShaderType::TEXTURE:
|
||||
info_name += "texture";
|
||||
break;
|
||||
}
|
||||
info_name += clip ? "_clip" : "_no_clip";
|
||||
shader_ptr = GPU_shader_create_from_info_name(info_name.c_str());
|
||||
return shader_ptr;
|
||||
}
|
||||
|
||||
GPUShader *ShaderCache::resolve_shader_get(ePipelineType pipeline_type,
|
||||
eLightingType lighting_type,
|
||||
bool cavity,
|
||||
bool curvature,
|
||||
bool shadow)
|
||||
{
|
||||
GPUShader *&shader_ptr =
|
||||
resolve_shader_cache_[int(pipeline_type)][int(lighting_type)][cavity][curvature][shadow];
|
||||
std::string smoke[] = {"_smoke", "_object"};
|
||||
std::string interpolation[] = {"_linear", "_cubic", "_closest"};
|
||||
std::string coba[] = {"_no_coba", "_coba"};
|
||||
std::string slice[] = {"_no_slice", "_slice"};
|
||||
|
||||
if (shader_ptr != nullptr) {
|
||||
return shader_ptr;
|
||||
for (auto sm : IndexRange(2) /*smoke*/) {
|
||||
for (auto i : IndexRange(3) /*interpolation*/) {
|
||||
for (auto c : IndexRange(2) /*coba*/) {
|
||||
for (auto sl : IndexRange(2) /*slice*/) {
|
||||
volume_[sm][i][c][sl] = {"workbench_volume" + smoke[sm] + interpolation[i] + coba[c] +
|
||||
slice[sl]};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
std::string info_name = "workbench_resolve_";
|
||||
switch (pipeline_type) {
|
||||
case ePipelineType::OPAQUE:
|
||||
info_name += "opaque_";
|
||||
break;
|
||||
case ePipelineType::TRANSPARENT:
|
||||
info_name += "transparent_";
|
||||
break;
|
||||
case ePipelineType::SHADOW:
|
||||
BLI_assert_unreachable();
|
||||
break;
|
||||
}
|
||||
switch (lighting_type) {
|
||||
case eLightingType::FLAT:
|
||||
info_name += "flat";
|
||||
break;
|
||||
case eLightingType::STUDIO:
|
||||
info_name += "studio";
|
||||
break;
|
||||
case eLightingType::MATCAP:
|
||||
info_name += "matcap";
|
||||
break;
|
||||
}
|
||||
info_name += cavity ? "_cavity" : "_no_cavity";
|
||||
info_name += curvature ? "_curvature" : "_no_curvature";
|
||||
info_name += shadow ? "_shadow" : "_no_shadow";
|
||||
|
||||
shader_ptr = GPU_shader_create_from_info_name(info_name.c_str());
|
||||
return shader_ptr;
|
||||
}
|
||||
|
||||
} // namespace blender::workbench
|
||||
|
||||
@@ -21,17 +21,8 @@
|
||||
|
||||
#include "workbench_private.hh"
|
||||
|
||||
#define DEBUG_SHADOW_VOLUME 0
|
||||
|
||||
namespace blender::workbench {
|
||||
|
||||
ShadowPass::ShadowView::ShadowView() : View("ShadowPass.View"){};
|
||||
ShadowPass::ShadowView::~ShadowView()
|
||||
{
|
||||
DRW_SHADER_FREE_SAFE(dynamic_pass_type_shader_);
|
||||
DRW_SHADER_FREE_SAFE(static_pass_type_shader_);
|
||||
}
|
||||
|
||||
void ShadowPass::ShadowView::setup(View &view, float3 light_direction, bool force_fail_method)
|
||||
{
|
||||
force_fail_method_ = force_fail_method;
|
||||
@@ -244,18 +235,9 @@ void ShadowPass::ShadowView::compute_visibility(ObjectBoundsBuf &bounds,
|
||||
|
||||
if (do_visibility_) {
|
||||
/* TODO(@pragma37): Use regular culling for the caps pass. */
|
||||
|
||||
if (dynamic_pass_type_shader_ == nullptr) {
|
||||
dynamic_pass_type_shader_ = GPU_shader_create_from_info_name(
|
||||
"workbench_shadow_visibility_compute_dynamic_pass_type");
|
||||
}
|
||||
if (static_pass_type_shader_ == nullptr) {
|
||||
static_pass_type_shader_ = GPU_shader_create_from_info_name(
|
||||
"workbench_shadow_visibility_compute_static_pass_type");
|
||||
}
|
||||
|
||||
GPUShader *shader = current_pass_type_ == ShadowPass::FORCED_FAIL ? static_pass_type_shader_ :
|
||||
dynamic_pass_type_shader_;
|
||||
GPUShader *shader = current_pass_type_ == ShadowPass::FORCED_FAIL ?
|
||||
ShaderCache::get().shadow_visibility_static.get() :
|
||||
ShaderCache::get().shadow_visibility_dynamic.get();
|
||||
GPU_shader_bind(shader);
|
||||
GPU_shader_uniform_1i(shader, "resource_len", resource_len);
|
||||
GPU_shader_uniform_1i(shader, "view_len", view_len_);
|
||||
@@ -296,39 +278,11 @@ VisibilityBuf &ShadowPass::ShadowView::get_visibility_buffer()
|
||||
return visibility_buf_;
|
||||
}
|
||||
|
||||
ShadowPass::~ShadowPass()
|
||||
{
|
||||
for (int depth_pass : IndexRange(2)) {
|
||||
for (int manifold : IndexRange(2)) {
|
||||
for (int cap : IndexRange(2)) {
|
||||
DRW_SHADER_FREE_SAFE(shaders_[depth_pass][manifold][cap]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PassMain::Sub *&ShadowPass::get_pass_ptr(PassType type, bool manifold, bool cap /*=false*/)
|
||||
{
|
||||
return passes_[type][manifold][cap];
|
||||
}
|
||||
|
||||
GPUShader *ShadowPass::get_shader(bool depth_pass, bool manifold, bool cap /*=false*/)
|
||||
{
|
||||
GPUShader *&shader = shaders_[depth_pass][manifold][cap];
|
||||
|
||||
if (shader == nullptr) {
|
||||
std::string create_info_name = "workbench_shadow";
|
||||
create_info_name += (depth_pass) ? "_pass" : "_fail";
|
||||
create_info_name += (manifold) ? "_manifold" : "_no_manifold";
|
||||
create_info_name += (cap) ? "_caps" : "_no_caps";
|
||||
#if DEBUG_SHADOW_VOLUME
|
||||
create_info_name += "_debug";
|
||||
#endif
|
||||
shader = GPU_shader_create_from_info_name(create_info_name.c_str());
|
||||
}
|
||||
return shader;
|
||||
}
|
||||
|
||||
void ShadowPass::init(const SceneState &scene_state, SceneResources &resources)
|
||||
{
|
||||
enabled_ = scene_state.draw_shadows;
|
||||
@@ -397,7 +351,7 @@ void ShadowPass::sync()
|
||||
for (bool manifold : {false, true}) {
|
||||
PassMain::Sub *&ps = get_pass_ptr(PASS, manifold);
|
||||
ps = &pass_ps_.sub(manifold ? "manifold" : "non_manifold");
|
||||
ps->shader_set(get_shader(true, manifold));
|
||||
ps->shader_set(ShaderCache::get().shadow_get(true, manifold));
|
||||
ps->bind_ubo("pass_data", pass_data_);
|
||||
|
||||
for (PassType fail_type : {FAIL, FORCED_FAIL}) {
|
||||
@@ -405,12 +359,12 @@ void ShadowPass::sync()
|
||||
|
||||
PassMain::Sub *&ps = get_pass_ptr(fail_type, manifold, false);
|
||||
ps = &ps_main.sub(manifold ? "NoCaps.manifold" : "NoCaps.non_manifold");
|
||||
ps->shader_set(get_shader(false, manifold, false));
|
||||
ps->shader_set(ShaderCache::get().shadow_get(false, manifold, false));
|
||||
ps->bind_ubo("pass_data", pass_data_);
|
||||
|
||||
PassMain::Sub *&caps_ps = get_pass_ptr(fail_type, manifold, true);
|
||||
caps_ps = &ps_main.sub(manifold ? "Caps.manifold" : "Caps.non_manifold");
|
||||
caps_ps->shader_set(get_shader(false, manifold, true));
|
||||
caps_ps->shader_set(ShaderCache::get().shadow_get(false, manifold, true));
|
||||
caps_ps->bind_ubo("pass_data", pass_data_);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,18 +12,6 @@
|
||||
|
||||
namespace blender::workbench {
|
||||
|
||||
VolumePass::~VolumePass()
|
||||
{
|
||||
GPUShader **sh_p = &shaders_[0][0][0][0];
|
||||
const int n = ARRAY_SIZE(shaders_);
|
||||
for (int i = 0; i < n; i++, sh_p++) {
|
||||
GPUShader *sh = *sh_p;
|
||||
if (sh) {
|
||||
GPU_shader_free(sh);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VolumePass::sync(SceneResources &resources)
|
||||
{
|
||||
active_ = false;
|
||||
@@ -61,7 +49,8 @@ void VolumePass::object_sync_volume(Manager &manager,
|
||||
|
||||
const bool use_slice = (volume->display.axis_slice_method == AXIS_SLICE_SINGLE);
|
||||
|
||||
sub_ps.shader_set(get_shader(use_slice, false, volume->display.interpolation_method, false));
|
||||
sub_ps.shader_set(ShaderCache::get().volume_get(
|
||||
false, volume->display.interpolation_method, false, use_slice));
|
||||
sub_ps.push_constant("do_depth_test", scene_state.shading.type >= OB_SOLID);
|
||||
|
||||
const float density_scale = volume->display.density *
|
||||
@@ -128,7 +117,8 @@ void VolumePass::object_sync_modifier(Manager &manager,
|
||||
|
||||
const bool use_slice = settings.axis_slice_method == AXIS_SLICE_SINGLE;
|
||||
|
||||
sub_ps.shader_set(get_shader(use_slice, settings.use_coba, settings.interp_method, true));
|
||||
sub_ps.shader_set(
|
||||
ShaderCache::get().volume_get(true, settings.interp_method, settings.use_coba, use_slice));
|
||||
sub_ps.push_constant("do_depth_test", scene_state.shading.type >= OB_SOLID);
|
||||
|
||||
if (settings.use_coba) {
|
||||
@@ -202,33 +192,6 @@ void VolumePass::draw(Manager &manager, View &view, SceneResources &resources)
|
||||
manager.submit(ps_, view);
|
||||
}
|
||||
|
||||
GPUShader *VolumePass::get_shader(bool slice, bool coba, int interpolation, bool smoke)
|
||||
{
|
||||
GPUShader *&shader = shaders_[slice][coba][interpolation][smoke];
|
||||
|
||||
if (shader == nullptr) {
|
||||
std::string create_info_name = "workbench_volume";
|
||||
create_info_name += (smoke) ? "_smoke" : "_object";
|
||||
switch (interpolation) {
|
||||
case VOLUME_DISPLAY_INTERP_LINEAR:
|
||||
create_info_name += "_linear";
|
||||
break;
|
||||
case VOLUME_DISPLAY_INTERP_CUBIC:
|
||||
create_info_name += "_cubic";
|
||||
break;
|
||||
case VOLUME_DISPLAY_INTERP_CLOSEST:
|
||||
create_info_name += "_closest";
|
||||
break;
|
||||
default:
|
||||
BLI_assert_unreachable();
|
||||
}
|
||||
create_info_name += (coba) ? "_coba" : "_no_coba";
|
||||
create_info_name += (slice) ? "_slice" : "_no_slice";
|
||||
shader = GPU_shader_create_from_info_name(create_info_name.c_str());
|
||||
}
|
||||
return shader;
|
||||
}
|
||||
|
||||
void VolumePass::draw_slice_ps(
|
||||
Manager &manager, PassMain::Sub &ps, ObjectRef &ob_ref, int slice_axis_enum, float slice_depth)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user