Changeset View
Changeset View
Standalone View
Standalone View
source/blender/gpu/metal/mtl_shader.mm
| Show First 20 Lines • Show All 118 Lines • ▼ Show 20 Lines | for (const MTLRenderPipelineStateInstance *pso_inst : pso_cache_.values()) { | ||||
| } | } | ||||
| if (pso_inst->pso) { | if (pso_inst->pso) { | ||||
| [pso_inst->pso release]; | [pso_inst->pso release]; | ||||
| } | } | ||||
| delete pso_inst; | delete pso_inst; | ||||
| } | } | ||||
| pso_cache_.clear(); | pso_cache_.clear(); | ||||
| /* Free Compute pipeline state object. */ | |||||
| if (compute_pso_instance_.compute) { | |||||
| [compute_pso_instance_.compute release]; | |||||
| compute_pso_instance_.compute = nil; | |||||
| } | |||||
| if (compute_pso_instance_.pso) { | |||||
| [compute_pso_instance_.pso release]; | |||||
| compute_pso_instance_.pso = nil; | |||||
| } | |||||
| /* NOTE(Metal): #ShaderInterface deletion is handled in the super destructor `~Shader()`. */ | /* NOTE(Metal): #ShaderInterface deletion is handled in the super destructor `~Shader()`. */ | ||||
| } | } | ||||
| valid_ = false; | valid_ = false; | ||||
| if (shd_builder_ != nullptr) { | if (shd_builder_ != nullptr) { | ||||
| delete shd_builder_; | delete shd_builder_; | ||||
| shd_builder_ = nullptr; | shd_builder_ = nullptr; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 41 Lines • ▼ Show 20 Lines | void MTLShader::fragment_shader_from_glsl(MutableSpan<const char *> sources) | ||||
| for (int i = 0; i < sources.size(); i++) { | for (int i = 0; i < sources.size(); i++) { | ||||
| ss << sources[i] << std::endl; | ss << sources[i] << std::endl; | ||||
| } | } | ||||
| shd_builder_->glsl_fragment_source_ = ss.str(); | shd_builder_->glsl_fragment_source_ = ss.str(); | ||||
| } | } | ||||
| void MTLShader::compute_shader_from_glsl(MutableSpan<const char *> sources) | void MTLShader::compute_shader_from_glsl(MutableSpan<const char *> sources) | ||||
| { | { | ||||
| /* Flag source as not being compiled from native MSL. */ | |||||
| BLI_assert(shd_builder_ != nullptr); | |||||
| shd_builder_->source_from_msl_ = false; | |||||
| /* Remove #version tag entry. */ | /* Remove #version tag entry. */ | ||||
| sources[0] = ""; | sources[0] = ""; | ||||
| /* TODO(Metal): Support compute shaders in Metal. */ | /* Consolidate GLSL compute sources. */ | ||||
| MTL_LOG_WARNING( | std::stringstream ss; | ||||
| "MTLShader::compute_shader_from_glsl - Compute shaders currently unsupported!\n"); | for (int i = 0; i < sources.size(); i++) { | ||||
| ss << sources[i] << std::endl; | |||||
| } | |||||
| shd_builder_->glsl_compute_source_ = ss.str(); | |||||
| } | } | ||||
| bool MTLShader::finalize(const shader::ShaderCreateInfo *info) | bool MTLShader::finalize(const shader::ShaderCreateInfo *info) | ||||
| { | { | ||||
| /* Check if Shader has already been finalized. */ | /* Check if Shader has already been finalized. */ | ||||
| if (this->is_valid()) { | if (this->is_valid()) { | ||||
| MTL_LOG_ERROR("Shader (%p) '%s' has already been finalized!\n", this, this->name_get()); | MTL_LOG_ERROR("Shader (%p) '%s' has already been finalized!\n", this, this->name_get()); | ||||
| } | } | ||||
| /* Compute shaders. */ | |||||
| bool is_compute = false; | |||||
| if (shd_builder_->glsl_compute_source_.size() > 0) { | |||||
| BLI_assert_msg(info != nullptr, "Compute shaders must use CreateInfo.\n"); | |||||
| BLI_assert_msg(!shd_builder_->source_from_msl_, "Compute shaders must compile from GLSL."); | |||||
| is_compute = true; | |||||
| } | |||||
| /* Perform GLSL to MSL source translation. */ | /* Perform GLSL to MSL source translation. */ | ||||
| BLI_assert(shd_builder_ != nullptr); | BLI_assert(shd_builder_ != nullptr); | ||||
| if (!shd_builder_->source_from_msl_) { | if (!shd_builder_->source_from_msl_) { | ||||
| bool success = generate_msl_from_glsl(info); | bool success = generate_msl_from_glsl(info); | ||||
| if (!success) { | if (!success) { | ||||
| /* GLSL to MSL translation has failed, or is unsupported for this shader. */ | /* GLSL to MSL translation has failed, or is unsupported for this shader. */ | ||||
| valid_ = false; | valid_ = false; | ||||
| BLI_assert_msg(false, "Shader translation from GLSL to MSL has failed. \n"); | BLI_assert_msg(false, "Shader translation from GLSL to MSL has failed. \n"); | ||||
| Show All 14 Lines | bool MTLShader::finalize(const shader::ShaderCreateInfo *info) | ||||
| BLI_assert(mtl_interface != nullptr); | BLI_assert(mtl_interface != nullptr); | ||||
| /* Verify Context handle, fetch device and compile shader. */ | /* Verify Context handle, fetch device and compile shader. */ | ||||
| BLI_assert(context_); | BLI_assert(context_); | ||||
| id<MTLDevice> device = context_->device; | id<MTLDevice> device = context_->device; | ||||
| BLI_assert(device != nil); | BLI_assert(device != nil); | ||||
| /* Ensure source and stage entry-point names are set. */ | /* Ensure source and stage entry-point names are set. */ | ||||
| BLI_assert(shd_builder_ != nullptr); | |||||
| if (is_compute) { | |||||
| /* Compute path. */ | |||||
| BLI_assert([compute_function_name_ length] > 0); | |||||
| BLI_assert([shd_builder_->msl_source_compute_ length] > 0); | |||||
| } | |||||
| else { | |||||
| /* Vertex/Fragment path. */ | |||||
| BLI_assert([vertex_function_name_ length] > 0); | BLI_assert([vertex_function_name_ length] > 0); | ||||
| if (transform_feedback_type_ == GPU_SHADER_TFB_NONE) { | if (transform_feedback_type_ == GPU_SHADER_TFB_NONE) { | ||||
| BLI_assert([fragment_function_name_ length] > 0); | BLI_assert([fragment_function_name_ length] > 0); | ||||
| } | } | ||||
| BLI_assert(shd_builder_ != nullptr); | |||||
| BLI_assert([shd_builder_->msl_source_vert_ length] > 0); | BLI_assert([shd_builder_->msl_source_vert_ length] > 0); | ||||
| } | |||||
| @autoreleasepool { | @autoreleasepool { | ||||
| MTLCompileOptions *options = [[[MTLCompileOptions alloc] init] autorelease]; | MTLCompileOptions *options = [[[MTLCompileOptions alloc] init] autorelease]; | ||||
| options.languageVersion = MTLLanguageVersion2_2; | options.languageVersion = MTLLanguageVersion2_2; | ||||
| options.fastMathEnabled = YES; | options.fastMathEnabled = YES; | ||||
| NSString *source_to_compile = shd_builder_->msl_source_vert_; | NSString *source_to_compile = shd_builder_->msl_source_vert_; | ||||
| for (int src_stage = 0; src_stage <= 1; src_stage++) { | |||||
| source_to_compile = (src_stage == 0) ? shd_builder_->msl_source_vert_ : | /* Vertex/Fragment compile stages 0 and/or 1. | ||||
| shd_builder_->msl_source_frag_; | * Compute shaders compile as stage 2. */ | ||||
| ShaderStage initial_stage = (is_compute) ? ShaderStage::COMPUTE : ShaderStage::VERTEX; | |||||
| ShaderStage src_stage = initial_stage; | |||||
| uint8_t total_stages = (is_compute) ? 1 : 2; | |||||
| for (int stage_count = 0; stage_count < total_stages; stage_count++) { | |||||
| source_to_compile = (src_stage == ShaderStage::VERTEX) ? | |||||
| shd_builder_->msl_source_vert_ : | |||||
| ((src_stage == ShaderStage::COMPUTE) ? | |||||
| shd_builder_->msl_source_compute_ : | |||||
| shd_builder_->msl_source_frag_); | |||||
| /* Transform feedback, skip compilation. */ | /* Transform feedback, skip compilation. */ | ||||
| if (src_stage == 1 && (transform_feedback_type_ != GPU_SHADER_TFB_NONE)) { | if (src_stage == ShaderStage::FRAGMENT && | ||||
| (transform_feedback_type_ != GPU_SHADER_TFB_NONE)) { | |||||
| shader_library_frag_ = nil; | shader_library_frag_ = nil; | ||||
| break; | break; | ||||
| } | } | ||||
| /* Concatenate common source. */ | /* Concatenate common source. */ | ||||
| NSString *str = [NSString stringWithUTF8String:datatoc_mtl_shader_common_msl]; | NSString *str = [NSString stringWithUTF8String:datatoc_mtl_shader_common_msl]; | ||||
| NSString *source_with_header_a = [str stringByAppendingString:source_to_compile]; | NSString *source_with_header_a = [str stringByAppendingString:source_to_compile]; | ||||
| Show All 14 Lines | for (int stage_count = 0; stage_count < total_stages; stage_count++) { | ||||
| NSError *error = nullptr; | NSError *error = nullptr; | ||||
| id<MTLLibrary> library = [device newLibraryWithSource:source_with_header | id<MTLLibrary> library = [device newLibraryWithSource:source_with_header | ||||
| options:options | options:options | ||||
| error:&error]; | error:&error]; | ||||
| if (error) { | if (error) { | ||||
| /* Only exit out if genuine error and not warning. */ | /* Only exit out if genuine error and not warning. */ | ||||
| if ([[error localizedDescription] rangeOfString:@"Compilation succeeded"].location == | if ([[error localizedDescription] rangeOfString:@"Compilation succeeded"].location == | ||||
| NSNotFound) { | NSNotFound) { | ||||
| NSLog( | NSLog(@"Compile Error - Metal Shader Library (Stage: %hhu), error %@ \n", | ||||
| @"Compile Error - Metal Shader Library (Stage: %d), error %@ \n", src_stage, error); | src_stage, | ||||
| error); | |||||
| BLI_assert(false); | BLI_assert(false); | ||||
| /* Release temporary compilation resources. */ | /* Release temporary compilation resources. */ | ||||
| delete shd_builder_; | delete shd_builder_; | ||||
| shd_builder_ = nullptr; | shd_builder_ = nullptr; | ||||
| return false; | return false; | ||||
| } | } | ||||
| } | } | ||||
| MTL_LOG_INFO("Successfully compiled Metal Shader Library (Stage: %d) for shader; %s\n", | |||||
| src_stage, | |||||
| name); | |||||
| BLI_assert(library != nil); | BLI_assert(library != nil); | ||||
| if (src_stage == 0) { | |||||
| switch (src_stage) { | |||||
| case ShaderStage::VERTEX: { | |||||
| /* Retain generated library and assign debug name. */ | /* Retain generated library and assign debug name. */ | ||||
| shader_library_vert_ = library; | shader_library_vert_ = library; | ||||
| [shader_library_vert_ retain]; | [shader_library_vert_ retain]; | ||||
| shader_library_vert_.label = [NSString stringWithUTF8String:this->name]; | shader_library_vert_.label = [NSString stringWithUTF8String:this->name]; | ||||
| } | } break; | ||||
| else { | case ShaderStage::FRAGMENT: { | ||||
| /* Retain generated library for fragment shader and assign debug name. */ | /* Retain generated library for fragment shader and assign debug name. */ | ||||
| shader_library_frag_ = library; | shader_library_frag_ = library; | ||||
| [shader_library_frag_ retain]; | [shader_library_frag_ retain]; | ||||
| shader_library_frag_.label = [NSString stringWithUTF8String:this->name]; | shader_library_frag_.label = [NSString stringWithUTF8String:this->name]; | ||||
| } break; | |||||
| case ShaderStage::COMPUTE: { | |||||
| /* Retain generated library for fragment shader and assign debug name. */ | |||||
| shader_library_compute_ = library; | |||||
| [shader_library_compute_ retain]; | |||||
| shader_library_compute_.label = [NSString stringWithUTF8String:this->name]; | |||||
| } break; | |||||
| case ShaderStage::ANY: { | |||||
| /* Supress warnings. */ | |||||
| BLI_assert_unreachable(); | |||||
| } break; | |||||
| } | } | ||||
| [source_with_header autorelease]; | [source_with_header autorelease]; | ||||
| /* Move onto next compilation stage. */ | |||||
| if (!is_compute) { | |||||
| src_stage = ShaderStage::FRAGMENT; | |||||
| } | |||||
| else { | |||||
| break; | |||||
| } | |||||
| } | } | ||||
| pso_descriptor_.label = [NSString stringWithUTF8String:this->name]; | |||||
| /* Prepare descriptor. */ | /* Create descriptors. | ||||
| * Each shader type requires a differing descriptor. */ | |||||
| if (!is_compute) { | |||||
| /* Prepare Render pipeline descriptor. */ | |||||
| pso_descriptor_ = [[MTLRenderPipelineDescriptor alloc] init]; | pso_descriptor_ = [[MTLRenderPipelineDescriptor alloc] init]; | ||||
| [pso_descriptor_ retain]; | [pso_descriptor_ retain]; | ||||
| pso_descriptor_.label = [NSString stringWithUTF8String:this->name]; | |||||
| } | |||||
| /* Shader has successfully been created. */ | /* Shader has successfully been created. */ | ||||
| valid_ = true; | valid_ = true; | ||||
| /* Prepare backing data storage for local uniforms. */ | /* Prepare backing data storage for local uniforms. */ | ||||
| const MTLShaderUniformBlock &push_constant_block = mtl_interface->get_push_constant_block(); | const MTLShaderUniformBlock &push_constant_block = mtl_interface->get_push_constant_block(); | ||||
| if (push_constant_block.size > 0) { | if (push_constant_block.size > 0) { | ||||
| push_constant_data_ = MEM_callocN(push_constant_block.size, __func__); | push_constant_data_ = MEM_callocN(push_constant_block.size, __func__); | ||||
| this->push_constant_bindstate_mark_dirty(true); | this->push_constant_bindstate_mark_dirty(true); | ||||
| } | } | ||||
| else { | else { | ||||
| push_constant_data_ = nullptr; | push_constant_data_ = nullptr; | ||||
| } | } | ||||
| /* If this is a compute shader, bake PSO for compute straight-away. */ | |||||
| if (is_compute) { | |||||
| this->bake_compute_pipeline_state(context_); | |||||
| } | |||||
| } | } | ||||
| /* Release temporary compilation resources. */ | /* Release temporary compilation resources. */ | ||||
| delete shd_builder_; | delete shd_builder_; | ||||
| shd_builder_ = nullptr; | shd_builder_ = nullptr; | ||||
| return true; | return true; | ||||
| } | } | ||||
| const MTLComputePipelineStateInstance &MTLShader::get_compute_pipeline_state() | |||||
| { | |||||
| return this->compute_pso_instance_; | |||||
| } | |||||
| void MTLShader::transform_feedback_names_set(Span<const char *> name_list, | void MTLShader::transform_feedback_names_set(Span<const char *> name_list, | ||||
| const eGPUShaderTFBType geom_type) | const eGPUShaderTFBType geom_type) | ||||
| { | { | ||||
| tf_output_name_list_.clear(); | tf_output_name_list_.clear(); | ||||
| for (int i = 0; i < name_list.size(); i++) { | for (int i = 0; i < name_list.size(); i++) { | ||||
| tf_output_name_list_.append(std::string(name_list[i])); | tf_output_name_list_.append(std::string(name_list[i])); | ||||
| } | } | ||||
| transform_feedback_type_ = geom_type; | transform_feedback_type_ = geom_type; | ||||
| ▲ Show 20 Lines • Show All 208 Lines • ▼ Show 20 Lines | void MTLShader::set_vertex_function_name(NSString *vert_function_name) | ||||
| vertex_function_name_ = vert_function_name; | vertex_function_name_ = vert_function_name; | ||||
| } | } | ||||
| void MTLShader::set_fragment_function_name(NSString *frag_function_name) | void MTLShader::set_fragment_function_name(NSString *frag_function_name) | ||||
| { | { | ||||
| fragment_function_name_ = frag_function_name; | fragment_function_name_ = frag_function_name; | ||||
| } | } | ||||
| void MTLShader::set_compute_function_name(NSString *compute_function_name) | |||||
| { | |||||
| compute_function_name_ = compute_function_name; | |||||
| } | |||||
| void MTLShader::shader_source_from_msl(NSString *input_vertex_source, | void MTLShader::shader_source_from_msl(NSString *input_vertex_source, | ||||
| NSString *input_fragment_source) | NSString *input_fragment_source) | ||||
| { | { | ||||
| BLI_assert(shd_builder_ != nullptr); | BLI_assert(shd_builder_ != nullptr); | ||||
| shd_builder_->msl_source_vert_ = input_vertex_source; | shd_builder_->msl_source_vert_ = input_vertex_source; | ||||
| shd_builder_->msl_source_frag_ = input_fragment_source; | shd_builder_->msl_source_frag_ = input_fragment_source; | ||||
| shd_builder_->source_from_msl_ = true; | shd_builder_->source_from_msl_ = true; | ||||
| } | } | ||||
| void MTLShader::shader_compute_source_from_msl(NSString *input_compute_source) | |||||
| { | |||||
| BLI_assert(shd_builder_ != nullptr); | |||||
| shd_builder_->msl_source_compute_ = input_compute_source; | |||||
| shd_builder_->source_from_msl_ = true; | |||||
| } | |||||
| void MTLShader::set_interface(MTLShaderInterface *interface) | void MTLShader::set_interface(MTLShaderInterface *interface) | ||||
| { | { | ||||
| /* Assign gpu::Shader super-class interface. */ | /* Assign gpu::Shader super-class interface. */ | ||||
| BLI_assert(Shader::interface == nullptr); | BLI_assert(Shader::interface == nullptr); | ||||
| Shader::interface = interface; | Shader::interface = interface; | ||||
| } | } | ||||
| /** \} */ | /** \} */ | ||||
| ▲ Show 20 Lines • Show All 404 Lines • ▼ Show 20 Lines | for (int color_attachment = 0; color_attachment < GPU_FB_MAX_COLOR_ATTACHMENT; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| desc.depthAttachmentPixelFormat = current_state.depth_attachment_format; | desc.depthAttachmentPixelFormat = current_state.depth_attachment_format; | ||||
| desc.stencilAttachmentPixelFormat = current_state.stencil_attachment_format; | desc.stencilAttachmentPixelFormat = current_state.stencil_attachment_format; | ||||
| /* Compile PSO */ | /* Compile PSO */ | ||||
| MTLAutoreleasedRenderPipelineReflection reflection_data; | MTLAutoreleasedRenderPipelineReflection reflection_data; | ||||
| id<MTLRenderPipelineState> pso = [ctx->device | id<MTLRenderPipelineState> pso = [ctx->device | ||||
| newRenderPipelineStateWithDescriptor:desc | newRenderPipelineStateWithDescriptor:desc | ||||
| options:MTLPipelineOptionBufferTypeInfo | options:MTLPipelineOptionBufferTypeInfo | ||||
| reflection:&reflection_data | reflection:&reflection_data | ||||
| error:&error]; | error:&error]; | ||||
| if (error) { | if (error) { | ||||
| NSLog(@"Failed to create PSO for shader: %s error %@\n", this->name, error); | NSLog(@"Failed to create PSO for shader: %s error %@\n", this->name, error); | ||||
| BLI_assert(false); | BLI_assert(false); | ||||
| return nullptr; | return nullptr; | ||||
| } | } | ||||
| else if (!pso) { | else if (!pso) { | ||||
| NSLog(@"Failed to create PSO for shader: %s, but no error was provided!\n", this->name); | NSLog(@"Failed to create PSO for shader: %s, but no error was provided!\n", this->name); | ||||
| BLI_assert(false); | BLI_assert(false); | ||||
| return nullptr; | return nullptr; | ||||
| } | } | ||||
| else { | else { | ||||
| #ifndef NDEBUG | |||||
| NSLog(@"Successfully compiled PSO for shader: %s (Metal Context: %p)\n", this->name, ctx); | NSLog(@"Successfully compiled PSO for shader: %s (Metal Context: %p)\n", this->name, ctx); | ||||
| #endif | |||||
| } | } | ||||
| /* Prepare pipeline state instance. */ | /* Prepare pipeline state instance. */ | ||||
| MTLRenderPipelineStateInstance *pso_inst = new MTLRenderPipelineStateInstance(); | MTLRenderPipelineStateInstance *pso_inst = new MTLRenderPipelineStateInstance(); | ||||
| pso_inst->vert = desc.vertexFunction; | pso_inst->vert = desc.vertexFunction; | ||||
| pso_inst->frag = desc.fragmentFunction; | pso_inst->frag = desc.fragmentFunction; | ||||
| pso_inst->pso = pso; | pso_inst->pso = pso; | ||||
| pso_inst->base_uniform_buffer_index = MTL_uniform_buffer_base_index; | pso_inst->base_uniform_buffer_index = MTL_uniform_buffer_base_index; | ||||
| ▲ Show 20 Lines • Show All 86 Lines • ▼ Show 20 Lines | #endif | ||||
| /* Insert into pso cache. */ | /* Insert into pso cache. */ | ||||
| pso_cache_.add(pipeline_descriptor, pso_inst); | pso_cache_.add(pipeline_descriptor, pso_inst); | ||||
| shader_debug_printf("PSO CACHE: Stored new variant in PSO cache for shader '%s'\n", | shader_debug_printf("PSO CACHE: Stored new variant in PSO cache for shader '%s'\n", | ||||
| this->name); | this->name); | ||||
| return pso_inst; | return pso_inst; | ||||
| } | } | ||||
| } | } | ||||
| bool MTLShader::bake_compute_pipeline_state(MTLContext *ctx) | |||||
| { | |||||
| /* NOTE(Metal): Bakes and caches a PSO for compute. */ | |||||
| BLI_assert(this); | |||||
| BLI_assert(this->is_valid()); | |||||
| BLI_assert(shader_library_compute_ != nil); | |||||
| if (compute_pso_instance_.pso == nil) { | |||||
| /* Prepare Compute Pipeline Descriptor. */ | |||||
| /* Setup function specialization constants, used to modify and optimize | |||||
| * generated code based on current render pipeline configuration. */ | |||||
| MTLFunctionConstantValues *values = [[MTLFunctionConstantValues new] autorelease]; | |||||
| /* Offset the bind index for Uniform buffers such that they begin after the VBO | |||||
| * buffer bind slots. `MTL_uniform_buffer_base_index` is passed as a function | |||||
| * specialization constant, customized per unique pipeline state permutation. | |||||
| * | |||||
| * For Compute shaders, this offset is always zero, but this needs setting as | |||||
| * it is expected as part of the common Metal shader header.*/ | |||||
| int MTL_uniform_buffer_base_index = 0; | |||||
| [values setConstantValue:&MTL_uniform_buffer_base_index | |||||
| type:MTLDataTypeInt | |||||
| withName:@"MTL_uniform_buffer_base_index"]; | |||||
| /* TODO: SSBO binding base index. */ | |||||
| /* Compile compute function. */ | |||||
| NSError *error = nullptr; | |||||
| id<MTLFunction> compute_function = [shader_library_compute_ | |||||
| newFunctionWithName:compute_function_name_ | |||||
| constantValues:values | |||||
| error:&error]; | |||||
| if (error) { | |||||
| NSLog(@"Compile Error - Metal Shader compute function, error %@", error); | |||||
| /* Only exit out if genuine error and not warning */ | |||||
| if ([[error localizedDescription] rangeOfString:@"Compilation succeeded"].location == | |||||
| NSNotFound) { | |||||
| BLI_assert(false); | |||||
| return false; | |||||
| } | |||||
| } | |||||
| /* Compile PSO. */ | |||||
| id<MTLComputePipelineState> pso = [ctx->device | |||||
| newComputePipelineStateWithFunction:compute_function | |||||
| error:&error]; | |||||
| if (error) { | |||||
| NSLog(@"Failed to create PSO for compute shader: %s error %@\n", this->name, error); | |||||
| BLI_assert(false); | |||||
| return false; | |||||
| } | |||||
| else if (!pso) { | |||||
| NSLog(@"Failed to create PSO for compute shader: %s, but no error was provided!\n", | |||||
| this->name); | |||||
| BLI_assert(false); | |||||
| return false; | |||||
| } | |||||
| else { | |||||
| #ifndef NDEBUG | |||||
| NSLog(@"Successfully compiled compute PSO for shader: %s (Metal Context: %p)\n", | |||||
| this->name, | |||||
| ctx); | |||||
| #endif | |||||
| } | |||||
| /* Gather reflection data and create MTLComputePipelineStateInstance to store results. */ | |||||
| compute_pso_instance_.compute = [compute_function retain]; | |||||
| compute_pso_instance_.pso = [pso retain]; | |||||
| compute_pso_instance_.base_uniform_buffer_index = MTL_uniform_buffer_base_index; | |||||
| /* TODO: Add SSBO base buffer index support. */ | |||||
| compute_pso_instance_.base_ssbo_buffer_index = -1; | |||||
| } | |||||
| return true; | |||||
| } | |||||
| /** \} */ | /** \} */ | ||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| /** \name SSBO-vertex-fetch-mode attribute control. | /** \name SSBO-vertex-fetch-mode attribute control. | ||||
| * \{ */ | * \{ */ | ||||
| int MTLShader::ssbo_vertex_type_to_attr_type(MTLVertexFormat attribute_type) | int MTLShader::ssbo_vertex_type_to_attr_type(MTLVertexFormat attribute_type) | ||||
| { | { | ||||
| ▲ Show 20 Lines • Show All 172 Lines • Show Last 20 Lines | |||||