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
This commit is contained in:
Jeroen Bakker
2023-09-26 16:04:08 +02:00
parent e4c89baf53
commit 7dbe689b63
4 changed files with 18 additions and 4 deletions

View File

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

View File

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

View File

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

View File

@@ -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<shader::Type>(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.