diff options
author | mano-wii <germano.costa@ig.com.br> | 2018-09-14 15:32:19 +0300 |
---|---|---|
committer | mano-wii <germano.costa@ig.com.br> | 2018-09-14 15:46:19 +0300 |
commit | 1287965089a851c46e9a1a23c55ebc90b00b4e14 (patch) | |
tree | 430505da2894fda1e95ccb82b6bc4845ee7d5c4c /source/blender | |
parent | d15928c2344718e47d9025fe5b18ff033366dc5c (diff) |
GPU module: Initial implementation of the `gpu.shader` submodule.
Differential Revision: https://developer.blender.org/D3688
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/gpu/GPU_shader.h | 5 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_shader.c | 593 | ||||
-rw-r--r-- | source/blender/python/gpu/CMakeLists.txt | 2 | ||||
-rw-r--r-- | source/blender/python/gpu/gpu_py_api.c | 10 | ||||
-rw-r--r-- | source/blender/python/gpu/gpu_py_batch.c | 23 | ||||
-rw-r--r-- | source/blender/python/gpu/gpu_py_shader.c | 635 | ||||
-rw-r--r-- | source/blender/python/gpu/gpu_py_shader.h | 41 | ||||
-rw-r--r-- | source/blender/python/gpu/gpu_py_types.c | 3 | ||||
-rw-r--r-- | source/blender/python/gpu/gpu_py_types.h | 1 |
9 files changed, 1073 insertions, 240 deletions
diff --git a/source/blender/gpu/GPU_shader.h b/source/blender/gpu/GPU_shader.h index c9a87a7e187..8b0a1b2b51f 100644 --- a/source/blender/gpu/GPU_shader.h +++ b/source/blender/gpu/GPU_shader.h @@ -366,6 +366,11 @@ typedef enum GPUInterlaceShader { GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader); +void GPU_shader_get_builtin_shader_code( + GPUBuiltinShader shader, + const char **vert, const char **frag, + const char **geom, const char **defines); + void GPU_shader_free_builtin_shaders(void); /* Vertex attributes for shaders */ diff --git a/source/blender/gpu/intern/gpu_shader.c b/source/blender/gpu/intern/gpu_shader.c index 55ba862548e..5c3776fc7b7 100644 --- a/source/blender/gpu/intern/gpu_shader.c +++ b/source/blender/gpu/intern/gpu_shader.c @@ -648,251 +648,352 @@ int GPU_shader_get_attribute(GPUShader *shader, const char *name) return attrib ? attrib->location : -1; } +static const GPUShaderStages builtin_shader_stages[GPU_NUM_BUILTIN_SHADERS] = { + [GPU_SHADER_SMOKE] = + { datatoc_gpu_shader_smoke_vert_glsl, + datatoc_gpu_shader_smoke_frag_glsl }, + [GPU_SHADER_SMOKE_FIRE] = + { datatoc_gpu_shader_smoke_vert_glsl, + datatoc_gpu_shader_smoke_frag_glsl }, + [GPU_SHADER_SMOKE_COBA] = + { datatoc_gpu_shader_smoke_vert_glsl, + datatoc_gpu_shader_smoke_frag_glsl }, + + [GPU_SHADER_TEXT] = + { datatoc_gpu_shader_text_vert_glsl, + datatoc_gpu_shader_text_frag_glsl, + datatoc_gpu_shader_text_geom_glsl }, + [GPU_SHADER_TEXT_SIMPLE] = + { datatoc_gpu_shader_text_simple_vert_glsl, + datatoc_gpu_shader_text_frag_glsl, + datatoc_gpu_shader_text_simple_geom_glsl }, + [GPU_SHADER_KEYFRAME_DIAMOND] = + { datatoc_gpu_shader_keyframe_diamond_vert_glsl, + datatoc_gpu_shader_keyframe_diamond_frag_glsl }, + [GPU_SHADER_EDGES_FRONT_BACK_PERSP] = + { datatoc_gpu_shader_edges_front_back_persp_vert_glsl, + datatoc_gpu_shader_flat_color_frag_glsl, /* this version is */ + datatoc_gpu_shader_edges_front_back_persp_geom_glsl }, /* magical but slooow */ + [GPU_SHADER_EDGES_FRONT_BACK_ORTHO] = + { datatoc_gpu_shader_edges_front_back_ortho_vert_glsl, + datatoc_gpu_shader_flat_color_frag_glsl }, + [GPU_SHADER_EDGES_OVERLAY_SIMPLE] = + { datatoc_gpu_shader_3D_vert_glsl, + datatoc_gpu_shader_edges_overlay_frag_glsl, + datatoc_gpu_shader_edges_overlay_simple_geom_glsl }, + [GPU_SHADER_EDGES_OVERLAY] = + { datatoc_gpu_shader_edges_overlay_vert_glsl, + datatoc_gpu_shader_edges_overlay_frag_glsl, + datatoc_gpu_shader_edges_overlay_geom_glsl }, + [GPU_SHADER_SIMPLE_LIGHTING] = + { datatoc_gpu_shader_3D_normal_vert_glsl, + datatoc_gpu_shader_simple_lighting_frag_glsl }, + /* Use 'USE_FLAT_NORMAL' to make flat shader from smooth */ + [GPU_SHADER_SIMPLE_LIGHTING_FLAT_COLOR] = + { datatoc_gpu_shader_3D_normal_smooth_color_vert_glsl, + datatoc_gpu_shader_simple_lighting_smooth_color_frag_glsl }, + [GPU_SHADER_SIMPLE_LIGHTING_SMOOTH_COLOR] = + { datatoc_gpu_shader_3D_normal_smooth_color_vert_glsl, + datatoc_gpu_shader_simple_lighting_smooth_color_frag_glsl }, + [GPU_SHADER_SIMPLE_LIGHTING_SMOOTH_COLOR_ALPHA] = + { datatoc_gpu_shader_3D_normal_smooth_color_vert_glsl, + datatoc_gpu_shader_simple_lighting_smooth_color_alpha_frag_glsl }, + + [GPU_SHADER_2D_IMAGE_MASK_UNIFORM_COLOR] = + { datatoc_gpu_shader_3D_image_vert_glsl, + datatoc_gpu_shader_image_mask_uniform_color_frag_glsl }, + [GPU_SHADER_3D_IMAGE_MODULATE_ALPHA] = + { datatoc_gpu_shader_3D_image_vert_glsl, + datatoc_gpu_shader_image_modulate_alpha_frag_glsl }, + [GPU_SHADER_3D_IMAGE_DEPTH] = + { datatoc_gpu_shader_3D_image_vert_glsl, + datatoc_gpu_shader_image_depth_linear_frag_glsl }, + [GPU_SHADER_3D_IMAGE_DEPTH_COPY] = + { datatoc_gpu_shader_3D_image_vert_glsl, + datatoc_gpu_shader_image_depth_copy_frag_glsl }, + [GPU_SHADER_2D_IMAGE_MULTISAMPLE_2] = + { datatoc_gpu_shader_2D_vert_glsl, + datatoc_gpu_shader_image_multisample_resolve_frag_glsl }, + [GPU_SHADER_2D_IMAGE_MULTISAMPLE_4] = + { datatoc_gpu_shader_2D_vert_glsl, + datatoc_gpu_shader_image_multisample_resolve_frag_glsl }, + [GPU_SHADER_2D_IMAGE_MULTISAMPLE_8] = + { datatoc_gpu_shader_2D_vert_glsl, + datatoc_gpu_shader_image_multisample_resolve_frag_glsl }, + [GPU_SHADER_2D_IMAGE_MULTISAMPLE_16] = + { datatoc_gpu_shader_2D_vert_glsl, + datatoc_gpu_shader_image_multisample_resolve_frag_glsl }, + [GPU_SHADER_2D_IMAGE_MULTISAMPLE_2_DEPTH_TEST] = + { datatoc_gpu_shader_2D_vert_glsl, + datatoc_gpu_shader_image_multisample_resolve_frag_glsl }, + [GPU_SHADER_2D_IMAGE_MULTISAMPLE_4_DEPTH_TEST] = + { datatoc_gpu_shader_2D_vert_glsl, + datatoc_gpu_shader_image_multisample_resolve_frag_glsl }, + [GPU_SHADER_2D_IMAGE_MULTISAMPLE_8_DEPTH_TEST] = + { datatoc_gpu_shader_2D_vert_glsl, + datatoc_gpu_shader_image_multisample_resolve_frag_glsl }, + [GPU_SHADER_2D_IMAGE_MULTISAMPLE_16_DEPTH_TEST] = + { datatoc_gpu_shader_2D_vert_glsl, + datatoc_gpu_shader_image_multisample_resolve_frag_glsl }, + + [GPU_SHADER_2D_IMAGE_INTERLACE] = + { datatoc_gpu_shader_2D_image_vert_glsl, + datatoc_gpu_shader_image_interlace_frag_glsl }, + [GPU_SHADER_2D_CHECKER] = + { datatoc_gpu_shader_2D_vert_glsl, + datatoc_gpu_shader_checker_frag_glsl }, + + [GPU_SHADER_2D_DIAG_STRIPES] = + { datatoc_gpu_shader_2D_vert_glsl, + datatoc_gpu_shader_diag_stripes_frag_glsl }, + + [GPU_SHADER_2D_UNIFORM_COLOR] = + { datatoc_gpu_shader_2D_vert_glsl, + datatoc_gpu_shader_uniform_color_frag_glsl }, + [GPU_SHADER_2D_FLAT_COLOR] = + { datatoc_gpu_shader_2D_flat_color_vert_glsl, + datatoc_gpu_shader_flat_color_frag_glsl }, + [GPU_SHADER_2D_SMOOTH_COLOR] = + { datatoc_gpu_shader_2D_smooth_color_vert_glsl, + datatoc_gpu_shader_2D_smooth_color_frag_glsl }, + [GPU_SHADER_2D_SMOOTH_COLOR_DITHER] = + { datatoc_gpu_shader_2D_smooth_color_vert_glsl, + datatoc_gpu_shader_2D_smooth_color_dithered_frag_glsl }, + [GPU_SHADER_2D_IMAGE_LINEAR_TO_SRGB] = + { datatoc_gpu_shader_2D_image_vert_glsl, + datatoc_gpu_shader_image_linear_frag_glsl }, + [GPU_SHADER_2D_IMAGE] = + { datatoc_gpu_shader_2D_image_vert_glsl, + datatoc_gpu_shader_image_frag_glsl }, + [GPU_SHADER_2D_IMAGE_COLOR] = + { datatoc_gpu_shader_2D_image_vert_glsl, + datatoc_gpu_shader_image_color_frag_glsl }, + [GPU_SHADER_2D_IMAGE_DESATURATE_COLOR] = + { datatoc_gpu_shader_2D_image_vert_glsl, + datatoc_gpu_shader_image_desaturate_frag_glsl }, + [GPU_SHADER_2D_IMAGE_ALPHA_COLOR] = + { datatoc_gpu_shader_2D_image_vert_glsl, + datatoc_gpu_shader_image_alpha_color_frag_glsl }, + [GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR] = + { datatoc_gpu_shader_2D_image_vert_glsl, + datatoc_gpu_shader_image_shuffle_color_frag_glsl }, + [GPU_SHADER_2D_IMAGE_RECT_COLOR] = + { datatoc_gpu_shader_2D_image_rect_vert_glsl, + datatoc_gpu_shader_image_color_frag_glsl }, + [GPU_SHADER_2D_IMAGE_MULTI_RECT_COLOR] = + { datatoc_gpu_shader_2D_image_multi_rect_vert_glsl, + datatoc_gpu_shader_image_varying_color_frag_glsl }, + + [GPU_SHADER_3D_UNIFORM_COLOR] = + { datatoc_gpu_shader_3D_vert_glsl, + datatoc_gpu_shader_uniform_color_frag_glsl }, + [GPU_SHADER_3D_UNIFORM_COLOR_U32] = + { datatoc_gpu_shader_3D_vert_glsl, + datatoc_gpu_shader_uniform_color_frag_glsl }, + [GPU_SHADER_3D_FLAT_COLOR] = + { datatoc_gpu_shader_3D_flat_color_vert_glsl, + datatoc_gpu_shader_flat_color_frag_glsl }, + [GPU_SHADER_3D_FLAT_COLOR_U32] = + { datatoc_gpu_shader_3D_flat_color_vert_glsl, + datatoc_gpu_shader_flat_color_frag_glsl }, + [GPU_SHADER_3D_SMOOTH_COLOR] = + { datatoc_gpu_shader_3D_smooth_color_vert_glsl, + datatoc_gpu_shader_3D_smooth_color_frag_glsl }, + [GPU_SHADER_3D_DEPTH_ONLY] = + { datatoc_gpu_shader_3D_vert_glsl, + datatoc_gpu_shader_depth_only_frag_glsl }, + [GPU_SHADER_3D_CLIPPED_UNIFORM_COLOR] = + { datatoc_gpu_shader_3D_clipped_uniform_color_vert_glsl, + datatoc_gpu_shader_uniform_color_frag_glsl }, + + [GPU_SHADER_3D_GROUNDPOINT] = + { datatoc_gpu_shader_3D_groundpoint_vert_glsl, + datatoc_gpu_shader_point_uniform_color_frag_glsl }, + [GPU_SHADER_3D_GROUNDLINE] = + { datatoc_gpu_shader_3D_passthrough_vert_glsl, + datatoc_gpu_shader_uniform_color_frag_glsl, + datatoc_gpu_shader_3D_groundline_geom_glsl }, + + [GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR] = + { datatoc_gpu_shader_2D_line_dashed_uniform_color_vert_glsl, + datatoc_gpu_shader_2D_line_dashed_frag_glsl, + datatoc_gpu_shader_2D_line_dashed_geom_glsl }, + [GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR] = + { datatoc_gpu_shader_3D_line_dashed_uniform_color_vert_glsl, + datatoc_gpu_shader_2D_line_dashed_frag_glsl, + datatoc_gpu_shader_2D_line_dashed_geom_glsl }, + + [GPU_SHADER_3D_OBJECTSPACE_SIMPLE_LIGHTING_VARIYING_COLOR] = + { datatoc_gpu_shader_instance_objectspace_variying_color_vert_glsl, + datatoc_gpu_shader_simple_lighting_frag_glsl}, + [GPU_SHADER_3D_OBJECTSPACE_VARIYING_COLOR] = + { datatoc_gpu_shader_instance_objectspace_variying_color_vert_glsl, + datatoc_gpu_shader_flat_color_frag_glsl}, + [GPU_SHADER_3D_SCREENSPACE_VARIYING_COLOR] = + { datatoc_gpu_shader_instance_screenspace_variying_color_vert_glsl, + datatoc_gpu_shader_flat_color_frag_glsl}, + [GPU_SHADER_3D_INSTANCE_SCREEN_ALIGNED_AXIS] = + { datatoc_gpu_shader_instance_screen_aligned_vert_glsl, + datatoc_gpu_shader_flat_color_frag_glsl}, + [GPU_SHADER_3D_INSTANCE_SCREEN_ALIGNED] = + { datatoc_gpu_shader_instance_screen_aligned_vert_glsl, + datatoc_gpu_shader_flat_color_frag_glsl}, + + [GPU_SHADER_CAMERA] = + { datatoc_gpu_shader_instance_camera_vert_glsl, + datatoc_gpu_shader_flat_color_frag_glsl}, + [GPU_SHADER_DISTANCE_LINES] = + { datatoc_gpu_shader_instance_distance_line_vert_glsl, + datatoc_gpu_shader_flat_color_frag_glsl}, + + [GPU_SHADER_2D_POINT_FIXED_SIZE_UNIFORM_COLOR] = + { datatoc_gpu_shader_2D_vert_glsl, + datatoc_gpu_shader_point_uniform_color_frag_glsl }, + [GPU_SHADER_2D_POINT_VARYING_SIZE_VARYING_COLOR] = + { datatoc_gpu_shader_2D_point_varying_size_varying_color_vert_glsl, + datatoc_gpu_shader_point_varying_color_frag_glsl }, + [GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA] = + { datatoc_gpu_shader_2D_point_uniform_size_aa_vert_glsl, + datatoc_gpu_shader_point_uniform_color_aa_frag_glsl }, + [GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA] = + { datatoc_gpu_shader_2D_point_uniform_size_outline_aa_vert_glsl, + datatoc_gpu_shader_point_uniform_color_outline_aa_frag_glsl }, + [GPU_SHADER_2D_POINT_UNIFORM_SIZE_VARYING_COLOR_OUTLINE_AA] = + { datatoc_gpu_shader_2D_point_uniform_size_varying_color_outline_aa_vert_glsl, + datatoc_gpu_shader_point_varying_color_outline_aa_frag_glsl }, + [GPU_SHADER_3D_POINT_FIXED_SIZE_UNIFORM_COLOR] = + { datatoc_gpu_shader_3D_vert_glsl, + datatoc_gpu_shader_point_uniform_color_frag_glsl }, + [GPU_SHADER_3D_POINT_FIXED_SIZE_VARYING_COLOR] = + { datatoc_gpu_shader_3D_point_fixed_size_varying_color_vert_glsl, + datatoc_gpu_shader_point_varying_color_frag_glsl }, + [GPU_SHADER_3D_POINT_VARYING_SIZE_UNIFORM_COLOR] = + { datatoc_gpu_shader_3D_point_varying_size_vert_glsl, + datatoc_gpu_shader_point_uniform_color_frag_glsl }, + [GPU_SHADER_3D_POINT_VARYING_SIZE_VARYING_COLOR] = + { datatoc_gpu_shader_3D_point_varying_size_varying_color_vert_glsl, + datatoc_gpu_shader_point_varying_color_frag_glsl }, + [GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA] = + { datatoc_gpu_shader_3D_point_uniform_size_aa_vert_glsl, + datatoc_gpu_shader_point_uniform_color_aa_frag_glsl }, + [GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA] = + { datatoc_gpu_shader_3D_point_uniform_size_outline_aa_vert_glsl, + datatoc_gpu_shader_point_uniform_color_outline_aa_frag_glsl }, + + [GPU_SHADER_INSTANCE_UNIFORM_COLOR] = + { datatoc_gpu_shader_instance_vert_glsl, + datatoc_gpu_shader_uniform_color_frag_glsl }, + [GPU_SHADER_INSTANCE_VARIYING_ID_VARIYING_SIZE] = + { datatoc_gpu_shader_instance_variying_size_variying_id_vert_glsl, + datatoc_gpu_shader_flat_id_frag_glsl }, + [GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SIZE] = + { datatoc_gpu_shader_instance_variying_size_variying_color_vert_glsl, + datatoc_gpu_shader_flat_color_frag_glsl }, + [GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SCALE] = + { datatoc_gpu_shader_instance_variying_size_variying_color_vert_glsl, + datatoc_gpu_shader_flat_color_frag_glsl }, + [GPU_SHADER_INSTANCE_EDGES_VARIYING_COLOR] = + { datatoc_gpu_shader_instance_edges_variying_color_vert_glsl, + datatoc_gpu_shader_flat_color_frag_glsl, + datatoc_gpu_shader_instance_edges_variying_color_geom_glsl}, + + [GPU_SHADER_2D_AREA_EDGES] = + { datatoc_gpu_shader_2D_area_borders_vert_glsl, + datatoc_gpu_shader_uniform_color_frag_glsl}, + [GPU_SHADER_2D_WIDGET_BASE] = + { datatoc_gpu_shader_2D_widget_base_vert_glsl, + datatoc_gpu_shader_2D_widget_base_frag_glsl}, + [GPU_SHADER_2D_WIDGET_BASE_INST] = + { datatoc_gpu_shader_2D_widget_base_vert_glsl, + datatoc_gpu_shader_2D_widget_base_frag_glsl}, + [GPU_SHADER_2D_WIDGET_SHADOW] = + { datatoc_gpu_shader_2D_widget_shadow_vert_glsl, + datatoc_gpu_shader_2D_widget_shadow_frag_glsl }, + [GPU_SHADER_2D_NODELINK] = + { datatoc_gpu_shader_2D_nodelink_vert_glsl, + datatoc_gpu_shader_2D_nodelink_frag_glsl }, + [GPU_SHADER_2D_NODELINK_INST] = + { datatoc_gpu_shader_2D_nodelink_vert_glsl, + datatoc_gpu_shader_2D_nodelink_frag_glsl }, + + [GPU_SHADER_GPENCIL_STROKE] = + { datatoc_gpu_shader_gpencil_stroke_vert_glsl, + datatoc_gpu_shader_gpencil_stroke_frag_glsl, + datatoc_gpu_shader_gpencil_stroke_geom_glsl }, + + [GPU_SHADER_GPENCIL_FILL] = + { datatoc_gpu_shader_gpencil_fill_vert_glsl, + datatoc_gpu_shader_gpencil_fill_frag_glsl }, +}; + +/* just a few special cases */ +static const char *gpu_shader_get_builtin_shader_defines( + GPUBuiltinShader shader) +{ + switch (shader) { + case GPU_SHADER_2D_IMAGE_MULTISAMPLE_2: + return "#define SAMPLES 2\n"; + + case GPU_SHADER_2D_IMAGE_MULTISAMPLE_2_DEPTH_TEST: + return "#define SAMPLES 2\n" + "#define USE_DEPTH\n"; + + case GPU_SHADER_2D_IMAGE_MULTISAMPLE_4: + return "#define SAMPLES 4\n"; + + case GPU_SHADER_2D_IMAGE_MULTISAMPLE_4_DEPTH_TEST: + return "#define SAMPLES 4\n" + "#define USE_DEPTH\n"; + + case GPU_SHADER_2D_IMAGE_MULTISAMPLE_8: + return "#define SAMPLES 8\n"; + + case GPU_SHADER_2D_IMAGE_MULTISAMPLE_8_DEPTH_TEST: + return "#define SAMPLES 8\n" + "#define USE_DEPTH\n"; + + case GPU_SHADER_2D_IMAGE_MULTISAMPLE_16: + return "#define SAMPLES 16\n"; + + case GPU_SHADER_2D_IMAGE_MULTISAMPLE_16_DEPTH_TEST: + return "#define SAMPLES 16\n" + "#define USE_DEPTH\n"; + + case GPU_SHADER_2D_WIDGET_BASE_INST: + case GPU_SHADER_2D_NODELINK_INST: + return "#define USE_INSTANCE\n"; + + case GPU_SHADER_SMOKE_COBA: + return "#define USE_COBA\n"; + + case GPU_SHADER_INSTANCE_VARIYING_ID_VARIYING_SIZE: + case GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SIZE: + return "#define UNIFORM_SCALE\n"; + + case GPU_SHADER_3D_INSTANCE_SCREEN_ALIGNED_AXIS: + return "#define AXIS_NAME\n"; + + case GPU_SHADER_3D_OBJECTSPACE_SIMPLE_LIGHTING_VARIYING_COLOR: + return "#define USE_INSTANCE_COLOR\n"; + + case GPU_SHADER_3D_FLAT_COLOR_U32: + case GPU_SHADER_3D_UNIFORM_COLOR_U32: + return "#define USE_COLOR_U32\n"; + + case GPU_SHADER_SIMPLE_LIGHTING_FLAT_COLOR: + return "#define USE_FLAT_NORMAL\n"; + + default: + return NULL; + } +} + GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader) { BLI_assert(shader != GPU_NUM_BUILTIN_SHADERS); /* don't be a troll */ - static const GPUShaderStages builtin_shader_stages[GPU_NUM_BUILTIN_SHADERS] = { - [GPU_SHADER_SMOKE] = { datatoc_gpu_shader_smoke_vert_glsl, datatoc_gpu_shader_smoke_frag_glsl }, - [GPU_SHADER_SMOKE_FIRE] = { datatoc_gpu_shader_smoke_vert_glsl, datatoc_gpu_shader_smoke_frag_glsl }, - [GPU_SHADER_SMOKE_COBA] = { datatoc_gpu_shader_smoke_vert_glsl, datatoc_gpu_shader_smoke_frag_glsl }, - - [GPU_SHADER_TEXT] = { datatoc_gpu_shader_text_vert_glsl, - datatoc_gpu_shader_text_frag_glsl, - datatoc_gpu_shader_text_geom_glsl }, - [GPU_SHADER_TEXT_SIMPLE] = { datatoc_gpu_shader_text_simple_vert_glsl, - datatoc_gpu_shader_text_frag_glsl, - datatoc_gpu_shader_text_simple_geom_glsl }, - [GPU_SHADER_KEYFRAME_DIAMOND] = { datatoc_gpu_shader_keyframe_diamond_vert_glsl, - datatoc_gpu_shader_keyframe_diamond_frag_glsl }, - [GPU_SHADER_EDGES_FRONT_BACK_PERSP] = { datatoc_gpu_shader_edges_front_back_persp_vert_glsl, - /* this version is */ datatoc_gpu_shader_flat_color_frag_glsl, - /* magical but slooow */ datatoc_gpu_shader_edges_front_back_persp_geom_glsl }, - [GPU_SHADER_EDGES_FRONT_BACK_ORTHO] = { datatoc_gpu_shader_edges_front_back_ortho_vert_glsl, - datatoc_gpu_shader_flat_color_frag_glsl }, - [GPU_SHADER_EDGES_OVERLAY_SIMPLE] = { datatoc_gpu_shader_3D_vert_glsl, datatoc_gpu_shader_edges_overlay_frag_glsl, - datatoc_gpu_shader_edges_overlay_simple_geom_glsl }, - [GPU_SHADER_EDGES_OVERLAY] = { datatoc_gpu_shader_edges_overlay_vert_glsl, - datatoc_gpu_shader_edges_overlay_frag_glsl, - datatoc_gpu_shader_edges_overlay_geom_glsl }, - [GPU_SHADER_SIMPLE_LIGHTING] = { datatoc_gpu_shader_3D_normal_vert_glsl, datatoc_gpu_shader_simple_lighting_frag_glsl }, - /* Use 'USE_FLAT_NORMAL' to make flat shader from smooth */ - [GPU_SHADER_SIMPLE_LIGHTING_FLAT_COLOR] = { datatoc_gpu_shader_3D_normal_smooth_color_vert_glsl, datatoc_gpu_shader_simple_lighting_smooth_color_frag_glsl }, - [GPU_SHADER_SIMPLE_LIGHTING_SMOOTH_COLOR] = { datatoc_gpu_shader_3D_normal_smooth_color_vert_glsl, datatoc_gpu_shader_simple_lighting_smooth_color_frag_glsl }, - [GPU_SHADER_SIMPLE_LIGHTING_SMOOTH_COLOR_ALPHA] = { datatoc_gpu_shader_3D_normal_smooth_color_vert_glsl, datatoc_gpu_shader_simple_lighting_smooth_color_alpha_frag_glsl }, - - [GPU_SHADER_2D_IMAGE_MASK_UNIFORM_COLOR] = { datatoc_gpu_shader_3D_image_vert_glsl, - datatoc_gpu_shader_image_mask_uniform_color_frag_glsl }, - [GPU_SHADER_3D_IMAGE_MODULATE_ALPHA] = { datatoc_gpu_shader_3D_image_vert_glsl, - datatoc_gpu_shader_image_modulate_alpha_frag_glsl }, - [GPU_SHADER_3D_IMAGE_DEPTH] = { datatoc_gpu_shader_3D_image_vert_glsl, - datatoc_gpu_shader_image_depth_linear_frag_glsl }, - [GPU_SHADER_3D_IMAGE_DEPTH_COPY] = { datatoc_gpu_shader_3D_image_vert_glsl, - datatoc_gpu_shader_image_depth_copy_frag_glsl }, - [GPU_SHADER_2D_IMAGE_MULTISAMPLE_2] = { datatoc_gpu_shader_2D_vert_glsl, datatoc_gpu_shader_image_multisample_resolve_frag_glsl }, - [GPU_SHADER_2D_IMAGE_MULTISAMPLE_4] = { datatoc_gpu_shader_2D_vert_glsl, datatoc_gpu_shader_image_multisample_resolve_frag_glsl }, - [GPU_SHADER_2D_IMAGE_MULTISAMPLE_8] = { datatoc_gpu_shader_2D_vert_glsl, datatoc_gpu_shader_image_multisample_resolve_frag_glsl }, - [GPU_SHADER_2D_IMAGE_MULTISAMPLE_16] = { datatoc_gpu_shader_2D_vert_glsl, datatoc_gpu_shader_image_multisample_resolve_frag_glsl }, - [GPU_SHADER_2D_IMAGE_MULTISAMPLE_2_DEPTH_TEST] = { datatoc_gpu_shader_2D_vert_glsl, datatoc_gpu_shader_image_multisample_resolve_frag_glsl }, - [GPU_SHADER_2D_IMAGE_MULTISAMPLE_4_DEPTH_TEST] = { datatoc_gpu_shader_2D_vert_glsl, datatoc_gpu_shader_image_multisample_resolve_frag_glsl }, - [GPU_SHADER_2D_IMAGE_MULTISAMPLE_8_DEPTH_TEST] = { datatoc_gpu_shader_2D_vert_glsl, datatoc_gpu_shader_image_multisample_resolve_frag_glsl }, - [GPU_SHADER_2D_IMAGE_MULTISAMPLE_16_DEPTH_TEST] = { datatoc_gpu_shader_2D_vert_glsl, datatoc_gpu_shader_image_multisample_resolve_frag_glsl }, - - [GPU_SHADER_2D_IMAGE_INTERLACE] = { datatoc_gpu_shader_2D_image_vert_glsl, - datatoc_gpu_shader_image_interlace_frag_glsl }, - [GPU_SHADER_2D_CHECKER] = { datatoc_gpu_shader_2D_vert_glsl, datatoc_gpu_shader_checker_frag_glsl }, - - [GPU_SHADER_2D_DIAG_STRIPES] = { datatoc_gpu_shader_2D_vert_glsl, datatoc_gpu_shader_diag_stripes_frag_glsl }, - - [GPU_SHADER_2D_UNIFORM_COLOR] = { datatoc_gpu_shader_2D_vert_glsl, datatoc_gpu_shader_uniform_color_frag_glsl }, - [GPU_SHADER_2D_FLAT_COLOR] = { datatoc_gpu_shader_2D_flat_color_vert_glsl, - datatoc_gpu_shader_flat_color_frag_glsl }, - [GPU_SHADER_2D_SMOOTH_COLOR] = { datatoc_gpu_shader_2D_smooth_color_vert_glsl, - datatoc_gpu_shader_2D_smooth_color_frag_glsl }, - [GPU_SHADER_2D_SMOOTH_COLOR_DITHER] = { datatoc_gpu_shader_2D_smooth_color_vert_glsl, - datatoc_gpu_shader_2D_smooth_color_dithered_frag_glsl }, - [GPU_SHADER_2D_IMAGE_LINEAR_TO_SRGB] = { datatoc_gpu_shader_2D_image_vert_glsl, - datatoc_gpu_shader_image_linear_frag_glsl }, - [GPU_SHADER_2D_IMAGE] = { datatoc_gpu_shader_2D_image_vert_glsl, - datatoc_gpu_shader_image_frag_glsl }, - [GPU_SHADER_2D_IMAGE_COLOR] = { datatoc_gpu_shader_2D_image_vert_glsl, - datatoc_gpu_shader_image_color_frag_glsl }, - [GPU_SHADER_2D_IMAGE_DESATURATE_COLOR] = { datatoc_gpu_shader_2D_image_vert_glsl, - datatoc_gpu_shader_image_desaturate_frag_glsl }, - [GPU_SHADER_2D_IMAGE_ALPHA_COLOR] = { datatoc_gpu_shader_2D_image_vert_glsl, - datatoc_gpu_shader_image_alpha_color_frag_glsl }, - [GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR] = { datatoc_gpu_shader_2D_image_vert_glsl, - datatoc_gpu_shader_image_shuffle_color_frag_glsl }, - [GPU_SHADER_2D_IMAGE_RECT_COLOR] = { datatoc_gpu_shader_2D_image_rect_vert_glsl, - datatoc_gpu_shader_image_color_frag_glsl }, - [GPU_SHADER_2D_IMAGE_MULTI_RECT_COLOR] = { datatoc_gpu_shader_2D_image_multi_rect_vert_glsl, - datatoc_gpu_shader_image_varying_color_frag_glsl }, - - [GPU_SHADER_3D_UNIFORM_COLOR] = { datatoc_gpu_shader_3D_vert_glsl, datatoc_gpu_shader_uniform_color_frag_glsl }, - [GPU_SHADER_3D_UNIFORM_COLOR_U32] = { datatoc_gpu_shader_3D_vert_glsl, datatoc_gpu_shader_uniform_color_frag_glsl }, - [GPU_SHADER_3D_FLAT_COLOR] = { datatoc_gpu_shader_3D_flat_color_vert_glsl, - datatoc_gpu_shader_flat_color_frag_glsl }, - [GPU_SHADER_3D_FLAT_COLOR_U32] = { datatoc_gpu_shader_3D_flat_color_vert_glsl, - datatoc_gpu_shader_flat_color_frag_glsl }, - [GPU_SHADER_3D_SMOOTH_COLOR] = { datatoc_gpu_shader_3D_smooth_color_vert_glsl, - datatoc_gpu_shader_3D_smooth_color_frag_glsl }, - [GPU_SHADER_3D_DEPTH_ONLY] = { datatoc_gpu_shader_3D_vert_glsl, datatoc_gpu_shader_depth_only_frag_glsl }, - [GPU_SHADER_3D_CLIPPED_UNIFORM_COLOR] = { datatoc_gpu_shader_3D_clipped_uniform_color_vert_glsl, - datatoc_gpu_shader_uniform_color_frag_glsl }, - - [GPU_SHADER_3D_GROUNDPOINT] = { datatoc_gpu_shader_3D_groundpoint_vert_glsl, datatoc_gpu_shader_point_uniform_color_frag_glsl }, - [GPU_SHADER_3D_GROUNDLINE] = { datatoc_gpu_shader_3D_passthrough_vert_glsl, - datatoc_gpu_shader_uniform_color_frag_glsl, - datatoc_gpu_shader_3D_groundline_geom_glsl }, - - [GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR] = { datatoc_gpu_shader_2D_line_dashed_uniform_color_vert_glsl, - datatoc_gpu_shader_2D_line_dashed_frag_glsl, - datatoc_gpu_shader_2D_line_dashed_geom_glsl }, - [GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR] = { datatoc_gpu_shader_3D_line_dashed_uniform_color_vert_glsl, - datatoc_gpu_shader_2D_line_dashed_frag_glsl, - datatoc_gpu_shader_2D_line_dashed_geom_glsl }, - - [GPU_SHADER_3D_OBJECTSPACE_SIMPLE_LIGHTING_VARIYING_COLOR] = - { datatoc_gpu_shader_instance_objectspace_variying_color_vert_glsl, - datatoc_gpu_shader_simple_lighting_frag_glsl}, - [GPU_SHADER_3D_OBJECTSPACE_VARIYING_COLOR] = { datatoc_gpu_shader_instance_objectspace_variying_color_vert_glsl, - datatoc_gpu_shader_flat_color_frag_glsl}, - [GPU_SHADER_3D_SCREENSPACE_VARIYING_COLOR] = { datatoc_gpu_shader_instance_screenspace_variying_color_vert_glsl, - datatoc_gpu_shader_flat_color_frag_glsl}, - [GPU_SHADER_3D_INSTANCE_SCREEN_ALIGNED_AXIS] = { datatoc_gpu_shader_instance_screen_aligned_vert_glsl, - datatoc_gpu_shader_flat_color_frag_glsl}, - [GPU_SHADER_3D_INSTANCE_SCREEN_ALIGNED] = { datatoc_gpu_shader_instance_screen_aligned_vert_glsl, - datatoc_gpu_shader_flat_color_frag_glsl}, - - [GPU_SHADER_CAMERA] = { datatoc_gpu_shader_instance_camera_vert_glsl, - datatoc_gpu_shader_flat_color_frag_glsl}, - [GPU_SHADER_DISTANCE_LINES] = { datatoc_gpu_shader_instance_distance_line_vert_glsl, - datatoc_gpu_shader_flat_color_frag_glsl}, - - [GPU_SHADER_2D_POINT_FIXED_SIZE_UNIFORM_COLOR] = - { datatoc_gpu_shader_2D_vert_glsl, datatoc_gpu_shader_point_uniform_color_frag_glsl }, - [GPU_SHADER_2D_POINT_VARYING_SIZE_VARYING_COLOR] = - { datatoc_gpu_shader_2D_point_varying_size_varying_color_vert_glsl, - datatoc_gpu_shader_point_varying_color_frag_glsl }, - [GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA] = - { datatoc_gpu_shader_2D_point_uniform_size_aa_vert_glsl, - datatoc_gpu_shader_point_uniform_color_aa_frag_glsl }, - [GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA] = - { datatoc_gpu_shader_2D_point_uniform_size_outline_aa_vert_glsl, - datatoc_gpu_shader_point_uniform_color_outline_aa_frag_glsl }, - [GPU_SHADER_2D_POINT_UNIFORM_SIZE_VARYING_COLOR_OUTLINE_AA] = - { datatoc_gpu_shader_2D_point_uniform_size_varying_color_outline_aa_vert_glsl, - datatoc_gpu_shader_point_varying_color_outline_aa_frag_glsl }, - [GPU_SHADER_3D_POINT_FIXED_SIZE_UNIFORM_COLOR] = { datatoc_gpu_shader_3D_vert_glsl, - datatoc_gpu_shader_point_uniform_color_frag_glsl }, - [GPU_SHADER_3D_POINT_FIXED_SIZE_VARYING_COLOR] = { datatoc_gpu_shader_3D_point_fixed_size_varying_color_vert_glsl, - datatoc_gpu_shader_point_varying_color_frag_glsl }, - [GPU_SHADER_3D_POINT_VARYING_SIZE_UNIFORM_COLOR] = { datatoc_gpu_shader_3D_point_varying_size_vert_glsl, - datatoc_gpu_shader_point_uniform_color_frag_glsl }, - [GPU_SHADER_3D_POINT_VARYING_SIZE_VARYING_COLOR] = - { datatoc_gpu_shader_3D_point_varying_size_varying_color_vert_glsl, - datatoc_gpu_shader_point_varying_color_frag_glsl }, - [GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA] = - { datatoc_gpu_shader_3D_point_uniform_size_aa_vert_glsl, - datatoc_gpu_shader_point_uniform_color_aa_frag_glsl }, - [GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA] = - { datatoc_gpu_shader_3D_point_uniform_size_outline_aa_vert_glsl, - datatoc_gpu_shader_point_uniform_color_outline_aa_frag_glsl }, - - [GPU_SHADER_INSTANCE_UNIFORM_COLOR] = { datatoc_gpu_shader_instance_vert_glsl, datatoc_gpu_shader_uniform_color_frag_glsl }, - [GPU_SHADER_INSTANCE_VARIYING_ID_VARIYING_SIZE] = - { datatoc_gpu_shader_instance_variying_size_variying_id_vert_glsl, - datatoc_gpu_shader_flat_id_frag_glsl }, - [GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SIZE] = - { datatoc_gpu_shader_instance_variying_size_variying_color_vert_glsl, - datatoc_gpu_shader_flat_color_frag_glsl }, - [GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SCALE] = - { datatoc_gpu_shader_instance_variying_size_variying_color_vert_glsl, - datatoc_gpu_shader_flat_color_frag_glsl }, - [GPU_SHADER_INSTANCE_EDGES_VARIYING_COLOR] = { datatoc_gpu_shader_instance_edges_variying_color_vert_glsl, - datatoc_gpu_shader_flat_color_frag_glsl, - datatoc_gpu_shader_instance_edges_variying_color_geom_glsl}, - - [GPU_SHADER_2D_AREA_EDGES] = { datatoc_gpu_shader_2D_area_borders_vert_glsl, - datatoc_gpu_shader_uniform_color_frag_glsl}, - [GPU_SHADER_2D_WIDGET_BASE] = { datatoc_gpu_shader_2D_widget_base_vert_glsl, - datatoc_gpu_shader_2D_widget_base_frag_glsl}, - [GPU_SHADER_2D_WIDGET_BASE_INST] = { datatoc_gpu_shader_2D_widget_base_vert_glsl, - datatoc_gpu_shader_2D_widget_base_frag_glsl}, - [GPU_SHADER_2D_WIDGET_SHADOW] = { datatoc_gpu_shader_2D_widget_shadow_vert_glsl, - datatoc_gpu_shader_2D_widget_shadow_frag_glsl }, - [GPU_SHADER_2D_NODELINK] = { datatoc_gpu_shader_2D_nodelink_vert_glsl, - datatoc_gpu_shader_2D_nodelink_frag_glsl }, - [GPU_SHADER_2D_NODELINK_INST] = { datatoc_gpu_shader_2D_nodelink_vert_glsl, - datatoc_gpu_shader_2D_nodelink_frag_glsl }, - - [GPU_SHADER_GPENCIL_STROKE] = { datatoc_gpu_shader_gpencil_stroke_vert_glsl, - datatoc_gpu_shader_gpencil_stroke_frag_glsl, - datatoc_gpu_shader_gpencil_stroke_geom_glsl }, - - [GPU_SHADER_GPENCIL_FILL] = { datatoc_gpu_shader_gpencil_fill_vert_glsl, - datatoc_gpu_shader_gpencil_fill_frag_glsl }, - }; - if (builtin_shaders[shader] == NULL) { - /* just a few special cases */ - const char *defines = NULL; - switch (shader) { - case GPU_SHADER_2D_IMAGE_MULTISAMPLE_2: - defines = "#define SAMPLES 2\n"; - break; - case GPU_SHADER_2D_IMAGE_MULTISAMPLE_2_DEPTH_TEST: - defines = "#define SAMPLES 2\n" - "#define USE_DEPTH\n"; - break; - case GPU_SHADER_2D_IMAGE_MULTISAMPLE_4: - defines = "#define SAMPLES 4\n"; - break; - case GPU_SHADER_2D_IMAGE_MULTISAMPLE_4_DEPTH_TEST: - defines = "#define SAMPLES 4\n" - "#define USE_DEPTH\n"; - break; - case GPU_SHADER_2D_IMAGE_MULTISAMPLE_8: - defines = "#define SAMPLES 8\n"; - break; - case GPU_SHADER_2D_IMAGE_MULTISAMPLE_8_DEPTH_TEST: - defines = "#define SAMPLES 8\n" - "#define USE_DEPTH\n"; - break; - case GPU_SHADER_2D_IMAGE_MULTISAMPLE_16: - defines = "#define SAMPLES 16\n"; - break; - case GPU_SHADER_2D_IMAGE_MULTISAMPLE_16_DEPTH_TEST: - defines = "#define SAMPLES 16\n" - "#define USE_DEPTH\n"; - break; - case GPU_SHADER_2D_WIDGET_BASE_INST: - case GPU_SHADER_2D_NODELINK_INST: - defines = "#define USE_INSTANCE\n"; - break; - case GPU_SHADER_SMOKE_COBA: - defines = "#define USE_COBA\n"; - break; - case GPU_SHADER_INSTANCE_VARIYING_ID_VARIYING_SIZE: - case GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SIZE: - defines = "#define UNIFORM_SCALE\n"; - break; - case GPU_SHADER_3D_INSTANCE_SCREEN_ALIGNED_AXIS: - defines = "#define AXIS_NAME\n"; - break; - case GPU_SHADER_3D_OBJECTSPACE_SIMPLE_LIGHTING_VARIYING_COLOR: - defines = "#define USE_INSTANCE_COLOR\n"; - break; - case GPU_SHADER_3D_FLAT_COLOR_U32: - case GPU_SHADER_3D_UNIFORM_COLOR_U32: - defines = "#define USE_COLOR_U32\n"; - break; - case GPU_SHADER_SIMPLE_LIGHTING_FLAT_COLOR: - defines = "#define USE_FLAT_NORMAL\n"; - break; - default: - break; - } + const char *defines = gpu_shader_get_builtin_shader_defines(shader); const GPUShaderStages *stages = builtin_shader_stages + shader; @@ -922,6 +1023,18 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader) return builtin_shaders[shader]; } +void GPU_shader_get_builtin_shader_code( + GPUBuiltinShader shader, + const char **vert, const char **frag, + const char **geom, const char **defines) +{ + const GPUShaderStages *stages = builtin_shader_stages + shader; + *vert = stages->vert; + *frag = stages->frag; + *geom = stages->geom; + *defines = gpu_shader_get_builtin_shader_defines(shader); +} + #define MAX_DEFINES 100 void GPU_shader_free_builtin_shaders(void) diff --git a/source/blender/python/gpu/CMakeLists.txt b/source/blender/python/gpu/CMakeLists.txt index bf317a4ebc5..bdd8fa1b996 100644 --- a/source/blender/python/gpu/CMakeLists.txt +++ b/source/blender/python/gpu/CMakeLists.txt @@ -39,6 +39,7 @@ set(SRC gpu_py_matrix.c gpu_py_offscreen.c gpu_py_select.c + gpu_py_shader.c gpu_py_types.c gpu_py_vertex_buffer.c gpu_py_vertex_format.c @@ -48,6 +49,7 @@ set(SRC gpu_py_matrix.h gpu_py_offscreen.h gpu_py_select.h + gpu_py_shader.h gpu_py_types.h gpu_py_vertex_buffer.h gpu_py_vertex_format.h diff --git a/source/blender/python/gpu/gpu_py_api.c b/source/blender/python/gpu/gpu_py_api.c index 04a27af09f1..8f22a287463 100644 --- a/source/blender/python/gpu/gpu_py_api.c +++ b/source/blender/python/gpu/gpu_py_api.c @@ -51,6 +51,7 @@ PyDoc_STRVAR(GPU_doc, " gpu.types.rst\n" " gpu.matrix.rst\n" " gpu.select.rst\n" +" gpu.shader.rst\n" "\n" ); static struct PyModuleDef GPU_module_def = { @@ -62,6 +63,7 @@ static struct PyModuleDef GPU_module_def = { PyObject *BPyInit_gpu(void) { PyObject *sys_modules = PyImport_GetModuleDict(); + PyObject *subsubmodule; PyObject *submodule; PyObject *mod; @@ -79,5 +81,13 @@ PyObject *BPyInit_gpu(void) PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule); Py_INCREF(submodule); + PyModule_AddObject(mod, "shader", (submodule = BPyInit_gpu_shader())); + PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule); + Py_INCREF(submodule); + + PyModule_AddObject(submodule, "builtin", (subsubmodule = BPyInit_gpu_shader_builtin())); + PyDict_SetItem(sys_modules, PyModule_GetNameObject(subsubmodule), subsubmodule); + Py_INCREF(subsubmodule); + return mod; } diff --git a/source/blender/python/gpu/gpu_py_batch.c b/source/blender/python/gpu/gpu_py_batch.c index ccbb0b3ecd2..4e6df73a2d9 100644 --- a/source/blender/python/gpu/gpu_py_batch.c +++ b/source/blender/python/gpu/gpu_py_batch.c @@ -45,6 +45,7 @@ #include "../generic/py_capi_utils.h" +#include "gpu_py_shader.h" #include "gpu_py_vertex_buffer.h" #include "gpu_py_batch.h" /* own include */ @@ -152,6 +153,26 @@ static PyObject *bpygpu_VertBatch_vertbuf_add(BPyGPUBatch *self, BPyGPUVertBuf * Py_RETURN_NONE; } +PyDoc_STRVAR(bpygpu_VertBatch_program_set_doc, +"TODO" +); +static PyObject *bpygpu_VertBatch_program_set(BPyGPUBatch *self, BPyGPUShader *py_shader) +{ + if (!BPyGPUShader_Check(py_shader)) { + PyErr_Format(PyExc_TypeError, + "Expected a GPUShader, got %s", + Py_TYPE(py_shader)->tp_name); + return NULL; + } + + GPUShader *shader = py_shader->shader; + GPU_batch_program_set(self->batch, + GPU_shader_get_program(shader), + GPU_shader_get_interface(shader)); + + Py_RETURN_NONE; +} + PyDoc_STRVAR(bpygpu_VertBatch_program_set_builtin_doc, "TODO" ); @@ -297,6 +318,8 @@ static PyObject *bpygpu_VertBatch_program_use_end(BPyGPUBatch *self) static struct PyMethodDef bpygpu_VertBatch_methods[] = { {"vertbuf_add", (PyCFunction)bpygpu_VertBatch_vertbuf_add, METH_O, bpygpu_VertBatch_vertbuf_add_doc}, + {"program_set", (PyCFunction)bpygpu_VertBatch_program_set, + METH_O, bpygpu_VertBatch_program_set_doc}, {"program_set_builtin", (PyCFunction)bpygpu_VertBatch_program_set_builtin, METH_VARARGS | METH_KEYWORDS, bpygpu_VertBatch_program_set_builtin_doc}, {"uniform_bool", (PyCFunction)bpygpu_VertBatch_uniform_bool, diff --git a/source/blender/python/gpu/gpu_py_shader.c b/source/blender/python/gpu/gpu_py_shader.c new file mode 100644 index 00000000000..561924c42ad --- /dev/null +++ b/source/blender/python/gpu/gpu_py_shader.c @@ -0,0 +1,635 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * 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. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/python/gpu/gpu_py_shader.c + * \ingroup bpygpu + * + * - Use ``bpygpu_`` for local API. + * - Use ``BPyGPU`` for public API. + */ + +#include <Python.h> + +#include "BLI_utildefines.h" + +#include "GPU_shader.h" +#include "GPU_shader_interface.h" + +#include "../generic/py_capi_utils.h" +#include "../generic/python_utildefines.h" + +#include "gpu_py_shader.h" /* own include */ + + + /* -------------------------------------------------------------------- */ + + /** \name Enum Conversion. + * \{ */ + +static void bpygpu_shader_add_enum_objects(PyObject *submodule) +{ + PyObject *dict = PyModule_GetDict(submodule); + PyObject *item; + +#define PY_DICT_ADD_INT(x) PyDict_SetItemString(dict, #x, item = PyLong_FromLong(x)); Py_DECREF(item) + + /* Shaders */ + PY_DICT_ADD_INT(GPU_SHADER_2D_UNIFORM_COLOR); + PY_DICT_ADD_INT(GPU_SHADER_2D_FLAT_COLOR); + PY_DICT_ADD_INT(GPU_SHADER_2D_SMOOTH_COLOR); + PY_DICT_ADD_INT(GPU_SHADER_3D_UNIFORM_COLOR); + PY_DICT_ADD_INT(GPU_SHADER_3D_FLAT_COLOR); + PY_DICT_ADD_INT(GPU_SHADER_3D_SMOOTH_COLOR); + +#undef PY_DICT_ADD_INT +} + +static int bpygpu_pyLong_as_shader_enum(PyObject *o) +{ + uint id = (uint)PyLong_AsUnsignedLong(o); + + if (id >= GPU_NUM_BUILTIN_SHADERS) { + PyErr_SetString(PyExc_ValueError, + "not a builtin shader identifier"); + return -1; + } + + return (int)id; +} + +/** \} */ + + +/* -------------------------------------------------------------------- */ + +/** \name Shader Type + * \{ */ + +static PyObject *bpygpu_shader_new(PyTypeObject *UNUSED(type), PyObject *args, PyObject *kwds) +{ + static const char *kwlist[] = { + "vertexcode", "fragcode", "geocode", + "libcode", "defines", NULL}; + + struct { + const char *vertexcode; + const char *fragcode; + const char *geocode; + const char *libcode; + const char *defines; + } params = {0}; + + if (!PyArg_ParseTupleAndKeywords( + args, kwds, "ss|$sss:GPUShader.__new__", (char **)kwlist, + ¶ms.vertexcode, ¶ms.fragcode, ¶ms.geocode, + ¶ms.libcode, ¶ms.defines)) + { + return NULL; + } + + GPUShader *shader = GPU_shader_create( + params.vertexcode, + params.fragcode, + params.geocode, + params.libcode, + params.defines, + NULL); + + if (shader == NULL) { + PyErr_SetString(PyExc_Exception, + "Shader Compile Error, see console for more details"); + return NULL; + } + + return BPyGPUShader_CreatePyObject(shader); +} + +PyDoc_STRVAR(bpygpu_shader_bind_doc, +".. method:: bind()\n" +"\n" +" Bind the Shader object.\n" +); +static PyObject *bpygpu_shader_bind(BPyGPUShader *self) +{ + GPU_shader_bind(self->shader); + Py_RETURN_NONE; +} + +PyDoc_STRVAR(bpygpu_shader_transform_feedback_enable_doc, +".. method:: transform_feedback_enable(vbo_id)\n" +"\n" +" Start transform feedback operation.\n" +"\n" +" :return: true if transform feedback was succesfully enabled.\n" +" :rtype: `bool`\n" +); +static PyObject *bpygpu_shader_transform_feedback_enable( + BPyGPUShader *self, PyObject *arg) +{ + uint vbo_id; + if ((vbo_id = PyC_Long_AsU32(arg)) == (uint)-1) { + return NULL; + } + return PyBool_FromLong(GPU_shader_transform_feedback_enable(self->shader, vbo_id)); +} + +PyDoc_STRVAR(bpygpu_shader_transform_feedback_disable_doc, +".. method:: transform_feedback_disable()\n" +"\n" +" Disable transform feedback.\n" +); +static PyObject *bpygpu_transform_feedback_disable(BPyGPUShader *self) +{ + GPU_shader_transform_feedback_disable(self->shader); + Py_RETURN_NONE; +} + +PyDoc_STRVAR(bpygpu_shader_uniform_from_name_doc, +".. method:: uniform_from_name(name)\n" +"\n" +" Get uniform location by name.\n" +"\n" +" :param name: name of the uniform variable whose location is to be queried.\n" +" :type name: `str`\n" +" :return: the location of the uniform variable.\n" +" :rtype: `int`\n" +); +static PyObject *bpygpu_shader_uniform_from_name( + BPyGPUShader *self, PyObject *arg) +{ + const char *name = PyUnicode_AsUTF8(arg); + if (name == NULL) { + return NULL; + } + + int uniform = GPU_shader_get_uniform(self->shader, name); + + if (uniform == -1) { + PyErr_SetString(PyExc_SyntaxError, + "GPUShader.get_uniform: uniform not found."); + return NULL; + } + + return PyLong_FromLong(uniform); +} + +PyDoc_STRVAR(bpygpu_shader_uniform_block_from_name_doc, +".. method:: uniform_block_from_name(name)\n" +"\n" +" Get uniform block location by name.\n" +"\n" +" :param name: name of the uniform block variable whose location is to be queried.\n" +" :type name: `str`\n" +" :return: the location of the uniform block variable.\n" +" :rtype: `int`\n" +); +static PyObject *bpygpu_shader_uniform_block_from_name( + BPyGPUShader *self, PyObject *arg) +{ + const char *name = PyUnicode_AsUTF8(arg); + if (name == NULL) { + return NULL; + } + + int uniform = GPU_shader_get_uniform_block(self->shader, name); + + if (uniform == -1) { + PyErr_SetString(PyExc_SyntaxError, + "GPUShader.get_uniform_block: uniform not found"); + return NULL; + } + + return PyLong_FromLong(uniform); +} + +static bool bpygpu_shader_uniform_vector_imp( + PyObject *args, int elem_size, + int *r_location, int *r_length, int *r_count, Py_buffer *r_pybuffer) +{ + PyObject *buffer; + + *r_count = 1; + if (!PyArg_ParseTuple( + args, "iOi|i:GPUShader.uniform_vector_*", + r_location, &buffer, r_length, r_count)) + { + return false; + } + + if (PyObject_GetBuffer(buffer, r_pybuffer, PyBUF_SIMPLE) == -1) { + /* PyObject_GetBuffer raise a PyExc_BufferError */ + return false; + } + + if (r_pybuffer->len != (*r_length * *r_count * elem_size)) { + PyErr_SetString( + PyExc_BufferError, + "GPUShader.uniform_vector_*: buffer size does not match."); + return false; + } + + return true; +} + +PyDoc_STRVAR(bpygpu_shader_uniform_vector_float_doc, +".. method:: uniform_vector_float(location, buffer, length, count)\n" +"\n" +" Set the buffer to fill the uniform.\n" +"\n" +" :param location: location of the uniform variable to be modified.\n" +" :type location: `int`\n" +" :param buffer: buffer object with format float.\n" +" :type buffer: `buffer object`\n" +" :param length: size of the uniform data type:\n" +" 1: float\n" +" 2: vec2 or float[2]\n" +" 3: vec3 or float[3]\n" +" 4: vec4 or float[4]\n" +" 9: mat3\n" +" 16: mat4\n" +" :type length: `int`\n" +" :param count: specifies the number of elements, vector or matrices that are to be modified.\n" +" :type count: `int`\n" +); +static PyObject *bpygpu_shader_uniform_vector_float( + BPyGPUShader *self, PyObject *args) +{ + int location, length, count; + + Py_buffer pybuffer; + + if (!bpygpu_shader_uniform_vector_imp( + args, sizeof(float), + &location, &length, &count, &pybuffer)) + { + return NULL; + } + + GPU_shader_uniform_vector( + self->shader, location, length, + count, pybuffer.buf); + + PyBuffer_Release(&pybuffer); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(bpygpu_shader_uniform_vector_int_doc, +".. method:: uniform_vector_int(location, buffer, length, count)\n" +"\n" +" See GPUShader.uniform_vector_float(...) description.\n." +); +static PyObject *bpygpu_shader_uniform_vector_int( + BPyGPUShader *self, PyObject *args) +{ + int location, length, count; + + Py_buffer pybuffer; + + if (!bpygpu_shader_uniform_vector_imp( + args, sizeof(int), + &location, &length, &count, &pybuffer)) + { + return NULL; + } + + GPU_shader_uniform_vector_int( + self->shader, location, length, + count, pybuffer.buf); + + PyBuffer_Release(&pybuffer); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(bpygpu_shader_uniform_int_doc, +".. method:: uniform_int(location, value)\n" +"\n" +" Set uniform value.\n" +"\n" +" :param location: builtin identifier.\n" +" :type location: `int`\n" +" :param value: builtin identifier.\n" +" :type value: `int`\n" +); +static PyObject *bpygpu_shader_uniform_int( + BPyGPUShader *self, PyObject *args) +{ + int location, value; + + if (!PyArg_ParseTuple( + args, "ii:GPUShader.uniform_int", + &location, &value)) + { + return NULL; + } + + GPU_shader_uniform_int(self->shader, location, value); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(bpygpu_shader_attr_from_name_doc, +".. method:: attr_from_name(name)\n" +"\n" +" Get attribute location by name.\n" +"\n" +" :param name: the name of the attribute variable whose location is to be queried.\n" +" :type name: `str`\n" +" :return: the location of an attribute variable.\n" +" :rtype: `int`\n" +); +static PyObject *bpygpu_shader_attr_from_name( + BPyGPUShader *self, PyObject *arg) +{ + const char *name = PyUnicode_AsUTF8(arg); + if (name == NULL) { + return NULL; + } + + int attrib = GPU_shader_get_attribute(self->shader, name); + + if (attrib == -1) { + PyErr_SetString(PyExc_SyntaxError, + "GPUShader.attr_from_name: attribute not found."); + return NULL; + } + + return PyLong_FromLong(attrib); +} + +PyDoc_STRVAR(bpygpu_shader_program_doc, +".. method:: The name of the program object for use by the OpenGL API (read-only).\n" +"\n" +" :rtype: `int`\n" +); +static PyObject *bpygpu_shader_program_get(BPyGPUShader *self, void *UNUSED(closure)) +{ + return PyLong_FromLong(GPU_shader_get_program(self->shader)); +} + +static struct PyMethodDef bpygpu_shader_methods[] = { + {"bind", (PyCFunction)bpygpu_shader_bind, + METH_NOARGS, bpygpu_shader_bind_doc}, + {"transform_feedback_enable", + (PyCFunction)bpygpu_shader_transform_feedback_enable, + METH_O, bpygpu_shader_transform_feedback_enable_doc}, + {"transform_feedback_disable", + (PyCFunction)bpygpu_transform_feedback_disable, + METH_NOARGS, bpygpu_shader_transform_feedback_disable_doc}, + {"uniform_from_name", + (PyCFunction)bpygpu_shader_uniform_from_name, + METH_O, bpygpu_shader_uniform_from_name_doc}, + {"uniform_block_from_name", + (PyCFunction)bpygpu_shader_uniform_block_from_name, + METH_O, bpygpu_shader_uniform_block_from_name_doc}, + {"uniform_vector_float", + (PyCFunction)bpygpu_shader_uniform_vector_float, + METH_VARARGS, bpygpu_shader_uniform_vector_float_doc}, + {"uniform_vector_int", + (PyCFunction)bpygpu_shader_uniform_vector_int, + METH_VARARGS, bpygpu_shader_uniform_vector_int_doc}, + {"uniform_int", + (PyCFunction)bpygpu_shader_uniform_int, + METH_VARARGS, bpygpu_shader_uniform_int_doc}, + {"attr_from_name", + (PyCFunction)bpygpu_shader_attr_from_name, + METH_O, bpygpu_shader_attr_from_name_doc}, + {NULL, NULL, 0, NULL} +}; + +static PyGetSetDef bpygpu_shader_getseters[] = { + {"program", + (getter)bpygpu_shader_program_get, (setter)NULL, + bpygpu_shader_program_doc, NULL}, + {NULL, NULL, NULL, NULL, NULL} /* Sentinel */ +}; + + +static void bpygpu_shader_dealloc(BPyGPUShader *self) +{ + GPU_shader_free(self->shader); + Py_TYPE(self)->tp_free((PyObject *)self); +} + + +PyDoc_STRVAR(bpygpu_shader_doc, +"GPUShader(vertexcode, fragcode, geocode=None, libcode=None, defines=None)\n" +"\n" +"GPUShader combines multiple GLSL shaders into a program used for drawing.\n" +"It must contain a vertex and fragment shaders, with an optional geometry shader.\n" +"\n" +"The GLSL #version directive is automatically included at the top of shaders, and set to 330.\n" +"\n" +"Some preprocessor directives are automatically added according to the Operating System or availability.\n" +"These are:\n" +" \"#define GPU_ATI\\n\"\n" +" \"#define GPU_NVIDIA\\n\"\n" +" \"#define GPU_INTEL\\n\"\n" +"\n" +"The following extensions are enabled by default if supported by the GPU:\n" +" \"#extension GL_ARB_texture_gather: enable\\n\"\n" +" \"#extension GL_ARB_texture_query_lod: enable\\n\"\n" +"\n" +"To debug shaders, use the --debug-gpu-shaders command line option" +" to see full GLSL shader compilation and linking errors.\n" +"\n" +" :param vertexcode: vertex Shader Code.\n" +" :type vertexcode: `str`\n" +" :param fragcode: fragment Shader Code.\n" +" :type value: `str`\n" +" :param geocode: geometry Shader Code.\n" +" :type value: `str`\n" +" :param libcode: code with functions and presets to be shared between shaders.\n" +" :type value: `str`\n" +" :param defines: preprocessor directives.\n" +" :type value: `str`\n" +); +PyTypeObject BPyGPUShader_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + .tp_name = "GPUShader", + .tp_basicsize = sizeof(BPyGPUShader), + .tp_dealloc = (destructor)bpygpu_shader_dealloc, + .tp_flags = Py_TPFLAGS_DEFAULT, + .tp_doc = bpygpu_shader_doc, + .tp_methods = bpygpu_shader_methods, + .tp_getset = bpygpu_shader_getseters, + .tp_new = bpygpu_shader_new, +}; + +/** \} */ + + +/* -------------------------------------------------------------------- */ + +/** \name gpu.shader Module API + * \{ */ + +PyDoc_STRVAR(bpygpu_shader_unbind_doc, +".. function:: unbind()\n" +"\n" +" Unbind the bound shader object.\n" +); +static PyObject *bpygpu_shader_unbind(BPyGPUShader *UNUSED(self)) +{ + GPU_shader_unbind(); + Py_RETURN_NONE; +} + +PyDoc_STRVAR(bpygpu_shader_from_builtin_doc, +".. function:: shader_from_builtin(shader_id)\n" +"\n" +" :param shader_id: shader identifier.\n" +" :type shader_id: `int`\n" +); +static PyObject *bpygpu_shader_from_builtin(PyObject *UNUSED(self), PyObject *arg) +{ + int shader_id = bpygpu_pyLong_as_shader_enum(arg); + if (shader_id == -1) { + return NULL; + } + + GPUShader *shader = GPU_shader_get_builtin_shader(shader_id); + + return BPyGPUShader_CreatePyObject(shader); +} + +PyDoc_STRVAR(bpygpu_shader_code_from_builtin_doc, +".. function:: shader_code_from_builtin(shader_id)\n" +"\n" +" :param shader_id: shader identifier.\n" +" :type shader_id: `int`\n" +" :return: vertex, fragment and geometry shader codes.\n" +" :rtype: `dict`\n" +); +static PyObject *bpygpu_shader_code_from_builtin(BPyGPUShader *UNUSED(self), PyObject *arg) +{ + const char *vert; + const char *frag; + const char *geom; + const char *defines; + + PyObject *item, *r_dict; + + int shader_id = bpygpu_pyLong_as_shader_enum(arg); + if (shader_id == -1) { + return NULL; + } + + GPU_shader_get_builtin_shader_code( + shader_id, &vert, &frag, &geom, &defines); + + r_dict = PyDict_New(); + + PyDict_SetItemString(r_dict, "vertex_shader", item = PyUnicode_FromString(vert)); + Py_DECREF(item); + + PyDict_SetItemString(r_dict, "fragment_shader", item = PyUnicode_FromString(frag)); + Py_DECREF(item); + + if (geom) { + PyDict_SetItemString(r_dict, "geometry_shader", item = PyUnicode_FromString(geom)); + Py_DECREF(item); + } + if (defines) { + PyDict_SetItemString(r_dict, "defines", item = PyUnicode_FromString(defines)); + Py_DECREF(item); + } + return r_dict; +} + +static struct PyMethodDef bpygpu_shader_module_methods[] = { + {"unbind", + (PyCFunction)bpygpu_shader_unbind, + METH_NOARGS, bpygpu_shader_unbind_doc}, + {"shader_from_builtin", + (PyCFunction)bpygpu_shader_from_builtin, + METH_O, bpygpu_shader_from_builtin_doc}, + {"shader_code_from_builtin", + (PyCFunction)bpygpu_shader_code_from_builtin, + METH_O, bpygpu_shader_code_from_builtin_doc}, + {NULL, NULL, 0, NULL} +}; + +PyDoc_STRVAR(bpygpu_shader_module_doc, +"This module provides access to GPUShader internal functions." +); +static PyModuleDef BPyGPU_shader_module_def = { + PyModuleDef_HEAD_INIT, + .m_name = "gpu.shader", + .m_doc = bpygpu_shader_module_doc, + .m_methods = bpygpu_shader_module_methods, +}; + +/** \} */ + + +/* -------------------------------------------------------------------- */ + +/** \name gpu.shader.buitin Module API + * \{ */ + +PyDoc_STRVAR(bpygpu_shader_builtin_module_doc, +"This module contains integers that identify the built-in shader ids." +); +static PyModuleDef BPyGPU_shader_builtin_module_def = { + PyModuleDef_HEAD_INIT, + .m_name = "gpu.shader.builtin", + .m_doc = bpygpu_shader_builtin_module_doc, +}; + +/** \} */ + + +/* -------------------------------------------------------------------- */ + +/** \name Public API + * \{ */ + +PyObject *BPyGPUShader_CreatePyObject(GPUShader *shader) +{ + BPyGPUShader *self; + + self = PyObject_New(BPyGPUShader, &BPyGPUShader_Type); + self->shader = shader; + + return (PyObject *)self; +} + +PyObject *BPyInit_gpu_shader(void) +{ + PyObject *submodule; + + submodule = PyModule_Create(&BPyGPU_shader_module_def); + + return submodule; +} + +PyObject *BPyInit_gpu_shader_builtin(void) +{ + PyObject *submodule; + + submodule = PyModule_Create(&BPyGPU_shader_builtin_module_def); + bpygpu_shader_add_enum_objects(submodule); + + return submodule; +} + +/** \} */ diff --git a/source/blender/python/gpu/gpu_py_shader.h b/source/blender/python/gpu/gpu_py_shader.h new file mode 100644 index 00000000000..d9457cd9b72 --- /dev/null +++ b/source/blender/python/gpu/gpu_py_shader.h @@ -0,0 +1,41 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * 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. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/python/gpu/gpu_py_shader.h + * \ingroup bpygpu + */ + +#ifndef __GPU_PY_SHADER_H__ +#define __GPU_PY_SHADER_H__ + +extern PyTypeObject BPyGPUShader_Type; + +#define BPyGPUShader_Check(v) (Py_TYPE(v) == &BPyGPUShader_Type) + +typedef struct BPyGPUShader { + PyObject_VAR_HEAD + struct GPUShader *shader; +} BPyGPUShader; + +PyObject *BPyGPUShader_CreatePyObject(struct GPUShader *shader); +PyObject *BPyInit_gpu_shader(void); +PyObject *BPyInit_gpu_shader_builtin(void); + +#endif /* __GPU_PY_SHADER_H__ */ diff --git a/source/blender/python/gpu/gpu_py_types.c b/source/blender/python/gpu/gpu_py_types.c index 62694189ce3..876d56ad761 100644 --- a/source/blender/python/gpu/gpu_py_types.c +++ b/source/blender/python/gpu/gpu_py_types.c @@ -57,6 +57,8 @@ PyObject *BPyInit_gpu_types(void) return NULL; if (PyType_Ready(&BPyGPUOffScreen_Type) < 0) return NULL; + if (PyType_Ready(&BPyGPUShader_Type) < 0) + return NULL; #define MODULE_TYPE_ADD(s, t) \ PyModule_AddObject(s, t.tp_name, (PyObject *)&t); Py_INCREF((PyObject *)&t) @@ -65,6 +67,7 @@ PyObject *BPyInit_gpu_types(void) MODULE_TYPE_ADD(submodule, BPyGPUVertBuf_Type); MODULE_TYPE_ADD(submodule, BPyGPUBatch_Type); MODULE_TYPE_ADD(submodule, BPyGPUOffScreen_Type); + MODULE_TYPE_ADD(submodule, BPyGPUShader_Type); #undef MODULE_TYPE_ADD diff --git a/source/blender/python/gpu/gpu_py_types.h b/source/blender/python/gpu/gpu_py_types.h index 0b1a62b78e9..0a60b58822e 100644 --- a/source/blender/python/gpu/gpu_py_types.h +++ b/source/blender/python/gpu/gpu_py_types.h @@ -29,6 +29,7 @@ #include "gpu_py_vertex_buffer.h" #include "gpu_py_batch.h" #include "gpu_py_offscreen.h" +#include "gpu_py_shader.h" PyObject *BPyInit_gpu_types(void); |