Blender
V4.3
source
blender
gpu
metal
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
11
namespace
blender::gpu
{
12
13
static
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
*/
17
static
const
size_t
VISIBILITY_RESULT_SIZE_IN_BYTES
= 8;
18
19
MTLQueryPool::MTLQueryPool
()
20
{
21
allocate();
22
}
23
MTLQueryPool::~MTLQueryPool
()
24
{
25
for
(
gpu::MTLBuffer
*buf : buffer_) {
26
BLI_assert
(buf);
27
buf->free();
28
}
29
}
30
31
void
MTLQueryPool::allocate()
32
{
33
/* Allocate Metal buffer for visibility results. */
34
size_t
buffer_size_in_bytes =
VISIBILITY_COUNT_PER_BUFFER
*
VISIBILITY_RESULT_SIZE_IN_BYTES
;
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
46
static
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
55
void
MTLQueryPool::init
(
GPUQueryType
type)
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
64
void
MTLQueryPool::begin_query
()
65
{
66
MTLContext
*ctx =
MTLContext::get
();
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
83
ctx->
ensure_begin_render_pass
();
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
) *
87
VISIBILITY_RESULT_SIZE_IN_BYTES
];
88
query_issued_ += 1;
89
}
90
91
void
MTLQueryPool::end_query
()
92
{
93
MTLContext
*ctx =
MTLContext::get
();
94
95
id<MTLRenderCommandEncoder> rec = ctx->
main_command_buffer
.
get_active_render_command_encoder
();
96
[rec setVisibilityResultMode:MTLVisibilityResultModeDisabled offset:0];
97
}
98
99
void
MTLQueryPool::get_occlusion_result
(
MutableSpan<uint32_t>
r_values)
100
{
101
MTLContext
*ctx =
MTLContext::get
();
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
}
111
BLI_assert
(ctx->
get_inside_frame
());
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
BLI_assert
#define BLI_assert(a)
Definition
BLI_assert.h:50
GPU_finish
void GPU_finish()
Definition
gpu_state.cc:299
blender::IndexRange
Definition
BLI_index_range.hh:50
blender::MutableSpan
Definition
BLI_span.hh:444
blender::gpu::MTLBufferPool::allocate
gpu::MTLBuffer * allocate(uint64_t size, bool cpu_visible)
Definition
mtl_memory.mm:96
blender::gpu::MTLBuffer
Definition
mtl_memory.hh:110
blender::gpu::MTLBuffer::flush
void flush()
Definition
mtl_memory.mm:763
blender::gpu::MTLBuffer::get_host_ptr
void * get_host_ptr() const
Definition
mtl_memory.mm:726
blender::gpu::MTLCommandBufferManager::ensure_begin_blit_encoder
id< MTLBlitCommandEncoder > ensure_begin_blit_encoder()
Definition
mtl_command_buffer.mm:366
blender::gpu::MTLCommandBufferManager::get_active_render_command_encoder
id< MTLRenderCommandEncoder > get_active_render_command_encoder()
Definition
mtl_command_buffer.mm:197
blender::gpu::MTLContext
Definition
mtl_context.hh:672
blender::gpu::MTLContext::set_visibility_buffer
void set_visibility_buffer(gpu::MTLBuffer *buffer)
Definition
mtl_context.mm:2359
blender::gpu::MTLContext::ensure_begin_render_pass
id< MTLRenderCommandEncoder > ensure_begin_render_pass()
Definition
mtl_context.mm:489
blender::gpu::MTLContext::get
static MTLContext * get()
Definition
mtl_context.hh:773
blender::gpu::MTLContext::device
id< MTLDevice > device
Definition
mtl_context.hh:689
blender::gpu::MTLContext::main_command_buffer
MTLCommandBufferManager main_command_buffer
Definition
mtl_context.hh:703
blender::gpu::MTLContext::get_inside_frame
bool get_inside_frame()
Definition
mtl_context.hh:897
blender::gpu::MTLContext::get_global_memory_manager
static MTLBufferPool * get_global_memory_manager()
Definition
mtl_context.hh:937
blender::gpu::MTLQueryPool::begin_query
void begin_query() override
Definition
mtl_query.mm:64
blender::gpu::MTLQueryPool::MTLQueryPool
MTLQueryPool()
Definition
mtl_query.mm:19
blender::gpu::MTLQueryPool::init
void init(GPUQueryType type) override
Definition
mtl_query.mm:55
blender::gpu::MTLQueryPool::end_query
void end_query() override
Definition
mtl_query.mm:91
blender::gpu::MTLQueryPool::get_occlusion_result
void get_occlusion_result(MutableSpan< uint32_t > r_values) override
Definition
mtl_query.mm:99
blender::gpu::MTLQueryPool::~MTLQueryPool
~MTLQueryPool()
Definition
mtl_query.mm:23
mtl_query.hh
blender::gpu
Definition
blf_internal_types.hh:23
blender::gpu::VISIBILITY_COUNT_PER_BUFFER
static const size_t VISIBILITY_COUNT_PER_BUFFER
Definition
mtl_query.mm:13
blender::gpu::GPUQueryType
GPUQueryType
Definition
gpu_query.hh:17
blender::gpu::GPU_QUERY_OCCLUSION
@ GPU_QUERY_OCCLUSION
Definition
gpu_query.hh:18
blender::gpu::VISIBILITY_RESULT_SIZE_IN_BYTES
static const size_t VISIBILITY_RESULT_SIZE_IN_BYTES
Definition
mtl_query.mm:17
blender::gpu::to_mtl_type
static MTLSamplerAddressMode to_mtl_type(GPUSamplerExtendMode wrap_mode)
Definition
mtl_context.mm:2490
uint32_t
unsigned int uint32_t
Definition
stdint.h:80
uint64_t
unsigned __int64 uint64_t
Definition
stdint.h:90
Generated on Thu Feb 6 2025 07:36:39 for Blender by
doxygen
1.11.0