Changeset View
Changeset View
Standalone View
Standalone View
source/blender/gpu/metal/mtl_batch.mm
| Show First 20 Lines • Show All 148 Lines • ▼ Show 20 Lines | for (uint32_t n_idx = 0; n_idx < a->name_len; n_idx++) { | ||||
| MTL_LOG_WARNING( | MTL_LOG_WARNING( | ||||
| "MTLBatch: Could not find attribute with name '%s' (defined in active vertex format) " | "MTLBatch: Could not find attribute with name '%s' (defined in active vertex format) " | ||||
| "in the shader interface for shader '%s'\n", | "in the shader interface for shader '%s'\n", | ||||
| name, | name, | ||||
| interface->get_name()); | interface->get_name()); | ||||
| continue; | continue; | ||||
| } | } | ||||
| /* Fetch metal attribute information. */ | /* Fetch metal attribute information (ShaderInput->binding is used to fetch the corresponding | ||||
| const MTLShaderInputAttribute &mtl_attr = interface->get_attribute(input->location); | * slot. */ | ||||
| const MTLShaderInputAttribute &mtl_attr = interface->get_attribute(input->binding); | |||||
| BLI_assert(mtl_attr.location >= 0); | BLI_assert(mtl_attr.location >= 0); | ||||
| /* Verify that the attribute location from the shader interface | /* Verify that the attribute location from the shader interface | ||||
| * matches the attribute location returned. */ | * matches the attribute location returned in the input table. These should always be the | ||||
| * same. */ | |||||
| BLI_assert(mtl_attr.location == input->location); | BLI_assert(mtl_attr.location == input->location); | ||||
| /* Check if attribute is already present in the given slot. */ | /* Check if attribute is already present in the given slot. */ | ||||
| if ((~attr_mask) & (1 << mtl_attr.location)) { | if ((~attr_mask) & (1 << mtl_attr.location)) { | ||||
| MTL_LOG_INFO( | MTL_LOG_INFO( | ||||
| " -- [Batch] Skipping attribute with input location %d (As one is already bound)\n", | " -- [Batch] Skipping attribute with input location %d (As one is already bound)\n", | ||||
| mtl_attr.location); | mtl_attr.location); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 72 Lines • ▼ Show 20 Lines | for (uint32_t n_idx = 0; n_idx < a->name_len; n_idx++) { | ||||
| * the offset by 16 bytes. */ | * the offset by 16 bytes. */ | ||||
| desc.vertex_descriptor.attributes[mtl_attr.location + i].offset = | desc.vertex_descriptor.attributes[mtl_attr.location + i].offset = | ||||
| attribute_offset + i * 16; | attribute_offset + i * 16; | ||||
| /* All source data for a matrix is in the same singular buffer. */ | /* All source data for a matrix is in the same singular buffer. */ | ||||
| desc.vertex_descriptor.attributes[mtl_attr.location + i].buffer_index = | desc.vertex_descriptor.attributes[mtl_attr.location + i].buffer_index = | ||||
| buffer_index; | buffer_index; | ||||
| /* Update total attribute account. */ | /* Update total attribute account. */ | ||||
| desc.vertex_descriptor.num_attributes = max_ii( | desc.vertex_descriptor.total_attributes++; | ||||
| mtl_attr.location + i + 1, desc.vertex_descriptor.num_attributes); | desc.vertex_descriptor.max_attribute_value = max_ii( | ||||
| mtl_attr.location + i, desc.vertex_descriptor.max_attribute_value); | |||||
| MTL_LOG_INFO("-- Sub-Attrib Location: %d, offset: %d, buffer index: %d\n", | MTL_LOG_INFO("-- Sub-Attrib Location: %d, offset: %d, buffer index: %d\n", | ||||
| mtl_attr.location + i, | mtl_attr.location + i, | ||||
| attribute_offset + i * 16, | attribute_offset + i * 16, | ||||
| buffer_index); | buffer_index); | ||||
| /* Update attribute used-slot mask for array elements. */ | |||||
| attr_mask &= ~(1 << (mtl_attr.location + i)); | |||||
| } | } | ||||
| MTL_LOG_INFO( | MTL_LOG_INFO( | ||||
| "Float4x4 attribute type added for '%s' at attribute locations: %d to %d\n", | "Float4x4 attribute type added for '%s' at attribute locations: %d to %d\n", | ||||
| name, | name, | ||||
| mtl_attr.location, | mtl_attr.location, | ||||
| mtl_attr.location + 3); | mtl_attr.location + 3); | ||||
| } | } | ||||
| /* Ensure we are not exceeding the attribute limit. */ | /* Ensure we are not exceeding the attribute limit. */ | ||||
| BLI_assert(desc.vertex_descriptor.num_attributes <= MTL_MAX_VERTEX_INPUT_ATTRIBUTES); | BLI_assert(desc.vertex_descriptor.max_attribute_value < | ||||
| MTL_MAX_VERTEX_INPUT_ATTRIBUTES); | |||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| /* Handle Any required format conversions. | /* Handle Any required format conversions. | ||||
| * NOTE(Metal): If there is a mis-match between the format of an attribute | * NOTE(Metal): If there is a mis-match between the format of an attribute | ||||
| * in the shader interface, and the specified format in the VertexBuffer VertexFormat, | * in the shader interface, and the specified format in the VertexBuffer VertexFormat, | ||||
| * we need to perform a format conversion. | * we need to perform a format conversion. | ||||
| ▲ Show 20 Lines • Show All 51 Lines • ▼ Show 20 Lines | for (uint32_t n_idx = 0; n_idx < a->name_len; n_idx++) { | ||||
| mtl_attr.format; | mtl_attr.format; | ||||
| desc.vertex_descriptor.attributes[mtl_attr.location].format_conversion_mode = | desc.vertex_descriptor.attributes[mtl_attr.location].format_conversion_mode = | ||||
| (GPUVertFetchMode)a->fetch_mode; | (GPUVertFetchMode)a->fetch_mode; | ||||
| BLI_assert(desc.vertex_descriptor.attributes[mtl_attr.location].format != | BLI_assert(desc.vertex_descriptor.attributes[mtl_attr.location].format != | ||||
| MTLVertexFormatInvalid); | MTLVertexFormatInvalid); | ||||
| } | } | ||||
| desc.vertex_descriptor.attributes[mtl_attr.location].offset = attribute_offset; | desc.vertex_descriptor.attributes[mtl_attr.location].offset = attribute_offset; | ||||
| desc.vertex_descriptor.attributes[mtl_attr.location].buffer_index = buffer_index; | desc.vertex_descriptor.attributes[mtl_attr.location].buffer_index = buffer_index; | ||||
| desc.vertex_descriptor.num_attributes = ((mtl_attr.location + 1) > | desc.vertex_descriptor.max_attribute_value = | ||||
| desc.vertex_descriptor.num_attributes) ? | ((mtl_attr.location) > desc.vertex_descriptor.max_attribute_value) ? | ||||
| (mtl_attr.location + 1) : | (mtl_attr.location) : | ||||
| desc.vertex_descriptor.num_attributes; | desc.vertex_descriptor.max_attribute_value; | ||||
| desc.vertex_descriptor.total_attributes++; | |||||
| /* SSBO Vertex Fetch attribute bind. */ | /* SSBO Vertex Fetch attribute bind. */ | ||||
| if (active_shader_->get_uses_ssbo_vertex_fetch()) { | if (active_shader_->get_uses_ssbo_vertex_fetch()) { | ||||
| BLI_assert_msg(desc.vertex_descriptor.attributes[mtl_attr.location].format == | BLI_assert_msg(desc.vertex_descriptor.attributes[mtl_attr.location].format == | ||||
| mtl_attr.format, | mtl_attr.format, | ||||
| "SSBO Vertex Fetch does not support attribute conversion."); | "SSBO Vertex Fetch does not support attribute conversion."); | ||||
| MTLSSBOAttribute ssbo_attr( | MTLSSBOAttribute ssbo_attr( | ||||
| mtl_attr.index, | mtl_attr.index, | ||||
| buffer_index, | buffer_index, | ||||
| attribute_offset, | attribute_offset, | ||||
| buffer_stride, | buffer_stride, | ||||
| MTLShader::ssbo_vertex_type_to_attr_type( | MTLShader::ssbo_vertex_type_to_attr_type( | ||||
| desc.vertex_descriptor.attributes[mtl_attr.location].format), | desc.vertex_descriptor.attributes[mtl_attr.location].format), | ||||
| instanced); | instanced); | ||||
| active_shader_->ssbo_vertex_fetch_bind_attribute(ssbo_attr); | active_shader_->ssbo_vertex_fetch_bind_attribute(ssbo_attr); | ||||
| desc.vertex_descriptor.ssbo_attributes[desc.vertex_descriptor.num_ssbo_attributes] = | desc.vertex_descriptor.ssbo_attributes[desc.vertex_descriptor.num_ssbo_attributes] = | ||||
| ssbo_attr; | ssbo_attr; | ||||
| desc.vertex_descriptor.num_ssbo_attributes++; | desc.vertex_descriptor.num_ssbo_attributes++; | ||||
| } | } | ||||
| /* NOTE: We are setting num_attributes to be up to the maximum found index, because of | /* NOTE: We are setting max_attribute_value to be up to the maximum found index, because | ||||
| * this, it is possible that we may skip over certain attributes if they were not in the | * of this, it is possible that we may skip over certain attributes if they were not in | ||||
| * source GPUVertFormat. */ | * the source GPUVertFormat. */ | ||||
| MTL_LOG_INFO( | MTL_LOG_INFO( | ||||
| " -- Batch Attribute(%d): ORIG Shader Format: %d, ORIG Vert format: %d, Vert " | " -- Batch Attribute(%d): ORIG Shader Format: %d, ORIG Vert format: %d, Vert " | ||||
| "components: %d, Fetch Mode %d --> FINAL FORMAT: %d\n", | "components: %d, Fetch Mode %d --> FINAL FORMAT: %d\n", | ||||
| mtl_attr.location, | mtl_attr.location, | ||||
| (int)mtl_attr.format, | (int)mtl_attr.format, | ||||
| (int)a->comp_type, | (int)a->comp_type, | ||||
| (int)a->comp_len, | (int)a->comp_len, | ||||
| (int)a->fetch_mode, | (int)a->fetch_mode, | ||||
| ▲ Show 20 Lines • Show All 97 Lines • ▼ Show 20 Lines | if (G.debug & G_DEBUG_GPU) { | ||||
| [rec pushDebugGroup:[NSString stringWithFormat:@"batch_bind%@(shader: %s)", | [rec pushDebugGroup:[NSString stringWithFormat:@"batch_bind%@(shader: %s)", | ||||
| this->elem ? @"(indexed)" : @"", | this->elem ? @"(indexed)" : @"", | ||||
| active_shader_->get_interface()->get_name()]]; | active_shader_->get_interface()->get_name()]]; | ||||
| [rec insertDebugSignpost:[NSString | [rec insertDebugSignpost:[NSString | ||||
| stringWithFormat:@"batch_bind%@(shader: %s)", | stringWithFormat:@"batch_bind%@(shader: %s)", | ||||
| this->elem ? @"(indexed)" : @"", | this->elem ? @"(indexed)" : @"", | ||||
| active_shader_->get_interface()->get_name()]]; | active_shader_->get_interface()->get_name()]]; | ||||
| } | } | ||||
| /*** Bind Vertex Buffers and Index Buffers **/ | |||||
| /* SSBO Vertex Fetch Buffer bindings. */ | /* SSBO Vertex Fetch Buffer bindings. */ | ||||
| if (uses_ssbo_fetch) { | if (uses_ssbo_fetch) { | ||||
| /* SSBO Vertex Fetch - Bind Index Buffer to appropriate slot -- if used. */ | /* SSBO Vertex Fetch - Bind Index Buffer to appropriate slot -- if used. */ | ||||
| id<MTLBuffer> idx_buffer = nil; | id<MTLBuffer> idx_buffer = nil; | ||||
| GPUPrimType final_prim_type = this->prim_type; | GPUPrimType final_prim_type = this->prim_type; | ||||
| if (mtl_elem != nullptr) { | if (mtl_elem != nullptr) { | ||||
| ▲ Show 20 Lines • Show All 48 Lines • ▼ Show 20 Lines | GPU_shader_uniform_vector_int(reinterpret_cast<GPUShader *>(wrap(active_shader_)), | ||||
| 1, | 1, | ||||
| (const int *)(&v_count)); | (const int *)(&v_count)); | ||||
| } | } | ||||
| /* Ensure Context Render Pipeline State is fully setup and ready to execute the draw. | /* 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. */ | * This should happen after all other final rendering setup is complete. */ | ||||
| MTLPrimitiveType mtl_prim_type = gpu_prim_type_to_metal(this->prim_type); | MTLPrimitiveType mtl_prim_type = gpu_prim_type_to_metal(this->prim_type); | ||||
| if (!ctx->ensure_render_pipeline_state(mtl_prim_type)) { | if (!ctx->ensure_render_pipeline_state(mtl_prim_type)) { | ||||
| printf("FAILED TO ENSURE RENDER PIPELINE STATE"); | MTL_LOG_ERROR("Failed to prepare and apply render pipeline state.\n"); | ||||
| BLI_assert(false); | BLI_assert(false); | ||||
| if (G.debug & G_DEBUG_GPU) { | if (G.debug & G_DEBUG_GPU) { | ||||
| [rec popDebugGroup]; | [rec popDebugGroup]; | ||||
| } | } | ||||
| return nil; | return nil; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 152 Lines • ▼ Show 20 Lines | if (!this->vao_cache.insert(pair)) { | ||||
| "[Performance Warning] cache is full (Size: %d), vertex descriptor will not be cached\n", | "[Performance Warning] cache is full (Size: %d), vertex descriptor will not be cached\n", | ||||
| GPU_VAO_STATIC_LEN); | GPU_VAO_STATIC_LEN); | ||||
| } | } | ||||
| } | } | ||||
| /* DEBUG: verify if our attribute bindings have been fully provided as expected. */ | /* DEBUG: verify if our attribute bindings have been fully provided as expected. */ | ||||
| #if MTL_DEBUG_SHADER_ATTRIBUTES == 1 | #if MTL_DEBUG_SHADER_ATTRIBUTES == 1 | ||||
| if (attr_mask != 0) { | if (attr_mask != 0) { | ||||
| for (uint16_t mask = 1, a = 0; a < 16; a++, mask <<= 1) { | /* Attributes are not necessarily contiguous. */ | ||||
| if (attr_mask & mask) { | for (int i = 0; i < active_shader_->get_interface()->get_total_attributes(); i++) { | ||||
| /* Fallback for setting default attributes, for missed slots. Attributes flagged with | const MTLShaderInputAttribute &attr = active_shader_->get_interface()->get_attribute(i); | ||||
| * 'MTLVertexFormatInvalid' in the vertex descriptor are bound to a NULL buffer during PSO | if (attr_mask & (1 << attr.location)) { | ||||
| * creation. */ | MTL_LOG_WARNING( | ||||
| MTL_LOG_WARNING("MTLBatch: Missing expected attribute '%s' at index '%d' for shader: %s\n", | "Warning: Missing expected attribute '%s' with location: %u in shader %s (attr " | ||||
| this->active_shader->interface->attributes[a].name, | "number: %u)\n", | ||||
| a, | active_shader_->get_interface()->get_name_at_offset(attr.name_offset), | ||||
| interface->name); | attr.location, | ||||
| /* Ensure any assigned attribute has not been given an invalid format. This should not | active_shader_->name_get(), | ||||
| * occur and may be the result of an unsupported attribute type conversion. */ | i); | ||||
| BLI_assert(desc.attributes[a].format == MTLVertexFormatInvalid); | |||||
| /* If an attribute is not included, then format in vertex descriptor should be invalid due | |||||
| * to nil assignment. */ | |||||
| BLI_assert(desc.vertex_descriptor.attributes[attr.location].format == | |||||
| MTLVertexFormatInvalid); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| #endif | #endif | ||||
| } | } | ||||
| void MTLBatch::draw_advanced(int v_first, int v_count, int i_first, int i_count) | void MTLBatch::draw_advanced(int v_first, int v_count, int i_first, int i_count) | ||||
| { | { | ||||
| ▲ Show 20 Lines • Show All 273 Lines • Show Last 20 Lines | |||||