Draw: Added testcases for hair refine shaders.
This commit is contained in:
parent
ad9fd47d7b
commit
3f1111b2a8
|
@ -85,6 +85,7 @@ set(SRC
|
|||
intern/draw_manager_text.c
|
||||
intern/draw_manager_texture.c
|
||||
intern/draw_select_buffer.c
|
||||
intern/draw_shader.c
|
||||
intern/draw_view.c
|
||||
engines/basic/basic_engine.c
|
||||
engines/image/image_engine.c
|
||||
|
@ -185,6 +186,7 @@ set(SRC
|
|||
intern/draw_manager_testing.h
|
||||
intern/draw_manager_text.h
|
||||
intern/draw_view.h
|
||||
intern/draw_shader.h
|
||||
intern/smaa_textures.h
|
||||
engines/basic/basic_engine.h
|
||||
engines/eevee/eevee_engine.h
|
||||
|
|
|
@ -43,26 +43,26 @@
|
|||
#include "GPU_vertex_buffer.h"
|
||||
|
||||
#include "draw_hair_private.h"
|
||||
#include "draw_shader.h"
|
||||
|
||||
#ifndef __APPLE__
|
||||
# define USE_TRANSFORM_FEEDBACK
|
||||
# define USE_COMPUTE_SHADERS
|
||||
#endif
|
||||
|
||||
BLI_INLINE bool drw_hair_use_compute_shaders(void)
|
||||
BLI_INLINE eParticleRefineShaderType drw_hair_shader_type_get(void)
|
||||
{
|
||||
#ifdef USE_COMPUTE_SHADERS
|
||||
return GPU_compute_shader_support();
|
||||
#else
|
||||
return false;
|
||||
if (GPU_compute_shader_support()) {
|
||||
return PART_REFINE_SHADER_COMPUTE;
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_TRANSFORM_FEEDBACK
|
||||
return PART_REFINE_SHADER_TRANSFORM_FEEDBACK;
|
||||
#endif
|
||||
return PART_REFINE_SHADER_TRANSFORM_FEEDBACK_WORKAROUND;
|
||||
}
|
||||
|
||||
typedef enum ParticleRefineShader {
|
||||
PART_REFINE_CATMULL_ROM = 0,
|
||||
PART_REFINE_MAX_SHADER,
|
||||
} ParticleRefineShader;
|
||||
|
||||
#ifndef USE_TRANSFORM_FEEDBACK
|
||||
typedef struct ParticleRefineCall {
|
||||
struct ParticleRefineCall *next;
|
||||
|
@ -79,89 +79,11 @@ static int g_tf_target_height;
|
|||
|
||||
static GPUVertBuf *g_dummy_vbo = NULL;
|
||||
static GPUTexture *g_dummy_texture = NULL;
|
||||
static GPUShader *g_refine_shaders[PART_REFINE_MAX_SHADER] = {NULL};
|
||||
static DRWPass *g_tf_pass; /* XXX can be a problem with multiple DRWManager in the future */
|
||||
|
||||
extern char datatoc_common_hair_lib_glsl[];
|
||||
extern char datatoc_common_hair_refine_vert_glsl[];
|
||||
extern char datatoc_common_hair_refine_comp_glsl[];
|
||||
extern char datatoc_gpu_shader_3D_smooth_color_frag_glsl[];
|
||||
|
||||
/* TODO(jbakker): move shader creation to `draw_shaders` and add test cases. */
|
||||
/* TODO(jbakker): replace defines with `constexpr` to check compilation on all OS's.
|
||||
* Currently the `__APPLE__` code-path does not compile on other platforms and vice versa. */
|
||||
#ifdef USE_COMPUTE_SHADERS
|
||||
static GPUShader *hair_refine_shader_compute_create(ParticleRefineShader UNUSED(refinement))
|
||||
{
|
||||
GPUShader *sh = NULL;
|
||||
sh = GPU_shader_create_compute(datatoc_common_hair_refine_comp_glsl,
|
||||
datatoc_common_hair_lib_glsl,
|
||||
"#define HAIR_PHASE_SUBDIV\n",
|
||||
__func__);
|
||||
return sh;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_TRANSFORM_FEEDBACK
|
||||
static GPUShader *hair_refine_shader_transform_feedback_create(
|
||||
ParticleRefineShader UNUSED(refinement))
|
||||
{
|
||||
GPUShader *sh = NULL;
|
||||
|
||||
char *shader_src = BLI_string_joinN(datatoc_common_hair_lib_glsl,
|
||||
datatoc_common_hair_refine_vert_glsl);
|
||||
const char *var_names[1] = {"finalColor"};
|
||||
sh = DRW_shader_create_with_transform_feedback(
|
||||
shader_src, NULL, "#define HAIR_PHASE_SUBDIV\n", GPU_SHADER_TFB_POINTS, var_names, 1);
|
||||
MEM_freeN(shader_src);
|
||||
|
||||
return sh;
|
||||
}
|
||||
#endif
|
||||
|
||||
static GPUShader *hair_refine_shader_transform_feedback_workaround_create(
|
||||
ParticleRefineShader UNUSED(refinement))
|
||||
{
|
||||
GPUShader *sh = NULL;
|
||||
|
||||
char *shader_src = BLI_string_joinN(datatoc_common_hair_lib_glsl,
|
||||
datatoc_common_hair_refine_vert_glsl);
|
||||
sh = DRW_shader_create(shader_src,
|
||||
NULL,
|
||||
datatoc_gpu_shader_3D_smooth_color_frag_glsl,
|
||||
"#define blender_srgb_to_framebuffer_space(a) a\n"
|
||||
"#define HAIR_PHASE_SUBDIV\n"
|
||||
"#define TF_WORKAROUND\n");
|
||||
MEM_freeN(shader_src);
|
||||
|
||||
return sh;
|
||||
}
|
||||
|
||||
static GPUShader *hair_refine_shader_get(ParticleRefineShader refinement)
|
||||
{
|
||||
if (g_refine_shaders[refinement]) {
|
||||
return g_refine_shaders[refinement];
|
||||
}
|
||||
|
||||
#ifdef USE_COMPUTE_SHADERS
|
||||
if (drw_hair_use_compute_shaders()) {
|
||||
g_refine_shaders[refinement] = hair_refine_shader_compute_create(refinement);
|
||||
if (g_refine_shaders[refinement]) {
|
||||
return g_refine_shaders[refinement];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_TRANSFORM_FEEDBACK
|
||||
g_refine_shaders[refinement] = hair_refine_shader_transform_feedback_create(refinement);
|
||||
if (g_refine_shaders[refinement]) {
|
||||
return g_refine_shaders[refinement];
|
||||
}
|
||||
#endif
|
||||
|
||||
g_refine_shaders[refinement] = hair_refine_shader_transform_feedback_workaround_create(
|
||||
refinement);
|
||||
return g_refine_shaders[refinement];
|
||||
return DRW_shader_hair_refine_get(refinement, drw_hair_shader_type_get());
|
||||
}
|
||||
|
||||
void DRW_hair_init(void)
|
||||
|
@ -265,7 +187,7 @@ static ParticleHairCache *drw_hair_particle_cache_get(
|
|||
}
|
||||
|
||||
if (update) {
|
||||
if (drw_hair_use_compute_shaders()) {
|
||||
if (drw_hair_shader_type_get() == PART_REFINE_SHADER_COMPUTE) {
|
||||
drw_hair_particle_cache_update_compute(cache, subdiv);
|
||||
}
|
||||
else {
|
||||
|
@ -473,7 +395,7 @@ void DRW_hair_update(void)
|
|||
#else
|
||||
/* Just render the pass when using compute shaders or transform feedback. */
|
||||
DRW_draw_pass(g_tf_pass);
|
||||
if (drw_hair_use_compute_shaders()) {
|
||||
if (drw_hair_shader_type_get() == PART_REFINE_SHADER_COMPUTE) {
|
||||
GPU_memory_barrier(GPU_BARRIER_SHADER_STORAGE);
|
||||
}
|
||||
#endif
|
||||
|
@ -481,10 +403,6 @@ void DRW_hair_update(void)
|
|||
|
||||
void DRW_hair_free(void)
|
||||
{
|
||||
for (int i = 0; i < PART_REFINE_MAX_SHADER; i++) {
|
||||
DRW_SHADER_FREE_SAFE(g_refine_shaders[i]);
|
||||
}
|
||||
|
||||
GPU_VERTBUF_DISCARD_SAFE(g_dummy_vbo);
|
||||
DRW_TEXTURE_FREE_SAFE(g_dummy_texture);
|
||||
}
|
||||
|
|
|
@ -23,11 +23,20 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define MAX_LAYER_NAME_CT 4 /* u0123456789, u, au, a0123456789 */
|
||||
#define MAX_LAYER_NAME_LEN (GPU_MAX_SAFE_ATTR_NAME + 2)
|
||||
#define MAX_THICKRES 2 /* see eHairType */
|
||||
#define MAX_HAIR_SUBDIV 4 /* see hair_subdiv rna */
|
||||
|
||||
typedef enum ParticleRefineShader {
|
||||
PART_REFINE_CATMULL_ROM = 0,
|
||||
PART_REFINE_MAX_SHADER,
|
||||
} ParticleRefineShader;
|
||||
|
||||
struct ModifierData;
|
||||
struct Object;
|
||||
struct ParticleHairCache;
|
||||
|
@ -91,3 +100,7 @@ bool hair_ensure_procedural_data(struct Object *object,
|
|||
struct ParticleHairCache **r_hair_cache,
|
||||
int subdiv,
|
||||
int thickness_res);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -87,6 +87,7 @@
|
|||
#include "draw_manager_profiling.h"
|
||||
#include "draw_manager_testing.h"
|
||||
#include "draw_manager_text.h"
|
||||
#include "draw_shader.h"
|
||||
|
||||
/* only for callbacks */
|
||||
#include "draw_cache_impl.h"
|
||||
|
@ -2987,6 +2988,7 @@ void DRW_engines_free(void)
|
|||
DRW_TEXTURE_FREE_SAFE(g_select_buffer.texture_depth);
|
||||
GPU_FRAMEBUFFER_FREE_SAFE(g_select_buffer.framebuffer_depth_only);
|
||||
|
||||
DRW_shaders_free();
|
||||
DRW_hair_free();
|
||||
DRW_shape_cache_free();
|
||||
DRW_stats_free();
|
||||
|
|
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* Copyright 2020, Blender Foundation.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \ingroup draw_engine
|
||||
*/
|
||||
|
||||
#include "DRW_render.h"
|
||||
|
||||
#include "BLI_dynstr.h"
|
||||
#include "BLI_string_utils.h"
|
||||
|
||||
#include "GPU_batch.h"
|
||||
#include "GPU_index_buffer.h"
|
||||
#include "GPU_vertex_buffer.h"
|
||||
|
||||
#include "draw_shader.h"
|
||||
|
||||
extern char datatoc_common_hair_lib_glsl[];
|
||||
|
||||
extern char datatoc_common_hair_refine_vert_glsl[];
|
||||
extern char datatoc_common_hair_refine_comp_glsl[];
|
||||
extern char datatoc_gpu_shader_3D_smooth_color_frag_glsl[];
|
||||
|
||||
static struct {
|
||||
struct GPUShader *hair_refine_sh[PART_REFINE_MAX_SHADER];
|
||||
} e_data = {{NULL}};
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Hair refinement
|
||||
* \{ */
|
||||
|
||||
static GPUShader *hair_refine_shader_compute_create(ParticleRefineShader UNUSED(refinement))
|
||||
{
|
||||
GPUShader *sh = NULL;
|
||||
sh = GPU_shader_create_compute(datatoc_common_hair_refine_comp_glsl,
|
||||
datatoc_common_hair_lib_glsl,
|
||||
"#define HAIR_PHASE_SUBDIV\n",
|
||||
__func__);
|
||||
return sh;
|
||||
}
|
||||
|
||||
static GPUShader *hair_refine_shader_transform_feedback_create(
|
||||
ParticleRefineShader UNUSED(refinement))
|
||||
{
|
||||
GPUShader *sh = NULL;
|
||||
|
||||
char *shader_src = BLI_string_joinN(datatoc_common_hair_lib_glsl,
|
||||
datatoc_common_hair_refine_vert_glsl);
|
||||
const char *var_names[1] = {"finalColor"};
|
||||
sh = DRW_shader_create_with_transform_feedback(
|
||||
shader_src, NULL, "#define HAIR_PHASE_SUBDIV\n", GPU_SHADER_TFB_POINTS, var_names, 1);
|
||||
MEM_freeN(shader_src);
|
||||
|
||||
return sh;
|
||||
}
|
||||
|
||||
static GPUShader *hair_refine_shader_transform_feedback_workaround_create(
|
||||
ParticleRefineShader UNUSED(refinement))
|
||||
{
|
||||
GPUShader *sh = NULL;
|
||||
|
||||
char *shader_src = BLI_string_joinN(datatoc_common_hair_lib_glsl,
|
||||
datatoc_common_hair_refine_vert_glsl);
|
||||
sh = DRW_shader_create(shader_src,
|
||||
NULL,
|
||||
datatoc_gpu_shader_3D_smooth_color_frag_glsl,
|
||||
"#define blender_srgb_to_framebuffer_space(a) a\n"
|
||||
"#define HAIR_PHASE_SUBDIV\n"
|
||||
"#define TF_WORKAROUND\n");
|
||||
MEM_freeN(shader_src);
|
||||
|
||||
return sh;
|
||||
}
|
||||
|
||||
GPUShader *DRW_shader_hair_refine_get(ParticleRefineShader refinement,
|
||||
eParticleRefineShaderType sh_type)
|
||||
{
|
||||
if (e_data.hair_refine_sh[refinement] == NULL) {
|
||||
GPUShader *sh = NULL;
|
||||
switch (sh_type) {
|
||||
case PART_REFINE_SHADER_COMPUTE:
|
||||
sh = hair_refine_shader_compute_create(refinement);
|
||||
break;
|
||||
case PART_REFINE_SHADER_TRANSFORM_FEEDBACK:
|
||||
sh = hair_refine_shader_transform_feedback_create(refinement);
|
||||
break;
|
||||
case PART_REFINE_SHADER_TRANSFORM_FEEDBACK_WORKAROUND:
|
||||
sh = hair_refine_shader_transform_feedback_workaround_create(refinement);
|
||||
break;
|
||||
default:
|
||||
BLI_assert(!"Incorrect shader type");
|
||||
}
|
||||
e_data.hair_refine_sh[refinement] = sh;
|
||||
}
|
||||
|
||||
return e_data.hair_refine_sh[refinement];
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
void DRW_shaders_free(void)
|
||||
{
|
||||
for (int i = 0; i < PART_REFINE_MAX_SHADER; i++) {
|
||||
DRW_SHADER_FREE_SAFE(e_data.hair_refine_sh[i]);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2021 by Blender Foundation.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \ingroup draw
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "draw_hair_private.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct GPUShader;
|
||||
|
||||
typedef enum eParticleRefineShaderType {
|
||||
PART_REFINE_SHADER_TRANSFORM_FEEDBACK,
|
||||
PART_REFINE_SHADER_TRANSFORM_FEEDBACK_WORKAROUND,
|
||||
PART_REFINE_SHADER_COMPUTE,
|
||||
} eParticleRefineShaderType;
|
||||
|
||||
/* draw_shader.c */
|
||||
struct GPUShader *DRW_shader_hair_refine_get(ParticleRefineShader refinement,
|
||||
eParticleRefineShaderType sh_type);
|
||||
void DRW_shaders_free(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -3,17 +3,22 @@
|
|||
#include "testing/testing.h"
|
||||
|
||||
#include "draw_testing.hh"
|
||||
#include "intern/draw_manager_testing.h"
|
||||
|
||||
#include "GPU_context.h"
|
||||
#include "GPU_index_buffer.h"
|
||||
#include "GPU_init_exit.h"
|
||||
#include "GPU_shader.h"
|
||||
#include "GPU_texture.h"
|
||||
#include "GPU_vertex_buffer.h"
|
||||
|
||||
#include "intern/draw_manager_testing.h"
|
||||
|
||||
#include "engines/eevee/eevee_private.h"
|
||||
#include "engines/gpencil/gpencil_engine.h"
|
||||
#include "engines/image/image_private.h"
|
||||
#include "engines/overlay/overlay_private.h"
|
||||
#include "engines/workbench/workbench_private.h"
|
||||
#include "intern/draw_shader.h"
|
||||
|
||||
namespace blender::draw {
|
||||
|
||||
|
@ -366,4 +371,20 @@ TEST_F(DrawTest, eevee_glsl_shaders_static)
|
|||
EEVEE_shaders_free();
|
||||
}
|
||||
|
||||
static void test_draw_shaders(eParticleRefineShaderType sh_type)
|
||||
{
|
||||
DRW_shaders_free();
|
||||
EXPECT_NE(DRW_shader_hair_refine_get(PART_REFINE_CATMULL_ROM, sh_type), nullptr);
|
||||
DRW_shaders_free();
|
||||
}
|
||||
|
||||
TEST_F(DrawTest, draw_glsl_shaders)
|
||||
{
|
||||
#ifndef __APPLE__
|
||||
test_draw_shaders(PART_REFINE_SHADER_TRANSFORM_FEEDBACK);
|
||||
test_draw_shaders(PART_REFINE_SHADER_COMPUTE);
|
||||
#endif
|
||||
test_draw_shaders(PART_REFINE_SHADER_TRANSFORM_FEEDBACK_WORKAROUND);
|
||||
}
|
||||
|
||||
} // namespace blender::draw
|
||||
|
|
Loading…
Reference in New Issue