Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukas Stockner <lukas.stockner@freenet.de>2022-10-30 00:41:21 +0300
committerLukas Stockner <lukas.stockner@freenet.de>2022-10-30 01:14:59 +0300
commitbc37e8d8399eef686b71341aa90eced9bc117786 (patch)
tree92e4af388150209df9bc44e2cba6f2f303aa7baf /source/blender/gpu/metal/mtl_context.hh
parent552abb838c76d44a0d7d1226b59a1ab381e88386 (diff)
parentd1d2f002c7caaf4ab457ec27bbc44666d7aac624 (diff)
Merge remote-tracking branch 'origin/master' into principled-v2
Diffstat (limited to 'source/blender/gpu/metal/mtl_context.hh')
-rw-r--r--source/blender/gpu/metal/mtl_context.hh153
1 files changed, 126 insertions, 27 deletions
diff --git a/source/blender/gpu/metal/mtl_context.hh b/source/blender/gpu/metal/mtl_context.hh
index 0db87bf5da5..6229afcef79 100644
--- a/source/blender/gpu/metal/mtl_context.hh
+++ b/source/blender/gpu/metal/mtl_context.hh
@@ -3,7 +3,6 @@
/** \file
* \ingroup gpu
*/
-
#pragma once
#include "MEM_guardedalloc.h"
@@ -13,11 +12,17 @@
#include "GPU_common_types.h"
#include "GPU_context.h"
+#include "intern/GHOST_Context.h"
+#include "intern/GHOST_ContextCGL.h"
+#include "intern/GHOST_Window.h"
+
#include "mtl_backend.hh"
#include "mtl_capabilities.hh"
#include "mtl_common.hh"
#include "mtl_framebuffer.hh"
#include "mtl_memory.hh"
+#include "mtl_shader.hh"
+#include "mtl_shader_interface.hh"
#include "mtl_texture.hh"
#include <Cocoa/Cocoa.h>
@@ -33,7 +38,6 @@ namespace blender::gpu {
/* Forward Declarations */
class MTLContext;
class MTLCommandBufferManager;
-class MTLShader;
class MTLUniformBuf;
/* Structs containing information on current binding state for textures and samplers. */
@@ -41,7 +45,7 @@ struct MTLTextureBinding {
bool used;
/* Same value as index in bindings array. */
- uint texture_slot_index;
+ uint slot_index;
gpu::MTLTexture *texture_resource;
};
@@ -57,9 +61,10 @@ struct MTLSamplerBinding {
/* Metal Context Render Pass State -- Used to track active RenderCommandEncoder state based on
* bound MTLFrameBuffer's.Owned by MTLContext. */
-struct MTLRenderPassState {
+class MTLRenderPassState {
friend class MTLContext;
+ public:
MTLRenderPassState(MTLContext &context, MTLCommandBufferManager &command_buffer_manager)
: ctx(context), cmd(command_buffer_manager){};
@@ -174,9 +179,9 @@ struct MTLContextDepthStencilState {
bool has_depth_target;
bool has_stencil_target;
- /* TODO(Metal): Consider optimizing this function using memcmp.
+ /* TODO(Metal): Consider optimizing this function using `memcmp`.
* Un-used, but differing, stencil state leads to over-generation
- * of state objects when doing trivial compare. */
+ * of state objects when doing trivial compare. */
bool operator==(const MTLContextDepthStencilState &other) const
{
bool depth_state_equality = (has_depth_target == other.has_depth_target &&
@@ -247,7 +252,7 @@ struct MTLContextTextureUtils {
/* Depth texture updates are not directly supported with Blit operations, similarly, we cannot
* use a compute shader to write to depth, so we must instead render to a depth target.
* These processes use vertex/fragment shaders to render texture data from an intermediate
- * source, in order to prime the depth buffer*/
+ * source, in order to prime the depth buffer. */
blender::Map<DepthTextureUpdateRoutineSpecialisation, GPUShader *> depth_2d_update_shaders;
GPUShader *fullscreen_blit_shader = nullptr;
@@ -347,7 +352,7 @@ struct MTLSamplerArray {
{
uint32_t hash = this->num_samplers;
for (int i = 0; i < this->num_samplers; i++) {
- hash ^= (uint32_t)this->mtl_sampler_flags[i] << (i % 3);
+ hash ^= uint32_t(this->mtl_sampler_flags[i]) << (i % 3);
}
return hash;
}
@@ -357,7 +362,7 @@ typedef enum MTLPipelineStateDirtyFlag {
MTL_PIPELINE_STATE_NULL_FLAG = 0,
/* Whether we need to call setViewport. */
MTL_PIPELINE_STATE_VIEWPORT_FLAG = (1 << 0),
- /* Whether we need to call setScissor.*/
+ /* Whether we need to call setScissor. */
MTL_PIPELINE_STATE_SCISSOR_FLAG = (1 << 1),
/* Whether we need to update/rebind active depth stencil state. */
MTL_PIPELINE_STATE_DEPTHSTENCIL_FLAG = (1 << 2),
@@ -564,18 +569,55 @@ class MTLCommandBufferManager {
};
/** MTLContext -- Core render loop and state management. **/
-/* NOTE(Metal): Partial MTLContext stub to provide wrapper functionality
- * for work-in-progress MTL* classes. */
+/* NOTE(Metal): Partial #MTLContext stub to provide wrapper functionality
+ * for work-in-progress `MTL*` classes. */
class MTLContext : public Context {
friend class MTLBackend;
+ friend class MTLRenderPassState;
+
+ public:
+ /* Swap-chain and latency management. */
+ static std::atomic<int> max_drawables_in_flight;
+ static std::atomic<int64_t> avg_drawable_latency_us;
+ static int64_t frame_latency[MTL_FRAME_AVERAGE_COUNT];
+
+ public:
+ /* Shaders and Pipeline state. */
+ MTLContextGlobalShaderPipelineState pipeline_state;
+
+ /* Metal API Resource Handles. */
+ id<MTLCommandQueue> queue = nil;
+ id<MTLDevice> device = nil;
+
+#ifndef NDEBUG
+ /* Label for Context debug name assignment. */
+ NSString *label = nil;
+#endif
+
+ /* Memory Management. */
+ MTLScratchBufferManager memory_manager;
+ static MTLBufferPool global_memory_manager;
+
+ /* CommandBuffer managers. */
+ MTLCommandBufferManager main_command_buffer;
private:
+ /* Parent Context. */
+ GHOST_ContextCGL *ghost_context_;
+
+ /* Render Passes and Frame-buffers. */
+ id<MTLTexture> default_fbo_mtltexture_ = nil;
+ gpu::MTLTexture *default_fbo_gputexture_ = nullptr;
+
+ /* Depth-stencil state cache. */
+ blender::Map<MTLContextDepthStencilState, id<MTLDepthStencilState>> depth_stencil_state_cache;
+
/* Compute and specialization caches. */
MTLContextTextureUtils texture_utils_;
/* Texture Samplers. */
- /* Cache of generated MTLSamplerState objects based on permutations of `eGPUSamplerState`. */
+ /* Cache of generated #MTLSamplerState objects based on permutations of `eGPUSamplerState`. */
id<MTLSamplerState> sampler_state_cache_[GPU_SAMPLER_MAX];
id<MTLSamplerState> default_sampler_state_ = nil;
@@ -595,23 +637,20 @@ class MTLContext : public Context {
gpu::MTLBuffer *visibility_buffer_ = nullptr;
bool visibility_is_dirty_ = false;
- public:
- /* Shaders and Pipeline state. */
- MTLContextGlobalShaderPipelineState pipeline_state;
-
- /* Metal API Resource Handles. */
- id<MTLCommandQueue> queue = nil;
- id<MTLDevice> device = nil;
-
- /* Memory Management */
- MTLScratchBufferManager memory_manager;
- static MTLBufferPool global_memory_manager;
+ /* Null buffers for empty/uninitialized bindings.
+ * Null attribute buffer follows default attribute format of OpenGL Backend. */
+ id<MTLBuffer> null_buffer_; /* All zero's. */
+ id<MTLBuffer> null_attribute_buffer_; /* Value float4(0.0,0.0,0.0,1.0). */
- /* CommandBuffer managers. */
- MTLCommandBufferManager main_command_buffer;
+ /** Dummy Resources */
+ /* Maximum of 32 texture types. Though most combinations invalid. */
+ gpu::MTLTexture *dummy_textures_[GPU_TEXTURE_BUFFER] = {nullptr};
+ GPUVertFormat dummy_vertformat_;
+ GPUVertBuf *dummy_verts_ = nullptr;
+ public:
/* GPUContext interface. */
- MTLContext(void *ghost_window);
+ MTLContext(void *ghost_window, void *ghost_context);
~MTLContext();
static void check_error(const char *info);
@@ -667,6 +706,35 @@ class MTLContext : public Context {
void pipeline_state_init();
MTLShader *get_active_shader();
+ /* These functions ensure that the current RenderCommandEncoder has
+ * the correct global state assigned. This should be called prior
+ * to every draw call, to ensure that all state is applied and up
+ * to date. We handle:
+ *
+ * - Buffer bindings (Vertex buffers, Uniforms, UBOs, transform feedback)
+ * - Texture bindings
+ * - Sampler bindings (+ argument buffer bindings)
+ * - Dynamic Render pipeline state (on encoder)
+ * - Baking Pipeline State Objects (PSOs) for current shader, based
+ * on final pipeline state.
+ *
+ * `ensure_render_pipeline_state` will return false if the state is
+ * invalid and cannot be applied. This should cancel a draw call. */
+ bool ensure_render_pipeline_state(MTLPrimitiveType prim_type);
+ bool ensure_uniform_buffer_bindings(
+ id<MTLRenderCommandEncoder> rec,
+ const MTLShaderInterface *shader_interface,
+ const MTLRenderPipelineStateInstance *pipeline_state_instance);
+ void ensure_texture_bindings(id<MTLRenderCommandEncoder> rec,
+ MTLShaderInterface *shader_interface,
+ const MTLRenderPipelineStateInstance *pipeline_state_instance);
+ void ensure_depth_stencil_state(MTLPrimitiveType prim_type);
+
+ id<MTLBuffer> get_null_buffer();
+ id<MTLBuffer> get_null_attribute_buffer();
+ gpu::MTLTexture *get_dummy_texture(eGPUTextureType type);
+ void free_dummy_resources();
+
/* State assignment. */
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);
@@ -678,7 +746,7 @@ class MTLContext : public Context {
/* Flag whether the visibility buffer for query results
* has changed. This requires a new RenderPass in order
- * to update.*/
+ * to update. */
bool is_visibility_dirty() const;
/* Reset dirty flag state for visibility buffer. */
@@ -714,6 +782,37 @@ class MTLContext : public Context {
{
return MTLContext::global_memory_manager;
}
+
+ /* Swap-chain and latency management. */
+ static void latency_resolve_average(int64_t frame_latency_us)
+ {
+ int64_t avg = 0;
+ int64_t frame_c = 0;
+ for (int i = MTL_FRAME_AVERAGE_COUNT - 1; i > 0; i--) {
+ MTLContext::frame_latency[i] = MTLContext::frame_latency[i - 1];
+ avg += MTLContext::frame_latency[i];
+ frame_c += (MTLContext::frame_latency[i] > 0) ? 1 : 0;
+ }
+ MTLContext::frame_latency[0] = frame_latency_us;
+ avg += MTLContext::frame_latency[0];
+ if (frame_c > 0) {
+ avg /= frame_c;
+ }
+ else {
+ avg = 0;
+ }
+ MTLContext::avg_drawable_latency_us = avg;
+ }
+
+ private:
+ void set_ghost_context(GHOST_ContextHandle ghostCtxHandle);
+ void set_ghost_window(GHOST_WindowHandle ghostWinHandle);
};
+/* GHOST Context callback and present. */
+void present(MTLRenderPassDescriptor *blit_descriptor,
+ id<MTLRenderPipelineState> blit_pso,
+ id<MTLTexture> swapchain_texture,
+ id<CAMetalDrawable> drawable);
+
} // namespace blender::gpu