Blender  V3.3
mtl_query.mm
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
7 #include "mtl_query.hh"
8 
9 namespace blender::gpu {
10 
11 static const size_t VISIBILITY_COUNT_PER_BUFFER = 512;
12 /* defined in the documentation but not queryable programmatically:
13  * https://developer.apple.com/documentation/metal/mtlvisibilityresultmode/mtlvisibilityresultmodeboolean?language=objc
14  */
15 static const size_t VISIBILITY_RESULT_SIZE_IN_BYTES = 8;
16 
18 {
19  allocate_buffer();
20 }
22 {
23  for (gpu::MTLBuffer *buf : buffer_) {
24  BLI_assert(buf);
25  buf->free();
26  }
27 }
28 
29 void MTLQueryPool::allocate_buffer()
30 {
31  /* Allocate Metal buffer for visibility results. */
32  size_t buffer_size_in_bytes = VISIBILITY_COUNT_PER_BUFFER * VISIBILITY_RESULT_SIZE_IN_BYTES;
34  buffer_size_in_bytes, true);
36  buffer_.append(buffer);
37 }
38 
39 static inline MTLVisibilityResultMode to_mtl_type(GPUQueryType type)
40 {
41  if (type == GPU_QUERY_OCCLUSION) {
42  return MTLVisibilityResultModeBoolean;
43  }
44  BLI_assert(0);
45  return MTLVisibilityResultModeBoolean;
46 }
47 
49 {
50  BLI_assert(initialized_ == false);
51  initialized_ = true;
52  type_ = type;
53  mtl_type_ = to_mtl_type(type);
54  query_issued_ = 0;
55 }
56 
58 {
59  MTLContext *ctx = reinterpret_cast<MTLContext *>(GPU_context_active_get());
60 
61  /* Ensure our allocated buffer pool has enough space for the current queries. */
62  int query_id = query_issued_;
63  int requested_buffer = query_id / VISIBILITY_COUNT_PER_BUFFER;
64  if (requested_buffer >= buffer_.size()) {
65  allocate_buffer();
66  }
67 
68  BLI_assert(requested_buffer < buffer_.size());
69  gpu::MTLBuffer *buffer = buffer_[requested_buffer];
70 
71  /* Ensure visibility buffer is set on the context. If visibility buffer changes,
72  * we need to begin a new render pass with an updated reference in the
73  * MTLRenderPassDescriptor. */
75 
77  id<MTLRenderCommandEncoder> rec = ctx->main_command_buffer.get_active_render_command_encoder();
78  [rec setVisibilityResultMode:mtl_type_
79  offset:(query_id % VISIBILITY_COUNT_PER_BUFFER) *
81  query_issued_ += 1;
82 }
83 
85 {
86  MTLContext *ctx = reinterpret_cast<MTLContext *>(GPU_context_active_get());
87 
88  id<MTLRenderCommandEncoder> rec = ctx->main_command_buffer.get_active_render_command_encoder();
89  [rec setVisibilityResultMode:MTLVisibilityResultModeDisabled offset:0];
90 }
91 
93 {
94  MTLContext *ctx = reinterpret_cast<MTLContext *>(GPU_context_active_get());
95 
96  /* Create a blit encoder to synchronize the query buffer results between
97  * GPU and CPU when not using shared-memory. */
98  if ([ctx->device hasUnifiedMemory] == false) {
99  id<MTLBlitCommandEncoder> blit_encoder = ctx->main_command_buffer.ensure_begin_blit_encoder();
100  BLI_assert(blit_encoder);
101  for (gpu::MTLBuffer *buf : buffer_) {
102  [blit_encoder synchronizeResource:buf->get_metal_buffer()];
103  }
105  }
106 
107  /* Wait for GPU operations to complete and for query buffer contents
108  * to be synchronized back to host memory. */
109  GPU_finish();
110 
111  /* Iterate through all possible visibility buffers and copy results into provided
112  * container. */
113  for (const int i : IndexRange(query_issued_)) {
114  int requested_buffer = i / VISIBILITY_COUNT_PER_BUFFER;
115  const uint64_t *queries = static_cast<const uint64_t *>(
116  buffer_[requested_buffer]->get_host_ptr());
117  r_values[i] = static_cast<uint32_t>(queries[i % VISIBILITY_COUNT_PER_BUFFER]);
118  }
119  ctx->set_visibility_buffer(nullptr);
120 }
121 
122 } // namespace blender::gpu
#define BLI_assert(a)
Definition: BLI_assert.h:46
GPUContext * GPU_context_active_get(void)
Definition: gpu_context.cc:142
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
void GPU_finish(void)
Definition: gpu_state.cc:296
id< MTLBlitCommandEncoder > ensure_begin_blit_encoder()
id< MTLRenderCommandEncoder > get_active_render_command_encoder()
void set_visibility_buffer(gpu::MTLBuffer *buffer)
Definition: mtl_context.mm:379
id< MTLRenderCommandEncoder > ensure_begin_render_pass()
Definition: mtl_context.mm:164
id< MTLDevice > device
Definition: mtl_context.hh:604
MTLCommandBufferManager main_command_buffer
Definition: mtl_context.hh:611
static MTLBufferPool & get_global_memory_manager()
Definition: mtl_context.hh:713
void begin_query() override
Definition: mtl_query.mm:57
void init(GPUQueryType type) override
Definition: mtl_query.mm:48
void end_query() override
Definition: mtl_query.mm:84
void get_occlusion_result(MutableSpan< uint32_t > r_values) override
Definition: mtl_query.mm:92
ccl_global float * buffer
ccl_gpu_kernel_postfix ccl_global float int int int int float bool int offset
static const size_t VISIBILITY_COUNT_PER_BUFFER
Definition: mtl_query.mm:11
@ GPU_QUERY_OCCLUSION
Definition: gpu_query.hh:17
static const size_t VISIBILITY_RESULT_SIZE_IN_BYTES
Definition: mtl_query.mm:15
static MTLVisibilityResultMode to_mtl_type(GPUQueryType type)
Definition: mtl_query.mm:39
unsigned int uint32_t
Definition: stdint.h:80
unsigned __int64 uint64_t
Definition: stdint.h:90