Changeset View
Changeset View
Standalone View
Standalone View
source/blender/gpu/metal/mtl_context.hh
| Show First 20 Lines • Show All 60 Lines • ▼ Show 20 Lines | struct MTLSamplerBinding { | ||||
| MTLSamplerState state; | MTLSamplerState state; | ||||
| bool operator==(MTLSamplerBinding const &other) const | bool operator==(MTLSamplerBinding const &other) const | ||||
| { | { | ||||
| return (used == other.used && state == other.state); | return (used == other.used && state == other.state); | ||||
| } | } | ||||
| }; | }; | ||||
| /* Metal Context Render Pass State -- Used to track active RenderCommandEncoder state based on | |||||
| * bound MTLFrameBuffer's.Owned by MTLContext. */ | |||||
| class MTLRenderPassState { | |||||
| friend class MTLContext; | |||||
| public: | |||||
| MTLRenderPassState(MTLContext &context, MTLCommandBufferManager &command_buffer_manager) | |||||
| : ctx(context), cmd(command_buffer_manager){}; | |||||
| /* Given a RenderPassState is associated with a live RenderCommandEncoder, | |||||
| * this state sits within the MTLCommandBufferManager. */ | |||||
| MTLContext &ctx; | |||||
| MTLCommandBufferManager &cmd; | |||||
| /* Caching of resource bindings for active MTLRenderCommandEncoder. | /* Caching of resource bindings for active MTLRenderCommandEncoder. | ||||
| * In Metal, resource bindings are local to the MTLCommandEncoder, | * In Metal, resource bindings are local to the MTLCommandEncoder, | ||||
| * not globally to the whole pipeline/cmd buffer. */ | * not globally to the whole pipeline/cmd buffer. */ | ||||
| struct MTLBoundShaderState { | struct MTLBoundShaderState { | ||||
| MTLShader *shader_ = nullptr; | MTLShader *shader_ = nullptr; | ||||
| uint pso_index_; | uint pso_index_; | ||||
| void set(MTLShader *shader, uint pso_index) | void set(MTLShader *shader, uint pso_index) | ||||
| { | { | ||||
| shader_ = shader; | shader_ = shader; | ||||
| pso_index_ = pso_index; | pso_index_ = pso_index; | ||||
| } | } | ||||
| }; | }; | ||||
| MTLBoundShaderState last_bound_shader_state; | |||||
| id<MTLRenderPipelineState> bound_pso = nil; | |||||
| id<MTLDepthStencilState> bound_ds_state = nil; | |||||
| uint last_used_stencil_ref_value = 0; | |||||
| MTLScissorRect last_scissor_rect; | |||||
| /* Caching of CommandEncoder Vertex/Fragment buffer bindings. */ | /* Caching of CommandEncoder Vertex/Fragment buffer bindings. */ | ||||
| struct BufferBindingCached { | struct BufferBindingCached { | ||||
| /* Whether the given binding slot uses byte data (Push Constant equivalent) | /* Whether the given binding slot uses byte data (Push Constant equivalent) | ||||
| * or an MTLBuffer. */ | * or an MTLBuffer. */ | ||||
| bool is_bytes; | bool is_bytes; | ||||
| id<MTLBuffer> metal_buffer; | id<MTLBuffer> metal_buffer; | ||||
| int offset; | int offset; | ||||
| }; | }; | ||||
| BufferBindingCached cached_vertex_buffer_bindings[MTL_MAX_UNIFORM_BUFFER_BINDINGS]; | |||||
| BufferBindingCached cached_fragment_buffer_bindings[MTL_MAX_UNIFORM_BUFFER_BINDINGS]; | |||||
| /* Caching of CommandEncoder textures bindings. */ | /* Caching of CommandEncoder textures bindings. */ | ||||
| struct TextureBindingCached { | struct TextureBindingCached { | ||||
| id<MTLTexture> metal_texture; | id<MTLTexture> metal_texture; | ||||
| }; | }; | ||||
| TextureBindingCached cached_vertex_texture_bindings[MTL_MAX_TEXTURE_SLOTS]; | |||||
| TextureBindingCached cached_fragment_texture_bindings[MTL_MAX_TEXTURE_SLOTS]; | |||||
| /* Cached of CommandEncoder sampler states. */ | /* Cached of CommandEncoder sampler states. */ | ||||
| struct SamplerStateBindingCached { | struct SamplerStateBindingCached { | ||||
| MTLSamplerState binding_state; | MTLSamplerState binding_state; | ||||
| id<MTLSamplerState> sampler_state; | id<MTLSamplerState> sampler_state; | ||||
| bool is_arg_buffer_binding; | bool is_arg_buffer_binding; | ||||
| }; | }; | ||||
| /* Metal Context Render Pass State -- Used to track active RenderCommandEncoder state based on | |||||
| * bound MTLFrameBuffer's.Owned by MTLContext. */ | |||||
| class MTLRenderPassState { | |||||
| friend class MTLContext; | |||||
| public: | |||||
| MTLRenderPassState(MTLContext &context, MTLCommandBufferManager &command_buffer_manager) | |||||
| : ctx(context), cmd(command_buffer_manager){}; | |||||
| /* Given a RenderPassState is associated with a live RenderCommandEncoder, | |||||
| * this state sits within the MTLCommandBufferManager. */ | |||||
| MTLContext &ctx; | |||||
| MTLCommandBufferManager &cmd; | |||||
| MTLBoundShaderState last_bound_shader_state; | |||||
| id<MTLRenderPipelineState> bound_pso = nil; | |||||
| id<MTLDepthStencilState> bound_ds_state = nil; | |||||
| uint last_used_stencil_ref_value = 0; | |||||
| MTLScissorRect last_scissor_rect; | |||||
| BufferBindingCached cached_vertex_buffer_bindings[MTL_MAX_BUFFER_BINDINGS]; | |||||
| BufferBindingCached cached_fragment_buffer_bindings[MTL_MAX_BUFFER_BINDINGS]; | |||||
| TextureBindingCached cached_vertex_texture_bindings[MTL_MAX_TEXTURE_SLOTS]; | |||||
| TextureBindingCached cached_fragment_texture_bindings[MTL_MAX_TEXTURE_SLOTS]; | |||||
| SamplerStateBindingCached cached_vertex_sampler_state_bindings[MTL_MAX_TEXTURE_SLOTS]; | SamplerStateBindingCached cached_vertex_sampler_state_bindings[MTL_MAX_TEXTURE_SLOTS]; | ||||
| SamplerStateBindingCached cached_fragment_sampler_state_bindings[MTL_MAX_TEXTURE_SLOTS]; | SamplerStateBindingCached cached_fragment_sampler_state_bindings[MTL_MAX_TEXTURE_SLOTS]; | ||||
| /* Reset RenderCommandEncoder binding state. */ | /* Reset RenderCommandEncoder binding state. */ | ||||
| void reset_state(); | void reset_state(); | ||||
| /* Texture Binding (RenderCommandEncoder). */ | /* Texture Binding (RenderCommandEncoder). */ | ||||
| void bind_vertex_texture(id<MTLTexture> tex, uint slot); | void bind_vertex_texture(id<MTLTexture> tex, uint slot); | ||||
| Show All 9 Lines | public: | ||||
| /* Buffer binding (RenderCommandEncoder). */ | /* Buffer binding (RenderCommandEncoder). */ | ||||
| void bind_vertex_buffer(id<MTLBuffer> buffer, uint buffer_offset, uint index); | void bind_vertex_buffer(id<MTLBuffer> buffer, uint buffer_offset, uint index); | ||||
| void bind_fragment_buffer(id<MTLBuffer> buffer, uint buffer_offset, uint index); | void bind_fragment_buffer(id<MTLBuffer> buffer, uint buffer_offset, uint index); | ||||
| void bind_vertex_bytes(void *bytes, uint length, uint index); | void bind_vertex_bytes(void *bytes, uint length, uint index); | ||||
| void bind_fragment_bytes(void *bytes, uint length, uint index); | void bind_fragment_bytes(void *bytes, uint length, uint index); | ||||
| }; | }; | ||||
| /* Metal Context Compute Pass State -- Used to track active ComputeCommandEncoder state. */ | |||||
| class MTLComputeState { | |||||
| friend class MTLContext; | |||||
| public: | |||||
| MTLComputeState(MTLContext &context, MTLCommandBufferManager &command_buffer_manager) | |||||
| : ctx(context), cmd(command_buffer_manager){}; | |||||
| /* Given a ComputePassState is associated with a live ComputeCommandEncoder, | |||||
| * this state sits within the MTLCommandBufferManager. */ | |||||
| MTLContext &ctx; | |||||
| MTLCommandBufferManager &cmd; | |||||
| id<MTLComputePipelineState> bound_pso = nil; | |||||
| BufferBindingCached cached_compute_buffer_bindings[MTL_MAX_BUFFER_BINDINGS]; | |||||
| TextureBindingCached cached_compute_texture_bindings[MTL_MAX_TEXTURE_SLOTS]; | |||||
| SamplerStateBindingCached cached_compute_sampler_state_bindings[MTL_MAX_TEXTURE_SLOTS]; | |||||
| /* Reset ComputeCommandEncoder binding state. */ | |||||
| void reset_state(); | |||||
| /* PSO Binding. */ | |||||
| void bind_pso(id<MTLComputePipelineState> pso); | |||||
| /* Texture Binding (ComputeCommandEncoder). */ | |||||
| void bind_compute_texture(id<MTLTexture> tex, uint slot); | |||||
| /* Sampler Binding (ComputeCommandEncoder). */ | |||||
| void bind_compute_sampler(MTLSamplerBinding &sampler_binding, | |||||
| bool use_argument_buffer_for_samplers, | |||||
| uint slot); | |||||
| /* Buffer binding (ComputeCommandEncoder). */ | |||||
| void bind_compute_buffer(id<MTLBuffer> buffer, | |||||
| uint buffer_offset, | |||||
| uint index, | |||||
| bool writeable = false); | |||||
| void bind_compute_bytes(void *bytes, uint length, uint index); | |||||
| }; | |||||
| /* Depth Stencil State */ | /* Depth Stencil State */ | ||||
| struct MTLContextDepthStencilState { | struct MTLContextDepthStencilState { | ||||
| /* Depth State. */ | /* Depth State. */ | ||||
| bool depth_write_enable; | bool depth_write_enable; | ||||
| bool depth_test_enabled; | bool depth_test_enabled; | ||||
| float depth_range_near; | float depth_range_near; | ||||
| float depth_range_far; | float depth_range_far; | ||||
| ▲ Show 20 Lines • Show All 354 Lines • ▼ Show 20 Lines | private: | ||||
| id<MTLBlitCommandEncoder> active_blit_command_encoder_ = nil; | id<MTLBlitCommandEncoder> active_blit_command_encoder_ = nil; | ||||
| id<MTLComputeCommandEncoder> active_compute_command_encoder_ = nil; | id<MTLComputeCommandEncoder> active_compute_command_encoder_ = nil; | ||||
| /* State associated with active RenderCommandEncoder. */ | /* State associated with active RenderCommandEncoder. */ | ||||
| MTLRenderPassState render_pass_state_; | MTLRenderPassState render_pass_state_; | ||||
| MTLFrameBuffer *active_frame_buffer_ = nullptr; | MTLFrameBuffer *active_frame_buffer_ = nullptr; | ||||
| MTLRenderPassDescriptor *active_pass_descriptor_ = nullptr; | MTLRenderPassDescriptor *active_pass_descriptor_ = nullptr; | ||||
| /* State associated with active ComputeCommandEncoder. */ | |||||
| MTLComputeState compute_state_; | |||||
| /* Workload heuristics - We may need to split command buffers to optimize workload and balancing. | /* Workload heuristics - We may need to split command buffers to optimize workload and balancing. | ||||
| */ | */ | ||||
| int current_draw_call_count_ = 0; | int current_draw_call_count_ = 0; | ||||
| int encoder_count_ = 0; | int encoder_count_ = 0; | ||||
| int vertex_submitted_count_ = 0; | int vertex_submitted_count_ = 0; | ||||
| bool empty_ = true; | bool empty_ = true; | ||||
| public: | public: | ||||
| MTLCommandBufferManager(MTLContext &context) | MTLCommandBufferManager(MTLContext &context) | ||||
| : context_(context), render_pass_state_(context, *this){}; | : context_(context), render_pass_state_(context, *this), compute_state_(context, *this){}; | ||||
| void prepare(bool supports_render = true); | void prepare(bool supports_render = true); | ||||
| /* If wait is true, CPU will stall until GPU work has completed. */ | /* If wait is true, CPU will stall until GPU work has completed. */ | ||||
| bool submit(bool wait); | bool submit(bool wait); | ||||
| /* Fetch/query current encoder. */ | /* Fetch/query current encoder. */ | ||||
| bool is_inside_render_pass(); | bool is_inside_render_pass(); | ||||
| bool is_inside_blit(); | bool is_inside_blit(); | ||||
| bool is_inside_compute(); | bool is_inside_compute(); | ||||
| id<MTLRenderCommandEncoder> get_active_render_command_encoder(); | id<MTLRenderCommandEncoder> get_active_render_command_encoder(); | ||||
| id<MTLBlitCommandEncoder> get_active_blit_command_encoder(); | id<MTLBlitCommandEncoder> get_active_blit_command_encoder(); | ||||
| id<MTLComputeCommandEncoder> get_active_compute_command_encoder(); | id<MTLComputeCommandEncoder> get_active_compute_command_encoder(); | ||||
| MTLFrameBuffer *get_active_framebuffer(); | MTLFrameBuffer *get_active_framebuffer(); | ||||
| /* RenderPassState for RenderCommandEncoder. */ | /* RenderPassState for RenderCommandEncoder. */ | ||||
| MTLRenderPassState &get_render_pass_state() | MTLRenderPassState &get_render_pass_state() | ||||
| { | { | ||||
| /* Render pass state should only be valid if we are inside a render pass. */ | /* Render pass state should only be valid if we are inside a render pass. */ | ||||
| BLI_assert(this->is_inside_render_pass()); | BLI_assert(this->is_inside_render_pass()); | ||||
| return render_pass_state_; | return render_pass_state_; | ||||
| } | } | ||||
| /* RenderPassState for RenderCommandEncoder. */ | |||||
| MTLComputeState &get_compute_state() | |||||
| { | |||||
| /* Render pass state should only be valid if we are inside a compute encoder. */ | |||||
| BLI_assert(this->is_inside_compute()); | |||||
| return compute_state_; | |||||
| } | |||||
| /* Rendering Heuristics. */ | /* Rendering Heuristics. */ | ||||
| void register_draw_counters(int vertex_submission); | void register_draw_counters(int vertex_submission); | ||||
| void reset_counters(); | void reset_counters(); | ||||
| bool do_break_submission(); | bool do_break_submission(); | ||||
| /* Encoder and Pass management. */ | /* Encoder and Pass management. */ | ||||
| /* End currently active MTLCommandEncoder. */ | /* End currently active MTLCommandEncoder. */ | ||||
| bool end_active_command_encoder(); | bool end_active_command_encoder(); | ||||
| Show All 24 Lines | |||||
| /** MTLContext -- Core render loop and state management. **/ | /** MTLContext -- Core render loop and state management. **/ | ||||
| /* NOTE(Metal): Partial #MTLContext stub to provide wrapper functionality | /* NOTE(Metal): Partial #MTLContext stub to provide wrapper functionality | ||||
| * for work-in-progress `MTL*` classes. */ | * for work-in-progress `MTL*` classes. */ | ||||
| class MTLContext : public Context { | class MTLContext : public Context { | ||||
| friend class MTLBackend; | friend class MTLBackend; | ||||
| friend class MTLRenderPassState; | friend class MTLRenderPassState; | ||||
| friend class MTLComputeState; | |||||
| public: | public: | ||||
| /* Swap-chain and latency management. */ | /* Swap-chain and latency management. */ | ||||
| static std::atomic<int> max_drawables_in_flight; | static std::atomic<int> max_drawables_in_flight; | ||||
| static std::atomic<int64_t> avg_drawable_latency_us; | static std::atomic<int64_t> avg_drawable_latency_us; | ||||
| static int64_t frame_latency[MTL_FRAME_AVERAGE_COUNT]; | static int64_t frame_latency[MTL_FRAME_AVERAGE_COUNT]; | ||||
| public: | public: | ||||
| ▲ Show 20 Lines • Show All 136 Lines • ▼ Show 20 Lines | public: | ||||
| * | * | ||||
| * `ensure_render_pipeline_state` will return false if the state is | * `ensure_render_pipeline_state` will return false if the state is | ||||
| * invalid and cannot be applied. This should cancel a draw call. */ | * invalid and cannot be applied. This should cancel a draw call. */ | ||||
| bool ensure_render_pipeline_state(MTLPrimitiveType prim_type); | bool ensure_render_pipeline_state(MTLPrimitiveType prim_type); | ||||
| bool ensure_uniform_buffer_bindings( | bool ensure_uniform_buffer_bindings( | ||||
| id<MTLRenderCommandEncoder> rec, | id<MTLRenderCommandEncoder> rec, | ||||
| const MTLShaderInterface *shader_interface, | const MTLShaderInterface *shader_interface, | ||||
| const MTLRenderPipelineStateInstance *pipeline_state_instance); | const MTLRenderPipelineStateInstance *pipeline_state_instance); | ||||
| bool ensure_uniform_buffer_bindings( | |||||
| id<MTLComputeCommandEncoder> rec, | |||||
| const MTLShaderInterface *shader_interface, | |||||
| const MTLComputePipelineStateInstance &pipeline_state_instance); | |||||
| void ensure_texture_bindings(id<MTLRenderCommandEncoder> rec, | void ensure_texture_bindings(id<MTLRenderCommandEncoder> rec, | ||||
| MTLShaderInterface *shader_interface, | MTLShaderInterface *shader_interface, | ||||
| const MTLRenderPipelineStateInstance *pipeline_state_instance); | const MTLRenderPipelineStateInstance *pipeline_state_instance); | ||||
| void ensure_texture_bindings(id<MTLComputeCommandEncoder> rec, | |||||
| MTLShaderInterface *shader_interface, | |||||
| const MTLComputePipelineStateInstance &pipeline_state_instance); | |||||
| void ensure_depth_stencil_state(MTLPrimitiveType prim_type); | void ensure_depth_stencil_state(MTLPrimitiveType prim_type); | ||||
| id<MTLBuffer> get_null_buffer(); | id<MTLBuffer> get_null_buffer(); | ||||
| id<MTLBuffer> get_null_attribute_buffer(); | id<MTLBuffer> get_null_attribute_buffer(); | ||||
| gpu::MTLTexture *get_dummy_texture(eGPUTextureType type, eGPUSamplerFormat sampler_format); | gpu::MTLTexture *get_dummy_texture(eGPUTextureType type, eGPUSamplerFormat sampler_format); | ||||
| void free_dummy_resources(); | void free_dummy_resources(); | ||||
| /* Compute. */ | |||||
| bool ensure_compute_pipeline_state(); | |||||
| void compute_dispatch(int groups_x_len, int groups_y_len, int groups_z_len); | |||||
| /* State assignment. */ | /* State assignment. */ | ||||
| void set_viewport(int origin_x, int origin_y, int width, int height); | void set_viewport(int origin_x, int origin_y, int width, int height); | ||||
| void set_scissor(int scissor_x, int scissor_y, int scissor_width, int scissor_height); | void set_scissor(int scissor_x, int scissor_y, int scissor_width, int scissor_height); | ||||
| void set_scissor_enabled(bool scissor_enabled); | void set_scissor_enabled(bool scissor_enabled); | ||||
| /* Visibility buffer control. */ | /* Visibility buffer control. */ | ||||
| void set_visibility_buffer(gpu::MTLBuffer *buffer); | void set_visibility_buffer(gpu::MTLBuffer *buffer); | ||||
| gpu::MTLBuffer *get_visibility_buffer() const; | gpu::MTLBuffer *get_visibility_buffer() const; | ||||
| ▲ Show 20 Lines • Show All 99 Lines • Show Last 20 Lines | |||||