Blender V4.3
mtl_query.mm
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2022-2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include "mtl_query.hh"
10
11namespace blender::gpu {
12
13static const size_t VISIBILITY_COUNT_PER_BUFFER = 512;
14/* Defined in the documentation but can't be queried programmatically:
15 * https://developer.apple.com/documentation/metal/mtlvisibilityresultmode/mtlvisibilityresultmodeboolean?language=objc
16 */
17static const size_t VISIBILITY_RESULT_SIZE_IN_BYTES = 8;
18
20{
21 allocate();
22}
24{
25 for (gpu::MTLBuffer *buf : buffer_) {
26 BLI_assert(buf);
27 buf->free();
28 }
29}
30
31void MTLQueryPool::allocate()
32{
33 /* Allocate Metal buffer for visibility results. */
35 gpu::MTLBuffer *buffer = MTLContext::get_global_memory_manager()->allocate(buffer_size_in_bytes,
36 true);
37 BLI_assert(buffer);
38
39 /* We must zero-initialize the query buffer as visibility queries with no draws between
40 * begin and end will not write any result to the buffer. */
41 memset(buffer->get_host_ptr(), 0, buffer_size_in_bytes);
42 buffer->flush();
43 buffer_.append(buffer);
44}
45
46static inline MTLVisibilityResultMode to_mtl_type(GPUQueryType type)
47{
48 if (type == GPU_QUERY_OCCLUSION) {
49 return MTLVisibilityResultModeBoolean;
50 }
51 BLI_assert(0);
52 return MTLVisibilityResultModeBoolean;
53}
54
56{
57 BLI_assert(initialized_ == false);
58 initialized_ = true;
59 type_ = type;
60 mtl_type_ = to_mtl_type(type);
61 query_issued_ = 0;
62}
63
65{
67
68 /* Ensure our allocated buffer pool has enough space for the current queries. */
69 int query_id = query_issued_;
70 int requested_buffer = query_id / VISIBILITY_COUNT_PER_BUFFER;
71 if (requested_buffer >= buffer_.size()) {
72 allocate();
73 }
74
75 BLI_assert(requested_buffer < buffer_.size());
76 gpu::MTLBuffer *buffer = buffer_[requested_buffer];
77
78 /* Ensure visibility buffer is set on the context. If visibility buffer changes,
79 * we need to begin a new render pass with an updated reference in the
80 * MTLRenderPassDescriptor. */
81 ctx->set_visibility_buffer(buffer);
82
84 id<MTLRenderCommandEncoder> rec = ctx->main_command_buffer.get_active_render_command_encoder();
85 [rec setVisibilityResultMode:mtl_type_
86 offset:(query_id % VISIBILITY_COUNT_PER_BUFFER) *
88 query_issued_ += 1;
89}
90
92{
94
95 id<MTLRenderCommandEncoder> rec = ctx->main_command_buffer.get_active_render_command_encoder();
96 [rec setVisibilityResultMode:MTLVisibilityResultModeDisabled offset:0];
97}
98
100{
102
103 /* Create a blit encoder to synchronize the query buffer results between
104 * GPU and CPU when not using shared-memory. */
105 if ([ctx->device hasUnifiedMemory] == false) {
106 id<MTLBlitCommandEncoder> blit_encoder = ctx->main_command_buffer.ensure_begin_blit_encoder();
107 BLI_assert(blit_encoder);
108 for (gpu::MTLBuffer *buf : buffer_) {
109 [blit_encoder synchronizeResource:buf->get_metal_buffer()];
110 }
112 }
113
114 /* Wait for GPU operations to complete and for query buffer contents
115 * to be synchronized back to host memory. */
116 GPU_finish();
117
118 /* Iterate through all possible visibility buffers and copy results into provided
119 * container. */
120 for (const int i : IndexRange(query_issued_)) {
121 int requested_buffer = i / VISIBILITY_COUNT_PER_BUFFER;
122 const uint64_t *queries = static_cast<const uint64_t *>(
123 buffer_[requested_buffer]->get_host_ptr());
124 r_values[i] = static_cast<uint32_t>(queries[i % VISIBILITY_COUNT_PER_BUFFER]);
125 }
126 ctx->set_visibility_buffer(nullptr);
127}
128
129} // namespace blender::gpu
#define BLI_assert(a)
Definition BLI_assert.h:50
void GPU_finish()
Definition gpu_state.cc:299
gpu::MTLBuffer * allocate(uint64_t size, bool cpu_visible)
Definition mtl_memory.mm:96
void * get_host_ptr() const
id< MTLBlitCommandEncoder > ensure_begin_blit_encoder()
id< MTLRenderCommandEncoder > get_active_render_command_encoder()
void set_visibility_buffer(gpu::MTLBuffer *buffer)
id< MTLRenderCommandEncoder > ensure_begin_render_pass()
static MTLContext * get()
MTLCommandBufferManager main_command_buffer
static MTLBufferPool * get_global_memory_manager()
void begin_query() override
Definition mtl_query.mm:64
void init(GPUQueryType type) override
Definition mtl_query.mm:55
void end_query() override
Definition mtl_query.mm:91
void get_occlusion_result(MutableSpan< uint32_t > r_values) override
Definition mtl_query.mm:99
static const size_t VISIBILITY_COUNT_PER_BUFFER
Definition mtl_query.mm:13
@ GPU_QUERY_OCCLUSION
Definition gpu_query.hh:18
static const size_t VISIBILITY_RESULT_SIZE_IN_BYTES
Definition mtl_query.mm:17
static MTLSamplerAddressMode to_mtl_type(GPUSamplerExtendMode wrap_mode)
unsigned int uint32_t
Definition stdint.h:80
unsigned __int64 uint64_t
Definition stdint.h:90