From 7dbe689b6396f762ab20855e2d4d00c7281cd858 Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Tue, 26 Sep 2023 16:04:08 +0200 Subject: [PATCH] Vulkan: Use Point Shaders When Drawing Points In Vulkan (and Metal) it is not possible to use a global as point size. It needs to be set for each vertex when drawing points. Blender has specialized shaders for that, but not all code respect those shaders. This PR will add an assert inside the vulkan backend when incorrect usage of shaders are detected. Pull Request: https://projects.blender.org/blender/blender/pulls/112906 --- source/blender/editors/interface/view2d.cc | 7 +++---- source/blender/gpu/vulkan/vk_context.cc | 7 +++++++ source/blender/gpu/vulkan/vk_shader_interface.cc | 1 + source/blender/gpu/vulkan/vk_shader_interface.hh | 7 +++++++ 4 files changed, 18 insertions(+), 4 deletions(-) diff --git a/source/blender/editors/interface/view2d.cc b/source/blender/editors/interface/view2d.cc index 155a271a906..4e161c1d1be 100644 --- a/source/blender/editors/interface/view2d.cc +++ b/source/blender/editors/interface/view2d.cc @@ -1304,8 +1304,7 @@ void UI_view2d_dot_grid_draw(const View2D *v2d, GPUVertFormat *format = immVertexFormat(); const uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - const uint color_id = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR); + immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA); /* Scaling the dots fully with the zoom looks too busy, but a bit of size variation is nice. */ const float min_point_size = 2.0f * U.pixelsize; @@ -1368,7 +1367,8 @@ void UI_view2d_dot_grid_draw(const View2D *v2d, continue; } - GPU_point_size(point_size_draw); + immUniform1f("size", point_size_draw); + immUniform4fv("color", color); immBegin(GPU_PRIM_POINTS, count_x * count_y); /* Theoretically drawing on top of lower grid levels could be avoided, but it would also @@ -1377,7 +1377,6 @@ void UI_view2d_dot_grid_draw(const View2D *v2d, const float y = start_y + step * i_y; for (int i_x = 0; i_x < count_x; i_x++) { const float x = start_x + step * i_x; - immAttr4fv(color_id, color); immVertex2f(pos, x + point_size_offset, y + point_size_offset); } } diff --git a/source/blender/gpu/vulkan/vk_context.cc b/source/blender/gpu/vulkan/vk_context.cc index 2510fd19932..01d5bf73032 100644 --- a/source/blender/gpu/vulkan/vk_context.cc +++ b/source/blender/gpu/vulkan/vk_context.cc @@ -13,6 +13,7 @@ #include "vk_immediate.hh" #include "vk_memory.hh" #include "vk_shader.hh" +#include "vk_shader_interface.hh" #include "vk_state_manager.hh" #include "vk_texture.hh" @@ -201,6 +202,12 @@ void VKContext::bind_graphics_pipeline(const GPUPrimType prim_type, { VKShader *shader = unwrap(this->shader); BLI_assert(shader); + BLI_assert_msg( + prim_type != GPU_PRIM_POINTS || shader->interface_get().is_point_shader(), + "GPU_PRIM_POINTS is used with a shader that doesn't set point size before " + "drawing fragments. Calling code should be adapted to use a shader that sets the " + "gl_PointSize before entering the fragment stage. For example `GPU_SHADER_3D_POINT_*`."); + shader->update_graphics_pipeline(*this, prim_type, vertex_attribute_object); VKPipeline &pipeline = shader->pipeline_get(); diff --git a/source/blender/gpu/vulkan/vk_shader_interface.cc b/source/blender/gpu/vulkan/vk_shader_interface.cc index 09424ae63b2..858d4c45208 100644 --- a/source/blender/gpu/vulkan/vk_shader_interface.cc +++ b/source/blender/gpu/vulkan/vk_shader_interface.cc @@ -18,6 +18,7 @@ void VKShaderInterface::init(const shader::ShaderCreateInfo &info) static size_t PUSH_CONSTANTS_FALLBACK_NAME_LEN = strlen(PUSH_CONSTANTS_FALLBACK_NAME); using namespace blender::gpu::shader; + shader_builtins_ = info.builtins_; attr_len_ = info.vertex_inputs_.size(); uniform_len_ = info.push_constants_.size(); diff --git a/source/blender/gpu/vulkan/vk_shader_interface.hh b/source/blender/gpu/vulkan/vk_shader_interface.hh index 3fbcc6062f4..afac41eb847 100644 --- a/source/blender/gpu/vulkan/vk_shader_interface.hh +++ b/source/blender/gpu/vulkan/vk_shader_interface.hh @@ -32,6 +32,8 @@ class VKShaderInterface : public ShaderInterface { VKPushConstants::Layout push_constants_layout_; + shader::BuiltinBits shader_builtins_; + public: VKShaderInterface() = default; @@ -53,6 +55,11 @@ class VKShaderInterface : public ShaderInterface { return static_cast(attr_types_[location]); } + bool is_point_shader() const + { + return (shader_builtins_ & shader::BuiltinBits::POINT_SIZE) == shader::BuiltinBits::POINT_SIZE; + } + private: /** * Retrieve the shader input for the given resource.