Changeset View
Standalone View
source/blender/gpu/metal/mtl_context.mm
| /* SPDX-License-Identifier: GPL-2.0-or-later */ | /* SPDX-License-Identifier: GPL-2.0-or-later */ | ||||||||||||||||||||||||||||||
| /** \file | /** \file | ||||||||||||||||||||||||||||||
| * \ingroup gpu | * \ingroup gpu | ||||||||||||||||||||||||||||||
| */ | */ | ||||||||||||||||||||||||||||||
| #include "mtl_context.hh" | #include "mtl_context.hh" | ||||||||||||||||||||||||||||||
| #include "mtl_debug.hh" | #include "mtl_debug.hh" | ||||||||||||||||||||||||||||||
| #include "mtl_shader.hh" | |||||||||||||||||||||||||||||||
| #include "mtl_shader_interface.hh" | |||||||||||||||||||||||||||||||
| #include "mtl_state.hh" | #include "mtl_state.hh" | ||||||||||||||||||||||||||||||
| #include "DNA_userdef_types.h" | #include "DNA_userdef_types.h" | ||||||||||||||||||||||||||||||
| #include "GPU_capabilities.h" | #include "GPU_capabilities.h" | ||||||||||||||||||||||||||||||
| using namespace blender; | using namespace blender; | ||||||||||||||||||||||||||||||
| using namespace blender::gpu; | using namespace blender::gpu; | ||||||||||||||||||||||||||||||
| namespace blender::gpu { | namespace blender::gpu { | ||||||||||||||||||||||||||||||
| /* Global memory manager. */ | /* Global memory manager. */ | ||||||||||||||||||||||||||||||
| MTLBufferPool MTLContext::global_memory_manager; | MTLBufferPool MTLContext::global_memory_manager; | ||||||||||||||||||||||||||||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||||||||||||||||||||||||||||
| /** \name MTLContext | /** \name MTLContext | ||||||||||||||||||||||||||||||
| * \{ */ | * \{ */ | ||||||||||||||||||||||||||||||
| /* Placeholder functions */ | /* Placeholder functions */ | ||||||||||||||||||||||||||||||
| MTLContext::MTLContext(void *ghost_window) : memory_manager(*this), main_command_buffer(*this) | MTLContext::MTLContext(void *ghost_window) : memory_manager(*this), main_command_buffer(*this) | ||||||||||||||||||||||||||||||
| { | { | ||||||||||||||||||||||||||||||
| /* Init debug. */ | /* Init debug. */ | ||||||||||||||||||||||||||||||
| debug::mtl_debug_init(); | debug::mtl_debug_init(); | ||||||||||||||||||||||||||||||
| /* Device creation. | |||||||||||||||||||||||||||||||
| * TODO(Metal): This is a temporary initialisation path to enable testing of features | |||||||||||||||||||||||||||||||
| * and shader compilation tests. Future functionality should fetch the existing device | |||||||||||||||||||||||||||||||
| * from GHOST_ContextCGL.mm. Plumbing to be updated in future. */ | |||||||||||||||||||||||||||||||
| this->device = MTLCreateSystemDefaultDevice(); | |||||||||||||||||||||||||||||||
| /* Initialize command buffer state. */ | /* Initialize command buffer state. */ | ||||||||||||||||||||||||||||||
| this->main_command_buffer.prepare(); | this->main_command_buffer.prepare(); | ||||||||||||||||||||||||||||||
| /* Initialise imm and pipeline state */ | |||||||||||||||||||||||||||||||
| this->pipeline_state.initialised = false; | |||||||||||||||||||||||||||||||
| /* Frame management. */ | /* Frame management. */ | ||||||||||||||||||||||||||||||
| is_inside_frame_ = false; | is_inside_frame_ = false; | ||||||||||||||||||||||||||||||
| current_frame_index_ = 0; | current_frame_index_ = 0; | ||||||||||||||||||||||||||||||
| /* Prepare null data buffer */ | |||||||||||||||||||||||||||||||
| null_buffer_ = nil; | |||||||||||||||||||||||||||||||
| null_attribute_buffer_ = nil; | |||||||||||||||||||||||||||||||
| /* Create FrameBuffer handles. */ | /* Create FrameBuffer handles. */ | ||||||||||||||||||||||||||||||
| MTLFrameBuffer *mtl_front_left = new MTLFrameBuffer(this, "front_left"); | MTLFrameBuffer *mtl_front_left = new MTLFrameBuffer(this, "front_left"); | ||||||||||||||||||||||||||||||
| MTLFrameBuffer *mtl_back_left = new MTLFrameBuffer(this, "back_left"); | MTLFrameBuffer *mtl_back_left = new MTLFrameBuffer(this, "back_left"); | ||||||||||||||||||||||||||||||
| this->front_left = mtl_front_left; | this->front_left = mtl_front_left; | ||||||||||||||||||||||||||||||
| this->back_left = mtl_back_left; | this->back_left = mtl_back_left; | ||||||||||||||||||||||||||||||
| this->active_fb = this->back_left; | this->active_fb = this->back_left; | ||||||||||||||||||||||||||||||
| /* Prepare platform and capabilities. (NOTE: With METAL, this needs to be done after CTX | /* Prepare platform and capabilities. (NOTE: With METAL, this needs to be done after CTX | ||||||||||||||||||||||||||||||
| * initialization). */ | * initialization). */ | ||||||||||||||||||||||||||||||
| MTLBackend::platform_init(this); | MTLBackend::platform_init(this); | ||||||||||||||||||||||||||||||
| MTLBackend::capabilities_init(this); | MTLBackend::capabilities_init(this); | ||||||||||||||||||||||||||||||
| /* Initialize Metal modules. */ | /* Initialize Metal modules. */ | ||||||||||||||||||||||||||||||
| this->memory_manager.init(); | this->memory_manager.init(); | ||||||||||||||||||||||||||||||
| this->state_manager = new MTLStateManager(this); | this->state_manager = new MTLStateManager(this); | ||||||||||||||||||||||||||||||
| Show All 35 Lines | MTLContext::~MTLContext() | ||||||||||||||||||||||||||||||
| /* Release Sampler States. */ | /* Release Sampler States. */ | ||||||||||||||||||||||||||||||
| for (int i = 0; i < GPU_SAMPLER_MAX; i++) { | for (int i = 0; i < GPU_SAMPLER_MAX; i++) { | ||||||||||||||||||||||||||||||
| if (sampler_state_cache_[i] != nil) { | if (sampler_state_cache_[i] != nil) { | ||||||||||||||||||||||||||||||
| [sampler_state_cache_[i] release]; | [sampler_state_cache_[i] release]; | ||||||||||||||||||||||||||||||
| sampler_state_cache_[i] = nil; | sampler_state_cache_[i] = nil; | ||||||||||||||||||||||||||||||
| } | } | ||||||||||||||||||||||||||||||
| } | } | ||||||||||||||||||||||||||||||
| if (null_buffer_) { | |||||||||||||||||||||||||||||||
| [null_buffer_ release]; | |||||||||||||||||||||||||||||||
| } | |||||||||||||||||||||||||||||||
| if (null_attribute_buffer_) { | |||||||||||||||||||||||||||||||
| [null_attribute_buffer_ release]; | |||||||||||||||||||||||||||||||
| } | |||||||||||||||||||||||||||||||
| } | } | ||||||||||||||||||||||||||||||
| void MTLContext::begin_frame() | void MTLContext::begin_frame() | ||||||||||||||||||||||||||||||
| { | { | ||||||||||||||||||||||||||||||
| BLI_assert(MTLBackend::get()->is_inside_render_boundary()); | BLI_assert(MTLBackend::get()->is_inside_render_boundary()); | ||||||||||||||||||||||||||||||
| if (this->get_inside_frame()) { | if (this->get_inside_frame()) { | ||||||||||||||||||||||||||||||
| return; | return; | ||||||||||||||||||||||||||||||
| } | } | ||||||||||||||||||||||||||||||
| ▲ Show 20 Lines • Show All 118 Lines • ▼ Show 20 Lines | MTLFrameBuffer *MTLContext::get_current_framebuffer() | ||||||||||||||||||||||||||||||
| return last_bound ? last_bound : this->get_default_framebuffer(); | return last_bound ? last_bound : this->get_default_framebuffer(); | ||||||||||||||||||||||||||||||
| } | } | ||||||||||||||||||||||||||||||
| MTLFrameBuffer *MTLContext::get_default_framebuffer() | MTLFrameBuffer *MTLContext::get_default_framebuffer() | ||||||||||||||||||||||||||||||
| { | { | ||||||||||||||||||||||||||||||
| return static_cast<MTLFrameBuffer *>(this->back_left); | return static_cast<MTLFrameBuffer *>(this->back_left); | ||||||||||||||||||||||||||||||
| } | } | ||||||||||||||||||||||||||||||
| MTLShader *MTLContext::get_active_shader() | |||||||||||||||||||||||||||||||
| { | |||||||||||||||||||||||||||||||
| return this->pipeline_state.active_shader; | |||||||||||||||||||||||||||||||
| } | |||||||||||||||||||||||||||||||
fclem: missing space between functions. same below. | |||||||||||||||||||||||||||||||
| id<MTLBuffer> MTLContext::get_null_buffer() | |||||||||||||||||||||||||||||||
| { | |||||||||||||||||||||||||||||||
| if (null_buffer_ != nil) { | |||||||||||||||||||||||||||||||
| return null_buffer_; | |||||||||||||||||||||||||||||||
Not Done Inline ActionsIt is not a define. Use lower case. Also why does it have to be that big? Where is this null buffer used? fclem: It is not a define. Use lower case.
Also why does it have to be that big? Where is this null… | |||||||||||||||||||||||||||||||
Not Done Inline ActionsThe size was likely excessive, so have reduced. It is used for any place where a vertex buffer may be required but is not yet ready. This is often a fallback, though there are a few cases where UBOs are bound but no data has yet been uploaded. (This is usually for cases where the UBO is not actually accessed, i.e. lighting data where no lights are present, but the binding still needs to be satisfied). So in practise, it only needs to be as big as the largest possible UBO. I believe 4k should be sufficient, though this may still be overkill. MichaelPW: The size was likely excessive, so have reduced. It is used for any place where a vertex buffer… | |||||||||||||||||||||||||||||||
Not Done Inline Actions
This should trigger an assert. You shouldn't have to satisfy bindings that are user fault. We check for that on debug builds but not release if I remember correctly. This was already crashing on some Mac in the past with Opengl. So I do expect that even pyGPU users will fulfill their bindings. Also, if this is really needed, this should definitely use calloc and discard it right away. The memset is not even the right size (should be sizeof(null_data) which is sizeof(uint32_t) * NULL_BUF_SIZE) . But you still allocate the UBO with NULL_BUF_SIZE which I guess is in bytes? then why uint32_t? would be happy if all of this wasn't necessary :D fclem: >This is usually for cases where the UBO is not actually accessed, i.e. lighting data where no… | |||||||||||||||||||||||||||||||
| } | |||||||||||||||||||||||||||||||
Not Done Inline ActionsThis is likely to increase executable size. Prefer calloc(). fclem: This is likely to increase executable size. Prefer `calloc()`. | |||||||||||||||||||||||||||||||
| static const int null_buffer_size = 4096; | |||||||||||||||||||||||||||||||
| null_buffer_ = [this->device newBufferWithLength:null_buffer_size | |||||||||||||||||||||||||||||||
| options:MTLResourceStorageModeManaged]; | |||||||||||||||||||||||||||||||
| [null_buffer_ retain]; | |||||||||||||||||||||||||||||||
| uint32_t *null_data = (uint32_t *)calloc(0, null_buffer_size); | |||||||||||||||||||||||||||||||
| memcpy([null_buffer_ contents], null_data, null_buffer_size); | |||||||||||||||||||||||||||||||
| [null_buffer_ didModifyRange:NSMakeRange(0, null_buffer_size)]; | |||||||||||||||||||||||||||||||
| free(null_data); | |||||||||||||||||||||||||||||||
| BLI_assert(null_buffer_ != nil); | |||||||||||||||||||||||||||||||
| return null_buffer_; | |||||||||||||||||||||||||||||||
Not Done Inline Actions
This is not in the style guide as it is not enforced, but prefer to use early out instead of indenting a block. fclem: This is not in the style guide as it is not enforced, but prefer to use early out instead of… | |||||||||||||||||||||||||||||||
| } | |||||||||||||||||||||||||||||||
| id<MTLBuffer> MTLContext::get_null_attribute_buffer() | |||||||||||||||||||||||||||||||
| { | |||||||||||||||||||||||||||||||
| if (null_attribute_buffer_ != nil) { | |||||||||||||||||||||||||||||||
| return null_attribute_buffer_; | |||||||||||||||||||||||||||||||
| } | |||||||||||||||||||||||||||||||
| /* Allocate Null buffer if it has not yet been created. | |||||||||||||||||||||||||||||||
Not Done Inline ActionsNot a define, use lower case. fclem: Not a define, use lower case. | |||||||||||||||||||||||||||||||
| * Min buffer size is 256 bytes -- though we only need 64 bytes of data. */ | |||||||||||||||||||||||||||||||
| static const int null_buffer_size = 256; | |||||||||||||||||||||||||||||||
| null_attribute_buffer_ = [this->device newBufferWithLength:null_buffer_size | |||||||||||||||||||||||||||||||
| options:MTLResourceStorageModeManaged]; | |||||||||||||||||||||||||||||||
| BLI_assert(null_attribute_buffer_ != nil); | |||||||||||||||||||||||||||||||
| [null_attribute_buffer_ retain]; | |||||||||||||||||||||||||||||||
| float data[4] = {0.0f, 0.0f, 0.0f, 1.0f}; | |||||||||||||||||||||||||||||||
| memcpy([null_attribute_buffer_ contents], data, sizeof(float) * 4); | |||||||||||||||||||||||||||||||
| [null_attribute_buffer_ didModifyRange:NSMakeRange(0, null_buffer_size)]; | |||||||||||||||||||||||||||||||
| return null_attribute_buffer_; | |||||||||||||||||||||||||||||||
| } | |||||||||||||||||||||||||||||||
| /** \} */ | /** \} */ | ||||||||||||||||||||||||||||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||||||||||||||||||||||||||||
| /** \name Global Context State | /** \name Global Context State | ||||||||||||||||||||||||||||||
| * \{ */ | * \{ */ | ||||||||||||||||||||||||||||||
| /* Metal Context Pipeline State. */ | /* Metal Context Pipeline State. */ | ||||||||||||||||||||||||||||||
| void MTLContext::pipeline_state_init() | void MTLContext::pipeline_state_init() | ||||||||||||||||||||||||||||||
| { | { | ||||||||||||||||||||||||||||||
| /*** Initialize state only once. ***/ | /*** Initialize state only once. ***/ | ||||||||||||||||||||||||||||||
| if (!this->pipeline_state.initialised) { | if (!this->pipeline_state.initialised) { | ||||||||||||||||||||||||||||||
| this->pipeline_state.initialised = true; | this->pipeline_state.initialised = true; | ||||||||||||||||||||||||||||||
| this->pipeline_state.active_shader = NULL; | this->pipeline_state.active_shader = nullptr; | ||||||||||||||||||||||||||||||
| /* Clear bindings state. */ | /* Clear bindings state. */ | ||||||||||||||||||||||||||||||
| for (int t = 0; t < GPU_max_textures(); t++) { | for (int t = 0; t < GPU_max_textures(); t++) { | ||||||||||||||||||||||||||||||
| this->pipeline_state.texture_bindings[t].used = false; | this->pipeline_state.texture_bindings[t].used = false; | ||||||||||||||||||||||||||||||
| this->pipeline_state.texture_bindings[t].texture_slot_index = t; | this->pipeline_state.texture_bindings[t].slot_index = -1; | ||||||||||||||||||||||||||||||
| this->pipeline_state.texture_bindings[t].texture_resource = NULL; | this->pipeline_state.texture_bindings[t].texture_resource = nullptr; | ||||||||||||||||||||||||||||||
| } | } | ||||||||||||||||||||||||||||||
| for (int s = 0; s < MTL_MAX_SAMPLER_SLOTS; s++) { | for (int s = 0; s < MTL_MAX_SAMPLER_SLOTS; s++) { | ||||||||||||||||||||||||||||||
| this->pipeline_state.sampler_bindings[s].used = false; | this->pipeline_state.sampler_bindings[s].used = false; | ||||||||||||||||||||||||||||||
| } | } | ||||||||||||||||||||||||||||||
| for (int u = 0; u < MTL_MAX_UNIFORM_BUFFER_BINDINGS; u++) { | for (int u = 0; u < MTL_MAX_UNIFORM_BUFFER_BINDINGS; u++) { | ||||||||||||||||||||||||||||||
| this->pipeline_state.ubo_bindings[u].bound = false; | this->pipeline_state.ubo_bindings[u].bound = false; | ||||||||||||||||||||||||||||||
| this->pipeline_state.ubo_bindings[u].ubo = NULL; | this->pipeline_state.ubo_bindings[u].ubo = nullptr; | ||||||||||||||||||||||||||||||
| } | } | ||||||||||||||||||||||||||||||
| } | } | ||||||||||||||||||||||||||||||
| /*** State defaults -- restored by GPU_state_init. ***/ | /*** State defaults -- restored by GPU_state_init. ***/ | ||||||||||||||||||||||||||||||
| /* Clear blending State. */ | /* Clear blending State. */ | ||||||||||||||||||||||||||||||
| this->pipeline_state.color_write_mask = MTLColorWriteMaskRed | MTLColorWriteMaskGreen | | this->pipeline_state.color_write_mask = MTLColorWriteMaskRed | MTLColorWriteMaskGreen | | ||||||||||||||||||||||||||||||
| MTLColorWriteMaskBlue | MTLColorWriteMaskAlpha; | MTLColorWriteMaskBlue | MTLColorWriteMaskAlpha; | ||||||||||||||||||||||||||||||
| this->pipeline_state.blending_enabled = false; | this->pipeline_state.blending_enabled = false; | ||||||||||||||||||||||||||||||
| ▲ Show 20 Lines • Show All 218 Lines • ▼ Show 20 Lines | |||||||||||||||||||||||||||||||
| { | { | ||||||||||||||||||||||||||||||
| BLI_assert((uint)sampler_state >= 0 && ((uint)sampler_state) < GPU_SAMPLER_MAX); | BLI_assert((uint)sampler_state >= 0 && ((uint)sampler_state) < GPU_SAMPLER_MAX); | ||||||||||||||||||||||||||||||
| return sampler_state_cache_[(uint)sampler_state]; | return sampler_state_cache_[(uint)sampler_state]; | ||||||||||||||||||||||||||||||
| } | } | ||||||||||||||||||||||||||||||
| id<MTLSamplerState> MTLContext::generate_sampler_from_state(MTLSamplerState sampler_state) | id<MTLSamplerState> MTLContext::generate_sampler_from_state(MTLSamplerState sampler_state) | ||||||||||||||||||||||||||||||
| { | { | ||||||||||||||||||||||||||||||
| /* Check if sampler already exists for given state. */ | /* Check if sampler already exists for given state. */ | ||||||||||||||||||||||||||||||
| id<MTLSamplerState> st = sampler_state_cache_[(uint)sampler_state]; | |||||||||||||||||||||||||||||||
| if (st != nil) { | |||||||||||||||||||||||||||||||
| return st; | |||||||||||||||||||||||||||||||
| } | |||||||||||||||||||||||||||||||
| else { | |||||||||||||||||||||||||||||||
| MTLSamplerDescriptor *descriptor = [[MTLSamplerDescriptor alloc] init]; | MTLSamplerDescriptor *descriptor = [[MTLSamplerDescriptor alloc] init]; | ||||||||||||||||||||||||||||||
| descriptor.normalizedCoordinates = true; | descriptor.normalizedCoordinates = true; | ||||||||||||||||||||||||||||||
| MTLSamplerAddressMode clamp_type = (sampler_state.state & GPU_SAMPLER_CLAMP_BORDER) ? | MTLSamplerAddressMode clamp_type = (sampler_state.state & GPU_SAMPLER_CLAMP_BORDER) ? | ||||||||||||||||||||||||||||||
| MTLSamplerAddressModeClampToBorderColor : | MTLSamplerAddressModeClampToBorderColor : | ||||||||||||||||||||||||||||||
| MTLSamplerAddressModeClampToEdge; | MTLSamplerAddressModeClampToEdge; | ||||||||||||||||||||||||||||||
| descriptor.rAddressMode = (sampler_state.state & GPU_SAMPLER_REPEAT_R) ? | descriptor.rAddressMode = (sampler_state.state & GPU_SAMPLER_REPEAT_R) ? | ||||||||||||||||||||||||||||||
| MTLSamplerAddressModeRepeat : | MTLSamplerAddressModeRepeat : | ||||||||||||||||||||||||||||||
| clamp_type; | clamp_type; | ||||||||||||||||||||||||||||||
| descriptor.sAddressMode = (sampler_state.state & GPU_SAMPLER_REPEAT_S) ? | descriptor.sAddressMode = (sampler_state.state & GPU_SAMPLER_REPEAT_S) ? | ||||||||||||||||||||||||||||||
| MTLSamplerAddressModeRepeat : | MTLSamplerAddressModeRepeat : | ||||||||||||||||||||||||||||||
| clamp_type; | clamp_type; | ||||||||||||||||||||||||||||||
| descriptor.tAddressMode = (sampler_state.state & GPU_SAMPLER_REPEAT_T) ? | descriptor.tAddressMode = (sampler_state.state & GPU_SAMPLER_REPEAT_T) ? | ||||||||||||||||||||||||||||||
| MTLSamplerAddressModeRepeat : | MTLSamplerAddressModeRepeat : | ||||||||||||||||||||||||||||||
| clamp_type; | clamp_type; | ||||||||||||||||||||||||||||||
| descriptor.borderColor = MTLSamplerBorderColorTransparentBlack; | descriptor.borderColor = MTLSamplerBorderColorTransparentBlack; | ||||||||||||||||||||||||||||||
| descriptor.minFilter = (sampler_state.state & GPU_SAMPLER_FILTER) ? | descriptor.minFilter = (sampler_state.state & GPU_SAMPLER_FILTER) ? | ||||||||||||||||||||||||||||||
| MTLSamplerMinMagFilterLinear : | MTLSamplerMinMagFilterLinear : | ||||||||||||||||||||||||||||||
| MTLSamplerMinMagFilterNearest; | MTLSamplerMinMagFilterNearest; | ||||||||||||||||||||||||||||||
| descriptor.magFilter = (sampler_state.state & GPU_SAMPLER_FILTER) ? | descriptor.magFilter = (sampler_state.state & GPU_SAMPLER_FILTER) ? | ||||||||||||||||||||||||||||||
| MTLSamplerMinMagFilterLinear : | MTLSamplerMinMagFilterLinear : | ||||||||||||||||||||||||||||||
| MTLSamplerMinMagFilterNearest; | MTLSamplerMinMagFilterNearest; | ||||||||||||||||||||||||||||||
| descriptor.mipFilter = (sampler_state.state & GPU_SAMPLER_MIPMAP) ? | descriptor.mipFilter = (sampler_state.state & GPU_SAMPLER_MIPMAP) ? | ||||||||||||||||||||||||||||||
| MTLSamplerMipFilterLinear : | MTLSamplerMipFilterLinear : | ||||||||||||||||||||||||||||||
| MTLSamplerMipFilterNotMipmapped; | MTLSamplerMipFilterNotMipmapped; | ||||||||||||||||||||||||||||||
| descriptor.lodMinClamp = -1000; | descriptor.lodMinClamp = -1000; | ||||||||||||||||||||||||||||||
| descriptor.lodMaxClamp = 1000; | descriptor.lodMaxClamp = 1000; | ||||||||||||||||||||||||||||||
| float aniso_filter = max_ff(16, U.anisotropic_filter); | float aniso_filter = max_ff(16, U.anisotropic_filter); | ||||||||||||||||||||||||||||||
| descriptor.maxAnisotropy = (sampler_state.state & GPU_SAMPLER_MIPMAP) ? aniso_filter : 1; | descriptor.maxAnisotropy = (sampler_state.state & GPU_SAMPLER_MIPMAP) ? aniso_filter : 1; | ||||||||||||||||||||||||||||||
| descriptor.compareFunction = (sampler_state.state & GPU_SAMPLER_COMPARE) ? | descriptor.compareFunction = (sampler_state.state & GPU_SAMPLER_COMPARE) ? | ||||||||||||||||||||||||||||||
| MTLCompareFunctionLessEqual : | MTLCompareFunctionLessEqual : | ||||||||||||||||||||||||||||||
| MTLCompareFunctionAlways; | MTLCompareFunctionAlways; | ||||||||||||||||||||||||||||||
| descriptor.supportArgumentBuffers = true; | descriptor.supportArgumentBuffers = true; | ||||||||||||||||||||||||||||||
| id<MTLSamplerState> state = [this->device newSamplerStateWithDescriptor:descriptor]; | id<MTLSamplerState> state = [this->device newSamplerStateWithDescriptor:descriptor]; | ||||||||||||||||||||||||||||||
| sampler_state_cache_[(uint)sampler_state] = state; | sampler_state_cache_[(uint)sampler_state] = state; | ||||||||||||||||||||||||||||||
| BLI_assert(state != nil); | BLI_assert(state != nil); | ||||||||||||||||||||||||||||||
| [descriptor autorelease]; | [descriptor autorelease]; | ||||||||||||||||||||||||||||||
| return state; | return state; | ||||||||||||||||||||||||||||||
| } | } | ||||||||||||||||||||||||||||||
| } | |||||||||||||||||||||||||||||||
| id<MTLSamplerState> MTLContext::get_default_sampler_state() | id<MTLSamplerState> MTLContext::get_default_sampler_state() | ||||||||||||||||||||||||||||||
| { | { | ||||||||||||||||||||||||||||||
| if (default_sampler_state_ == nil) { | if (default_sampler_state_ == nil) { | ||||||||||||||||||||||||||||||
| default_sampler_state_ = this->get_sampler_from_state(DEFAULT_SAMPLER_STATE); | default_sampler_state_ = this->get_sampler_from_state(DEFAULT_SAMPLER_STATE); | ||||||||||||||||||||||||||||||
| } | } | ||||||||||||||||||||||||||||||
| return default_sampler_state_; | return default_sampler_state_; | ||||||||||||||||||||||||||||||
| } | } | ||||||||||||||||||||||||||||||
| /** \} */ | /** \} */ | ||||||||||||||||||||||||||||||
| } // blender::gpu | } // blender::gpu | ||||||||||||||||||||||||||||||
missing space between functions. same below.