GPU: Move Polyline shader to primitive expansion
This port is not so straightforward. This shader is used in different configurations and is available to python bindings. So we need to keep compatibility with different attributes configurations. This is why attributes are loaded per component and a uniform sets the length of the component. Since this shader can be used from both the imm and batch API, we need to inject some workarounds to bind the buffers correctly. The end result is still less versatile than the previous metal workaround (i.e.: more attribute fetch mode supported), but it is also way less code. ### Limitations: The new shader has some limitation: - Both `color` and `pos` attributes need to be `F32`. - Each attribute needs to be 4byte aligned. - Fetch type needs to be `GPU_FETCH_FLOAT`. - Primitive type needs to be `GPU_PRIM_LINES`, `GPU_PRIM_LINE_STRIP` or `GPU_PRIM_LINE_LOOP`. - If drawing using an index buffer, it must contain no primitive restart. Rel #127493 Co-authored-by: Jeroen Bakker <jeroen@blender.org> Pull Request: https://projects.blender.org/blender/blender/pulls/129315
This commit is contained in:
committed by
Clément Foucault
parent
611940805e
commit
00a8d006fe
@@ -179,10 +179,12 @@ void Draw::execute(RecordingState &state) const
|
||||
|
||||
if (is_primitive_expansion()) {
|
||||
/* Expanded drawcall. */
|
||||
IndexRange vert_range = GPU_batch_draw_expanded_parameter_get(
|
||||
batch, GPUPrimType(expand_prim_type), vertex_len, vertex_first);
|
||||
IndexRange expanded_range = {vert_range.start() * expand_prim_len,
|
||||
vert_range.size() * expand_prim_len};
|
||||
IndexRange expanded_range = GPU_batch_draw_expanded_parameter_get(
|
||||
batch->prim_type,
|
||||
GPUPrimType(expand_prim_type),
|
||||
vertex_len,
|
||||
vertex_first,
|
||||
expand_prim_len);
|
||||
|
||||
if (expanded_range.is_empty()) {
|
||||
/* Nothing to draw, and can lead to asserts in GPU_batch_bind_as_resources. */
|
||||
@@ -803,13 +805,14 @@ void DrawMultiBuf::generate_commands(Vector<Header, 0> & /*headers*/,
|
||||
if (group.desc.expand_prim_type != GPU_PRIM_NONE) {
|
||||
/* Expanded drawcall. */
|
||||
IndexRange vert_range = GPU_batch_draw_expanded_parameter_get(
|
||||
group.desc.gpu_batch,
|
||||
group.desc.gpu_batch->prim_type,
|
||||
GPUPrimType(group.desc.expand_prim_type),
|
||||
group.vertex_len,
|
||||
group.vertex_first);
|
||||
group.vertex_first,
|
||||
group.desc.expand_prim_len);
|
||||
|
||||
group.vertex_first = vert_range.start() * group.desc.expand_prim_len;
|
||||
group.vertex_len = vert_range.size() * group.desc.expand_prim_len;
|
||||
group.vertex_first = vert_range.start();
|
||||
group.vertex_len = vert_range.size();
|
||||
/* Override base index to -1 as the generated drawcall will not use an index buffer and do
|
||||
* the indirection manually inside the shader. */
|
||||
group.base_index = -1;
|
||||
|
||||
@@ -504,9 +504,7 @@ set(GLSL_SRC
|
||||
shaders/gpu_shader_3D_flat_color_vert.glsl
|
||||
shaders/gpu_shader_3D_line_dashed_uniform_color_vert.glsl
|
||||
shaders/gpu_shader_3D_polyline_frag.glsl
|
||||
shaders/gpu_shader_3D_polyline_geom.glsl
|
||||
shaders/gpu_shader_3D_polyline_vert.glsl
|
||||
shaders/gpu_shader_3D_polyline_vert_no_geom.glsl
|
||||
shaders/gpu_shader_3D_smooth_color_vert.glsl
|
||||
shaders/gpu_shader_3D_smooth_color_frag.glsl
|
||||
shaders/gpu_shader_3D_clipped_uniform_color_vert.glsl
|
||||
|
||||
@@ -425,10 +425,11 @@ void GPU_batch_draw_parameter_get(blender::gpu::Batch *batch,
|
||||
/**
|
||||
* Return vertex range for this #blender::gpu::Batch when using primitive expansions.
|
||||
*/
|
||||
blender::IndexRange GPU_batch_draw_expanded_parameter_get(const blender::gpu::Batch *batch,
|
||||
GPUPrimType expanded_prim_type,
|
||||
blender::IndexRange GPU_batch_draw_expanded_parameter_get(GPUPrimType input_prim_type,
|
||||
GPUPrimType output_prim_type,
|
||||
int vertex_count,
|
||||
int vertex_first);
|
||||
int vertex_first,
|
||||
int output_primitive_cout);
|
||||
|
||||
/** \} */
|
||||
|
||||
|
||||
@@ -134,6 +134,14 @@ inline int indices_per_primitive(GPUPrimType prim_type)
|
||||
return 4;
|
||||
case GPU_PRIM_TRIS_ADJ:
|
||||
return 6;
|
||||
/** IMPORTANT: These last two expects no restart primitive.
|
||||
* Asserting for this would be too slow. Just don't be stupid.
|
||||
* This is needed for polylines but should be deprecated.
|
||||
* See GPU_batch_draw_expanded_parameter_get */
|
||||
case GPU_PRIM_LINE_STRIP:
|
||||
return 1; /* Minus one for the whole length. */
|
||||
case GPU_PRIM_LINE_LOOP:
|
||||
return 1;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -191,6 +191,7 @@ void GPU_shader_uniform_2fv(GPUShader *sh, const char *name, const float data[2]
|
||||
void GPU_shader_uniform_3fv(GPUShader *sh, const char *name, const float data[3]);
|
||||
void GPU_shader_uniform_4fv(GPUShader *sh, const char *name, const float data[4]);
|
||||
void GPU_shader_uniform_2iv(GPUShader *sh, const char *name, const int data[2]);
|
||||
void GPU_shader_uniform_3iv(GPUShader *sh, const char *name, const int data[3]);
|
||||
void GPU_shader_uniform_mat4(GPUShader *sh, const char *name, const float data[4][4]);
|
||||
void GPU_shader_uniform_mat3_as_mat4(GPUShader *sh, const char *name, const float data[3][3]);
|
||||
void GPU_shader_uniform_1f_array(GPUShader *sh, const char *name, int len, const float *val);
|
||||
|
||||
@@ -350,44 +350,83 @@ void GPU_batch_draw_parameter_get(Batch *gpu_batch,
|
||||
*r_instance_count = i_count;
|
||||
}
|
||||
|
||||
blender::IndexRange GPU_batch_draw_expanded_parameter_get(const blender::gpu::Batch *batch,
|
||||
GPUPrimType expanded_prim_type,
|
||||
blender::IndexRange GPU_batch_draw_expanded_parameter_get(GPUPrimType input_prim_type,
|
||||
GPUPrimType output_prim_type,
|
||||
int vertex_count,
|
||||
int vertex_first)
|
||||
int vertex_first,
|
||||
int output_primitive_cout)
|
||||
{
|
||||
int vert_per_original_primitive = indices_per_primitive(batch->prim_type);
|
||||
int vert_per_expanded_primitive = indices_per_primitive(expanded_prim_type);
|
||||
|
||||
BLI_assert_msg(vert_per_original_primitive != -1,
|
||||
"Primitive expansion only works for primitives with known amount of vertices");
|
||||
int vert_per_original_primitive = indices_per_primitive(input_prim_type);
|
||||
int vert_per_expanded_primitive = indices_per_primitive(output_prim_type);
|
||||
|
||||
int prim_first = vertex_first / vert_per_original_primitive;
|
||||
int prim_len = vertex_count / vert_per_original_primitive;
|
||||
|
||||
int out_vertex_first = prim_first * vert_per_expanded_primitive;
|
||||
int out_vertex_count = prim_len * vert_per_expanded_primitive;
|
||||
BLI_assert_msg(vert_per_original_primitive != -1,
|
||||
"Primitive expansion only works for primitives with known amount of vertices");
|
||||
|
||||
/* WORKAROUND: Needed for polyline_draw_workaround. */
|
||||
if (input_prim_type == GPU_PRIM_LINE_STRIP) {
|
||||
prim_len = vertex_count - 1;
|
||||
}
|
||||
|
||||
int out_vertex_first = prim_first * vert_per_expanded_primitive * output_primitive_cout;
|
||||
int out_vertex_count = prim_len * vert_per_expanded_primitive * output_primitive_cout;
|
||||
|
||||
return blender::IndexRange(out_vertex_first, out_vertex_count);
|
||||
}
|
||||
|
||||
static void polyline_draw_workaround(
|
||||
Batch *batch, int vertex_first, int vertex_count, int instance_first, int instance_count)
|
||||
{
|
||||
/* Check compatible input primitive. */
|
||||
BLI_assert(ELEM(batch->prim_type, GPU_PRIM_LINES, GPU_PRIM_LINE_STRIP, GPU_PRIM_LINE_LOOP));
|
||||
|
||||
GPU_batch_bind_as_resources(batch, batch->shader);
|
||||
blender::IndexRange range = GPU_batch_draw_expanded_parameter_get(
|
||||
batch->prim_type, GPU_PRIM_TRIS, vertex_count, vertex_first, 2);
|
||||
Batch *tri_batch = Context::get()->polyline_batch_get();
|
||||
GPU_batch_set_shader(tri_batch, batch->shader);
|
||||
|
||||
int vert_stride_count[3] = {(batch->prim_type == GPU_PRIM_LINES) ? 2 : 1, int(vertex_count), 0};
|
||||
GPU_shader_uniform_3iv(batch->shader, "gpu_vert_stride_count_offset", vert_stride_count);
|
||||
/* Assume GPU_FETCH_FLOAT for now. A bit cumbersome to assert for this or to find the correct
|
||||
* attribute. */
|
||||
GPU_shader_uniform_1b(batch->shader, "gpu_attr_0_fetch_int", false);
|
||||
|
||||
GPU_batch_draw_advanced(tri_batch, range.start(), range.size(), instance_first, instance_count);
|
||||
}
|
||||
|
||||
void GPU_batch_draw(Batch *batch)
|
||||
{
|
||||
BLI_assert(batch != nullptr);
|
||||
GPU_shader_bind(batch->shader);
|
||||
GPU_batch_draw_advanced(batch, 0, 0, 0, 0);
|
||||
if (unwrap(batch->shader)->is_polyline) {
|
||||
polyline_draw_workaround(batch, 0, batch->vertex_count_get(), 0, 0);
|
||||
}
|
||||
else {
|
||||
GPU_batch_draw_advanced(batch, 0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void GPU_batch_draw_range(Batch *batch, int vertex_first, int vertex_count)
|
||||
{
|
||||
BLI_assert(batch != nullptr);
|
||||
GPU_shader_bind(batch->shader);
|
||||
GPU_batch_draw_advanced(batch, vertex_first, vertex_count, 0, 0);
|
||||
if (unwrap(batch->shader)->is_polyline) {
|
||||
polyline_draw_workaround(batch, vertex_first, vertex_count, 0, 0);
|
||||
}
|
||||
else {
|
||||
GPU_batch_draw_advanced(batch, vertex_first, vertex_count, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void GPU_batch_draw_instance_range(Batch *batch, int instance_first, int instance_count)
|
||||
{
|
||||
BLI_assert(batch != nullptr);
|
||||
BLI_assert(batch->inst[0] == nullptr);
|
||||
/* Not polyline shaders support instancing. */
|
||||
BLI_assert(unwrap(batch->shader)->is_polyline == false);
|
||||
|
||||
GPU_shader_bind(batch->shader);
|
||||
GPU_batch_draw_advanced(batch, 0, 0, instance_first, instance_count);
|
||||
|
||||
@@ -76,6 +76,7 @@ Context::Context()
|
||||
Context::~Context()
|
||||
{
|
||||
GPU_matrix_state_discard(matrix_state);
|
||||
GPU_BATCH_DISCARD_SAFE(polyline_batch);
|
||||
delete state_manager;
|
||||
delete front_left;
|
||||
delete back_left;
|
||||
@@ -94,6 +95,22 @@ Context *Context::get()
|
||||
return active_ctx;
|
||||
}
|
||||
|
||||
Batch *Context::polyline_batch_get()
|
||||
{
|
||||
if (polyline_batch) {
|
||||
return polyline_batch;
|
||||
}
|
||||
|
||||
/* TODO(fclem): get rid of this dummy VBO. */
|
||||
GPUVertFormat format = {0};
|
||||
GPU_vertformat_attr_add(&format, "dummy", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
|
||||
blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
|
||||
GPU_vertbuf_data_alloc(*vbo, 1);
|
||||
|
||||
polyline_batch = GPU_batch_create_ex(GPU_PRIM_TRIS, vbo, nullptr, GPU_BATCH_OWNS_VBO);
|
||||
return polyline_batch;
|
||||
}
|
||||
|
||||
} // namespace blender::gpu
|
||||
|
||||
/** \} */
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "GPU_batch.hh"
|
||||
#include "GPU_context.hh"
|
||||
|
||||
#include "gpu_debug_private.hh"
|
||||
@@ -63,6 +64,9 @@ class Context {
|
||||
/* Used as a stack. Each render_begin/end pair will push pop from the stack. */
|
||||
Vector<GPUStorageBuf *> printf_buf;
|
||||
|
||||
/** Dummy triangle batch for polyline workaround. */
|
||||
Batch *polyline_batch = nullptr;
|
||||
|
||||
protected:
|
||||
/** Thread on which this context is active. */
|
||||
pthread_t thread_;
|
||||
@@ -104,6 +108,8 @@ class Context {
|
||||
virtual void debug_unbind_all_ssbo() = 0;
|
||||
|
||||
bool is_active_on_thread();
|
||||
|
||||
Batch *polyline_batch_get();
|
||||
};
|
||||
|
||||
/* Syntactic sugar. */
|
||||
|
||||
@@ -277,6 +277,71 @@ void immEnd()
|
||||
wide_line_workaround_end();
|
||||
}
|
||||
|
||||
void Immediate::polyline_draw_workaround(uint64_t offset)
|
||||
{
|
||||
/* Check compatible input primitive. */
|
||||
BLI_assert(ELEM(imm->prim_type, GPU_PRIM_LINES, GPU_PRIM_LINE_STRIP, GPU_PRIM_LINE_LOOP));
|
||||
|
||||
Batch *tri_batch = Context::get()->polyline_batch_get();
|
||||
GPU_batch_set_shader(tri_batch, imm->shader);
|
||||
|
||||
BLI_assert(offset % 4 == 0);
|
||||
|
||||
/* Setup primitive and index buffer. */
|
||||
int stride = (imm->prim_type == GPU_PRIM_LINES) ? 2 : 1;
|
||||
int data[3] = {stride, int(imm->vertex_idx), int(offset / 4)};
|
||||
GPU_shader_uniform_3iv(imm->shader, "gpu_vert_stride_count_offset", data);
|
||||
GPU_shader_uniform_1b(imm->shader, "gpu_index_no_buffer", true);
|
||||
|
||||
{
|
||||
/* Setup attributes metadata uniforms. */
|
||||
const GPUVertFormat &format = imm->vertex_format;
|
||||
/* Only support 4byte aligned formats. */
|
||||
BLI_assert((format.stride % 4) == 0);
|
||||
BLI_assert(format.attr_len > 0);
|
||||
|
||||
int pos_attr_id = -1;
|
||||
int col_attr_id = -1;
|
||||
|
||||
for (uint a_idx = 0; a_idx < format.attr_len; a_idx++) {
|
||||
const GPUVertAttr *a = &format.attrs[a_idx];
|
||||
const char *name = GPU_vertformat_attr_name_get(&format, a, 0);
|
||||
if (pos_attr_id == -1 && blender::StringRefNull(name) == "pos") {
|
||||
int descriptor[2] = {int(format.stride) / 4, int(a->offset) / 4};
|
||||
BLI_assert(ELEM(a->comp_type, GPU_COMP_F32, GPU_COMP_I32));
|
||||
BLI_assert(ELEM(a->fetch_mode, GPU_FETCH_FLOAT, GPU_FETCH_INT_TO_FLOAT));
|
||||
BLI_assert_msg((a->offset % 4) == 0, "Only support 4byte aligned attributes");
|
||||
const bool fetch_int = a->fetch_mode == GPU_FETCH_INT_TO_FLOAT;
|
||||
GPU_shader_uniform_2iv(imm->shader, "gpu_attr_0", descriptor);
|
||||
GPU_shader_uniform_1i(imm->shader, "gpu_attr_0_len", a->comp_len);
|
||||
GPU_shader_uniform_1b(imm->shader, "gpu_attr_0_fetch_int", fetch_int);
|
||||
pos_attr_id = a_idx;
|
||||
}
|
||||
else if (col_attr_id == -1 && blender::StringRefNull(name) == "color") {
|
||||
int descriptor[2] = {int(format.stride) / 4, int(a->offset) / 4};
|
||||
/* Maybe we can relax this if needed. */
|
||||
BLI_assert_msg(a->comp_type == GPU_COMP_F32, "Only support float attributes");
|
||||
BLI_assert_msg((a->offset % 4) == 0, "Only support 4byte aligned attributes");
|
||||
GPU_shader_uniform_2iv(imm->shader, "gpu_attr_1", descriptor);
|
||||
GPU_shader_uniform_1i(imm->shader, "gpu_attr_1_len", a->comp_len);
|
||||
col_attr_id = a_idx;
|
||||
}
|
||||
if (pos_attr_id != -1 && col_attr_id != -1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
BLI_assert(pos_attr_id != -1);
|
||||
/* Could check for color attribute but we need to know which variant of the polyline shader is
|
||||
* the one we are rendering with. */
|
||||
// BLI_assert(pos_attr_id != -1);
|
||||
}
|
||||
|
||||
blender::IndexRange range = GPU_batch_draw_expanded_parameter_get(
|
||||
imm->prim_type, GPU_PRIM_TRIS, imm->vertex_idx, 0, 2);
|
||||
GPU_batch_draw_advanced(tri_batch, range.start(), range.size(), 0, 0);
|
||||
}
|
||||
|
||||
static void setAttrValueBit(uint attr_id)
|
||||
{
|
||||
uint16_t mask = 1 << attr_id;
|
||||
|
||||
@@ -56,6 +56,9 @@ class Immediate {
|
||||
|
||||
virtual uchar *begin() = 0;
|
||||
virtual void end() = 0;
|
||||
|
||||
/* To be called after polyline SSBO binding. */
|
||||
void polyline_draw_workaround(uint64_t offset);
|
||||
};
|
||||
|
||||
} // namespace blender::gpu
|
||||
|
||||
@@ -786,6 +786,12 @@ void GPU_shader_uniform_2iv(GPUShader *sh, const char *name, const int data[2])
|
||||
GPU_shader_uniform_int_ex(sh, loc, 2, 1, data);
|
||||
}
|
||||
|
||||
void GPU_shader_uniform_3iv(GPUShader *sh, const char *name, const int data[3])
|
||||
{
|
||||
const int loc = GPU_shader_get_uniform(sh, name);
|
||||
GPU_shader_uniform_int_ex(sh, loc, 3, 1, data);
|
||||
}
|
||||
|
||||
void GPU_shader_uniform_mat4(GPUShader *sh, const char *name, const float data[4][4])
|
||||
{
|
||||
const int loc = GPU_shader_get_uniform(sh, name);
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
#include "GPU_capabilities.hh"
|
||||
#include "GPU_shader.hh"
|
||||
|
||||
#include "gpu_shader_private.hh"
|
||||
|
||||
/* Cache of built-in shaders (each is created on first use). */
|
||||
static GPUShader *builtin_shaders[GPU_SHADER_CFG_LEN][GPU_SHADER_BUILTIN_LEN] = {{nullptr}};
|
||||
|
||||
@@ -157,6 +159,8 @@ GPUShader *GPU_shader_get_builtin_shader_with_config(eGPUBuiltinShader shader,
|
||||
* Ideally this value should be set by the caller. */
|
||||
GPU_shader_bind(*sh_p);
|
||||
GPU_shader_uniform_1i(*sh_p, "lineSmooth", 1);
|
||||
/* WORKAROUND: See is_polyline declaration. */
|
||||
blender::gpu::unwrap(*sh_p)->is_polyline = true;
|
||||
}
|
||||
}
|
||||
else if (sh_cfg == GPU_SHADER_CFG_CLIPPED) {
|
||||
|
||||
@@ -494,13 +494,6 @@ void gpu_shader_create_info_init()
|
||||
#ifdef WITH_METAL_BACKEND
|
||||
/* Metal-specific alternatives for Geometry shaders. */
|
||||
if (GPU_type_matches_ex(GPU_DEVICE_ANY, GPU_OS_MAC, GPU_DRIVER_ANY, GPU_BACKEND_METAL)) {
|
||||
/* 3D polyline. */
|
||||
gpu_shader_3D_polyline_uniform_color = gpu_shader_3D_polyline_uniform_color_no_geom;
|
||||
gpu_shader_3D_polyline_flat_color = gpu_shader_3D_polyline_flat_color_no_geom;
|
||||
gpu_shader_3D_polyline_smooth_color = gpu_shader_3D_polyline_smooth_color_no_geom;
|
||||
gpu_shader_3D_polyline_uniform_color_clipped =
|
||||
gpu_shader_3D_polyline_uniform_color_clipped_no_geom;
|
||||
|
||||
/* Overlay Edit Mesh. */
|
||||
overlay_edit_mesh_edge = overlay_edit_mesh_edge_no_geom;
|
||||
overlay_edit_mesh_edge_flat = overlay_edit_mesh_edge_flat_no_geom;
|
||||
|
||||
@@ -38,6 +38,9 @@
|
||||
|
||||
/* Used for primitive expansion. */
|
||||
#define GPU_SSBO_INDEX_BUF_SLOT 7
|
||||
/* Used for polylines. */
|
||||
#define GPU_SSBO_POLYLINE_POS_BUF_SLOT 0
|
||||
#define GPU_SSBO_POLYLINE_COL_BUF_SLOT 1
|
||||
|
||||
#if defined(GLSL_CPP_STUBS)
|
||||
# define GPU_SHADER_NAMED_INTERFACE_INFO(_interface, _inst_name) \
|
||||
|
||||
@@ -64,6 +64,10 @@ class Shader {
|
||||
bool is_dirty;
|
||||
} constants;
|
||||
|
||||
/* WORKAROUND: True if this shader is a polyline shader and needs an appropriate setup to render.
|
||||
* Eventually, in the future, we should modify the user code instead of relying on such hacks. */
|
||||
bool is_polyline = false;
|
||||
|
||||
protected:
|
||||
/** For debugging purpose. */
|
||||
char name[64];
|
||||
|
||||
@@ -246,15 +246,15 @@ MTLContext::MTLContext(void *ghost_window, void *ghost_context)
|
||||
MTLBackend::platform_init(this);
|
||||
MTLBackend::capabilities_init(this);
|
||||
|
||||
/* Ensure global memory manager is initialized. */
|
||||
MTLContext::global_memory_manager_acquire_ref();
|
||||
MTLContext::get_global_memory_manager()->init(this->device);
|
||||
|
||||
/* Initialize Metal modules. */
|
||||
this->memory_manager.init();
|
||||
this->state_manager = new MTLStateManager(this);
|
||||
this->imm = new MTLImmediate(this);
|
||||
|
||||
/* Ensure global memory manager is initialized. */
|
||||
MTLContext::global_memory_manager_acquire_ref();
|
||||
MTLContext::get_global_memory_manager()->init(this->device);
|
||||
|
||||
/* Initialize texture read/update structures. */
|
||||
this->get_texture_utils().init();
|
||||
|
||||
|
||||
@@ -268,7 +268,14 @@ void MTLImmediate::end()
|
||||
(const int *)(&this->vertex_idx));
|
||||
}
|
||||
|
||||
if (unwrap(this->shader)->is_polyline) {
|
||||
context_->get_scratchbuffer_manager().bind_as_ssbo(GPU_SSBO_POLYLINE_POS_BUF_SLOT);
|
||||
context_->get_scratchbuffer_manager().bind_as_ssbo(GPU_SSBO_POLYLINE_COL_BUF_SLOT);
|
||||
context_->get_scratchbuffer_manager().bind_as_ssbo(GPU_SSBO_INDEX_BUF_SLOT);
|
||||
}
|
||||
|
||||
MTLPrimitiveType mtl_prim_type = gpu_prim_type_to_metal(this->prim_type);
|
||||
|
||||
if (context_->ensure_render_pipeline_state(mtl_prim_type)) {
|
||||
|
||||
/* Issue draw call. */
|
||||
@@ -364,7 +371,10 @@ void MTLImmediate::end()
|
||||
/* Set depth stencil state (requires knowledge of primitive type). */
|
||||
context_->ensure_depth_stencil_state(primitive_type);
|
||||
|
||||
if (active_mtl_shader->get_uses_ssbo_vertex_fetch()) {
|
||||
if (unwrap(this->shader)->is_polyline) {
|
||||
this->polyline_draw_workaround(current_allocation_.buffer_offset);
|
||||
}
|
||||
else if (active_mtl_shader->get_uses_ssbo_vertex_fetch()) {
|
||||
|
||||
/* Bind Null Buffers for empty/missing bind slots. */
|
||||
id<MTLBuffer> null_buffer = context_->get_null_buffer();
|
||||
@@ -412,6 +422,17 @@ void MTLImmediate::end()
|
||||
if (G.debug & G_DEBUG_GPU) {
|
||||
[rec popDebugGroup];
|
||||
}
|
||||
|
||||
if (unwrap(this->shader)->is_polyline) {
|
||||
context_->get_scratchbuffer_manager().unbind_as_ssbo();
|
||||
|
||||
context_->pipeline_state.ssbo_bindings[GPU_SSBO_POLYLINE_POS_BUF_SLOT].ssbo = nil;
|
||||
context_->pipeline_state.ssbo_bindings[GPU_SSBO_POLYLINE_COL_BUF_SLOT].ssbo = nil;
|
||||
context_->pipeline_state.ssbo_bindings[GPU_SSBO_INDEX_BUF_SLOT].ssbo = nil;
|
||||
context_->pipeline_state.ssbo_bindings[GPU_SSBO_POLYLINE_POS_BUF_SLOT].bound = false;
|
||||
context_->pipeline_state.ssbo_bindings[GPU_SSBO_POLYLINE_COL_BUF_SLOT].bound = false;
|
||||
context_->pipeline_state.ssbo_bindings[GPU_SSBO_INDEX_BUF_SLOT].bound = false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset allocation after draw submission. */
|
||||
|
||||
@@ -99,6 +99,7 @@ namespace blender::gpu {
|
||||
class MTLContext;
|
||||
class MTLCommandBufferManager;
|
||||
class MTLUniformBuf;
|
||||
class MTLStorageBuf;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Memory Management.
|
||||
@@ -211,6 +212,8 @@ class MTLCircularBuffer {
|
||||
|
||||
/* Wrapped MTLBuffer allocation handled. */
|
||||
gpu::MTLBuffer *cbuffer_;
|
||||
/* Allocated SSBO that serves as source for cbuffer. */
|
||||
MTLStorageBuf *ssbo_source_ = nullptr;
|
||||
|
||||
/* Current offset where next allocation will begin. */
|
||||
uint64_t current_offset_;
|
||||
@@ -513,6 +516,10 @@ class MTLScratchBufferManager {
|
||||
* the last offset the data was flushed from, to the current offset. */
|
||||
void flush_active_scratch_buffer();
|
||||
|
||||
/* Bind the whole scratch buffer as a SSBO resource. */
|
||||
void bind_as_ssbo(int slot);
|
||||
void unbind_as_ssbo();
|
||||
|
||||
MEM_CXX_CLASS_ALLOC_FUNCS("MTLBufferPool");
|
||||
};
|
||||
|
||||
|
||||
@@ -6,9 +6,12 @@
|
||||
|
||||
#include "DNA_userdef_types.h"
|
||||
|
||||
#include "BLI_math_base.h"
|
||||
|
||||
#include "mtl_context.hh"
|
||||
#include "mtl_debug.hh"
|
||||
#include "mtl_memory.hh"
|
||||
#include "mtl_storage_buffer.hh"
|
||||
|
||||
using namespace blender;
|
||||
using namespace blender::gpu;
|
||||
@@ -646,7 +649,6 @@ bool MTLSafeFreeList::should_flush()
|
||||
/** \name MTLBuffer wrapper class implementation.
|
||||
* \{ */
|
||||
|
||||
/* Construct a gpu::MTLBuffer wrapper around a newly created metal::MTLBuffer. */
|
||||
MTLBuffer::MTLBuffer(id<MTLDevice> mtl_device,
|
||||
uint64_t size,
|
||||
MTLResourceOptions options,
|
||||
@@ -916,15 +918,29 @@ void MTLScratchBufferManager::flush_active_scratch_buffer()
|
||||
active_scratch_buf->flush();
|
||||
}
|
||||
|
||||
void MTLScratchBufferManager::bind_as_ssbo(int slot)
|
||||
{
|
||||
/* Fetch active scratch buffer and verify context. */
|
||||
MTLCircularBuffer *active_scratch_buf = scratch_buffers_[current_scratch_buffer_];
|
||||
BLI_assert(&active_scratch_buf->own_context_ == &context_);
|
||||
active_scratch_buf->ssbo_source_->bind(slot);
|
||||
}
|
||||
|
||||
void MTLScratchBufferManager::unbind_as_ssbo()
|
||||
{
|
||||
/* Fetch active scratch buffer and verify context. */
|
||||
MTLCircularBuffer *active_scratch_buf = scratch_buffers_[current_scratch_buffer_];
|
||||
BLI_assert(&active_scratch_buf->own_context_ == &context_);
|
||||
active_scratch_buf->ssbo_source_->unbind();
|
||||
}
|
||||
|
||||
/* MTLCircularBuffer implementation. */
|
||||
MTLCircularBuffer::MTLCircularBuffer(MTLContext &ctx, uint64_t initial_size, bool allow_grow)
|
||||
: own_context_(ctx)
|
||||
{
|
||||
BLI_assert(this);
|
||||
MTLResourceOptions options = ([own_context_.device hasUnifiedMemory]) ?
|
||||
MTLResourceStorageModeShared :
|
||||
MTLResourceStorageModeManaged;
|
||||
cbuffer_ = new gpu::MTLBuffer(own_context_.device, initial_size, options, 256);
|
||||
ssbo_source_ = new gpu::MTLStorageBuf(initial_size);
|
||||
cbuffer_ = ssbo_source_->metal_buffer_;
|
||||
current_offset_ = 0;
|
||||
can_resize_ = allow_grow;
|
||||
cbuffer_->flag_in_use(true);
|
||||
@@ -940,7 +956,7 @@ MTLCircularBuffer::MTLCircularBuffer(MTLContext &ctx, uint64_t initial_size, boo
|
||||
|
||||
MTLCircularBuffer::~MTLCircularBuffer()
|
||||
{
|
||||
delete cbuffer_;
|
||||
delete ssbo_source_;
|
||||
}
|
||||
|
||||
MTLTemporaryBuffer MTLCircularBuffer::allocate_range(uint64_t alloc_size)
|
||||
@@ -1033,10 +1049,9 @@ MTLTemporaryBuffer MTLCircularBuffer::allocate_range_aligned(uint64_t alloc_size
|
||||
|
||||
/* Discard old buffer and create a new one - Relying on Metal reference counting to track
|
||||
* in-use buffers */
|
||||
MTLResourceOptions prev_options = cbuffer_->get_resource_options();
|
||||
uint prev_alignment = cbuffer_->get_alignment();
|
||||
delete cbuffer_;
|
||||
cbuffer_ = new gpu::MTLBuffer(own_context_.device, new_size, prev_options, prev_alignment);
|
||||
delete ssbo_source_;
|
||||
ssbo_source_ = new gpu::MTLStorageBuf(new_size);
|
||||
cbuffer_ = ssbo_source_->metal_buffer_;
|
||||
cbuffer_->flag_in_use(true);
|
||||
current_offset_ = 0;
|
||||
last_flush_base_offset_ = 0;
|
||||
|
||||
@@ -18,11 +18,14 @@ namespace blender::gpu {
|
||||
class MTLUniformBuf;
|
||||
class MTLVertBuf;
|
||||
class MTLIndexBuf;
|
||||
class MTLCircularBuffer;
|
||||
|
||||
/**
|
||||
* Implementation of Storage Buffers using Metal.
|
||||
*/
|
||||
class MTLStorageBuf : public StorageBuf {
|
||||
friend MTLCircularBuffer;
|
||||
|
||||
private:
|
||||
/** Allocation Handle or indirect wrapped instance.
|
||||
* MTLStorageBuf can wrap a MTLVertBuf, MTLIndexBuf or MTLUniformBuf for binding as a writeable
|
||||
@@ -68,6 +71,9 @@ class MTLStorageBuf : public StorageBuf {
|
||||
MTLStorageBuf(MTLIndexBuf *index_buf, size_t size);
|
||||
MTLStorageBuf(MTLTexture *texture, size_t size);
|
||||
|
||||
/* Only used internally to create a bindable buffer for #Immediate. */
|
||||
MTLStorageBuf(size_t size);
|
||||
|
||||
void update(const void *data) override;
|
||||
void bind(int slot) override;
|
||||
void unbind() override;
|
||||
|
||||
@@ -17,9 +17,11 @@
|
||||
#include "mtl_context.hh"
|
||||
#include "mtl_debug.hh"
|
||||
#include "mtl_index_buffer.hh"
|
||||
#include "mtl_memory.hh"
|
||||
#include "mtl_storage_buffer.hh"
|
||||
#include "mtl_uniform_buffer.hh"
|
||||
#include "mtl_vertex_buffer.hh"
|
||||
#include <cstdio>
|
||||
|
||||
namespace blender::gpu {
|
||||
|
||||
@@ -27,6 +29,13 @@ namespace blender::gpu {
|
||||
/** \name Creation & Deletion
|
||||
* \{ */
|
||||
|
||||
MTLStorageBuf::MTLStorageBuf(size_t size) : StorageBuf(size, "Immediate")
|
||||
{
|
||||
usage_ = GPU_USAGE_STREAM;
|
||||
storage_source_ = MTL_STORAGE_BUF_TYPE_DEFAULT;
|
||||
metal_buffer_ = MTLContext::get_global_memory_manager()->allocate_aligned(size, 256, true);
|
||||
}
|
||||
|
||||
MTLStorageBuf::MTLStorageBuf(size_t size, GPUUsageType usage, const char *name)
|
||||
: StorageBuf(size, name)
|
||||
{
|
||||
|
||||
@@ -69,6 +69,15 @@ uchar *GLImmediate::begin()
|
||||
/* Does the current buffer have enough room? */
|
||||
const size_t available_bytes = buffer_size() - buffer_offset();
|
||||
|
||||
#ifndef NDEBUG
|
||||
if (unwrap(this->shader)->is_polyline) {
|
||||
/* Silence error. These are bound inside `immEnd()`. */
|
||||
GLContext::get()->bound_ssbo_slots |= 1 << GPU_SSBO_POLYLINE_POS_BUF_SLOT;
|
||||
GLContext::get()->bound_ssbo_slots |= 1 << GPU_SSBO_POLYLINE_COL_BUF_SLOT;
|
||||
GLContext::get()->bound_ssbo_slots |= 1 << GPU_SSBO_INDEX_BUF_SLOT;
|
||||
}
|
||||
#endif
|
||||
|
||||
GL_CHECK_RESOURCES("Immediate");
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbo_id());
|
||||
@@ -135,7 +144,26 @@ void GLImmediate::end()
|
||||
}
|
||||
glUnmapBuffer(GL_ARRAY_BUFFER);
|
||||
|
||||
if (vertex_len > 0) {
|
||||
if (vertex_len == 0) {
|
||||
/* Noop. Nothing to draw. */
|
||||
}
|
||||
else if (unwrap(this->shader)->is_polyline) {
|
||||
GLintptr offset = buffer_offset();
|
||||
GLenum target = GL_SHADER_STORAGE_BUFFER;
|
||||
glBindBufferRange(target, GPU_SSBO_POLYLINE_POS_BUF_SLOT, vbo_id(), offset, buffer_bytes_used);
|
||||
glBindBufferRange(target, GPU_SSBO_POLYLINE_COL_BUF_SLOT, vbo_id(), offset, buffer_bytes_used);
|
||||
/* Not used. Satisfy the binding. */
|
||||
glBindBufferRange(target, GPU_SSBO_INDEX_BUF_SLOT, vbo_id(), offset, buffer_bytes_used);
|
||||
|
||||
this->polyline_draw_workaround(0);
|
||||
|
||||
#ifndef NDEBUG
|
||||
GLContext::get()->bound_ssbo_slots &= ~(1 << GPU_SSBO_POLYLINE_POS_BUF_SLOT);
|
||||
GLContext::get()->bound_ssbo_slots &= ~(1 << GPU_SSBO_POLYLINE_COL_BUF_SLOT);
|
||||
GLContext::get()->bound_ssbo_slots &= ~(1 << GPU_SSBO_INDEX_BUF_SLOT);
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
GLContext::get()->state_manager->apply_state();
|
||||
|
||||
/* We convert the offset in vertex offset from the buffer's start.
|
||||
|
||||
@@ -11,14 +11,13 @@ FRAGMENT_SHADER_CREATE_INFO(gpu_shader_3D_polyline_uniform_color)
|
||||
void main()
|
||||
{
|
||||
#ifdef CLIP
|
||||
if (interp.clip < 0.0) {
|
||||
if (clip < 0.0) {
|
||||
discard;
|
||||
}
|
||||
#endif
|
||||
fragColor = interp.final_color;
|
||||
fragColor = final_color;
|
||||
if (lineSmooth) {
|
||||
fragColor.a *= clamp(
|
||||
(lineWidth + SMOOTH_WIDTH) * 0.5 - abs(interp_noperspective.smoothline), 0.0, 1.0);
|
||||
fragColor.a *= clamp((lineWidth + SMOOTH_WIDTH) * 0.5 - abs(smoothline), 0.0, 1.0);
|
||||
}
|
||||
fragColor = blender_srgb_to_framebuffer_space(fragColor);
|
||||
}
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
/* SPDX-FileCopyrightText: 2020-2023 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/* Clips point to near clip plane before perspective divide. */
|
||||
vec4 clip_line_point_homogeneous_space(vec4 p, vec4 q)
|
||||
{
|
||||
if (p.z < -p.w) {
|
||||
/* Just solves p + (q - p) * A; for A when p.z / p.w = -1.0. */
|
||||
float denom = q.z - p.z + q.w - p.w;
|
||||
if (denom == 0.0) {
|
||||
/* No solution. */
|
||||
return p;
|
||||
}
|
||||
float A = (-p.z - p.w) / denom;
|
||||
p = p + (q - p) * A;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
void do_vertex(const int i, vec4 pos, vec2 ofs)
|
||||
{
|
||||
#if defined(UNIFORM)
|
||||
interp_out.final_color = color;
|
||||
|
||||
#elif defined(FLAT)
|
||||
/* WATCH: Assuming last provoking vertex. */
|
||||
interp_out.final_color = interp_in[1].final_color;
|
||||
|
||||
#elif defined(SMOOTH)
|
||||
interp_out.final_color = interp_in[i].final_color;
|
||||
#endif
|
||||
|
||||
#ifdef CLIP
|
||||
interp_out.clip = interp_in[i].clip;
|
||||
#endif
|
||||
|
||||
interp_noperspective_out.smoothline = (lineWidth + SMOOTH_WIDTH * float(lineSmooth)) * 0.5;
|
||||
gl_Position = pos;
|
||||
gl_Position.xy += ofs * pos.w;
|
||||
gpu_EmitVertex();
|
||||
|
||||
interp_noperspective_out.smoothline = -(lineWidth + SMOOTH_WIDTH * float(lineSmooth)) * 0.5;
|
||||
gl_Position = pos;
|
||||
gl_Position.xy -= ofs * pos.w;
|
||||
gpu_EmitVertex();
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 p0 = clip_line_point_homogeneous_space(gl_in[0].gl_Position, gl_in[1].gl_Position);
|
||||
vec4 p1 = clip_line_point_homogeneous_space(gl_in[1].gl_Position, gl_in[0].gl_Position);
|
||||
vec2 e = normalize(((p1.xy / p1.w) - (p0.xy / p0.w)) * viewportSize.xy);
|
||||
|
||||
#if 0 /* Hard turn when line direction changes quadrant. */
|
||||
e = abs(e);
|
||||
vec2 ofs = (e.x > e.y) ? vec2(0.0, 1.0 / e.x) : vec2(1.0 / e.y, 0.0);
|
||||
#else /* Use perpendicular direction. */
|
||||
vec2 ofs = vec2(-e.y, e.x);
|
||||
#endif
|
||||
ofs /= viewportSize.xy;
|
||||
ofs *= lineWidth + SMOOTH_WIDTH * float(lineSmooth);
|
||||
|
||||
do_vertex(0, p0, ofs);
|
||||
do_vertex(1, p1, ofs);
|
||||
|
||||
EndPrimitive();
|
||||
}
|
||||
@@ -2,13 +2,206 @@
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
void main()
|
||||
#include "gpu_shader_attribute_load_lib.glsl"
|
||||
#include "gpu_shader_index_load_lib.glsl"
|
||||
#include "gpu_shader_math_base_lib.glsl"
|
||||
#include "gpu_shader_utildefines_lib.glsl"
|
||||
|
||||
struct VertIn {
|
||||
vec3 ls_P;
|
||||
vec4 final_color;
|
||||
};
|
||||
|
||||
VertIn input_assembly(uint in_vertex_id)
|
||||
{
|
||||
gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
|
||||
uint v_i = gpu_index_load(in_vertex_id);
|
||||
uint ofs = uint(gpu_vert_stride_count_offset.z);
|
||||
|
||||
VertIn vert_in;
|
||||
vert_in.ls_P = vec3(0.0, 0.0, 0.0);
|
||||
/* Need to support 1, 2 and 3 dimensional input (sigh). */
|
||||
vert_in.ls_P.x = pos[gpu_attr_load_index(v_i, gpu_attr_0) + 0 + ofs];
|
||||
if (gpu_attr_0_len >= 2) {
|
||||
vert_in.ls_P.y = pos[gpu_attr_load_index(v_i, gpu_attr_0) + 1 + ofs];
|
||||
}
|
||||
if (gpu_attr_0_len >= 3) {
|
||||
vert_in.ls_P.z = pos[gpu_attr_load_index(v_i, gpu_attr_0) + 2 + ofs];
|
||||
}
|
||||
|
||||
if (gpu_attr_0_fetch_int) {
|
||||
vert_in.ls_P = vec3(floatBitsToInt(vert_in.ls_P));
|
||||
}
|
||||
#ifndef UNIFORM
|
||||
interp.final_color = color;
|
||||
vert_in.final_color = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
/* Need to support 1, 2, 3 and 4 dimensional input (sigh). */
|
||||
vert_in.final_color.x = color[gpu_attr_load_index(v_i, gpu_attr_1) + 0 + ofs];
|
||||
if (gpu_attr_1_len >= 2) {
|
||||
vert_in.final_color.y = color[gpu_attr_load_index(v_i, gpu_attr_1) + 1 + ofs];
|
||||
}
|
||||
if (gpu_attr_1_len >= 3) {
|
||||
vert_in.final_color.z = color[gpu_attr_load_index(v_i, gpu_attr_1) + 2 + ofs];
|
||||
}
|
||||
if (gpu_attr_1_len >= 4) {
|
||||
vert_in.final_color.w = color[gpu_attr_load_index(v_i, gpu_attr_1) + 3 + ofs];
|
||||
}
|
||||
#endif
|
||||
return vert_in;
|
||||
}
|
||||
|
||||
struct VertOut {
|
||||
vec4 gpu_position;
|
||||
vec4 final_color;
|
||||
float clip;
|
||||
};
|
||||
|
||||
VertOut vertex_main(VertIn vert_in)
|
||||
{
|
||||
VertOut vert_out;
|
||||
vert_out.gpu_position = ModelViewProjectionMatrix * vec4(vert_in.ls_P, 1.0);
|
||||
#ifndef UNIFORM
|
||||
vert_out.final_color = vert_in.final_color;
|
||||
#endif
|
||||
#ifdef CLIP
|
||||
interp.clip = dot(ModelMatrix * vec4(pos, 1.0), ClipPlane);
|
||||
vert_out.clip = dot(ModelMatrix * vec4(vert_in.ls_P, 1.0), ClipPlane);
|
||||
#endif
|
||||
return vert_out;
|
||||
}
|
||||
|
||||
/* Clips point to near clip plane before perspective divide. */
|
||||
vec4 clip_line_point_homogeneous_space(vec4 p, vec4 q)
|
||||
{
|
||||
if (p.z < -p.w) {
|
||||
/* Just solves p + (q - p) * A; for A when p.z / p.w = -1.0. */
|
||||
float denom = q.z - p.z + q.w - p.w;
|
||||
if (denom == 0.0) {
|
||||
/* No solution. */
|
||||
return p;
|
||||
}
|
||||
float A = (-p.z - p.w) / denom;
|
||||
p = p + (q - p) * A;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
struct GeomOut {
|
||||
vec4 gpu_position;
|
||||
vec4 final_color;
|
||||
float clip;
|
||||
float smoothline;
|
||||
};
|
||||
|
||||
void export_vertex(GeomOut geom_out)
|
||||
{
|
||||
gl_Position = geom_out.gpu_position;
|
||||
final_color = geom_out.final_color;
|
||||
smoothline = geom_out.smoothline;
|
||||
clip = geom_out.clip;
|
||||
}
|
||||
|
||||
void strip_EmitVertex(const uint strip_index,
|
||||
uint out_vertex_id,
|
||||
uint out_primitive_id,
|
||||
GeomOut geom_out)
|
||||
{
|
||||
bool is_odd_primitive = (out_primitive_id & 1u) != 0u;
|
||||
/* Maps triangle list primitives to triangle strip indices. */
|
||||
uint out_strip_index = (is_odd_primitive ? (2u - out_vertex_id) : out_vertex_id) +
|
||||
out_primitive_id;
|
||||
|
||||
if (out_strip_index == strip_index) {
|
||||
export_vertex(geom_out);
|
||||
}
|
||||
}
|
||||
|
||||
void do_vertex(const uint i,
|
||||
uint out_vertex_id,
|
||||
uint out_primitive_id,
|
||||
VertOut geom_in[2],
|
||||
vec4 position,
|
||||
vec2 ofs)
|
||||
{
|
||||
GeomOut geom_out;
|
||||
#if defined(UNIFORM)
|
||||
geom_out.final_color = color;
|
||||
|
||||
#elif defined(FLAT)
|
||||
/* WATCH: Assuming last provoking vertex. */
|
||||
geom_out.final_color = geom_in[1].final_color;
|
||||
|
||||
#elif defined(SMOOTH)
|
||||
geom_out.final_color = geom_in[i].final_color;
|
||||
#endif
|
||||
|
||||
#ifdef CLIP
|
||||
geom_out.clip = geom_in[i].clip;
|
||||
#endif
|
||||
|
||||
geom_out.smoothline = (lineWidth + SMOOTH_WIDTH * float(lineSmooth)) * 0.5;
|
||||
geom_out.gpu_position = position;
|
||||
geom_out.gpu_position.xy += ofs * position.w;
|
||||
strip_EmitVertex(i * 2u + 0u, out_vertex_id, out_primitive_id, geom_out);
|
||||
|
||||
geom_out.smoothline = -(lineWidth + SMOOTH_WIDTH * float(lineSmooth)) * 0.5;
|
||||
geom_out.gpu_position = position;
|
||||
geom_out.gpu_position.xy -= ofs * position.w;
|
||||
strip_EmitVertex(i * 2u + 1u, out_vertex_id, out_primitive_id, geom_out);
|
||||
}
|
||||
|
||||
void geometry_main(VertOut geom_in[2],
|
||||
uint out_vertex_id,
|
||||
uint out_primitive_id,
|
||||
uint out_invocation_id)
|
||||
{
|
||||
vec4 p0 = clip_line_point_homogeneous_space(geom_in[0].gpu_position, geom_in[1].gpu_position);
|
||||
vec4 p1 = clip_line_point_homogeneous_space(geom_in[1].gpu_position, geom_in[0].gpu_position);
|
||||
vec2 e = normalize(((p1.xy / p1.w) - (p0.xy / p0.w)) * viewportSize.xy);
|
||||
|
||||
#if 0 /* Hard turn when line direction changes quadrant. */
|
||||
e = abs(e);
|
||||
vec2 ofs = (e.x > e.y) ? vec2(0.0, 1.0 / e.x) : vec2(1.0 / e.y, 0.0);
|
||||
#else /* Use perpendicular direction. */
|
||||
vec2 ofs = vec2(-e.y, e.x);
|
||||
#endif
|
||||
ofs /= viewportSize.xy;
|
||||
ofs *= lineWidth + SMOOTH_WIDTH * float(lineSmooth);
|
||||
|
||||
do_vertex(0u, out_vertex_id, out_primitive_id, geom_in, p0, ofs);
|
||||
do_vertex(1u, out_vertex_id, out_primitive_id, geom_in, p1, ofs);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
/* Line list primitive. */
|
||||
uint input_primitive_vertex_count = uint(gpu_vert_stride_count_offset.x);
|
||||
/* Triangle list primitive (emulating triangle strip). */
|
||||
const uint ouput_primitive_vertex_count = 3u;
|
||||
const uint ouput_primitive_count = 2u;
|
||||
const uint ouput_invocation_count = 1u;
|
||||
const uint output_vertex_count_per_invocation = ouput_primitive_count *
|
||||
ouput_primitive_vertex_count;
|
||||
const uint output_vertex_count_per_input_primitive = output_vertex_count_per_invocation *
|
||||
ouput_invocation_count;
|
||||
|
||||
uint in_primitive_id = uint(gl_VertexID) / output_vertex_count_per_input_primitive;
|
||||
uint in_primitive_first_vertex = in_primitive_id * input_primitive_vertex_count;
|
||||
|
||||
uint out_vertex_id = uint(gl_VertexID) % ouput_primitive_vertex_count;
|
||||
uint out_primitive_id = (uint(gl_VertexID) / ouput_primitive_vertex_count) %
|
||||
ouput_primitive_count;
|
||||
uint out_invocation_id = (uint(gl_VertexID) / output_vertex_count_per_invocation) %
|
||||
ouput_invocation_count;
|
||||
/* Used to wrap around for the line loop case. */
|
||||
uint input_total_vertex_count = uint(gpu_vert_stride_count_offset.y);
|
||||
|
||||
VertIn vert_in[2];
|
||||
vert_in[0] = input_assembly(in_primitive_first_vertex + 0u);
|
||||
vert_in[1] = input_assembly((in_primitive_first_vertex + 1u) % input_total_vertex_count);
|
||||
|
||||
VertOut vert_out[2];
|
||||
vert_out[0] = vertex_main(vert_in[0]);
|
||||
vert_out[1] = vertex_main(vert_in[1]);
|
||||
|
||||
/* Discard by default. */
|
||||
gl_Position = vec4(NAN_FLT);
|
||||
geometry_main(vert_out, out_vertex_id, out_primitive_id, out_invocation_id);
|
||||
}
|
||||
|
||||
@@ -1,165 +0,0 @@
|
||||
/* SPDX-FileCopyrightText: 2022-2023 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#pragma USE_SSBO_VERTEX_FETCH(TriangleList, 6)
|
||||
|
||||
/* Local vars to store results per input vertex. */
|
||||
#if !defined(UNIFORM)
|
||||
vec4 finalColor_g[2];
|
||||
#endif
|
||||
|
||||
#ifdef CLIP
|
||||
float clip_g[2];
|
||||
#endif
|
||||
|
||||
#define SMOOTH_WIDTH 1.0
|
||||
|
||||
/* Clips point to near clip plane before perspective divide. */
|
||||
vec4 clip_line_point_homogeneous_space(vec4 p, vec4 q)
|
||||
{
|
||||
if (p.z < -p.w) {
|
||||
/* Just solves p + (q - p) * A; for A when p.z / p.w = -1.0. */
|
||||
float denom = q.z - p.z + q.w - p.w;
|
||||
if (denom == 0.0) {
|
||||
/* No solution. */
|
||||
return p;
|
||||
}
|
||||
float A = (-p.z - p.w) / denom;
|
||||
p = p + (q - p) * A;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
void do_vertex(int index, vec4 pos, vec2 ofs, float flip)
|
||||
{
|
||||
#if defined(UNIFORM)
|
||||
interp.final_color = color;
|
||||
|
||||
#elif defined(FLAT)
|
||||
/* WATCH: Assuming last provoking vertex. */
|
||||
interp.final_color = finalColor_g[index];
|
||||
|
||||
#elif defined(SMOOTH)
|
||||
interp.final_color = finalColor_g[index];
|
||||
#endif
|
||||
|
||||
#ifdef CLIP
|
||||
interp.clip = clip_g[index];
|
||||
#endif
|
||||
|
||||
interp_noperspective.smoothline = flip * (lineWidth + SMOOTH_WIDTH * float(lineSmooth)) * 0.5;
|
||||
gl_Position = pos;
|
||||
gl_Position.xy += flip * ofs * pos.w;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
/** Determine output quad primitive structure. */
|
||||
/* Index of the quad primitive. Each quad corresponds to one line in the input primitive. */
|
||||
int quad_id = gl_VertexID / 6;
|
||||
|
||||
/* Determine vertex within the quad (A, B, C)(A, C, D). */
|
||||
int quad_vertex_id = gl_VertexID % 6;
|
||||
|
||||
uint src_index_a;
|
||||
uint src_index_b;
|
||||
if (vertex_fetch_get_input_prim_type() == GPU_PRIM_LINE_STRIP) {
|
||||
src_index_a = quad_id;
|
||||
src_index_b = quad_id + 1;
|
||||
}
|
||||
else if (vertex_fetch_get_input_prim_type() == GPU_PRIM_LINES) {
|
||||
src_index_a = quad_id * 2;
|
||||
src_index_b = quad_id * 2 + 1;
|
||||
}
|
||||
else if (vertex_fetch_get_input_prim_type() == GPU_PRIM_LINE_LOOP) {
|
||||
src_index_a = quad_id;
|
||||
src_index_b = quad_id + 1;
|
||||
if (quad_id == vertex_fetch_get_input_vert_count() - 1) {
|
||||
src_index_b = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
src_index_a = 0;
|
||||
src_index_b = 0;
|
||||
}
|
||||
|
||||
/* Fetch input attributes for line prims -- either provided as vec2 or vec3 -- So we need to
|
||||
* query the type. */
|
||||
vec3 in_pos0, in_pos1;
|
||||
in_pos0 = vec3(0.0);
|
||||
in_pos1 = vec3(0.0);
|
||||
if (vertex_fetch_get_attr_type(pos) == GPU_SHADER_ATTR_TYPE_VEC4) {
|
||||
in_pos0 = vertex_fetch_attribute(src_index_a, pos, vec4).xyz;
|
||||
in_pos1 = vertex_fetch_attribute(src_index_b, pos, vec4).xyz;
|
||||
}
|
||||
else if (vertex_fetch_get_attr_type(pos) == GPU_SHADER_ATTR_TYPE_VEC3) {
|
||||
in_pos0 = vertex_fetch_attribute(src_index_a, pos, vec3);
|
||||
in_pos1 = vertex_fetch_attribute(src_index_b, pos, vec3);
|
||||
}
|
||||
else if (vertex_fetch_get_attr_type(pos) == GPU_SHADER_ATTR_TYPE_VEC2) {
|
||||
in_pos0 = vec3(vertex_fetch_attribute(src_index_a, pos, vec2), 0.0);
|
||||
in_pos1 = vec3(vertex_fetch_attribute(src_index_b, pos, vec2), 0.0);
|
||||
}
|
||||
#if !defined(UNIFORM)
|
||||
vec4 in_color0 = vec4(0.0);
|
||||
vec4 in_color1 = vec4(0.0);
|
||||
|
||||
if (vertex_fetch_get_attr_type(color) == GPU_SHADER_ATTR_TYPE_VEC4) {
|
||||
in_color0 = vertex_fetch_attribute(src_index_a, color, vec4);
|
||||
in_color1 = vertex_fetch_attribute(src_index_b, color, vec4);
|
||||
}
|
||||
else if (vertex_fetch_get_attr_type(color) == GPU_SHADER_ATTR_TYPE_VEC3) {
|
||||
in_color0 = vec4(vertex_fetch_attribute(src_index_a, color, vec3), 1.0);
|
||||
in_color1 = vec4(vertex_fetch_attribute(src_index_b, color, vec3), 1.0);
|
||||
}
|
||||
else if (vertex_fetch_get_attr_type(color) == GPU_SHADER_ATTR_TYPE_UCHAR4_NORM) {
|
||||
in_color0 = vec4(vertex_fetch_attribute(src_index_a, color, uchar4)) / vec4(255.0);
|
||||
in_color1 = vec4(vertex_fetch_attribute(src_index_b, color, uchar4)) / vec4(255.0);
|
||||
}
|
||||
else if (vertex_fetch_get_attr_type(color) == GPU_SHADER_ATTR_TYPE_UCHAR3_NORM) {
|
||||
in_color0 = vec4(vec3(vertex_fetch_attribute(src_index_a, color, uchar3)) / vec3(255.0), 1.0);
|
||||
in_color1 = vec4(vec3(vertex_fetch_attribute(src_index_b, color, uchar3)) / vec3(255.0), 1.0);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Calculate Vertex shader for both points in Line. */
|
||||
vec4 out_pos0 = ModelViewProjectionMatrix * vec4(in_pos0, 1.0);
|
||||
vec4 out_pos1 = ModelViewProjectionMatrix * vec4(in_pos1, 1.0);
|
||||
#if !defined(UNIFORM)
|
||||
finalColor_g[0] = in_color0;
|
||||
finalColor_g[1] = in_color1;
|
||||
#endif
|
||||
#ifdef CLIP
|
||||
clip_g[0] = dot(ModelMatrix * vec4(in_pos0, 1.0), ClipPlane);
|
||||
clip_g[1] = dot(ModelMatrix * vec4(in_pos1, 1.0), ClipPlane);
|
||||
#endif
|
||||
|
||||
/** Geometry Shader Alternative. */
|
||||
vec4 p0 = clip_line_point_homogeneous_space(out_pos0, out_pos1);
|
||||
vec4 p1 = clip_line_point_homogeneous_space(out_pos1, out_pos0);
|
||||
vec2 e = normalize(((p1.xy / p1.w) - (p0.xy / p0.w)) * viewportSize.xy);
|
||||
|
||||
#if 0 /* Hard turn when line direction changes quadrant. */
|
||||
e = abs(e);
|
||||
vec2 ofs = (e.x > e.y) ? vec2(0.0, 1.0 / e.x) : vec2(1.0 / e.y, 0.0);
|
||||
#else /* Use perpendicular direction. */
|
||||
vec2 ofs = vec2(-e.y, e.x);
|
||||
#endif
|
||||
|
||||
ofs /= viewportSize.xy;
|
||||
ofs *= lineWidth + SMOOTH_WIDTH * float(lineSmooth);
|
||||
|
||||
if (quad_vertex_id == 0) {
|
||||
do_vertex(0, p0, ofs, 1.0);
|
||||
}
|
||||
else if (quad_vertex_id == 1 || quad_vertex_id == 3) {
|
||||
do_vertex(0, p0, ofs, -1.0);
|
||||
}
|
||||
else if (quad_vertex_id == 2 || quad_vertex_id == 5) {
|
||||
do_vertex(1, p1, ofs, 1.0);
|
||||
}
|
||||
else if (quad_vertex_id == 4) {
|
||||
do_vertex(1, p1, ofs, -1.0);
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,7 @@
|
||||
# include "gpu_glsl_cpp_stubs.hh"
|
||||
|
||||
# include "GPU_shader_shared.hh"
|
||||
# include "gpu_index_load_info.hh"
|
||||
# include "gpu_srgb_to_framebuffer_space_info.hh"
|
||||
# define SMOOTH_WIDTH 1.0
|
||||
#endif
|
||||
@@ -18,14 +19,11 @@
|
||||
#include "gpu_interface_info.hh"
|
||||
#include "gpu_shader_create_info.hh"
|
||||
|
||||
GPU_SHADER_NAMED_INTERFACE_INFO(gpu_shader_3D_polyline_iface, interp)
|
||||
GPU_SHADER_INTERFACE_INFO(gpu_shader_3D_polyline_iface)
|
||||
SMOOTH(VEC4, final_color)
|
||||
SMOOTH(FLOAT, clip)
|
||||
GPU_SHADER_NAMED_INTERFACE_END(interp)
|
||||
|
||||
GPU_SHADER_NAMED_INTERFACE_INFO(gpu_shader_3D_polyline_noperspective_iface, interp_noperspective)
|
||||
NO_PERSPECTIVE(FLOAT, smoothline)
|
||||
GPU_SHADER_NAMED_INTERFACE_END(interp_noperspective)
|
||||
GPU_SHADER_INTERFACE_END()
|
||||
|
||||
GPU_SHADER_CREATE_INFO(gpu_shader_3D_polyline)
|
||||
DEFINE_VALUE("SMOOTH_WIDTH", "1.0")
|
||||
@@ -33,32 +31,17 @@ PUSH_CONSTANT(MAT4, ModelViewProjectionMatrix)
|
||||
PUSH_CONSTANT(VEC2, viewportSize)
|
||||
PUSH_CONSTANT(FLOAT, lineWidth)
|
||||
PUSH_CONSTANT(BOOL, lineSmooth)
|
||||
VERTEX_IN(0, VEC3, pos)
|
||||
STORAGE_BUF_FREQ(GPU_SSBO_POLYLINE_POS_BUF_SLOT, READ, float, pos[], GEOMETRY)
|
||||
PUSH_CONSTANT(IVEC2, gpu_attr_0)
|
||||
PUSH_CONSTANT(IVEC3, gpu_vert_stride_count_offset)
|
||||
PUSH_CONSTANT(INT, gpu_attr_0_len)
|
||||
PUSH_CONSTANT(BOOL, gpu_attr_0_fetch_int)
|
||||
VERTEX_OUT(gpu_shader_3D_polyline_iface)
|
||||
VERTEX_OUT(gpu_shader_3D_polyline_noperspective_iface)
|
||||
GEOMETRY_LAYOUT(PrimitiveIn::LINES, PrimitiveOut::TRIANGLE_STRIP, 4)
|
||||
GEOMETRY_OUT(gpu_shader_3D_polyline_iface)
|
||||
GEOMETRY_OUT(gpu_shader_3D_polyline_noperspective_iface)
|
||||
FRAGMENT_OUT(0, VEC4, fragColor)
|
||||
VERTEX_SOURCE("gpu_shader_3D_polyline_vert.glsl")
|
||||
GEOMETRY_SOURCE("gpu_shader_3D_polyline_geom.glsl")
|
||||
FRAGMENT_SOURCE("gpu_shader_3D_polyline_frag.glsl")
|
||||
ADDITIONAL_INFO(gpu_srgb_to_framebuffer_space)
|
||||
GPU_SHADER_CREATE_END()
|
||||
|
||||
GPU_SHADER_CREATE_INFO(gpu_shader_3D_polyline_no_geom)
|
||||
DEFINE_VALUE("SMOOTH_WIDTH", "1.0")
|
||||
PUSH_CONSTANT(MAT4, ModelViewProjectionMatrix)
|
||||
PUSH_CONSTANT(VEC2, viewportSize)
|
||||
PUSH_CONSTANT(FLOAT, lineWidth)
|
||||
PUSH_CONSTANT(BOOL, lineSmooth)
|
||||
VERTEX_IN(0, VEC3, pos)
|
||||
VERTEX_OUT(gpu_shader_3D_polyline_iface)
|
||||
VERTEX_OUT(gpu_shader_3D_polyline_noperspective_iface)
|
||||
FRAGMENT_OUT(0, VEC4, fragColor)
|
||||
VERTEX_SOURCE("gpu_shader_3D_polyline_vert_no_geom.glsl")
|
||||
FRAGMENT_SOURCE("gpu_shader_3D_polyline_frag.glsl")
|
||||
ADDITIONAL_INFO(gpu_srgb_to_framebuffer_space)
|
||||
ADDITIONAL_INFO(gpu_index_buffer_load)
|
||||
GPU_SHADER_CREATE_END()
|
||||
|
||||
GPU_SHADER_CREATE_INFO(gpu_shader_3D_polyline_uniform_color)
|
||||
@@ -68,14 +51,6 @@ PUSH_CONSTANT(VEC4, color)
|
||||
ADDITIONAL_INFO(gpu_shader_3D_polyline)
|
||||
GPU_SHADER_CREATE_END()
|
||||
|
||||
GPU_SHADER_CREATE_INFO(gpu_shader_3D_polyline_uniform_color_no_geom)
|
||||
METAL_BACKEND_ONLY()
|
||||
DO_STATIC_COMPILATION()
|
||||
DEFINE("UNIFORM")
|
||||
PUSH_CONSTANT(VEC4, color)
|
||||
ADDITIONAL_INFO(gpu_shader_3D_polyline_no_geom)
|
||||
GPU_SHADER_CREATE_END()
|
||||
|
||||
GPU_SHADER_CREATE_INFO(gpu_shader_3D_polyline_uniform_color_clipped)
|
||||
DO_STATIC_COMPILATION()
|
||||
/* TODO(fclem): Put in a UBO to fit the 128byte requirement. */
|
||||
@@ -85,42 +60,20 @@ DEFINE("CLIP")
|
||||
ADDITIONAL_INFO(gpu_shader_3D_polyline_uniform_color)
|
||||
GPU_SHADER_CREATE_END()
|
||||
|
||||
GPU_SHADER_CREATE_INFO(gpu_shader_3D_polyline_uniform_color_clipped_no_geom)
|
||||
METAL_BACKEND_ONLY()
|
||||
DO_STATIC_COMPILATION()
|
||||
/* TODO(fclem): Put in an UBO to fit the 128byte requirement. */
|
||||
PUSH_CONSTANT(MAT4, ModelMatrix)
|
||||
PUSH_CONSTANT(VEC4, ClipPlane)
|
||||
DEFINE("CLIP")
|
||||
ADDITIONAL_INFO(gpu_shader_3D_polyline_uniform_color_no_geom)
|
||||
GPU_SHADER_CREATE_END()
|
||||
|
||||
GPU_SHADER_CREATE_INFO(gpu_shader_3D_polyline_flat_color)
|
||||
DO_STATIC_COMPILATION()
|
||||
DEFINE("FLAT")
|
||||
VERTEX_IN(1, VEC4, color)
|
||||
STORAGE_BUF_FREQ(GPU_SSBO_POLYLINE_COL_BUF_SLOT, READ, float, color[], GEOMETRY)
|
||||
PUSH_CONSTANT(IVEC2, gpu_attr_1)
|
||||
PUSH_CONSTANT(INT, gpu_attr_1_len)
|
||||
ADDITIONAL_INFO(gpu_shader_3D_polyline)
|
||||
GPU_SHADER_CREATE_END()
|
||||
|
||||
GPU_SHADER_CREATE_INFO(gpu_shader_3D_polyline_flat_color_no_geom)
|
||||
METAL_BACKEND_ONLY()
|
||||
DO_STATIC_COMPILATION()
|
||||
DEFINE("FLAT")
|
||||
VERTEX_IN(1, VEC4, color)
|
||||
ADDITIONAL_INFO(gpu_shader_3D_polyline_no_geom)
|
||||
GPU_SHADER_CREATE_END()
|
||||
|
||||
GPU_SHADER_CREATE_INFO(gpu_shader_3D_polyline_smooth_color)
|
||||
DO_STATIC_COMPILATION()
|
||||
DEFINE("SMOOTH")
|
||||
VERTEX_IN(1, VEC4, color)
|
||||
STORAGE_BUF_FREQ(GPU_SSBO_POLYLINE_COL_BUF_SLOT, READ, float, color[], GEOMETRY)
|
||||
PUSH_CONSTANT(IVEC2, gpu_attr_1)
|
||||
PUSH_CONSTANT(INT, gpu_attr_1_len)
|
||||
ADDITIONAL_INFO(gpu_shader_3D_polyline)
|
||||
GPU_SHADER_CREATE_END()
|
||||
|
||||
GPU_SHADER_CREATE_INFO(gpu_shader_3D_polyline_smooth_color_no_geom)
|
||||
METAL_BACKEND_ONLY()
|
||||
DO_STATIC_COMPILATION()
|
||||
DEFINE("SMOOTH")
|
||||
VERTEX_IN(1, VEC4, color)
|
||||
ADDITIONAL_INFO(gpu_shader_3D_polyline_no_geom)
|
||||
GPU_SHADER_CREATE_END()
|
||||
|
||||
@@ -19,10 +19,11 @@ namespace blender::gpu {
|
||||
|
||||
void VKDescriptorSetTracker::bind_buffer(VkDescriptorType vk_descriptor_type,
|
||||
VkBuffer vk_buffer,
|
||||
VkDeviceSize buffer_offset,
|
||||
VkDeviceSize size_in_bytes,
|
||||
VKDescriptorSet::Location location)
|
||||
{
|
||||
vk_descriptor_buffer_infos_.append({vk_buffer, 0, size_in_bytes});
|
||||
vk_descriptor_buffer_infos_.append({vk_buffer, buffer_offset, size_in_bytes});
|
||||
vk_write_descriptor_sets_.append({VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||
nullptr,
|
||||
vk_descriptor_set,
|
||||
@@ -218,13 +219,22 @@ void VKDescriptorSetTracker::bind_storage_buffer_resource(
|
||||
vk_device_size = storage_buffer->size_in_bytes();
|
||||
break;
|
||||
}
|
||||
case BindSpaceStorageBuffers::Type::Buffer: {
|
||||
VKBuffer *buffer = static_cast<VKBuffer *>(elem.resource);
|
||||
vk_buffer = buffer->vk_handle();
|
||||
vk_device_size = buffer->size_in_bytes();
|
||||
break;
|
||||
}
|
||||
case BindSpaceStorageBuffers::Type::Unused: {
|
||||
BLI_assert_unreachable();
|
||||
}
|
||||
}
|
||||
|
||||
bind_buffer(
|
||||
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk_buffer, vk_device_size, resource_binding.location);
|
||||
bind_buffer(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||
vk_buffer,
|
||||
elem.offset,
|
||||
vk_device_size - elem.offset,
|
||||
resource_binding.location);
|
||||
access_info.buffers.append({vk_buffer, resource_binding.access_mask});
|
||||
}
|
||||
|
||||
@@ -237,6 +247,7 @@ void VKDescriptorSetTracker::bind_uniform_buffer_resource(
|
||||
uniform_buffer.ensure_updated();
|
||||
bind_buffer(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
||||
uniform_buffer.vk_handle(),
|
||||
0,
|
||||
uniform_buffer.size_in_bytes(),
|
||||
resource_binding.location);
|
||||
access_info.buffers.append({uniform_buffer.vk_handle(), resource_binding.access_mask});
|
||||
@@ -254,6 +265,7 @@ void VKDescriptorSetTracker::bind_push_constants(VKPushConstants &push_constants
|
||||
const VKUniformBuffer &uniform_buffer = *push_constants.uniform_buffer_get().get();
|
||||
bind_buffer(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
||||
uniform_buffer.vk_handle(),
|
||||
0,
|
||||
uniform_buffer.size_in_bytes(),
|
||||
push_constants.layout_get().descriptor_set_location_get());
|
||||
access_info.buffers.append({uniform_buffer.vk_handle(), VK_ACCESS_UNIFORM_READ_BIT});
|
||||
|
||||
@@ -130,6 +130,7 @@ class VKDescriptorSetTracker {
|
||||
void bind_texel_buffer(VkBufferView vk_buffer_view, VKDescriptorSet::Location location);
|
||||
void bind_buffer(VkDescriptorType vk_descriptor_type,
|
||||
VkBuffer vk_buffer,
|
||||
VkDeviceSize buffer_offset,
|
||||
VkDeviceSize size_in_bytes,
|
||||
VKDescriptorSet::Location location);
|
||||
void bind_image(VkDescriptorType vk_descriptor_type,
|
||||
|
||||
@@ -75,19 +75,38 @@ void VKImmediate::end()
|
||||
|
||||
VKContext &context = *VKContext::get();
|
||||
BLI_assert(context.shader == unwrap(shader));
|
||||
render_graph::VKResourceAccessInfo &resource_access_info = context.reset_and_get_access_info();
|
||||
vertex_attributes_.update_bindings(*this);
|
||||
context.active_framebuffer_get()->rendering_ensure(context);
|
||||
Shader &shader = *unwrap(this->shader);
|
||||
if (shader.is_polyline) {
|
||||
VKBuffer *buffer = active_buffers_.last().get();
|
||||
VKStateManager &state_manager = context.state_manager_get();
|
||||
state_manager.storage_buffer_bind(BindSpaceStorageBuffers::Type::Buffer,
|
||||
buffer,
|
||||
GPU_SSBO_POLYLINE_POS_BUF_SLOT,
|
||||
buffer_offset_);
|
||||
state_manager.storage_buffer_bind(BindSpaceStorageBuffers::Type::Buffer,
|
||||
buffer,
|
||||
GPU_SSBO_POLYLINE_COL_BUF_SLOT,
|
||||
buffer_offset_);
|
||||
/* Not used. Satisfy the binding. */
|
||||
state_manager.storage_buffer_bind(
|
||||
BindSpaceStorageBuffers::Type::Buffer, buffer, GPU_SSBO_INDEX_BUF_SLOT, buffer_offset_);
|
||||
this->polyline_draw_workaround(0);
|
||||
}
|
||||
else {
|
||||
render_graph::VKResourceAccessInfo &resource_access_info = context.reset_and_get_access_info();
|
||||
vertex_attributes_.update_bindings(*this);
|
||||
context.active_framebuffer_get()->rendering_ensure(context);
|
||||
|
||||
render_graph::VKDrawNode::CreateInfo draw(resource_access_info);
|
||||
draw.node_data.vertex_count = vertex_idx;
|
||||
draw.node_data.instance_count = 1;
|
||||
draw.node_data.first_vertex = 0;
|
||||
draw.node_data.first_instance = 0;
|
||||
vertex_attributes_.bind(draw.node_data.vertex_buffers);
|
||||
context.update_pipeline_data(prim_type, vertex_attributes_, draw.node_data.pipeline_data);
|
||||
render_graph::VKDrawNode::CreateInfo draw(resource_access_info);
|
||||
draw.node_data.vertex_count = vertex_idx;
|
||||
draw.node_data.instance_count = 1;
|
||||
draw.node_data.first_vertex = 0;
|
||||
draw.node_data.first_instance = 0;
|
||||
vertex_attributes_.bind(draw.node_data.vertex_buffers);
|
||||
context.update_pipeline_data(prim_type, vertex_attributes_, draw.node_data.pipeline_data);
|
||||
|
||||
context.render_graph.add_node(draw);
|
||||
context.render_graph.add_node(draw);
|
||||
}
|
||||
|
||||
buffer_offset_ += current_subbuffer_len_;
|
||||
current_subbuffer_len_ = 0;
|
||||
@@ -133,7 +152,8 @@ VKBuffer &VKImmediate::ensure_space(size_t bytes_needed)
|
||||
VKBuffer &result = *active_buffers_.last();
|
||||
result.create(new_buffer_size(bytes_needed),
|
||||
GPU_USAGE_DYNAMIC,
|
||||
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
|
||||
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT |
|
||||
VK_BUFFER_USAGE_TRANSFER_DST_BIT);
|
||||
debug::object_label(result.vk_handle(), "Immediate");
|
||||
|
||||
return result;
|
||||
|
||||
@@ -135,9 +135,10 @@ void VKStateManager::texel_buffer_unbind(VKVertexBuffer &vertex_buffer)
|
||||
|
||||
void VKStateManager::storage_buffer_bind(BindSpaceStorageBuffers::Type resource_type,
|
||||
void *resource,
|
||||
int binding)
|
||||
int binding,
|
||||
VkDeviceSize offset)
|
||||
{
|
||||
storage_buffers_.bind(resource_type, resource, binding);
|
||||
storage_buffers_.bind(resource_type, resource, binding, offset);
|
||||
is_dirty = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -115,20 +115,23 @@ class BindSpaceStorageBuffers {
|
||||
VertexBuffer,
|
||||
IndexBuffer,
|
||||
StorageBuffer,
|
||||
Buffer,
|
||||
};
|
||||
struct Elem {
|
||||
Type resource_type;
|
||||
void *resource;
|
||||
VkDeviceSize offset;
|
||||
};
|
||||
Vector<Elem> bound_resources;
|
||||
|
||||
void bind(Type resource_type, void *resource, int binding)
|
||||
void bind(Type resource_type, void *resource, int binding, VkDeviceSize offset)
|
||||
{
|
||||
if (bound_resources.size() <= binding) {
|
||||
bound_resources.resize(binding + 1);
|
||||
}
|
||||
bound_resources[binding].resource_type = resource_type;
|
||||
bound_resources[binding].resource = resource;
|
||||
bound_resources[binding].offset = offset;
|
||||
}
|
||||
|
||||
const Elem &get(int binding) const
|
||||
@@ -142,6 +145,7 @@ class BindSpaceStorageBuffers {
|
||||
if (bound_resources[index].resource == resource) {
|
||||
bound_resources[index].resource = nullptr;
|
||||
bound_resources[index].resource_type = Type::Unused;
|
||||
bound_resources[index].offset = 0u;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -234,7 +238,14 @@ class VKStateManager : public StateManager {
|
||||
|
||||
void storage_buffer_bind(BindSpaceStorageBuffers::Type resource_type,
|
||||
void *resource,
|
||||
int binding);
|
||||
int binding)
|
||||
{
|
||||
storage_buffer_bind(resource_type, resource, binding, 0u);
|
||||
}
|
||||
void storage_buffer_bind(BindSpaceStorageBuffers::Type resource_type,
|
||||
void *resource,
|
||||
int binding,
|
||||
VkDeviceSize offset);
|
||||
void storage_buffer_unbind(void *resource);
|
||||
void storage_buffer_unbind_all();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user