Metal: Remove SSBO Vertex Fetch

This API was used as a workaround to the lack of
geometry shader. It has been rendered redundant
since the introduction of #125782.
This commit is contained in:
Clément Foucault
2024-12-05 22:58:12 +01:00
parent 8d9bf47ba6
commit 994c43413a
18 changed files with 31 additions and 1054 deletions

View File

@@ -309,14 +309,6 @@ GPUShader *GPU_shader_create_ex(std::optional<blender::StringRefNull> vertcode,
bool GPU_shader_transform_feedback_enable(GPUShader *shader, blender::gpu::VertBuf *vertbuf);
void GPU_shader_transform_feedback_disable(GPUShader *shader);
/**
* SSBO Vertex-fetch is used as an alternative path to geometry shaders wherein the vertex count is
* expanded up-front. This function fetches the number of specified output vertices per input
* primitive.
*/
int GPU_shader_get_ssbo_vertex_fetch_num_verts_per_prim(GPUShader *shader);
bool GPU_shader_uses_ssbo_vertex_fetch(GPUShader *shader);
/**
* Shader cache warming.
* For each shader, rendering APIs perform a two-step compilation:

View File

@@ -699,15 +699,6 @@ int GPU_shader_get_program(GPUShader *shader)
return unwrap(shader)->program_handle_get();
}
int GPU_shader_get_ssbo_vertex_fetch_num_verts_per_prim(GPUShader *shader)
{
return unwrap(shader)->get_ssbo_vertex_fetch_output_num_verts();
}
bool GPU_shader_uses_ssbo_vertex_fetch(GPUShader *shader)
{
return unwrap(shader)->get_uses_ssbo_vertex_fetch();
}
/** \} */

View File

@@ -122,10 +122,6 @@ class Shader {
/* DEPRECATED: Kept only because of BGL API. */
virtual int program_handle_get() const = 0;
/* Only used by SSBO Vertex fetch. */
virtual bool get_uses_ssbo_vertex_fetch() const = 0;
virtual int get_ssbo_vertex_fetch_output_num_verts() const = 0;
inline StringRefNull name_get() const
{
return name;

View File

@@ -93,7 +93,7 @@ class MTLBatch : public Batch {
/* Returns an initialized RenderComandEncoder for drawing if all is good.
* Otherwise, nil. */
id<MTLRenderCommandEncoder> bind(uint v_count);
id<MTLRenderCommandEncoder> bind();
void unbind(id<MTLRenderCommandEncoder> rec);
/* Convenience getters. */

View File

@@ -128,12 +128,6 @@ int MTLBatch::prepare_vertex_binding(MTLVertBuf *verts,
int buffer_index = -1;
int attribute_offset = 0;
if (!active_shader_->get_uses_ssbo_vertex_fetch()) {
BLI_assert(
buffer_stride >= 4 &&
"In Metal, Vertex buffer stride should be 4. SSBO Vertex fetch is not affected by this");
}
/* Iterate over VertBuf vertex format and find attributes matching those in the active
* shader's interface. */
for (uint32_t a_idx = 0; a_idx < format->attr_len; a_idx++) {
@@ -211,23 +205,7 @@ int MTLBatch::prepare_vertex_binding(MTLVertBuf *verts,
"only mat4 attributes currently supported -- Not ready to handle other long "
"component length attributes yet");
/* SSBO Vertex Fetch Attribute safety checks. */
if (active_shader_->get_uses_ssbo_vertex_fetch()) {
/* When using SSBO vertex fetch, we do not need to expose split attributes,
* A matrix can be read directly as a whole block of contiguous data. */
MTLSSBOAttribute ssbo_attr(mtl_attr.index,
buffer_index,
attribute_offset,
buffer_stride,
GPU_SHADER_ATTR_TYPE_MAT4,
instanced);
active_shader_->ssbo_vertex_fetch_bind_attribute(ssbo_attr);
desc.vertex_descriptor.ssbo_attributes[desc.vertex_descriptor.num_ssbo_attributes] =
ssbo_attr;
desc.vertex_descriptor.num_ssbo_attributes++;
}
else {
{
/* Handle Mat4 attributes. */
if (a->comp_len == 16) {
/* Debug safety checks. */
@@ -341,26 +319,6 @@ int MTLBatch::prepare_vertex_binding(MTLVertBuf *verts,
(mtl_attr.location) :
desc.vertex_descriptor.max_attribute_value;
desc.vertex_descriptor.total_attributes++;
/* SSBO Vertex Fetch attribute bind. */
if (active_shader_->get_uses_ssbo_vertex_fetch()) {
BLI_assert_msg(desc.vertex_descriptor.attributes[mtl_attr.location].format ==
mtl_attr.format,
"SSBO Vertex Fetch does not support attribute conversion.");
MTLSSBOAttribute ssbo_attr(
mtl_attr.index,
buffer_index,
attribute_offset,
buffer_stride,
MTLShader::ssbo_vertex_type_to_attr_type(
desc.vertex_descriptor.attributes[mtl_attr.location].format),
instanced);
active_shader_->ssbo_vertex_fetch_bind_attribute(ssbo_attr);
desc.vertex_descriptor.ssbo_attributes[desc.vertex_descriptor.num_ssbo_attributes] =
ssbo_attr;
desc.vertex_descriptor.num_ssbo_attributes++;
}
/* NOTE: We are setting max_attribute_value to be up to the maximum found index, because
* of this, it is possible that we may skip over certain attributes if they were not in
@@ -393,7 +351,7 @@ int MTLBatch::prepare_vertex_binding(MTLVertBuf *verts,
return -1;
}
id<MTLRenderCommandEncoder> MTLBatch::bind(uint v_count)
id<MTLRenderCommandEncoder> MTLBatch::bind()
{
/* Setup draw call and render pipeline state here. Called by every draw, but setup here so that
* MTLDrawList only needs to perform setup a single time. */
@@ -417,12 +375,6 @@ id<MTLRenderCommandEncoder> MTLBatch::bind(uint v_count)
return nil;
}
/* Check if using SSBO Fetch Mode.
* This is an alternative drawing mode to geometry shaders, wherein vertex buffers
* are bound as readable (random-access) GPU buffers and certain descriptor properties
* are passed using Shader uniforms. */
bool uses_ssbo_fetch = active_shader_->get_uses_ssbo_vertex_fetch();
/* Prepare Vertex Descriptor and extract VertexBuffers to bind. */
MTLVertBuf *buffers[GPU_BATCH_VBO_MAX_LEN] = {nullptr};
int num_buffers = 0;
@@ -481,70 +433,6 @@ id<MTLRenderCommandEncoder> MTLBatch::bind(uint v_count)
/*** Bind Vertex Buffers and Index Buffers **/
/* SSBO Vertex Fetch Buffer bindings. */
if (uses_ssbo_fetch) {
/* SSBO Vertex Fetch - Bind Index Buffer to appropriate slot -- if used. */
id<MTLBuffer> idx_buffer = nil;
GPUPrimType final_prim_type = this->prim_type;
if (mtl_elem != nullptr) {
/* Fetch index buffer. This function can situationally return an optimized
* index buffer of a different primitive type. If this is the case, `final_prim_type`
* and `v_count` will be updated with the new format.
* NOTE: For indexed rendering, v_count represents the number of indices. */
idx_buffer = mtl_elem->get_index_buffer(final_prim_type, v_count);
BLI_assert(idx_buffer != nil);
/* Update uniforms for SSBO-vertex-fetch-mode indexed rendering to flag usage. */
int &uniform_ssbo_index_mode_u16 = active_shader_->uni_ssbo_uses_index_mode_u16;
BLI_assert(uniform_ssbo_index_mode_u16 != -1);
int uses_index_mode_u16 = (mtl_elem->index_type_ == GPU_INDEX_U16) ? 1 : 0;
active_shader_->uniform_int(uniform_ssbo_index_mode_u16, 1, 1, &uses_index_mode_u16);
BLI_assert(active_shader_->uni_ssbo_index_base_loc != -1);
int index_base = (int)mtl_elem->index_base_;
active_shader_->uniform_int(active_shader_->uni_ssbo_index_base_loc, 1, 1, &index_base);
}
else {
idx_buffer = ctx->get_null_buffer();
}
rps.bind_vertex_buffer(idx_buffer, 0, MTL_SSBO_VERTEX_FETCH_IBO_INDEX);
/* Ensure all attributes are set. */
active_shader_->ssbo_vertex_fetch_bind_attributes_end(rec);
/* Bind nullptr Buffers for unused vertex data slots. */
id<MTLBuffer> null_buffer = ctx->get_null_buffer();
BLI_assert(null_buffer != nil);
for (int i = num_buffers; i < MTL_SSBO_VERTEX_FETCH_MAX_VBOS; i++) {
if (rps.cached_vertex_buffer_bindings[i].metal_buffer == nil) {
rps.bind_vertex_buffer(null_buffer, 0, i);
}
}
/* Flag whether Indexed rendering is used or not. */
int &uniform_ssbo_use_indexed = active_shader_->uni_ssbo_uses_indexed_rendering;
BLI_assert(uniform_ssbo_use_indexed != -1);
int uses_indexed_rendering = (mtl_elem != nullptr) ? 1 : 0;
active_shader_->uniform_int(uniform_ssbo_use_indexed, 1, 1, &uses_indexed_rendering);
/* Set SSBO-fetch-mode status uniforms. */
BLI_assert(active_shader_->uni_ssbo_input_prim_type_loc != -1);
BLI_assert(active_shader_->uni_ssbo_input_vert_count_loc != -1);
GPU_shader_uniform_int_ex(reinterpret_cast<GPUShader *>(wrap(active_shader_)),
active_shader_->uni_ssbo_input_prim_type_loc,
1,
1,
(const int *)(&final_prim_type));
GPU_shader_uniform_int_ex(reinterpret_cast<GPUShader *>(wrap(active_shader_)),
active_shader_->uni_ssbo_input_vert_count_loc,
1,
1,
(const int *)(&v_count));
}
/* Ensure Context Render Pipeline State is fully setup and ready to execute the draw.
* This should happen after all other final rendering setup is complete. */
MTLPrimitiveType mtl_prim_type = gpu_prim_type_to_metal(this->prim_type);
@@ -606,11 +494,6 @@ void MTLBatch::prepare_vertex_descriptor_and_bindings(MTLVertBuf **buffers, int
Span<MTLVertBuf *> mtl_inst(reinterpret_cast<MTLVertBuf **>(this->inst),
GPU_BATCH_INST_VBO_MAX_LEN);
/* SSBO Vertex fetch also passes vertex descriptor information into the shader. */
if (active_shader_->get_uses_ssbo_vertex_fetch()) {
active_shader_->ssbo_vertex_fetch_bind_attributes_begin();
}
/* Resolve Metal vertex buffer bindings. */
/* Vertex Descriptors
* ------------------
@@ -641,15 +524,6 @@ void MTLBatch::prepare_vertex_descriptor_and_bindings(MTLVertBuf **buffers, int
}
}
}
/* Use cached ssbo attribute binding data. */
if (active_shader_->get_uses_ssbo_vertex_fetch()) {
BLI_assert(desc.vertex_descriptor.uses_ssbo_vertex_fetch);
for (int attr_id = 0; attr_id < desc.vertex_descriptor.num_ssbo_attributes; attr_id++) {
active_shader_->ssbo_vertex_fetch_bind_attribute(
desc.vertex_descriptor.ssbo_attributes[attr_id]);
}
}
}
else {
VertexDescriptorShaderInterfacePair pair{};
@@ -699,7 +573,6 @@ void MTLBatch::prepare_vertex_descriptor_and_bindings(MTLVertBuf **buffers, int
}
/* Add to VertexDescriptor cache */
desc.vertex_descriptor.uses_ssbo_vertex_fetch = active_shader_->get_uses_ssbo_vertex_fetch();
pair.attr_mask = attr_mask;
pair.vertex_descriptor = desc.vertex_descriptor;
pair.num_buffers = num_buffers;
@@ -741,7 +614,7 @@ void MTLBatch::draw_advanced(int v_first, int v_count, int i_first, int i_count)
/* Setup RenderPipelineState for batch. */
MTLContext *ctx = MTLContext::get();
id<MTLRenderCommandEncoder> rec = this->bind(v_count);
id<MTLRenderCommandEncoder> rec = this->bind();
if (rec == nil) {
/* End of draw. */
this->unbind(rec);
@@ -752,35 +625,10 @@ void MTLBatch::draw_advanced(int v_first, int v_count, int i_first, int i_count)
MTLIndexBuf *mtl_elem = static_cast<MTLIndexBuf *>(reinterpret_cast<IndexBuf *>(this->elem));
MTLPrimitiveType mtl_prim_type = gpu_prim_type_to_metal(this->prim_type);
/* Render using SSBO Vertex Fetch. */
if (active_shader_->get_uses_ssbo_vertex_fetch()) {
/* Submit draw call with modified vertex count, which reflects vertices per primitive defined
* in the USE_SSBO_VERTEX_FETCH pragma. */
int num_input_primitives = gpu_get_prim_count_from_type(v_count, this->prim_type);
int output_num_verts = num_input_primitives *
active_shader_->get_ssbo_vertex_fetch_output_num_verts();
BLI_assert_msg(
mtl_vertex_count_fits_primitive_type(
output_num_verts, active_shader_->get_ssbo_vertex_fetch_output_prim_type()),
"Output Vertex count is not compatible with the requested output vertex primitive type");
/* Set depth stencil state (requires knowledge of primitive type). */
ctx->ensure_depth_stencil_state(active_shader_->get_ssbo_vertex_fetch_output_prim_type());
[rec drawPrimitives:active_shader_->get_ssbo_vertex_fetch_output_prim_type()
vertexStart:0
vertexCount:output_num_verts
instanceCount:i_count
baseInstance:i_first];
ctx->main_command_buffer.register_draw_counters(output_num_verts * i_count);
}
/* Perform regular draw. */
else if (mtl_elem == nullptr) {
if (mtl_elem == nullptr) {
/* Primitive Type toplogy emulation. */
if (mtl_needs_topology_emulation(this->prim_type)) {
/* Generate index buffer for primitive types requiring emulation. */
GPUPrimType emulated_prim_type = this->prim_type;
uint32_t emulated_v_count = v_count;
@@ -883,7 +731,7 @@ void MTLBatch::draw_advanced_indirect(GPUStorageBuf *indirect_buf, intptr_t offs
{
/* Setup RenderPipelineState for batch. */
MTLContext *ctx = MTLContext::get();
id<MTLRenderCommandEncoder> rec = this->bind(0);
id<MTLRenderCommandEncoder> rec = this->bind();
if (rec == nil) {
printf("Failed to open Render Command encoder for DRAW INDIRECT\n");
@@ -904,24 +752,6 @@ void MTLBatch::draw_advanced_indirect(GPUStorageBuf *indirect_buf, intptr_t offs
return;
}
/* Indirect SSBO vertex fetch calls require the draw command in the buffer to be mutated at
* command encoding time. This takes place within the draw manager when a shader supporting
* SSBO Vertex-Fetch is used. */
if (active_shader_->get_uses_ssbo_vertex_fetch())
{ /* Set depth stencil state (requires knowledge of primitive type). */
ctx->ensure_depth_stencil_state(active_shader_->get_ssbo_vertex_fetch_output_prim_type());
/* Issue draw call. */
[rec drawPrimitives:active_shader_->get_ssbo_vertex_fetch_output_prim_type()
indirectBuffer:mtl_indirect_buf
indirectBufferOffset:offset];
ctx->main_command_buffer.register_draw_counters(1);
/* End of draw. */
this->unbind(rec);
return;
}
/* Unsupported primitive type check. */
BLI_assert_msg(this->prim_type != GPU_PRIM_TRI_FAN,
"TriangleFan is not supported in Metal for Indirect draws.");

View File

@@ -84,10 +84,8 @@ void MTLDrawList::init()
void MTLDrawList::append(Batch *gpu_batch, int i_first, int i_count)
{
/* Fallback when MultiDrawIndirect is not supported/enabled. */
MTLShader *shader = static_cast<MTLShader *>(unwrap(gpu_batch->shader));
bool requires_ssbo = (shader->get_uses_ssbo_vertex_fetch());
bool requires_emulation = mtl_needs_topology_emulation(gpu_batch->prim_type);
if (MDI_DISABLED || requires_ssbo || requires_emulation) {
if (MDI_DISABLED || requires_emulation) {
GPU_batch_draw_advanced(gpu_batch, 0, 0, i_first, i_count);
return;
}
@@ -170,13 +168,6 @@ void MTLDrawList::submit()
BLI_assert(ctx);
/* Execute indirect draw calls. */
MTLShader *shader = static_cast<MTLShader *>(unwrap(batch_->shader));
bool SSBO_MODE = (shader->get_uses_ssbo_vertex_fetch());
if (SSBO_MODE) {
can_use_MDI = false;
BLI_assert(false);
return;
}
/* Heuristic to determine whether using indirect drawing is more efficient. */
size_t command_size = MDI_INDEXED ? sizeof(MTLDrawIndexedPrimitivesIndirectArguments) :
@@ -186,7 +177,7 @@ void MTLDrawList::submit()
/* Bind Batch to setup render pipeline state. */
BLI_assert(batch_ != nullptr);
id<MTLRenderCommandEncoder> rec = batch_->bind(0);
id<MTLRenderCommandEncoder> rec = batch_->bind();
if (rec == nil) {
BLI_assert_msg(false, "A RenderCommandEncoder should always be available!\n");

View File

@@ -115,21 +115,6 @@ void MTLImmediate::end()
for (int i = 0; i < desc.vertex_descriptor.total_attributes; i++) {
desc.vertex_descriptor.attributes[i].format = MTLVertexFormatInvalid;
}
desc.vertex_descriptor.uses_ssbo_vertex_fetch =
active_mtl_shader->get_uses_ssbo_vertex_fetch();
desc.vertex_descriptor.num_ssbo_attributes = 0;
/* SSBO Vertex Fetch -- Verify Attributes. */
if (active_mtl_shader->get_uses_ssbo_vertex_fetch()) {
active_mtl_shader->ssbo_vertex_fetch_bind_attributes_begin();
/* Disable Indexed rendering in SSBO vertex fetch. */
int uniform_ssbo_use_indexed = active_mtl_shader->uni_ssbo_uses_indexed_rendering;
BLI_assert_msg(uniform_ssbo_use_indexed != -1,
"Expected valid uniform location for ssbo_uses_indexed_rendering.");
int uses_indexed_rendering = 0;
active_mtl_shader->uniform_int(uniform_ssbo_use_indexed, 1, 1, &uses_indexed_rendering);
}
/* Populate Vertex descriptor and verify attributes.
* TODO(Metal): Cache this vertex state based on Vertex format and shaders. */
@@ -211,23 +196,6 @@ void MTLImmediate::end()
/* Using attribute offset in vertex format, as this will be correct */
desc.vertex_descriptor.attributes[i].offset = attr->offset;
desc.vertex_descriptor.attributes[i].buffer_index = mtl_shader_attribute.buffer_index;
/* SSBO Vertex Fetch Attribute bind. */
if (active_mtl_shader->get_uses_ssbo_vertex_fetch()) {
BLI_assert_msg(mtl_shader_attribute.buffer_index == 0,
"All attributes should be in buffer index zero");
MTLSSBOAttribute ssbo_attr(
mtl_shader_attribute.index,
mtl_shader_attribute.buffer_index,
attr->offset,
this->vertex_format.stride,
MTLShader::ssbo_vertex_type_to_attr_type(desc.vertex_descriptor.attributes[i].format),
false);
desc.vertex_descriptor.ssbo_attributes[desc.vertex_descriptor.num_ssbo_attributes] =
ssbo_attr;
desc.vertex_descriptor.num_ssbo_attributes++;
active_mtl_shader->ssbo_vertex_fetch_bind_attribute(ssbo_attr);
}
}
/* Buffer bindings for singular vertex buffer. */
@@ -247,27 +215,6 @@ void MTLImmediate::end()
this->prim_type = GPU_PRIM_LINE_STRIP;
}
/* SSBO Vertex Fetch -- Verify Attributes. */
if (active_mtl_shader->get_uses_ssbo_vertex_fetch()) {
active_mtl_shader->ssbo_vertex_fetch_bind_attributes_end(rec);
/* Set Status uniforms. */
BLI_assert_msg(active_mtl_shader->uni_ssbo_input_prim_type_loc != -1,
"ssbo_input_prim_type uniform location invalid!");
BLI_assert_msg(active_mtl_shader->uni_ssbo_input_vert_count_loc != -1,
"ssbo_input_vert_count uniform location invalid!");
GPU_shader_uniform_int_ex(reinterpret_cast<GPUShader *>(wrap(active_mtl_shader)),
active_mtl_shader->uni_ssbo_input_prim_type_loc,
1,
1,
(const int *)(&this->prim_type));
GPU_shader_uniform_int_ex(reinterpret_cast<GPUShader *>(wrap(active_mtl_shader)),
active_mtl_shader->uni_ssbo_input_vert_count_loc,
1,
1,
(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);
@@ -295,13 +242,6 @@ void MTLImmediate::end()
/* Emulate Tri-fan. */
switch (this->prim_type) {
case GPU_PRIM_TRI_FAN: {
/* Debug safety check for SSBO FETCH MODE. */
if (active_mtl_shader->get_uses_ssbo_vertex_fetch()) {
BLI_assert(
false &&
"Topology emulation for TriangleFan not supported with SSBO Vertex Fetch mode");
}
/* Prepare Triangle-Fan emulation index buffer on CPU based on number of input
* vertices. */
uint32_t base_vert_count = this->vertex_idx;
@@ -374,44 +314,6 @@ void MTLImmediate::end()
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();
BLI_assert(null_buffer != nil);
for (int i = 1; i < MTL_SSBO_VERTEX_FETCH_MAX_VBOS; i++) {
/* We only need to ensure a buffer is bound to the context, its contents do not matter
* as it will not be used. */
if (rps.cached_vertex_buffer_bindings[i].metal_buffer == nil) {
rps.bind_vertex_buffer(null_buffer, 0, i);
}
}
/* SSBO vertex fetch - Nullify elements buffer. */
if (rps.cached_vertex_buffer_bindings[MTL_SSBO_VERTEX_FETCH_IBO_INDEX].metal_buffer ==
nil)
{
rps.bind_vertex_buffer(null_buffer, 0, MTL_SSBO_VERTEX_FETCH_IBO_INDEX);
}
/* Submit draw call with modified vertex count, which reflects vertices per primitive
* defined in the USE_SSBO_VERTEX_FETCH `pragma`. */
int num_input_primitives = gpu_get_prim_count_from_type(vertex_count, this->prim_type);
int output_num_verts = num_input_primitives *
active_mtl_shader->get_ssbo_vertex_fetch_output_num_verts();
#ifndef NDEBUG
BLI_assert(
mtl_vertex_count_fits_primitive_type(
output_num_verts, active_mtl_shader->get_ssbo_vertex_fetch_output_prim_type()) &&
"Output Vertex count is not compatible with the requested output vertex primitive "
"type");
#endif
[rec drawPrimitives:active_mtl_shader->get_ssbo_vertex_fetch_output_prim_type()
vertexStart:0
vertexCount:output_num_verts];
context_->main_command_buffer.register_draw_counters(output_num_verts);
}
else {
/* Regular draw. */
[rec drawPrimitives:primitive_type vertexStart:0 vertexCount:vertex_count];

View File

@@ -60,7 +60,7 @@ static inline MTLPrimitiveType gpu_prim_type_to_metal(GPUPrimType prim_type)
/* Certain primitive types are not supported in Metal, and require emulation.
* `GPU_PRIM_LINE_LOOP` and `GPU_PRIM_TRI_FAN` required index buffer patching.
* Adjacency types do not need emulation as the input structure is the same,
* and access is controlled from the vertex shader through SSBO vertex fetch.
* and access is controlled from the vertex shader through SSBO vertex pulling.
* -- These Adj cases are only used in geometry shaders in OpenGL. */
static inline bool mtl_needs_topology_emulation(GPUPrimType prim_type)
{

View File

@@ -128,13 +128,6 @@ struct MTLVertexDescriptor {
int num_vert_buffers;
MTLPrimitiveTopologyClass prim_topology_class;
/* WORKAROUND: SSBO Vertex-fetch attributes -- These follow the same structure
* but have slightly different binding rules, passed in via uniform
* push constant data block. */
bool uses_ssbo_vertex_fetch;
MTLSSBOAttribute ssbo_attributes[GPU_VERT_ATTR_MAX_LEN];
int num_ssbo_attributes;
bool operator==(const MTLVertexDescriptor &other) const
{
if ((this->max_attribute_value != other.max_attribute_value) ||
@@ -175,8 +168,6 @@ struct MTLVertexDescriptor {
for (const int b : IndexRange(this->num_vert_buffers)) {
hash ^= this->buffer_layouts[b].hash() << (b + 10);
}
/* NOTE: SSBO vertex fetch members not hashed as these will match attribute bindings. */
return hash;
}
};
@@ -341,8 +332,6 @@ struct MTLRenderPipelineStateDescriptor {
for (int i = 0; i < GPU_VERT_ATTR_MAX_LEN; i++) {
vertex_descriptor.attributes[i].reset();
}
vertex_descriptor.uses_ssbo_vertex_fetch = false;
vertex_descriptor.num_ssbo_attributes = 0;
}
};

View File

@@ -169,14 +169,6 @@ class MTLShader : public Shader {
friend shader::ShaderCreateInfo;
friend shader::StageInterfaceInfo;
public:
/* Cached SSBO vertex fetch attribute uniform locations. */
int uni_ssbo_input_prim_type_loc = -1;
int uni_ssbo_input_vert_count_loc = -1;
int uni_ssbo_uses_indexed_rendering = -1;
int uni_ssbo_uses_index_mode_u16 = -1;
int uni_ssbo_index_base_loc = -1;
private:
/* Context Handle. */
MTLContext *context_ = nullptr;
@@ -224,37 +216,6 @@ class MTLShader : public Shader {
/* True to enable multi-viewport rendering support. */
bool uses_gpu_viewport_index = false;
/** SSBO Vertex fetch pragma options. */
/* Indicates whether to pass in VertexBuffer's as regular buffer bindings
* and perform vertex assembly manually, rather than using Stage-in.
* This is used to give a vertex shader full access to all of the
* vertex data.
* This is primarily used for optimization techniques and
* alternative solutions for Geometry-shaders which are unsupported
* by Metal. */
bool use_ssbo_vertex_fetch_mode_ = false;
/* Output primitive type when rendering sing ssbo_vertex_fetch. */
MTLPrimitiveType ssbo_vertex_fetch_output_prim_type_;
/* Output vertices per original vertex shader instance.
* This number will be multiplied by the number of input primitives
* from the source draw call. */
uint32_t ssbo_vertex_fetch_output_num_verts_ = 0;
bool ssbo_vertex_attribute_bind_active_ = false;
int ssbo_vertex_attribute_bind_mask_ = 0;
bool ssbo_vbo_slot_used_[MTL_SSBO_VERTEX_FETCH_MAX_VBOS];
struct ShaderSSBOAttributeBinding {
int attribute_index = -1;
int uniform_stride;
int uniform_offset;
int uniform_fetchmode;
int uniform_vbo_id;
int uniform_attr_type;
};
ShaderSSBOAttributeBinding cached_ssbo_attribute_bindings_[MTL_MAX_VERTEX_INPUT_ATTRIBUTES] = {};
/* Metal Shader Uniform data store.
* This blocks is used to store current shader push_constant
* data before it is submitted to the GPU. This is currently
@@ -346,34 +307,12 @@ class MTLShader : public Shader {
bool get_push_constant_is_dirty();
void push_constant_bindstate_mark_dirty(bool is_dirty);
/* SSBO vertex fetch draw parameters. */
bool get_uses_ssbo_vertex_fetch() const override
{
return use_ssbo_vertex_fetch_mode_;
}
int get_ssbo_vertex_fetch_output_num_verts() const override
{
return ssbo_vertex_fetch_output_num_verts_;
}
/* DEPRECATED: Kept only because of BGL API. (Returning -1 in METAL). */
int program_handle_get() const override
{
return -1;
}
MTLPrimitiveType get_ssbo_vertex_fetch_output_prim_type()
{
return ssbo_vertex_fetch_output_prim_type_;
}
static int ssbo_vertex_type_to_attr_type(MTLVertexFormat attribute_type);
void prepare_ssbo_vertex_fetch_metadata();
/* SSBO Vertex Bindings Utility functions. */
void ssbo_vertex_fetch_bind_attributes_begin();
void ssbo_vertex_fetch_bind_attribute(const MTLSSBOAttribute &ssbo_attr);
void ssbo_vertex_fetch_bind_attributes_end(id<MTLRenderCommandEncoder> active_encoder);
/* Metal shader properties and source mapping. */
void set_vertex_function_name(NSString *vetex_function_name);
void set_fragment_function_name(NSString *fragment_function_name);

View File

@@ -988,17 +988,7 @@ MTLRenderPipelineStateInstance *MTLShader::bake_pipeline_state(
int null_buffer_index = pipeline_descriptor.vertex_descriptor.num_vert_buffers;
bool using_null_buffer = false;
if (this->get_uses_ssbo_vertex_fetch()) {
/* If using SSBO Vertex fetch mode, no vertex descriptor is required
* as we wont be using stage-in. */
desc.vertexDescriptor = nil;
desc.inputPrimitiveTopology = MTLPrimitiveTopologyClassUnspecified;
/* We want to offset the uniform buffer base to allow for sufficient VBO binding slots - We
* also require +1 slot for the Index buffer. */
MTL_uniform_buffer_base_index = MTL_SSBO_VERTEX_FETCH_IBO_INDEX + 1;
}
else {
{
for (const uint i :
IndexRange(pipeline_descriptor.vertex_descriptor.max_attribute_value + 1))
{
@@ -1626,162 +1616,6 @@ MTLComputePipelineStateInstance *MTLShader::bake_compute_pipeline_state(
/** \name SSBO-vertex-fetch-mode attribute control.
* \{ */
int MTLShader::ssbo_vertex_type_to_attr_type(MTLVertexFormat attribute_type)
{
switch (attribute_type) {
case MTLVertexFormatFloat:
return GPU_SHADER_ATTR_TYPE_FLOAT;
case MTLVertexFormatInt:
return GPU_SHADER_ATTR_TYPE_INT;
case MTLVertexFormatUInt:
return GPU_SHADER_ATTR_TYPE_UINT;
case MTLVertexFormatShort:
return GPU_SHADER_ATTR_TYPE_SHORT;
case MTLVertexFormatUChar:
return GPU_SHADER_ATTR_TYPE_CHAR;
case MTLVertexFormatUChar2:
return GPU_SHADER_ATTR_TYPE_CHAR2;
case MTLVertexFormatUChar3:
return GPU_SHADER_ATTR_TYPE_CHAR3;
case MTLVertexFormatUChar4:
return GPU_SHADER_ATTR_TYPE_CHAR4;
case MTLVertexFormatFloat2:
return GPU_SHADER_ATTR_TYPE_VEC2;
case MTLVertexFormatFloat3:
return GPU_SHADER_ATTR_TYPE_VEC3;
case MTLVertexFormatFloat4:
return GPU_SHADER_ATTR_TYPE_VEC4;
case MTLVertexFormatUInt2:
return GPU_SHADER_ATTR_TYPE_UVEC2;
case MTLVertexFormatUInt3:
return GPU_SHADER_ATTR_TYPE_UVEC3;
case MTLVertexFormatUInt4:
return GPU_SHADER_ATTR_TYPE_UVEC4;
case MTLVertexFormatInt2:
return GPU_SHADER_ATTR_TYPE_IVEC2;
case MTLVertexFormatInt3:
return GPU_SHADER_ATTR_TYPE_IVEC3;
case MTLVertexFormatInt4:
return GPU_SHADER_ATTR_TYPE_IVEC4;
case MTLVertexFormatUCharNormalized:
return GPU_SHADER_ATTR_TYPE_UCHAR_NORM;
case MTLVertexFormatUChar2Normalized:
return GPU_SHADER_ATTR_TYPE_UCHAR2_NORM;
case MTLVertexFormatUChar3Normalized:
return GPU_SHADER_ATTR_TYPE_UCHAR3_NORM;
case MTLVertexFormatUChar4Normalized:
return GPU_SHADER_ATTR_TYPE_UCHAR4_NORM;
case MTLVertexFormatInt1010102Normalized:
return GPU_SHADER_ATTR_TYPE_INT1010102_NORM;
case MTLVertexFormatShort3Normalized:
return GPU_SHADER_ATTR_TYPE_SHORT3_NORM;
default:
BLI_assert_msg(false,
"Not yet supported attribute type for SSBO vertex fetch -- Add entry "
"GPU_SHADER_ATTR_TYPE_** to shader defines, and in this table");
return -1;
}
return -1;
}
void MTLShader::ssbo_vertex_fetch_bind_attributes_begin()
{
MTLShaderInterface *mtl_interface = this->get_interface();
ssbo_vertex_attribute_bind_active_ = true;
ssbo_vertex_attribute_bind_mask_ = (1 << mtl_interface->get_total_attributes()) - 1;
/* Reset tracking of actively used VBO bind slots for SSBO vertex fetch mode. */
for (int i = 0; i < MTL_SSBO_VERTEX_FETCH_MAX_VBOS; i++) {
ssbo_vbo_slot_used_[i] = false;
}
}
void MTLShader::ssbo_vertex_fetch_bind_attribute(const MTLSSBOAttribute &ssbo_attr)
{
/* Fetch attribute. */
MTLShaderInterface *mtl_interface = this->get_interface();
BLI_assert(ssbo_attr.mtl_attribute_index >= 0 &&
ssbo_attr.mtl_attribute_index < mtl_interface->get_total_attributes());
UNUSED_VARS_NDEBUG(mtl_interface);
/* Update bind-mask to verify this attribute has been used. */
BLI_assert((ssbo_vertex_attribute_bind_mask_ & (1 << ssbo_attr.mtl_attribute_index)) ==
(1 << ssbo_attr.mtl_attribute_index) &&
"Attribute has already been bound");
ssbo_vertex_attribute_bind_mask_ &= ~(1 << ssbo_attr.mtl_attribute_index);
/* Fetch attribute uniform addresses from cache. */
ShaderSSBOAttributeBinding &cached_ssbo_attribute =
cached_ssbo_attribute_bindings_[ssbo_attr.mtl_attribute_index];
BLI_assert(cached_ssbo_attribute.attribute_index >= 0);
/* Write attribute descriptor properties to shader uniforms. */
this->uniform_int(cached_ssbo_attribute.uniform_offset, 1, 1, &ssbo_attr.attribute_offset);
this->uniform_int(cached_ssbo_attribute.uniform_stride, 1, 1, &ssbo_attr.per_vertex_stride);
int inst_val = (ssbo_attr.is_instance ? 1 : 0);
this->uniform_int(cached_ssbo_attribute.uniform_fetchmode, 1, 1, &inst_val);
this->uniform_int(cached_ssbo_attribute.uniform_vbo_id, 1, 1, &ssbo_attr.vbo_id);
BLI_assert(ssbo_attr.attribute_format >= 0);
this->uniform_int(cached_ssbo_attribute.uniform_attr_type, 1, 1, &ssbo_attr.attribute_format);
ssbo_vbo_slot_used_[ssbo_attr.vbo_id] = true;
}
void MTLShader::ssbo_vertex_fetch_bind_attributes_end(
id<MTLRenderCommandEncoder> /*active_encoder*/)
{
ssbo_vertex_attribute_bind_active_ = false;
/* If our mask is non-zero, we have unassigned attributes. */
if (ssbo_vertex_attribute_bind_mask_ != 0) {
MTLShaderInterface *mtl_interface = this->get_interface();
/* Determine if there is a free slot we can bind the null buffer to -- We should have at
* least ONE free slot in this instance. */
int null_attr_buffer_slot = -1;
for (int i = 0; i < MTL_SSBO_VERTEX_FETCH_MAX_VBOS; i++) {
if (!ssbo_vbo_slot_used_[i]) {
null_attr_buffer_slot = i;
break;
}
}
BLI_assert_msg(null_attr_buffer_slot >= 0,
"No suitable bind location for a NULL buffer was found");
for (int i = 0; i < mtl_interface->get_total_attributes(); i++) {
if (ssbo_vertex_attribute_bind_mask_ & (1 << i)) {
const MTLShaderInputAttribute *mtl_shader_attribute = &mtl_interface->get_attribute(i);
#if MTL_DEBUG_SHADER_ATTRIBUTES == 1
MTL_LOG_WARNING(
"SSBO Vertex Fetch missing attribute with index: %d. Shader: %s, Attr "
"Name: "
"%s - Null buffer bound",
i,
this->name_get(),
mtl_shader_attribute->name);
#endif
/* Bind Attribute with NULL buffer index and stride zero (for constant access). */
MTLSSBOAttribute ssbo_attr(
i, null_attr_buffer_slot, 0, 0, GPU_SHADER_ATTR_TYPE_FLOAT, false);
ssbo_vertex_fetch_bind_attribute(ssbo_attr);
MTL_LOG_WARNING(
"Unassigned Shader attribute: %s, Attr Name: %s -- Binding NULL BUFFER to "
"slot %d",
this->name_get().c_str(),
mtl_interface->get_name_at_offset(mtl_shader_attribute->name_offset),
null_attr_buffer_slot);
}
}
/* Bind NULL buffer to given VBO slot. */
MTLContext *ctx = MTLContext::get();
id<MTLBuffer> null_buf = ctx->get_null_attribute_buffer();
BLI_assert(null_buf);
MTLRenderPassState &rps = ctx->main_command_buffer.get_render_pass_state();
rps.bind_vertex_buffer(null_buf, 0, null_attr_buffer_slot);
}
}
blender::gpu::VertBuf *MTLShader::get_transform_feedback_active_buffer()
{
if (transform_feedback_type_ == GPU_SHADER_TFB_NONE || !transform_feedback_active_) {

View File

@@ -124,80 +124,8 @@
* Transform feedback buffer <-- MTL_transform_feedback_buffer_index ~last_buffer+2
*
* Up to a maximum of 31 bindings.
*
* -- SSBO-vertex-fetchmode --
*
* SSBO-vertex-fetchmode is a special option wherein vertex buffers are bound directly
* as buffers in the shader, rather than using the VertexDescriptor and [[stage_in]] vertex
* assembly.
*
* The purpose of this mode is to enable random-access reading of all vertex data. This is
* particularly useful for efficiently converting geometry shaders to Metal shading language,
* as these techniques are not supported natively in Metal.
*
* Geometry shaders can be re-created by firing off a vertex shader with the desired number of
* total output vertices. Each vertex can then read whichever input attributes it needs to
* achieve the output result.
* This manual reading is also used to provide support for GPU_provoking_vertex, wherein the
* output vertex for flat shading needs to change. In these cases, the manual vertex assembly
* can flip which vertices are read within the primitive.
*
* From an efficiency perspective, this is more GPU-friendly than geometry shading, due to improved
* parallelism throughout the whole pipe, and for Apple hardware specifically, there is no
* significant performance loss from manual vertex assembly vs under-the-hood assembly.
*
* This mode works by passing the required vertex descriptor information into the shader
* as uniform data, describing the type, stride, offset, step-mode and buffer index of each
* attribute, such that the shader SSBO-vertex-fetch utility functions know how to extract data.
*
* This also works with indexed rendering,
* by similarly binding the index buffer as a manual buffer.
*
* When this mode is used, the code generation and shader interface generation varies to
* accommodate the required features.
*
* This mode can be enabled in a shader with:
*
* `#pragma USE_SSBO_VERTEX_FETCH(TriangleList/LineList, output_vertex_count_per_input_primitive)`
*
* This mirrors the geometry shader interface `layout(triangle_strip, max_vertices = 3) out;`
*/
/* SSBO vertex fetch attribute uniform parameter names.
* These uniforms are used to pass the information
* required to perform manual vertex assembly within
* the vertex shader.
* Each vertex attribute requires a number of properties
* in order to correctly extract data from the bound vertex
* buffers. */
#ifndef NDEBUG
/* Global. */
# define UNIFORM_SSBO_USES_INDEXED_RENDERING_STR "uniform_ssbo_uses_indexed_rendering"
# define UNIFORM_SSBO_INDEX_MODE_U16_STR "uniform_ssbo_index_mode_u16"
# define UNIFORM_SSBO_INPUT_PRIM_TYPE_STR "uniform_ssbo_input_prim_type"
# define UNIFORM_SSBO_INPUT_VERT_COUNT_STR "uniform_ssbo_input_vert_count"
# define UNIFORM_SSBO_INDEX_BASE_STR "uniform_ssbo_index_base_"
/* Per-attribute. */
# define UNIFORM_SSBO_OFFSET_STR "uniform_ssbo_offset_"
# define UNIFORM_SSBO_STRIDE_STR "uniform_ssbo_stride_"
# define UNIFORM_SSBO_FETCHMODE_STR "uniform_ssbo_fetchmode_"
# define UNIFORM_SSBO_VBO_ID_STR "uniform_ssbo_vbo_id_"
# define UNIFORM_SSBO_TYPE_STR "uniform_ssbo_type_"
#else
/* Global. */
# define UNIFORM_SSBO_USES_INDEXED_RENDERING_STR "_ir"
# define UNIFORM_SSBO_INDEX_MODE_U16_STR "_mu"
# define UNIFORM_SSBO_INPUT_PRIM_TYPE_STR "_pt"
# define UNIFORM_SSBO_INPUT_VERT_COUNT_STR "_vc"
# define UNIFORM_SSBO_INDEX_BASE_STR "_ib"
/* Per-attribute. */
# define UNIFORM_SSBO_OFFSET_STR "_so"
# define UNIFORM_SSBO_STRIDE_STR "_ss"
# define UNIFORM_SSBO_FETCHMODE_STR "_sf"
# define UNIFORM_SSBO_VBO_ID_STR "_sv"
# define UNIFORM_SSBO_TYPE_STR "_st"
#endif
namespace blender::gpu {
struct MSLUniform {
@@ -473,11 +401,6 @@ class MSLGeneratorInterface {
* NOTE: Compute stage will re-use index 0. */
int sampler_argument_buffer_bind_index[3] = {-1, -1, -1};
/*** SSBO Vertex fetch mode. ***/
/* Indicates whether to pass in Vertex Buffer's as a regular buffers instead of using vertex
* assembly in the PSO descriptor. Enabled with special pragma. */
bool uses_ssbo_vertex_fetch_mode;
private:
/* Parent shader instance. */
MTLShader &parent_shader_;
@@ -491,22 +414,6 @@ class MSLGeneratorInterface {
/** Prepare MSLGeneratorInterface from create-info. **/
void prepare_from_createinfo(const shader::ShaderCreateInfo *info);
/* When SSBO Vertex Fetch mode is used, uniforms are used to pass on the required information
* about vertex attribute bindings, in order to perform manual vertex assembly and random-access
* vertex lookup throughout the bound VBOs.
*
* Some parameters are global for the shader, others change with the currently bound
* VertexBuffers, and their format, as they do with regular gpu::Batch's.
*
* (Where ##attr is the attributes name)
* uniform_ssbo_stride_##attr -- Representing the stride between elements of attribute(attr)
* uniform_ssbo_offset_##attr -- Representing the base offset within the vertex
* uniform_ssbo_fetchmode_##attr -- Whether using per-vertex fetch or per-instance fetch
* (0=vert, 1=inst) uniform_ssbo_vbo_id_##attr -- index of the vertex buffer within which the
* data for this attribute is contained uniform_ssbo_type_##attr - The type of data in the
* currently bound buffer -- Could be a mismatch with the Officially reported type. */
void prepare_ssbo_vertex_fetch_uniforms();
/* Samplers. */
bool use_argument_buffer_for_samplers() const;
uint32_t num_samplers_for_stage(ShaderStage stage) const;

View File

@@ -170,66 +170,6 @@ static void extract_and_replace_clipping_distances(std::string &vertex_source,
}
}
static bool extract_ssbo_pragma_info(const MTLShader *shader,
const MSLGeneratorInterface & /*msl_iface*/,
const std::string &in_vertex_src,
MTLPrimitiveType &out_prim_tye,
uint32_t &out_num_output_verts)
{
/* SSBO Vertex-fetch parameter extraction. */
static std::regex use_ssbo_fetch_mode_find(
"#pragma "
"USE_SSBO_VERTEX_FETCH\\(\\s*(TriangleList|LineList|TriangleStrip|\\w+)\\s*,\\s*([0-9]+)\\s*"
"\\)");
/* Perform regex search if pragma string found. */
std::smatch vertex_shader_ssbo_flags;
bool uses_ssbo_fetch = false;
if (in_vertex_src.find("#pragma USE_SSBO_VERTEX_FETCH") != std::string::npos) {
uses_ssbo_fetch = std::regex_search(
in_vertex_src, vertex_shader_ssbo_flags, use_ssbo_fetch_mode_find);
}
if (uses_ssbo_fetch) {
/* Extract Expected output primitive type:
* #pragma USE_SSBO_VERTEX_FETCH(Output Prim Type, num output vertices per input primitive)
*
* Supported Primitive Types (Others can be added if needed, but List types for efficiency):
* - TriangleList
* - LineList
* - TriangleStrip (To be used with caution).
*
* Output vertex count is determined by calculating the number of input primitives, and
* multiplying that by the number of output vertices specified. */
std::string str_output_primitive_type = vertex_shader_ssbo_flags[1].str();
std::string str_output_prim_count_per_vertex = vertex_shader_ssbo_flags[2].str();
/* Ensure output primitive type is valid. */
if (str_output_primitive_type == "TriangleList") {
out_prim_tye = MTLPrimitiveTypeTriangle;
}
else if (str_output_primitive_type == "LineList") {
out_prim_tye = MTLPrimitiveTypeLine;
}
else if (str_output_primitive_type == "TriangleStrip") {
out_prim_tye = MTLPrimitiveTypeTriangleStrip;
}
else {
MTL_LOG_ERROR("Unsupported output primitive type for SSBO VERTEX FETCH MODE. Shader: %s",
shader->name_get().c_str());
return false;
}
/* Assign output num vertices per primitive. */
out_num_output_verts = std::stoi(
std::regex_replace(str_output_prim_count_per_vertex, remove_non_numeric_characters, ""));
BLI_assert(out_num_output_verts > 0);
return true;
}
/* SSBO Vertex fetchmode not used. */
return false;
}
/** \} */
/* -------------------------------------------------------------------- */
@@ -476,31 +416,6 @@ bool MTLShader::generate_msl_from_glsl(const shader::ShaderCreateInfo *info)
shd_builder_->glsl_fragment_source_ = msl_defines_string + shd_builder_->glsl_fragment_source_;
}
/* Extract SSBO usage information from shader pragma:
*
* #pragma USE_SSBO_VERTEX_FETCH(Output Prim Type, num output vertices per input primitive)
*
* This will determine whether SSBO-vertex-fetch
* mode is used for this shader. Returns true if used, and populates output reference
* values with the output prim type and output number of vertices. */
MTLPrimitiveType vertex_fetch_ssbo_output_prim_type = MTLPrimitiveTypeTriangle;
uint32_t vertex_fetch_ssbo_num_output_verts = 0;
msl_iface.uses_ssbo_vertex_fetch_mode = extract_ssbo_pragma_info(
this,
msl_iface,
shd_builder_->glsl_vertex_source_,
vertex_fetch_ssbo_output_prim_type,
vertex_fetch_ssbo_num_output_verts);
if (msl_iface.uses_ssbo_vertex_fetch_mode) {
shader_debug_printf(
"[Shader] SSBO VERTEX FETCH Enabled for Shader '%s' With Output primitive type: %s, "
"vertex count: %u\n",
this->name_get(),
output_primitive_type.c_str(),
vertex_fetch_ssbo_num_output_verts);
}
/**** Extract usage of GL globals. ****/
/* NOTE(METAL): Currently still performing fallback string scan, as info->builtins_ does
* not always contain the usage flag. This can be removed once all appropriate create-info's
@@ -516,8 +431,7 @@ bool MTLShader::generate_msl_from_glsl(const shader::ShaderCreateInfo *info)
shd_builder_->glsl_vertex_source_.find("gl_InstanceID") !=
std::string::npos ||
shd_builder_->glsl_vertex_source_.find("gpu_InstanceIndex") !=
std::string::npos ||
msl_iface.uses_ssbo_vertex_fetch_mode;
std::string::npos;
/* instance ID in GL is `[0, instance_count]` in metal it is
* `[base_instance, base_instance + instance_count]`,
@@ -570,11 +484,6 @@ bool MTLShader::generate_msl_from_glsl(const shader::ShaderCreateInfo *info)
msl_iface.uses_early_fragment_test = info->early_fragment_test_;
}
/* Generate SSBO vertex fetch mode uniform data hooks. */
if (msl_iface.uses_ssbo_vertex_fetch_mode) {
msl_iface.prepare_ssbo_vertex_fetch_uniforms();
}
/* Extract gl_ClipDistances. */
extract_and_replace_clipping_distances(shd_builder_->glsl_vertex_source_, msl_iface);
@@ -603,34 +512,6 @@ bool MTLShader::generate_msl_from_glsl(const shader::ShaderCreateInfo *info)
ss_vertex << "#define ARGUMENT_BUFFER_NUM_SAMPLERS "
<< msl_iface.max_sampler_index_for_stage(ShaderStage::VERTEX) + 1 << std::endl;
}
if (msl_iface.uses_ssbo_vertex_fetch_mode) {
ss_vertex << "#define MTL_SSBO_VERTEX_FETCH 1" << std::endl;
for (const MSLVertexInputAttribute &attr : msl_iface.vertex_input_attributes) {
ss_vertex << "#define SSBO_ATTR_TYPE_" << attr.name << " " << attr.type << std::endl;
}
/* Macro's */
ss_vertex << "#define "
"UNIFORM_SSBO_USES_INDEXED_RENDERING_STR " UNIFORM_SSBO_USES_INDEXED_RENDERING_STR
"\n"
"#define UNIFORM_SSBO_INDEX_MODE_U16_STR " UNIFORM_SSBO_INDEX_MODE_U16_STR
"\n"
"#define UNIFORM_SSBO_INPUT_PRIM_TYPE_STR " UNIFORM_SSBO_INPUT_PRIM_TYPE_STR
"\n"
"#define UNIFORM_SSBO_INPUT_VERT_COUNT_STR " UNIFORM_SSBO_INPUT_VERT_COUNT_STR
"\n"
"#define UNIFORM_SSBO_INDEX_BASE_STR " UNIFORM_SSBO_INDEX_BASE_STR
"\n"
"#define UNIFORM_SSBO_OFFSET_STR " UNIFORM_SSBO_OFFSET_STR
"\n"
"#define UNIFORM_SSBO_STRIDE_STR " UNIFORM_SSBO_STRIDE_STR
"\n"
"#define UNIFORM_SSBO_FETCHMODE_STR " UNIFORM_SSBO_FETCHMODE_STR
"\n"
"#define UNIFORM_SSBO_VBO_ID_STR " UNIFORM_SSBO_VBO_ID_STR
"\n"
"#define UNIFORM_SSBO_TYPE_STR " UNIFORM_SSBO_TYPE_STR "\n";
}
/* Inject common Metal header. */
ss_vertex << msl_iface.msl_patch_default_get() << std::endl << std::endl;
@@ -710,9 +591,7 @@ bool MTLShader::generate_msl_from_glsl(const shader::ShaderCreateInfo *info)
/** Generate structs from MSL Interface. **/
/* Generate VertexIn struct. */
if (!msl_iface.uses_ssbo_vertex_fetch_mode) {
ss_vertex << msl_iface.generate_msl_vertex_in_struct();
}
ss_vertex << msl_iface.generate_msl_vertex_in_struct();
/* Generate Uniform data structs. */
ss_vertex << msl_iface.generate_msl_uniform_structs(ShaderStage::VERTEX);
@@ -744,16 +623,6 @@ bool MTLShader::generate_msl_from_glsl(const shader::ShaderCreateInfo *info)
ss_vertex << "int gpu_ViewportIndex = 0;" << std::endl;
}
/* Global vertex data pointers when using SSBO vertex fetch mode.
* Bound vertex buffers passed in via the entry point function
* are assigned to these pointers to be globally accessible
* from any function within the GLSL source shader. */
if (msl_iface.uses_ssbo_vertex_fetch_mode) {
ss_vertex << "constant uchar** MTL_VERTEX_DATA;" << std::endl;
ss_vertex << "constant ushort* MTL_INDEX_DATA_U16 = nullptr;" << std::endl;
ss_vertex << "constant uint32_t* MTL_INDEX_DATA_U32 = nullptr;" << std::endl;
}
/* Add Texture members.
* These members pack both a texture and a sampler into a single
* struct, as both are needed within texture functions.
@@ -955,12 +824,6 @@ bool MTLShader::generate_msl_from_glsl(const shader::ShaderCreateInfo *info)
/* Update other shader properties. */
uses_gpu_layer = msl_iface.uses_gpu_layer;
uses_gpu_viewport_index = msl_iface.uses_gpu_viewport_index;
use_ssbo_vertex_fetch_mode_ = msl_iface.uses_ssbo_vertex_fetch_mode;
if (msl_iface.uses_ssbo_vertex_fetch_mode) {
ssbo_vertex_fetch_output_prim_type_ = vertex_fetch_ssbo_output_prim_type;
ssbo_vertex_fetch_output_num_verts_ = vertex_fetch_ssbo_num_output_verts;
this->prepare_ssbo_vertex_fetch_metadata();
}
/* Successfully completed GLSL to MSL translation. */
return true;
@@ -1167,111 +1030,6 @@ constexpr size_t const_strlen(const char *str)
return (*str == '\0') ? 0 : const_strlen(str + 1) + 1;
}
void MTLShader::prepare_ssbo_vertex_fetch_metadata()
{
BLI_assert(use_ssbo_vertex_fetch_mode_);
/* Cache global SSBO-vertex-fetch uniforms locations. */
const ShaderInput *inp_prim_type = interface->uniform_get(UNIFORM_SSBO_INPUT_PRIM_TYPE_STR);
const ShaderInput *inp_vert_count = interface->uniform_get(UNIFORM_SSBO_INPUT_VERT_COUNT_STR);
const ShaderInput *inp_uses_indexed_rendering = interface->uniform_get(
UNIFORM_SSBO_USES_INDEXED_RENDERING_STR);
const ShaderInput *inp_uses_index_mode_u16 = interface->uniform_get(
UNIFORM_SSBO_INDEX_MODE_U16_STR);
const ShaderInput *inp_index_base = interface->uniform_get(UNIFORM_SSBO_INDEX_BASE_STR);
this->uni_ssbo_input_prim_type_loc = (inp_prim_type != nullptr) ? inp_prim_type->location : -1;
this->uni_ssbo_input_vert_count_loc = (inp_vert_count != nullptr) ? inp_vert_count->location :
-1;
this->uni_ssbo_index_base_loc = (inp_index_base != nullptr) ? inp_index_base->location : -1;
this->uni_ssbo_uses_indexed_rendering = (inp_uses_indexed_rendering != nullptr) ?
inp_uses_indexed_rendering->location :
-1;
this->uni_ssbo_uses_index_mode_u16 = (inp_uses_index_mode_u16 != nullptr) ?
inp_uses_index_mode_u16->location :
-1;
BLI_assert_msg(this->uni_ssbo_input_prim_type_loc != -1,
"uni_ssbo_input_prim_type_loc uniform location invalid!");
BLI_assert_msg(this->uni_ssbo_input_vert_count_loc != -1,
"uni_ssbo_input_vert_count_loc uniform location invalid!");
BLI_assert_msg(this->uni_ssbo_uses_indexed_rendering != -1,
"uni_ssbo_uses_indexed_rendering uniform location invalid!");
BLI_assert_msg(this->uni_ssbo_uses_index_mode_u16 != -1,
"uni_ssbo_uses_index_mode_u16 uniform location invalid!");
BLI_assert_msg(this->uni_ssbo_index_base_loc != -1,
"uni_ssbo_index_base_loc uniform location invalid!");
/* Prepare SSBO-vertex-fetch attribute uniform location cache. */
MTLShaderInterface *mtl_interface = this->get_interface();
for (int i = 0; i < mtl_interface->get_total_attributes(); i++) {
const MTLShaderInputAttribute &mtl_shader_attribute = mtl_interface->get_attribute(i);
const char *attr_name = mtl_interface->get_name_at_offset(mtl_shader_attribute.name_offset);
/* SSBO-vertex-fetch Attribute data is passed via uniforms. here we need to extract the uniform
* address for each attribute, and we can cache it for later use. */
ShaderSSBOAttributeBinding &cached_ssbo_attr = cached_ssbo_attribute_bindings_[i];
cached_ssbo_attr.attribute_index = i;
constexpr int len_UNIFORM_SSBO_STRIDE_STR = const_strlen(UNIFORM_SSBO_STRIDE_STR);
constexpr int len_UNIFORM_SSBO_OFFSET_STR = const_strlen(UNIFORM_SSBO_OFFSET_STR);
constexpr int len_UNIFORM_SSBO_FETCHMODE_STR = const_strlen(UNIFORM_SSBO_FETCHMODE_STR);
constexpr int len_UNIFORM_SSBO_VBO_ID_STR = const_strlen(UNIFORM_SSBO_VBO_ID_STR);
constexpr int len_UNIFORM_SSBO_TYPE_STR = const_strlen(UNIFORM_SSBO_TYPE_STR);
char strattr_buf_stride[GPU_VERT_ATTR_MAX_LEN + len_UNIFORM_SSBO_STRIDE_STR + 1] =
UNIFORM_SSBO_STRIDE_STR;
char strattr_buf_offset[GPU_VERT_ATTR_MAX_LEN + len_UNIFORM_SSBO_OFFSET_STR + 1] =
UNIFORM_SSBO_OFFSET_STR;
char strattr_buf_fetchmode[GPU_VERT_ATTR_MAX_LEN + len_UNIFORM_SSBO_FETCHMODE_STR + 1] =
UNIFORM_SSBO_FETCHMODE_STR;
char strattr_buf_vbo_id[GPU_VERT_ATTR_MAX_LEN + len_UNIFORM_SSBO_VBO_ID_STR + 1] =
UNIFORM_SSBO_VBO_ID_STR;
char strattr_buf_type[GPU_VERT_ATTR_MAX_LEN + len_UNIFORM_SSBO_TYPE_STR + 1] =
UNIFORM_SSBO_TYPE_STR;
BLI_strncpy(
&strattr_buf_stride[len_UNIFORM_SSBO_STRIDE_STR], attr_name, GPU_VERT_ATTR_MAX_LEN);
BLI_strncpy(
&strattr_buf_offset[len_UNIFORM_SSBO_OFFSET_STR], attr_name, GPU_VERT_ATTR_MAX_LEN);
BLI_strncpy(
&strattr_buf_fetchmode[len_UNIFORM_SSBO_FETCHMODE_STR], attr_name, GPU_VERT_ATTR_MAX_LEN);
BLI_strncpy(
&strattr_buf_vbo_id[len_UNIFORM_SSBO_VBO_ID_STR], attr_name, GPU_VERT_ATTR_MAX_LEN);
BLI_strncpy(&strattr_buf_type[len_UNIFORM_SSBO_TYPE_STR], attr_name, GPU_VERT_ATTR_MAX_LEN);
/* Fetch uniform locations and cache for fast access. */
const ShaderInput *inp_unf_stride = mtl_interface->uniform_get(strattr_buf_stride);
const ShaderInput *inp_unf_offset = mtl_interface->uniform_get(strattr_buf_offset);
const ShaderInput *inp_unf_fetchmode = mtl_interface->uniform_get(strattr_buf_fetchmode);
const ShaderInput *inp_unf_vbo_id = mtl_interface->uniform_get(strattr_buf_vbo_id);
const ShaderInput *inp_unf_attr_type = mtl_interface->uniform_get(strattr_buf_type);
BLI_assert(inp_unf_stride != nullptr);
BLI_assert(inp_unf_offset != nullptr);
BLI_assert(inp_unf_fetchmode != nullptr);
BLI_assert(inp_unf_vbo_id != nullptr);
BLI_assert(inp_unf_attr_type != nullptr);
cached_ssbo_attr.uniform_stride = (inp_unf_stride != nullptr) ? inp_unf_stride->location : -1;
cached_ssbo_attr.uniform_offset = (inp_unf_offset != nullptr) ? inp_unf_offset->location : -1;
cached_ssbo_attr.uniform_fetchmode = (inp_unf_fetchmode != nullptr) ?
inp_unf_fetchmode->location :
-1;
cached_ssbo_attr.uniform_vbo_id = (inp_unf_vbo_id != nullptr) ? inp_unf_vbo_id->location : -1;
cached_ssbo_attr.uniform_attr_type = (inp_unf_attr_type != nullptr) ?
inp_unf_attr_type->location :
-1;
BLI_assert(cached_ssbo_attr.uniform_offset != -1);
BLI_assert(cached_ssbo_attr.uniform_stride != -1);
BLI_assert(cached_ssbo_attr.uniform_fetchmode != -1);
BLI_assert(cached_ssbo_attr.uniform_vbo_id != -1);
BLI_assert(cached_ssbo_attr.uniform_attr_type != -1);
}
}
void MSLGeneratorInterface::prepare_from_createinfo(const shader::ShaderCreateInfo *info)
{
/** Assign info. */
@@ -1673,27 +1431,6 @@ uint32_t MSLGeneratorInterface::get_sampler_argument_buffer_bind_index(ShaderSta
return sampler_argument_buffer_bind_index[get_shader_stage_index(stage)];
}
void MSLGeneratorInterface::prepare_ssbo_vertex_fetch_uniforms()
{
BLI_assert(this->uses_ssbo_vertex_fetch_mode);
/* Add Special Uniforms for SSBO vertex fetch mode. */
this->uniforms.append(MSLUniform(Type::INT, UNIFORM_SSBO_INPUT_PRIM_TYPE_STR, false));
this->uniforms.append(MSLUniform(Type::INT, UNIFORM_SSBO_INPUT_VERT_COUNT_STR, false));
this->uniforms.append(MSLUniform(Type::INT, UNIFORM_SSBO_USES_INDEXED_RENDERING_STR, false));
this->uniforms.append(MSLUniform(Type::INT, UNIFORM_SSBO_INDEX_MODE_U16_STR, false));
this->uniforms.append(MSLUniform(Type::INT, UNIFORM_SSBO_INDEX_BASE_STR, false));
for (const MSLVertexInputAttribute &attr : this->vertex_input_attributes) {
const std::string &uname = attr.name;
this->uniforms.append(MSLUniform(Type::INT, UNIFORM_SSBO_STRIDE_STR + uname, false));
this->uniforms.append(MSLUniform(Type::INT, UNIFORM_SSBO_OFFSET_STR + uname, false));
this->uniforms.append(MSLUniform(Type::INT, UNIFORM_SSBO_FETCHMODE_STR + uname, false));
this->uniforms.append(MSLUniform(Type::INT, UNIFORM_SSBO_VBO_ID_STR + uname, false));
this->uniforms.append(MSLUniform(Type::INT, UNIFORM_SSBO_TYPE_STR + uname, false));
}
}
std::string MSLGeneratorInterface::generate_msl_vertex_entry_stub()
{
static const char *shader_stage_inst_name = get_shader_stage_instance_name(ShaderStage::VERTEX);
@@ -2029,21 +1766,10 @@ std::string MSLGeneratorInterface::generate_msl_vertex_inputs_string()
std::stringstream out;
bool is_first_parameter = true;
if (this->uses_ssbo_vertex_fetch_mode) {
/* Vertex Buffers bound as raw buffers. */
for (int i = 0; i < MTL_SSBO_VERTEX_FETCH_MAX_VBOS; i++) {
out << parameter_delimiter(is_first_parameter) << "\tconstant uchar* MTL_VERTEX_DATA_" << i
<< " [[buffer(" << i << ")]]\n";
}
out << parameter_delimiter(is_first_parameter)
<< "\tconstant ushort* MTL_INDEX_DATA[[buffer(MTL_SSBO_VERTEX_FETCH_IBO_INDEX)]]";
}
else {
if (this->vertex_input_attributes.is_empty() == false) {
/* Vertex Buffers use input assembly. */
out << get_stage_class_name(ShaderStage::VERTEX) << "::VertexIn v_in [[stage_in]]";
is_first_parameter = false;
}
if (this->vertex_input_attributes.is_empty() == false) {
/* Vertex Buffers use input assembly. */
out << get_stage_class_name(ShaderStage::VERTEX) << "::VertexIn v_in [[stage_in]]";
is_first_parameter = false;
}
if (this->uniforms.is_empty() == false) {
@@ -2248,7 +1974,7 @@ std::string MSLGeneratorInterface::generate_msl_vertex_in_struct()
* float4 __internal_modelmatrix_2 [[attribute(2)]];
* float4 __internal_modelmatrix_3 [[attribute(3)]];
*/
if (is_matrix_type(in_attr.type) && !this->uses_ssbo_vertex_fetch_mode) {
if (is_matrix_type(in_attr.type)) {
for (int elem = 0; elem < get_matrix_location_count(in_attr.type); elem++) {
out << "\t" << get_matrix_subtype(in_attr.type) << " __internal_" << in_attr.name << elem
<< " [[attribute(" << (in_attr.layout_location + elem) << ")]];" << std::endl;
@@ -2629,27 +2355,6 @@ std::string MSLGeneratorInterface::generate_msl_vertex_attribute_input_populatio
{
static const char *shader_stage_inst_name = get_shader_stage_instance_name(ShaderStage::VERTEX);
/* SSBO Vertex Fetch mode does not require local attribute population,
* we only need to pass over the buffer pointer references. */
if (this->uses_ssbo_vertex_fetch_mode) {
std::stringstream out;
out << "const constant uchar* GLOBAL_MTL_VERTEX_DATA[MTL_SSBO_VERTEX_FETCH_MAX_VBOS] = {"
<< std::endl;
for (int i = 0; i < MTL_SSBO_VERTEX_FETCH_MAX_VBOS; i++) {
char delimiter = (i < MTL_SSBO_VERTEX_FETCH_MAX_VBOS - 1) ? ',' : ' ';
out << "\t\tMTL_VERTEX_DATA_" << i << delimiter << std::endl;
}
out << "};" << std::endl;
out << "\t" << shader_stage_inst_name << ".MTL_VERTEX_DATA = GLOBAL_MTL_VERTEX_DATA;"
<< std::endl;
out << "\t" << shader_stage_inst_name << ".MTL_INDEX_DATA_U16 = MTL_INDEX_DATA;" << std::endl;
out << "\t" << shader_stage_inst_name
<< ".MTL_INDEX_DATA_U32 = reinterpret_cast<constant "
"uint32_t*>(MTL_INDEX_DATA);"
<< std::endl;
return out.str();
}
/* Populate local attribute variables. */
std::stringstream out;
out << "\t/* Copy Vertex Stage-in attributes into local variables */" << std::endl;
@@ -3210,24 +2915,19 @@ MTLShaderInterface *MSLGeneratorInterface::bake_shader_interface(
this->vertex_input_attributes[attribute].name +
std::to_string(elem);
/* IF Using SSBO vertex Fetch, we do not need to expose other dummy attributes in the
* shader interface, only the first one for the whole matrix, as we can pass whatever data
* we want in this mode, and do not need to split attributes. */
if (elem == 0 || !this->uses_ssbo_vertex_fetch_mode) {
interface->add_input_attribute(
name_buffer_copystr(&interface->name_buffer_,
_internal_name.c_str(),
name_buffer_size,
name_buffer_offset),
this->vertex_input_attributes[attribute].layout_location + elem,
mtl_datatype_to_vertex_type(mtl_type),
0,
size,
c_offset,
(elem == 0) ?
get_matrix_location_count(this->vertex_input_attributes[attribute].type) :
0);
}
interface->add_input_attribute(
name_buffer_copystr(&interface->name_buffer_,
_internal_name.c_str(),
name_buffer_size,
name_buffer_offset),
this->vertex_input_attributes[attribute].layout_location + elem,
mtl_datatype_to_vertex_type(mtl_type),
0,
size,
c_offset,
(elem == 0) ?
get_matrix_location_count(this->vertex_input_attributes[attribute].type) :
0);
c_offset += size;
}
shader_debug_printf(

View File

@@ -2,10 +2,6 @@
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/* Global parameters. */
#define MTL_SSBO_VERTEX_FETCH_MAX_VBOS 6 /* buffer bind 0..5 */
#define MTL_SSBO_VERTEX_FETCH_IBO_INDEX MTL_SSBO_VERTEX_FETCH_MAX_VBOS
/* Add Types as needed (Also need to be added to mtl_shader.h). */
#define GPU_SHADER_ATTR_TYPE_FLOAT 0
#define GPU_SHADER_ATTR_TYPE_INT 1

View File

@@ -407,7 +407,7 @@ void MTLStateManager::set_provoking_vert(const eGPUProvokingVertex /*vert*/)
/* NOTE(Metal): Provoking vertex is not a feature in the Metal API.
* Shaders are handled on a case-by-case basis using a modified vertex shader.
* For example, wireframe rendering and edit-mesh shaders utilize an SSBO-based
* vertex fetching mechanism which considers the inverse convention for flat
* vertex pulling mechanism which considers the inverse convention for flat
* shading, to ensure consistent results with OpenGL. */
}

View File

@@ -187,15 +187,6 @@ class GLShader : public Shader {
void uniform_float(int location, int comp_len, int array_size, const float *data) override;
void uniform_int(int location, int comp_len, int array_size, const int *data) override;
/* Unused: SSBO vertex fetch draw parameters. */
bool get_uses_ssbo_vertex_fetch() const override
{
return false;
}
int get_ssbo_vertex_fetch_output_num_verts() const override
{
return 0;
}
/** DEPRECATED: Kept only because of BGL API. */
int program_handle_get() const override;

View File

@@ -827,77 +827,6 @@ template<int N, int M> inline matrix<float, N, M> operator-(matrix<float, N, M>
return a * -1.0;
}
/* SSBO Vertex Fetch Mode. */
#ifdef MTL_SSBO_VERTEX_FETCH
/**
* Enabled when geometry is passed via raw buffer bindings, rather than using
* vertex assembly in the vertex-descriptor.
*
* To describe the layout of input attribute data, we will generate uniforms (defaulting to 0)
* with the names per unique input attribute with name `attr`:
*
* - uniform_ssbo_stride_##attr -- Representing the stride between element.
* - uniform_ssbo_offset_##attr -- Representing the base offset within the vertex.
* - uniform_ssbo_fetchmode_##attr - Whether using per-vertex (=0) or per-instance fetch (=1).
* - uniform_ssbo_vbo_id_##attr - buffer binding index for VBO with data for this attribute.
* - uniform_ssbo_type_##attr - The type of data in the currently bound buffer.
*
* If the uniform_ssbo_type_* does not match with the desired type, then it is the responsibility
* of the shader to perform the conversion. Types should always be read as the raw attribute type,
* and then converted. e.g. If the uniform_ssbo_type_* is `int`, but we want to read it to be
* normalized to a float.
* The implementation should query the attribute type using vertex_fetch_get_attr_type(attr_name):
*
* \code{.cc}
* float fweight = 0.0;
* if(vertex_fetch_get_attr_type(in_weight) == GPU_SHADER_ATTR_TYPE_INT) {
* int iweight = vertex_fetch_attribute(gl_VertexID, in_weight, int);
* fweight = (float)iweight/(float)INT32_MAX;
* } else {
* fweight = = vertex_fetch_attribute(gl_VertexID, in_weight, float);
* }
* \endcode
*
* Note: These uniforms are generated as part of the same data block used for regular uniforms
* and attribute data is written prior to each draw call, depending on the configuration of
* the vertex descriptor for an MTLBatch or MTLImmedaite call. */
# define PPCAT_NX(A, B) A##B
# define PPCAT(A, B) PPCAT_NX(A, B)
# define RESOLVE_VERTEX(v_id) \
((UNIFORM_SSBO_USES_INDEXED_RENDERING_STR > 0) ? \
(((UNIFORM_SSBO_INDEX_MODE_U16_STR > 0) ? MTL_INDEX_DATA_U16[v_id] : \
MTL_INDEX_DATA_U32[v_id]) + \
UNIFORM_SSBO_INDEX_BASE_STR) : \
v_id)
# define ATTR_TYPE(attr) PPCAT(SSBO_ATTR_TYPE_, attr)
# define vertex_fetch_attribute_raw(n, attr, type) \
(reinterpret_cast<constant type *>( \
&MTL_VERTEX_DATA[PPCAT(UNIFORM_SSBO_VBO_ID_STR, attr)] \
[(PPCAT(UNIFORM_SSBO_STRIDE_STR, attr) * \
((PPCAT(UNIFORM_SSBO_FETCHMODE_STR, attr)) ? gl_InstanceID : n)) + \
PPCAT(UNIFORM_SSBO_OFFSET_STR, attr)]))[0]
# define vertex_fetch_attribute(n, attr, type) \
vertex_fetch_attribute_raw(RESOLVE_VERTEX(n), attr, type)
# define vertex_id_from_index_id(n) RESOLVE_VERTEX(n)
# define vertex_fetch_get_input_prim_type() UNIFORM_SSBO_INPUT_PRIM_TYPE_STR
# define vertex_fetch_get_input_vert_count() UNIFORM_SSBO_INPUT_VERT_COUNT_STR
# define vertex_fetch_get_attr_type(attr) PPCAT(UNIFORM_SSBO_TYPE_STR, attr)
# define vertex_fetch_get_index_base() UNIFORM_SSBO_INDEX_BASE_STR
/* Must mirror GPU_primitive.hh. */
# define GPU_PRIM_POINTS 0
# define GPU_PRIM_LINES 1
# define GPU_PRIM_TRIS 2
# define GPU_PRIM_LINE_STRIP 3
# define GPU_PRIM_LINE_LOOP 4
# define GPU_PRIM_TRI_STRIP 5
# define GPU_PRIM_TRI_FAN 6
# define GPU_PRIM_LINES_ADJ 7
# define GPU_PRIM_TRIS_ADJ 8
# define GPU_PRIM_LINE_STRIP_ADJ 9
#endif
/* Common Functions. */
#define dFdx(x) dfdx(x)
#define dFdy(x) dfdy(x)

View File

@@ -94,16 +94,6 @@ class VKShader : public Shader {
std::string geometry_layout_declare(const shader::ShaderCreateInfo &info) const override;
std::string compute_layout_declare(const shader::ShaderCreateInfo &info) const override;
/* Unused: SSBO vertex fetch draw parameters. */
bool get_uses_ssbo_vertex_fetch() const override
{
return false;
}
int get_ssbo_vertex_fetch_output_num_verts() const override
{
return 0;
}
/* DEPRECATED: Kept only because of BGL API. */
int program_handle_get() const override;