37 void MTLCommandBufferManager::register_encoder_counters()
43 id<MTLCommandBuffer> MTLCommandBufferManager::ensure_begin()
45 if (active_command_buffer_ == nil) {
54 MTLCommandBufferDescriptor *desc = [[MTLCommandBufferDescriptor alloc]
init];
55 desc.errorOptions = MTLCommandBufferErrorOptionEncoderExecutionStatus;
56 desc.retainedReferences = YES;
57 active_command_buffer_ = [context_.
queue commandBufferWithDescriptor:desc];
60 active_command_buffer_ = [context_.
queue commandBuffer];
62 [active_command_buffer_ retain];
78 return active_command_buffer_;
85 if (empty_ || active_command_buffer_ == nil) {
91 BLI_assert(active_command_encoder_type_ == MTL_NO_COMMAND_ENCODER);
121 id<MTLCommandBuffer> cmd_buffer_ref = active_command_buffer_;
122 [cmd_buffer_ref retain];
124 [cmd_buffer_ref addCompletedHandler:^(id<MTLCommandBuffer> cb) {
130 [cmd_buffer_ref release];
137 [active_command_buffer_ commit];
141 [active_command_buffer_ waitUntilCompleted];
147 NSError *
error = [active_command_buffer_
error];
153 const char *stringAsChar = [[NSString stringWithFormat:
@"%@",
error] UTF8String];
155 std::ofstream outfile;
157 outfile << stringAsChar;
165 if (last_submitted_command_buffer_ != nil) {
168 [last_submitted_command_buffer_ autorelease];
169 last_submitted_command_buffer_ = nil;
171 last_submitted_command_buffer_ = active_command_buffer_;
172 active_command_buffer_ = nil;
186 return (active_command_encoder_type_ == MTL_RENDER_COMMAND_ENCODER);
191 return (active_command_encoder_type_ == MTL_BLIT_COMMAND_ENCODER);
196 return (active_command_encoder_type_ == MTL_COMPUTE_COMMAND_ENCODER);
202 return active_render_command_encoder_;
208 return active_blit_command_encoder_;
214 return active_compute_command_encoder_;
221 return active_frame_buffer_;
232 if (active_command_encoder_type_ != MTL_NO_COMMAND_ENCODER) {
234 switch (active_command_encoder_type_) {
235 case MTL_RENDER_COMMAND_ENCODER: {
237 BLI_assert(active_render_command_encoder_ != nil);
240 [active_render_command_encoder_ endEncoding];
241 [active_render_command_encoder_ release];
242 active_render_command_encoder_ = nil;
243 active_command_encoder_type_ = MTL_NO_COMMAND_ENCODER;
246 active_frame_buffer_ =
nullptr;
247 active_pass_descriptor_ =
nullptr;
251 case MTL_BLIT_COMMAND_ENCODER: {
253 BLI_assert(active_blit_command_encoder_ != nil);
254 [active_blit_command_encoder_ endEncoding];
255 [active_blit_command_encoder_ release];
256 active_blit_command_encoder_ = nil;
257 active_command_encoder_type_ = MTL_NO_COMMAND_ENCODER;
261 case MTL_COMPUTE_COMMAND_ENCODER: {
263 BLI_assert(active_compute_command_encoder_ != nil);
264 [active_compute_command_encoder_ endEncoding];
265 [active_compute_command_encoder_ release];
266 active_compute_command_encoder_ = nil;
267 active_command_encoder_type_ = MTL_NO_COMMAND_ENCODER;
272 BLI_assert(
false &&
"Invalid command encoder type");
279 BLI_assert(active_render_command_encoder_ == nil);
280 BLI_assert(active_blit_command_encoder_ == nil);
281 BLI_assert(active_compute_command_encoder_ == nil);
287 MTLFrameBuffer *ctx_framebuffer,
bool force_begin,
bool *new_pass)
293 id<MTLCommandBuffer> cmd_buf = this->ensure_begin();
298 if (active_command_encoder_type_ != MTL_RENDER_COMMAND_ENCODER ||
299 active_frame_buffer_ != ctx_framebuffer || force_begin) {
303 bool is_rebind = (active_frame_buffer_ == ctx_framebuffer);
307 active_frame_buffer_ = ctx_framebuffer;
313 this->active_pass_descriptor_.visibilityResultBuffer =
318 BLI_assert(active_render_command_encoder_ == nil);
321 active_render_command_encoder_ = [cmd_buf
322 renderCommandEncoderWithDescriptor:active_pass_descriptor_];
323 [active_render_command_encoder_ retain];
324 active_command_encoder_type_ = MTL_RENDER_COMMAND_ENCODER;
327 this->register_encoder_counters();
348 BLI_assert(active_render_command_encoder_ != nil);
349 return active_render_command_encoder_;
355 id<MTLCommandBuffer> cmd_buf = this->ensure_begin();
359 if (active_command_encoder_type_ != MTL_BLIT_COMMAND_ENCODER) {
364 if (active_blit_command_encoder_ == nil) {
365 active_blit_command_encoder_ = [cmd_buf blitCommandEncoder];
366 BLI_assert(active_blit_command_encoder_ != nil);
367 [active_blit_command_encoder_ retain];
368 active_command_encoder_type_ = MTL_BLIT_COMMAND_ENCODER;
371 this->register_encoder_counters();
373 BLI_assert(active_blit_command_encoder_ != nil);
374 return active_blit_command_encoder_;
380 id<MTLCommandBuffer> cmd_buf = this->ensure_begin();
384 if (active_command_encoder_type_ != MTL_COMPUTE_COMMAND_ENCODER) {
389 if (active_compute_command_encoder_ == nil) {
390 active_compute_command_encoder_ = [cmd_buf computeCommandEncoder];
391 BLI_assert(active_compute_command_encoder_ != nil);
392 [active_compute_command_encoder_ retain];
393 active_command_encoder_type_ = MTL_COMPUTE_COMMAND_ENCODER;
396 this->register_encoder_counters();
398 BLI_assert(active_compute_command_encoder_ != nil);
399 return active_compute_command_encoder_;
411 current_draw_call_count_++;
412 vertex_submitted_count_ += vertex_submission;
420 current_draw_call_count_ = 0;
422 vertex_submitted_count_ = 0;
429 if (active_command_buffer_ == nil) {
437 return ((current_draw_call_count_ > 30000) || (vertex_submitted_count_ > 100000000) ||
438 (encoder_count_ > 25));
455 id<MTLCommandBuffer> cmd = this->ensure_begin();
457 [cmd pushDebugGroup:[NSString stringWithFormat:
@"%s_%d", name, index]];
463 id<MTLCommandBuffer> cmd = this->ensure_begin();
475 if (@available(macOS 10.14, *)) {
478 MTLBarrierScope scope = 0;
481 scope = scope | MTLBarrierScopeTextures | MTLBarrierScopeRenderTargets;
486 scope = scope | MTLBarrierScopeBuffers;
491 switch (active_command_encoder_type_) {
492 case MTL_NO_COMMAND_ENCODER:
493 case MTL_BLIT_COMMAND_ENCODER: {
499 case MTL_RENDER_COMMAND_ENCODER: {
502 MTLRenderStages before_stage_flags = 0;
503 MTLRenderStages after_stage_flags = 0;
506 before_stage_flags = before_stage_flags | MTLRenderStageVertex;
509 before_stage_flags = before_stage_flags | MTLRenderStageFragment;
512 after_stage_flags = after_stage_flags | MTLRenderStageVertex;
515 after_stage_flags = MTLRenderStageFragment;
520 [rec memoryBarrierWithScope:scope
521 afterStages:after_stage_flags
522 beforeStages:before_stage_flags];
527 case MTL_COMPUTE_COMMAND_ENCODER: {
530 [rec memoryBarrierWithScope:scope];
563 (
uint)((fb !=
nullptr) ?
fb->get_width() : 0),
564 (
uint)((
fb !=
nullptr) ?
fb->get_height() : 0)};
595 [rec setVertexTexture:
tex atIndex:slot];
605 [rec setFragmentTexture:
tex atIndex:slot];
611 bool use_argument_buffer_for_samplers,
619 bool use_argument_buffer_for_samplers,
@ GPU_BARRIER_STAGE_FRAGMENT
@ GPU_BARRIER_STAGE_VERTEX
@ GPU_BARRIER_SHADER_STORAGE
@ GPU_BARRIER_TEXTURE_FETCH
@ GPU_BARRIER_ELEMENT_ARRAY
@ GPU_BARRIER_SHADER_IMAGE_ACCESS
@ GPU_BARRIER_VERTEX_ATTRIB_ARRAY
static MTLBackend * get()
MTLSafeFreeList * get_current_safe_list()
id< MTLBuffer > get_metal_buffer() const
MTLFrameBuffer * get_active_framebuffer()
id< MTLComputeCommandEncoder > get_active_compute_command_encoder()
bool end_active_command_encoder()
bool do_break_submission()
void register_draw_counters(int vertex_submission)
void prepare(bool supports_render=true)
static uint64_t event_signal_val
bool is_inside_render_pass()
id< MTLRenderCommandEncoder > ensure_begin_render_command_encoder(MTLFrameBuffer *ctx_framebuffer, bool force_begin, bool *new_pass)
static id< MTLEvent > sync_event
id< MTLComputeCommandEncoder > ensure_begin_compute_encoder()
bool insert_memory_barrier(eGPUBarrier barrier_bits, eGPUStageBarrierBits before_stages, eGPUStageBarrierBits after_stages)
static int num_active_cmd_bufs
id< MTLBlitCommandEncoder > ensure_begin_blit_encoder()
void push_debug_group(const char *name, int index)
id< MTLRenderCommandEncoder > get_active_render_command_encoder()
id< MTLBlitCommandEncoder > get_active_blit_command_encoder()
void clear_visibility_dirty()
gpu::MTLBuffer * get_visibility_buffer() const
MTLScratchBufferManager memory_manager
id< MTLCommandQueue > queue
static MTLBufferPool & get_global_memory_manager()
MTLRenderPassDescriptor * bake_render_pass_descriptor(bool load_contents)
void increment_reference()
void decrement_reference()
void flush_active_scratch_buffer()
void ensure_increment_scratch_buffer()
BLI_INLINE float fb(float length, float L)
ccl_global float * buffer
static void error(const char *str)
#define MTL_MAX_TEXTURE_SLOTS
#define MTL_MAX_UNIFORM_BUFFER_BINDINGS
#define MTL_MAX_COMMAND_BUFFERS
static int sampler_binding(int32_t program, uint32_t uniform_index, int32_t uniform_location, int *sampler_len)
T length(const vec_base< T, Size > &a)
static const pxr::TfToken out("out", pxr::TfToken::Immortal)
unsigned __int64 uint64_t
id< MTLBuffer > metal_buffer
void set(MTLShader *shader, uint pso_index)
bool is_arg_buffer_binding
id< MTLSamplerState > sampler_state
id< MTLTexture > metal_texture
void bind_fragment_bytes(void *bytes, uint length, uint index)
void bind_fragment_sampler(MTLSamplerBinding &sampler_binding, bool use_argument_buffer_for_samplers, uint slot)
BufferBindingCached cached_vertex_buffer_bindings[MTL_MAX_UNIFORM_BUFFER_BINDINGS]
SamplerStateBindingCached cached_fragment_sampler_state_bindings[MTL_MAX_TEXTURE_SLOTS]
void bind_vertex_sampler(MTLSamplerBinding &sampler_binding, bool use_argument_buffer_for_samplers, uint slot)
void bind_vertex_texture(id< MTLTexture > tex, uint slot)
void bind_vertex_bytes(void *bytes, uint length, uint index)
BufferBindingCached cached_fragment_buffer_bindings[MTL_MAX_UNIFORM_BUFFER_BINDINGS]
void bind_vertex_buffer(id< MTLBuffer > buffer, uint buffer_offset, uint index)
id< MTLDepthStencilState > bound_ds_state
TextureBindingCached cached_vertex_texture_bindings[MTL_MAX_TEXTURE_SLOTS]
SamplerStateBindingCached cached_vertex_sampler_state_bindings[MTL_MAX_TEXTURE_SLOTS]
MTLScissorRect last_scissor_rect
uint last_used_stencil_ref_value
MTLCommandBufferManager & cmd
void bind_fragment_buffer(id< MTLBuffer > buffer, uint buffer_offset, uint index)
id< MTLRenderPipelineState > bound_pso
TextureBindingCached cached_fragment_texture_bindings[MTL_MAX_TEXTURE_SLOTS]
MTLBoundShaderState last_bound_shader_state
void bind_fragment_texture(id< MTLTexture > tex, uint slot)