Fix #146559: Vulkan: Wide lines not working in custom PyGPU shaders

For wide line rendering it is preferred to use polyline shaders. However
creating a custom shader is complicated and a stone to far for many
scriptors.

This PR allows using line_width_set when wide line rendering is
supported by the platform.

Pull Request: https://projects.blender.org/blender/blender/pulls/146762
This commit is contained in:
Jeroen Bakker
2025-09-25 14:02:11 +02:00
parent ca2a13991e
commit 1a0a35ac93
20 changed files with 201 additions and 127 deletions

View File

@@ -487,6 +487,7 @@ struct GHOST_InstanceVK {
device_features.drawIndirectFirstInstance = VK_TRUE;
device_features.fragmentStoresAndAtomics = VK_TRUE;
device_features.samplerAnisotropy = device.features.features.samplerAnisotropy;
device_features.wideLines = device.features.features.wideLines;
VkDeviceCreateInfo device_create_info = {};
device_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;

View File

@@ -17,10 +17,9 @@ namespace blender::gpu::render_graph {
* Information stored inside the render graph node. See `VKRenderGraphNode`.
*/
struct VKDrawIndexedIndirectData {
VKPipelineData pipeline_data;
VKPipelineDataGraphics graphics;
VKIndexBufferBinding index_buffer;
VKVertexBufferBindings vertex_buffers;
VKViewportData viewport_data;
VkBuffer indirect_buffer;
VkDeviceSize offset;
uint32_t draw_count;
@@ -51,8 +50,8 @@ class VKDrawIndexedIndirectNode
static void set_node_data(Node &node, Storage &storage, const CreateInfo &create_info)
{
node.storage_index = storage.draw_indexed_indirect.append_and_get_index(create_info.node_data);
vk_pipeline_data_copy(storage.draw_indexed_indirect[node.storage_index].pipeline_data,
create_info.node_data.pipeline_data);
vk_pipeline_data_copy(storage.draw_indexed_indirect[node.storage_index].graphics,
create_info.node_data.graphics);
}
/**
@@ -82,10 +81,10 @@ class VKDrawIndexedIndirectNode
Data &data,
VKBoundPipelines &r_bound_pipelines) override
{
vk_pipeline_viewport_set_commands(
command_buffer, data.viewport_data, r_bound_pipelines.graphics.viewport_state);
vk_pipeline_dynamic_graphics_build_commands(
command_buffer, data.graphics.viewport, data.graphics.line_width, r_bound_pipelines);
vk_pipeline_data_build_commands(command_buffer,
data.pipeline_data,
data.graphics.pipeline_data,
r_bound_pipelines.graphics.pipeline,
VK_PIPELINE_BIND_POINT_GRAPHICS,
VK_SHADER_STAGE_ALL_GRAPHICS);
@@ -99,7 +98,7 @@ class VKDrawIndexedIndirectNode
void free_data(Data &data)
{
vk_pipeline_data_free(data.pipeline_data);
vk_pipeline_data_free(data.graphics);
}
};
} // namespace blender::gpu::render_graph

View File

@@ -17,10 +17,9 @@ namespace blender::gpu::render_graph {
* Information stored inside the render graph node. See `VKRenderGraphNode`.
*/
struct VKDrawIndexedData {
VKPipelineData pipeline_data;
VKPipelineDataGraphics graphics;
VKIndexBufferBinding index_buffer;
VKVertexBufferBindings vertex_buffers;
VKViewportData viewport_data;
uint32_t index_count;
uint32_t instance_count;
uint32_t first_index;
@@ -51,8 +50,8 @@ class VKDrawIndexedNode : public VKNodeInfo<VKNodeType::DRAW_INDEXED,
static void set_node_data(Node &node, Storage &storage, const CreateInfo &create_info)
{
node.storage_index = storage.draw_indexed.append_and_get_index(create_info.node_data);
vk_pipeline_data_copy(storage.draw_indexed[node.storage_index].pipeline_data,
create_info.node_data.pipeline_data);
vk_pipeline_data_copy(storage.draw_indexed[node.storage_index].graphics,
create_info.node_data.graphics);
}
/**
@@ -75,10 +74,10 @@ class VKDrawIndexedNode : public VKNodeInfo<VKNodeType::DRAW_INDEXED,
Data &data,
VKBoundPipelines &r_bound_pipelines) override
{
vk_pipeline_viewport_set_commands(
command_buffer, data.viewport_data, r_bound_pipelines.graphics.viewport_state);
vk_pipeline_dynamic_graphics_build_commands(
command_buffer, data.graphics.viewport, data.graphics.line_width, r_bound_pipelines);
vk_pipeline_data_build_commands(command_buffer,
data.pipeline_data,
data.graphics.pipeline_data,
r_bound_pipelines.graphics.pipeline,
VK_PIPELINE_BIND_POINT_GRAPHICS,
VK_SHADER_STAGE_ALL_GRAPHICS);
@@ -95,7 +94,7 @@ class VKDrawIndexedNode : public VKNodeInfo<VKNodeType::DRAW_INDEXED,
void free_data(Data &data)
{
vk_pipeline_data_free(data.pipeline_data);
vk_pipeline_data_free(data.graphics);
}
};
} // namespace blender::gpu::render_graph

View File

@@ -17,9 +17,8 @@ namespace blender::gpu::render_graph {
* Information stored inside the render graph node. See `VKRenderGraphNode`.
*/
struct VKDrawIndirectData {
VKPipelineData pipeline_data;
VKPipelineDataGraphics graphics;
VKVertexBufferBindings vertex_buffers;
VKViewportData viewport_data;
VkBuffer indirect_buffer;
VkDeviceSize offset;
uint32_t draw_count;
@@ -49,8 +48,8 @@ class VKDrawIndirectNode : public VKNodeInfo<VKNodeType::DRAW_INDIRECT,
static void set_node_data(Node &node, Storage &storage, const CreateInfo &create_info)
{
node.storage_index = storage.draw_indirect.append_and_get_index(create_info.node_data);
vk_pipeline_data_copy(storage.draw_indirect[node.storage_index].pipeline_data,
create_info.node_data.pipeline_data);
vk_pipeline_data_copy(storage.draw_indirect[node.storage_index].graphics,
create_info.node_data.graphics);
}
/**
@@ -75,10 +74,10 @@ class VKDrawIndirectNode : public VKNodeInfo<VKNodeType::DRAW_INDIRECT,
Data &data,
VKBoundPipelines &r_bound_pipelines) override
{
vk_pipeline_viewport_set_commands(
command_buffer, data.viewport_data, r_bound_pipelines.graphics.viewport_state);
vk_pipeline_dynamic_graphics_build_commands(
command_buffer, data.graphics.viewport, data.graphics.line_width, r_bound_pipelines);
vk_pipeline_data_build_commands(command_buffer,
data.pipeline_data,
data.graphics.pipeline_data,
r_bound_pipelines.graphics.pipeline,
VK_PIPELINE_BIND_POINT_GRAPHICS,
VK_SHADER_STAGE_ALL_GRAPHICS);
@@ -90,7 +89,7 @@ class VKDrawIndirectNode : public VKNodeInfo<VKNodeType::DRAW_INDIRECT,
void free_data(Data &data)
{
vk_pipeline_data_free(data.pipeline_data);
vk_pipeline_data_free(data.graphics);
}
};
} // namespace blender::gpu::render_graph

View File

@@ -18,9 +18,8 @@ namespace blender::gpu::render_graph {
* Information stored inside the render graph node. See `VKRenderGraphNode`.
*/
struct VKDrawData {
VKPipelineData pipeline_data;
VKPipelineDataGraphics graphics;
VKVertexBufferBindings vertex_buffers;
VKViewportData viewport_data;
uint32_t vertex_count;
uint32_t instance_count;
uint32_t first_vertex;
@@ -50,8 +49,8 @@ class VKDrawNode : public VKNodeInfo<VKNodeType::DRAW,
static void set_node_data(Node &node, Storage &storage, const CreateInfo &create_info)
{
node.storage_index = storage.draw.append_and_get_index(create_info.node_data);
vk_pipeline_data_copy(storage.draw[node.storage_index].pipeline_data,
create_info.node_data.pipeline_data);
vk_pipeline_data_copy(storage.draw[node.storage_index].graphics,
create_info.node_data.graphics);
}
/**
@@ -73,10 +72,10 @@ class VKDrawNode : public VKNodeInfo<VKNodeType::DRAW,
Data &data,
VKBoundPipelines &r_bound_pipelines) override
{
vk_pipeline_viewport_set_commands(
command_buffer, data.viewport_data, r_bound_pipelines.graphics.viewport_state);
vk_pipeline_dynamic_graphics_build_commands(
command_buffer, data.graphics.viewport, data.graphics.line_width, r_bound_pipelines);
vk_pipeline_data_build_commands(command_buffer,
data.pipeline_data,
data.graphics.pipeline_data,
r_bound_pipelines.graphics.pipeline,
VK_PIPELINE_BIND_POINT_GRAPHICS,
VK_SHADER_STAGE_ALL_GRAPHICS);
@@ -89,7 +88,7 @@ class VKDrawNode : public VKNodeInfo<VKNodeType::DRAW,
void free_data(Data &data)
{
vk_pipeline_data_free(data.pipeline_data);
vk_pipeline_data_free(data.graphics);
}
};
} // namespace blender::gpu::render_graph

View File

@@ -23,13 +23,19 @@ void vk_pipeline_data_copy(VKPipelineData &dst, const VKPipelineData &src)
}
}
void vk_pipeline_viewport_set_commands(VKCommandBufferInterface &command_buffer,
const VKViewportData &viewport_data,
VKViewportData &r_viewport_state)
void vk_pipeline_dynamic_graphics_build_commands(VKCommandBufferInterface &command_buffer,
const VKViewportData &viewport,
const std::optional<float> line_width,
VKBoundPipelines &r_bound_pipelines)
{
if (assign_if_different(r_viewport_state, viewport_data)) {
command_buffer.set_viewport(viewport_data.viewports);
command_buffer.set_scissor(viewport_data.scissors);
if (assign_if_different(r_bound_pipelines.graphics.viewport_state, viewport)) {
command_buffer.set_viewport(viewport.viewports);
command_buffer.set_scissor(viewport.scissors);
}
if (assign_if_different(r_bound_pipelines.graphics.line_width, line_width)) {
if (line_width.has_value()) {
command_buffer.set_line_width(*line_width);
}
}
}

View File

@@ -65,6 +65,12 @@ struct VKViewportData {
}
};
struct VKPipelineDataGraphics {
VKPipelineData pipeline_data;
VKViewportData viewport;
std::optional<float> line_width;
};
/** Resources bound for a compute/graphics pipeline. */
struct VKBoundPipeline {
VkPipeline vk_pipeline;
@@ -119,6 +125,7 @@ struct VKBoundPipelines {
VKIndexBufferBinding index_buffer;
VKVertexBufferBindings vertex_buffers;
VKViewportData viewport_state;
std::optional<float> line_width;
} graphics;
};
@@ -130,15 +137,23 @@ struct VKBoundPipelines {
* guardedalloc.
*/
void vk_pipeline_data_copy(VKPipelineData &dst, const VKPipelineData &src);
static inline void vk_pipeline_data_copy(VKPipelineDataGraphics &dst,
const VKPipelineDataGraphics &src)
{
vk_pipeline_data_copy(dst.pipeline_data, src.pipeline_data);
}
/**
* Record commands that set the viewport and scissor only if the desired
* viewport state is different than the current viewport state.
* Record commands that update the dynamic state.
*
* - viewports
* - scissors
* - line width
*/
void vk_pipeline_viewport_set_commands(VKCommandBufferInterface &command_buffer,
const VKViewportData &viewport_data,
VKViewportData &r_viewport_state);
void vk_pipeline_dynamic_graphics_build_commands(VKCommandBufferInterface &command_buffer,
const VKViewportData &viewport,
const std::optional<float> line_width,
VKBoundPipelines &r_bound_pipelines);
/**
* Record the commands to the given command buffer to bind the descriptor set, pipeline and push
@@ -161,6 +176,10 @@ void vk_pipeline_data_build_commands(VKCommandBufferInterface &command_buffer,
* Free localized data created by `vk_pipeline_data_copy`.
*/
void vk_pipeline_data_free(VKPipelineData &data);
static inline void vk_pipeline_data_free(VKPipelineDataGraphics &data)
{
vk_pipeline_data_free(data.pipeline_data);
}
void vk_index_buffer_binding_build_links(VKResourceStateTracker &resources,
VKRenderGraphNodeLinks &node_links,

View File

@@ -172,13 +172,13 @@ TEST_P(VKRenderGraphTestRender, begin_draw_end)
draw.node_data.first_vertex = 0;
draw.node_data.instance_count = 1;
draw.node_data.vertex_count = 4;
draw.node_data.pipeline_data.push_constants_data = nullptr;
draw.node_data.pipeline_data.push_constants_size = 0;
draw.node_data.pipeline_data.vk_descriptor_set = VK_NULL_HANDLE;
draw.node_data.pipeline_data.vk_pipeline = pipeline;
draw.node_data.pipeline_data.vk_pipeline_layout = pipeline_layout;
draw.node_data.viewport_data.viewports.append(VkViewport{});
draw.node_data.viewport_data.scissors.append(VkRect2D{});
draw.node_data.graphics.pipeline_data.push_constants_data = nullptr;
draw.node_data.graphics.pipeline_data.push_constants_size = 0;
draw.node_data.graphics.pipeline_data.vk_descriptor_set = VK_NULL_HANDLE;
draw.node_data.graphics.pipeline_data.vk_pipeline = pipeline;
draw.node_data.graphics.pipeline_data.vk_pipeline_layout = pipeline_layout;
draw.node_data.graphics.viewport.viewports.append(VkViewport{});
draw.node_data.graphics.viewport.scissors.append(VkRect2D{});
render_graph->add_node(draw);
}
@@ -258,13 +258,13 @@ TEST_P(VKRenderGraphTestRender, begin_draw_end__layered)
draw.node_data.first_vertex = 0;
draw.node_data.instance_count = 1;
draw.node_data.vertex_count = 4;
draw.node_data.pipeline_data.push_constants_data = nullptr;
draw.node_data.pipeline_data.push_constants_size = 0;
draw.node_data.pipeline_data.vk_descriptor_set = VK_NULL_HANDLE;
draw.node_data.pipeline_data.vk_pipeline = pipeline;
draw.node_data.pipeline_data.vk_pipeline_layout = pipeline_layout;
draw.node_data.viewport_data.viewports.append(VkViewport{});
draw.node_data.viewport_data.scissors.append(VkRect2D{});
draw.node_data.graphics.pipeline_data.push_constants_data = nullptr;
draw.node_data.graphics.pipeline_data.push_constants_size = 0;
draw.node_data.graphics.pipeline_data.vk_descriptor_set = VK_NULL_HANDLE;
draw.node_data.graphics.pipeline_data.vk_pipeline = pipeline;
draw.node_data.graphics.pipeline_data.vk_pipeline_layout = pipeline_layout;
draw.node_data.graphics.viewport.viewports.append(VkViewport{});
draw.node_data.graphics.viewport.scissors.append(VkRect2D{});
render_graph->add_node(draw);
}

View File

@@ -574,13 +574,13 @@ TEST_P(VKRenderGraphTestScheduler, begin_draw_copy_framebuffer_draw_end)
draw.node_data.first_vertex = 0;
draw.node_data.instance_count = 1;
draw.node_data.vertex_count = 4;
draw.node_data.pipeline_data.push_constants_data = nullptr;
draw.node_data.pipeline_data.push_constants_size = 0;
draw.node_data.pipeline_data.vk_descriptor_set = VK_NULL_HANDLE;
draw.node_data.pipeline_data.vk_pipeline = pipeline_combine;
draw.node_data.pipeline_data.vk_pipeline_layout = pipeline_layout_combine;
draw.node_data.viewport_data.viewports.append(VkViewport{});
draw.node_data.viewport_data.scissors.append(VkRect2D{});
draw.node_data.graphics.pipeline_data.push_constants_data = nullptr;
draw.node_data.graphics.pipeline_data.push_constants_size = 0;
draw.node_data.graphics.pipeline_data.vk_descriptor_set = VK_NULL_HANDLE;
draw.node_data.graphics.pipeline_data.vk_pipeline = pipeline_combine;
draw.node_data.graphics.pipeline_data.vk_pipeline_layout = pipeline_layout_combine;
draw.node_data.graphics.viewport.viewports.append(VkViewport{});
draw.node_data.graphics.viewport.scissors.append(VkRect2D{});
render_graph->add_node(draw);
}
@@ -606,13 +606,13 @@ TEST_P(VKRenderGraphTestScheduler, begin_draw_copy_framebuffer_draw_end)
draw.node_data.first_vertex = 0;
draw.node_data.instance_count = 1;
draw.node_data.vertex_count = 4;
draw.node_data.pipeline_data.push_constants_data = nullptr;
draw.node_data.pipeline_data.push_constants_size = 0;
draw.node_data.pipeline_data.vk_descriptor_set = VK_NULL_HANDLE;
draw.node_data.pipeline_data.vk_pipeline = pipeline_background;
draw.node_data.pipeline_data.vk_pipeline_layout = pipeline_layout_background;
draw.node_data.viewport_data.viewports.append(VkViewport{});
draw.node_data.viewport_data.scissors.append(VkRect2D{});
draw.node_data.graphics.pipeline_data.push_constants_data = nullptr;
draw.node_data.graphics.pipeline_data.push_constants_size = 0;
draw.node_data.graphics.pipeline_data.vk_descriptor_set = VK_NULL_HANDLE;
draw.node_data.graphics.pipeline_data.vk_pipeline = pipeline_background;
draw.node_data.graphics.pipeline_data.vk_pipeline_layout = pipeline_layout_background;
draw.node_data.graphics.viewport.viewports.append(VkViewport{});
draw.node_data.graphics.viewport.scissors.append(VkRect2D{});
render_graph->add_node(draw);
}
@@ -775,13 +775,13 @@ TEST_P(VKRenderGraphTestScheduler, begin_update_draw_update_draw_update_draw_end
draw.node_data.first_vertex = 0;
draw.node_data.instance_count = 1;
draw.node_data.vertex_count = 1;
draw.node_data.pipeline_data.push_constants_data = nullptr;
draw.node_data.pipeline_data.push_constants_size = 0;
draw.node_data.pipeline_data.vk_descriptor_set = VK_NULL_HANDLE;
draw.node_data.pipeline_data.vk_pipeline = pipeline;
draw.node_data.pipeline_data.vk_pipeline_layout = pipeline_layout;
draw.node_data.viewport_data.viewports.append(VkViewport{});
draw.node_data.viewport_data.scissors.append(VkRect2D{});
draw.node_data.graphics.pipeline_data.push_constants_data = nullptr;
draw.node_data.graphics.pipeline_data.push_constants_size = 0;
draw.node_data.graphics.pipeline_data.vk_descriptor_set = VK_NULL_HANDLE;
draw.node_data.graphics.pipeline_data.vk_pipeline = pipeline;
draw.node_data.graphics.pipeline_data.vk_pipeline_layout = pipeline_layout;
draw.node_data.graphics.viewport.viewports.append(VkViewport{});
draw.node_data.graphics.viewport.scissors.append(VkRect2D{});
render_graph->add_node(draw);
}
@@ -802,13 +802,13 @@ TEST_P(VKRenderGraphTestScheduler, begin_update_draw_update_draw_update_draw_end
draw.node_data.first_vertex = 0;
draw.node_data.instance_count = 1;
draw.node_data.vertex_count = 2;
draw.node_data.pipeline_data.push_constants_data = nullptr;
draw.node_data.pipeline_data.push_constants_size = 0;
draw.node_data.pipeline_data.vk_descriptor_set = VK_NULL_HANDLE;
draw.node_data.pipeline_data.vk_pipeline = pipeline;
draw.node_data.pipeline_data.vk_pipeline_layout = pipeline_layout;
draw.node_data.viewport_data.viewports.append(VkViewport{});
draw.node_data.viewport_data.scissors.append(VkRect2D{});
draw.node_data.graphics.pipeline_data.push_constants_data = nullptr;
draw.node_data.graphics.pipeline_data.push_constants_size = 0;
draw.node_data.graphics.pipeline_data.vk_descriptor_set = VK_NULL_HANDLE;
draw.node_data.graphics.pipeline_data.vk_pipeline = pipeline;
draw.node_data.graphics.pipeline_data.vk_pipeline_layout = pipeline_layout;
draw.node_data.graphics.viewport.viewports.append(VkViewport{});
draw.node_data.graphics.viewport.scissors.append(VkRect2D{});
render_graph->add_node(draw);
}
@@ -829,13 +829,13 @@ TEST_P(VKRenderGraphTestScheduler, begin_update_draw_update_draw_update_draw_end
draw.node_data.first_vertex = 0;
draw.node_data.instance_count = 1;
draw.node_data.vertex_count = 3;
draw.node_data.pipeline_data.push_constants_data = nullptr;
draw.node_data.pipeline_data.push_constants_size = 0;
draw.node_data.pipeline_data.vk_descriptor_set = VK_NULL_HANDLE;
draw.node_data.pipeline_data.vk_pipeline = pipeline;
draw.node_data.pipeline_data.vk_pipeline_layout = pipeline_layout;
draw.node_data.viewport_data.viewports.append(VkViewport{});
draw.node_data.viewport_data.scissors.append(VkRect2D{});
draw.node_data.graphics.pipeline_data.push_constants_data = nullptr;
draw.node_data.graphics.pipeline_data.push_constants_size = 0;
draw.node_data.graphics.pipeline_data.vk_descriptor_set = VK_NULL_HANDLE;
draw.node_data.graphics.pipeline_data.vk_pipeline = pipeline;
draw.node_data.graphics.pipeline_data.vk_pipeline_layout = pipeline_layout;
draw.node_data.graphics.viewport.viewports.append(VkViewport{});
draw.node_data.graphics.viewport.scissors.append(VkRect2D{});
render_graph->add_node(draw);
}
@@ -1000,13 +1000,13 @@ TEST_P(VKRenderGraphTestScheduler, begin_draw_copy_to_attachment_draw_end)
draw.node_data.first_vertex = 0;
draw.node_data.instance_count = 1;
draw.node_data.vertex_count = 4;
draw.node_data.pipeline_data.push_constants_data = nullptr;
draw.node_data.pipeline_data.push_constants_size = 0;
draw.node_data.pipeline_data.vk_descriptor_set = VK_NULL_HANDLE;
draw.node_data.pipeline_data.vk_pipeline = pipeline;
draw.node_data.pipeline_data.vk_pipeline_layout = pipeline_layout;
draw.node_data.viewport_data.viewports.append(VkViewport{});
draw.node_data.viewport_data.scissors.append(VkRect2D{});
draw.node_data.graphics.pipeline_data.push_constants_data = nullptr;
draw.node_data.graphics.pipeline_data.push_constants_size = 0;
draw.node_data.graphics.pipeline_data.vk_descriptor_set = VK_NULL_HANDLE;
draw.node_data.graphics.pipeline_data.vk_pipeline = pipeline;
draw.node_data.graphics.pipeline_data.vk_pipeline_layout = pipeline_layout;
draw.node_data.graphics.viewport.viewports.append(VkViewport{});
draw.node_data.graphics.viewport.scissors.append(VkRect2D{});
render_graph->add_node(draw);
}
@@ -1032,13 +1032,13 @@ TEST_P(VKRenderGraphTestScheduler, begin_draw_copy_to_attachment_draw_end)
draw.node_data.first_vertex = 0;
draw.node_data.instance_count = 1;
draw.node_data.vertex_count = 4;
draw.node_data.pipeline_data.push_constants_data = nullptr;
draw.node_data.pipeline_data.push_constants_size = 0;
draw.node_data.pipeline_data.vk_descriptor_set = VK_NULL_HANDLE;
draw.node_data.pipeline_data.vk_pipeline = pipeline;
draw.node_data.pipeline_data.vk_pipeline_layout = pipeline_layout;
draw.node_data.viewport_data.viewports.append(VkViewport{});
draw.node_data.viewport_data.scissors.append(VkRect2D{});
draw.node_data.graphics.pipeline_data.push_constants_data = nullptr;
draw.node_data.graphics.pipeline_data.push_constants_size = 0;
draw.node_data.graphics.pipeline_data.vk_descriptor_set = VK_NULL_HANDLE;
draw.node_data.graphics.pipeline_data.vk_pipeline = pipeline;
draw.node_data.graphics.pipeline_data.vk_pipeline_layout = pipeline_layout;
draw.node_data.graphics.viewport.viewports.append(VkViewport{});
draw.node_data.graphics.viewport.scissors.append(VkRect2D{});
render_graph->add_node(draw);
}

View File

@@ -453,6 +453,14 @@ class CommandBufferLog : public VKCommandBufferInterface {
log_.append(ss.str());
}
void set_line_width(const float line_width) override
{
EXPECT_TRUE(is_recording_);
std::stringstream ss;
ss << "set_line_width(line_width=" << line_width << ")";
log_.append(ss.str());
}
void begin_debug_utils_label(const VkDebugUtilsLabelEXT * /*vk_debug_utils_label*/) override {}
void end_debug_utils_label() override {}

View File

@@ -264,6 +264,10 @@ void VKCommandBufferWrapper::set_scissor(const Vector<VkRect2D> scissors)
{
vkCmdSetScissor(vk_command_buffer_, 0, scissors.size(), scissors.data());
}
void VKCommandBufferWrapper::set_line_width(const float line_width)
{
vkCmdSetLineWidth(vk_command_buffer_, line_width);
}
void VKCommandBufferWrapper::begin_rendering(const VkRenderingInfo *p_rendering_info)
{

View File

@@ -131,6 +131,7 @@ class VKCommandBufferInterface {
uint32_t query_count) = 0;
virtual void set_viewport(const Vector<VkViewport> viewports) = 0;
virtual void set_scissor(const Vector<VkRect2D> scissors) = 0;
virtual void set_line_width(const float line_width) = 0;
/* VK_KHR_dynamic_rendering */
virtual void begin_rendering(const VkRenderingInfo *p_rendering_info) = 0;
@@ -257,6 +258,7 @@ class VKCommandBufferWrapper : public VKCommandBufferInterface {
const void *p_values) override;
void set_viewport(const Vector<VkViewport> viewports) override;
void set_scissor(const Vector<VkRect2D> scissors) override;
void set_line_width(const float line_width) override;
void begin_query(VkQueryPool vk_query_pool,
uint32_t query_index,
VkQueryControlFlags vk_query_control_flags) override;

View File

@@ -428,6 +428,7 @@ void VKBackend::detect_workarounds(VKDevice &device)
extensions.dynamic_rendering_unused_attachments = false;
extensions.descriptor_buffer = false;
extensions.pageable_device_local_memory = false;
extensions.wide_lines = false;
GCaps.stencil_export_support = false;
device.workarounds_ = workarounds;
@@ -439,6 +440,7 @@ void VKBackend::detect_workarounds(VKDevice &device)
device.physical_device_vulkan_12_features_get().shaderOutputLayer;
extensions.shader_output_viewport_index =
device.physical_device_vulkan_12_features_get().shaderOutputViewportIndex;
extensions.wide_lines = device.physical_device_features_get().wideLines;
extensions.fragment_shader_barycentric = device.supports_extension(
VK_KHR_FRAGMENT_SHADER_BARYCENTRIC_EXTENSION_NAME);
extensions.dynamic_rendering_local_read = device.supports_extension(

View File

@@ -44,14 +44,14 @@ void VKBatch::draw(int vertex_first, int vertex_count, int instance_first, int i
draw_indexed.node_data.first_instance = instance_first;
context.active_framebuffer_get()->vk_viewports_append(
draw_indexed.node_data.viewport_data.viewports);
draw_indexed.node_data.graphics.viewport.viewports);
context.active_framebuffer_get()->vk_render_areas_append(
draw_indexed.node_data.viewport_data.scissors);
draw_indexed.node_data.graphics.viewport.scissors);
draw_indexed.node_data.index_buffer.buffer = index_buffer->vk_handle();
draw_indexed.node_data.index_buffer.index_type = index_buffer->vk_index_type();
vao.bind(draw_indexed.node_data.vertex_buffers);
context.update_pipeline_data(prim_type, vao, draw_indexed.node_data.pipeline_data);
context.update_pipeline_data(prim_type, vao, draw_indexed.node_data.graphics);
context.render_graph().add_node(draw_indexed);
}
@@ -61,12 +61,13 @@ void VKBatch::draw(int vertex_first, int vertex_count, int instance_first, int i
draw.node_data.instance_count = instance_count;
draw.node_data.first_vertex = vertex_first;
draw.node_data.first_instance = instance_first;
context.active_framebuffer_get()->vk_viewports_append(draw.node_data.viewport_data.viewports);
context.active_framebuffer_get()->vk_viewports_append(
draw.node_data.graphics.viewport.viewports);
context.active_framebuffer_get()->vk_render_areas_append(
draw.node_data.viewport_data.scissors);
draw.node_data.graphics.viewport.scissors);
vao.bind(draw.node_data.vertex_buffers);
context.update_pipeline_data(prim_type, vao, draw.node_data.pipeline_data);
context.update_pipeline_data(prim_type, vao, draw.node_data.graphics);
context.render_graph().add_node(draw);
}
@@ -114,14 +115,14 @@ void VKBatch::multi_draw_indirect(const VkBuffer indirect_buffer,
draw_indexed_indirect.node_data.stride = stride;
context.active_framebuffer_get()->vk_viewports_append(
draw_indexed_indirect.node_data.viewport_data.viewports);
draw_indexed_indirect.node_data.graphics.viewport.viewports);
context.active_framebuffer_get()->vk_render_areas_append(
draw_indexed_indirect.node_data.viewport_data.scissors);
draw_indexed_indirect.node_data.graphics.viewport.scissors);
draw_indexed_indirect.node_data.index_buffer.buffer = index_buffer->vk_handle();
draw_indexed_indirect.node_data.index_buffer.index_type = index_buffer->vk_index_type();
vao.bind(draw_indexed_indirect.node_data.vertex_buffers);
context.update_pipeline_data(prim_type, vao, draw_indexed_indirect.node_data.pipeline_data);
context.update_pipeline_data(prim_type, vao, draw_indexed_indirect.node_data.graphics);
context.render_graph().add_node(draw_indexed_indirect);
}
@@ -131,12 +132,13 @@ void VKBatch::multi_draw_indirect(const VkBuffer indirect_buffer,
draw.node_data.offset = offset;
draw.node_data.draw_count = count;
draw.node_data.stride = stride;
context.active_framebuffer_get()->vk_viewports_append(draw.node_data.viewport_data.viewports);
context.active_framebuffer_get()->vk_viewports_append(
draw.node_data.graphics.viewport.viewports);
context.active_framebuffer_get()->vk_render_areas_append(
draw.node_data.viewport_data.scissors);
draw.node_data.graphics.viewport.scissors);
vao.bind(draw.node_data.vertex_buffers);
context.update_pipeline_data(prim_type, vao, draw.node_data.pipeline_data);
context.update_pipeline_data(prim_type, vao, draw.node_data.graphics);
context.render_graph().add_node(draw);
}

View File

@@ -285,7 +285,7 @@ void VKContext::rendering_end()
void VKContext::update_pipeline_data(GPUPrimType primitive,
VKVertexAttributeObject &vao,
render_graph::VKPipelineData &r_pipeline_data)
render_graph::VKPipelineDataGraphics &r_pipeline_data)
{
VKShader &vk_shader = unwrap(*shader);
VKFrameBuffer &framebuffer = *active_framebuffer_get();
@@ -296,10 +296,28 @@ void VKContext::update_pipeline_data(GPUPrimType primitive,
GPU_shader_uniform_1f(shader, "size", -point_size);
}
/* Dynamic state line width */
const bool is_line_primitive = ELEM(primitive,
GPU_PRIM_LINES,
GPU_PRIM_LINE_LOOP,
GPU_PRIM_LINE_STRIP,
GPU_PRIM_LINES_ADJ,
GPU_PRIM_LINE_STRIP_ADJ);
if (is_line_primitive) {
const bool supports_wide_lines = VKBackend::get().device.extensions_get().wide_lines;
r_pipeline_data.line_width = supports_wide_lines ?
state_manager_get().mutable_state.line_width :
1.0f;
}
else {
r_pipeline_data.line_width.reset();
}
update_pipeline_data(vk_shader,
vk_shader.ensure_and_get_graphics_pipeline(
primitive, vao, state_manager_get(), framebuffer, constants_state_),
r_pipeline_data);
r_pipeline_data.pipeline_data);
}
void VKContext::update_pipeline_data(render_graph::VKPipelineData &r_pipeline_data)

View File

@@ -135,7 +135,7 @@ class VKContext : public Context, NonCopyable {
void update_pipeline_data(render_graph::VKPipelineData &r_pipeline_data);
void update_pipeline_data(GPUPrimType primitive,
VKVertexAttributeObject &vao,
render_graph::VKPipelineData &r_pipeline_data);
render_graph::VKPipelineDataGraphics &r_pipeline_data);
void sync_backbuffer();

View File

@@ -38,6 +38,7 @@ void VKExtensions::log() const
" - [%c] shader output viewport index\n"
" - [%c] shader output layer\n"
" - [%c] fragment shader barycentric\n"
" - [%c] wide lines\n"
"Device extensions\n"
" - [%c] descriptor buffer\n"
" - [%c] dynamic rendering local read\n"
@@ -50,6 +51,7 @@ void VKExtensions::log() const
shader_output_viewport_index ? 'X' : ' ',
shader_output_layer ? 'X' : ' ',
fragment_shader_barycentric ? 'X' : ' ',
wide_lines ? 'X' : ' ',
descriptor_buffer ? 'X' : ' ',
dynamic_rendering_local_read ? 'X' : ' ',
dynamic_rendering_unused_attachments ? 'X' : ' ',

View File

@@ -41,6 +41,12 @@ struct VKExtensions {
*/
bool fragment_shader_barycentric = false;
/**
* Does the device support wide line rendering
* VkPhysicalDeviceFeatures::wideLines
*/
bool wide_lines = false;
/**
* Does the device support VK_KHR_dynamic_rendering_local_read enabled.
*/

View File

@@ -90,12 +90,13 @@ void VKImmediate::end()
draw.node_data.first_vertex = 0;
draw.node_data.first_instance = 0;
context.active_framebuffer_get()->vk_viewports_append(draw.node_data.viewport_data.viewports);
context.active_framebuffer_get()->vk_viewports_append(
draw.node_data.graphics.viewport.viewports);
context.active_framebuffer_get()->vk_render_areas_append(
draw.node_data.viewport_data.scissors);
draw.node_data.graphics.viewport.scissors);
vertex_attributes_.bind(draw.node_data.vertex_buffers);
context.update_pipeline_data(prim_type, vertex_attributes_, draw.node_data.pipeline_data);
context.update_pipeline_data(prim_type, vertex_attributes_, draw.node_data.graphics);
context.render_graph().add_node(draw);
}

View File

@@ -101,7 +101,8 @@ VKPipelinePool::VKPipelinePool()
vk_pipeline_rasterization_provoking_vertex_state_info_.provokingVertexMode =
VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT;
vk_dynamic_states_ = {VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR};
vk_dynamic_states_ = {
VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR, VK_DYNAMIC_STATE_LINE_WIDTH};
vk_pipeline_dynamic_state_create_info_ = {};
vk_pipeline_dynamic_state_create_info_.sType =
VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
@@ -300,7 +301,13 @@ VkPipeline VKPipelinePool::get_or_create_graphics_pipeline(VKGraphicsInfo &graph
VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT;
/* Dynamic state */
vk_pipeline_dynamic_state_create_info_.dynamicStateCount = vk_dynamic_states_.size();
const bool is_line_topology = ELEM(graphics_info.vertex_in.vk_topology,
VK_PRIMITIVE_TOPOLOGY_LINE_LIST,
VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY,
VK_PRIMITIVE_TOPOLOGY_LINE_STRIP);
vk_pipeline_dynamic_state_create_info_.dynamicStateCount = is_line_topology ?
vk_dynamic_states_.size() :
vk_dynamic_states_.size() - 1;
vk_pipeline_dynamic_state_create_info_.pDynamicStates = vk_dynamic_states_.data();
/* Viewport state */
@@ -583,7 +590,7 @@ VkPipeline VKPipelinePool::get_or_create_graphics_pipeline(VKGraphicsInfo &graph
VKBackend &backend = VKBackend::get();
VKDevice &device = backend.device;
if (device.extensions_get().descriptor_buffer) {
vk_graphics_pipeline_create_info_.flags = VK_PIPELINE_CREATE_DESCRIPTOR_BUFFER_BIT_EXT;
vk_graphics_pipeline_create_info_.flags |= VK_PIPELINE_CREATE_DESCRIPTOR_BUFFER_BIT_EXT;
}
VkPipeline pipeline = VK_NULL_HANDLE;