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:
Diffstat (limited to 'source/blender/gpu/metal/mtl_context.mm')
-rw-r--r--source/blender/gpu/metal/mtl_context.mm236
1 files changed, 236 insertions, 0 deletions
diff --git a/source/blender/gpu/metal/mtl_context.mm b/source/blender/gpu/metal/mtl_context.mm
index 18ed38c373d..94f5682b11b 100644
--- a/source/blender/gpu/metal/mtl_context.mm
+++ b/source/blender/gpu/metal/mtl_context.mm
@@ -5,6 +5,11 @@
*/
#include "mtl_context.hh"
#include "mtl_debug.hh"
+#include "mtl_state.hh"
+
+#include "DNA_userdef_types.h"
+
+#include "GPU_capabilities.h"
using namespace blender;
using namespace blender::gpu;
@@ -44,6 +49,9 @@ MTLContext::MTLContext(void *ghost_window)
/* Init debug. */
debug::mtl_debug_init();
+ /* Initialize Metal modules. */
+ this->state_manager = new MTLStateManager(this);
+
/* TODO(Metal): Implement. */
}
@@ -98,6 +106,234 @@ void MTLContext::end_render_pass()
/* TODO(Metal): Implement. */
}
+bool MTLContext::is_render_pass_active()
+{
+ /* TODO(Metal): Implement. */
+ return false;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Global Context State
+ * \{ */
+
+/* Metal Context Pipeline State. */
+void MTLContext::pipeline_state_init()
+{
+ /*** Initialize state only once. ***/
+ if (!this->pipeline_state.initialised) {
+ this->pipeline_state.initialised = true;
+ this->pipeline_state.active_shader = NULL;
+
+ /* Clear bindings state. */
+ for (int t = 0; t < GPU_max_textures(); t++) {
+ this->pipeline_state.texture_bindings[t].used = false;
+ this->pipeline_state.texture_bindings[t].texture_slot_index = t;
+ this->pipeline_state.texture_bindings[t].texture_resource = NULL;
+ }
+ for (int s = 0; s < MTL_MAX_SAMPLER_SLOTS; s++) {
+ this->pipeline_state.sampler_bindings[s].used = false;
+ }
+ for (int u = 0; u < MTL_MAX_UNIFORM_BUFFER_BINDINGS; u++) {
+ this->pipeline_state.ubo_bindings[u].bound = false;
+ this->pipeline_state.ubo_bindings[u].ubo = NULL;
+ }
+ }
+
+ /*** State defaults -- restored by GPU_state_init. ***/
+ /* Clear blending State. */
+ this->pipeline_state.color_write_mask = MTLColorWriteMaskRed | MTLColorWriteMaskGreen |
+ MTLColorWriteMaskBlue | MTLColorWriteMaskAlpha;
+ this->pipeline_state.blending_enabled = false;
+ this->pipeline_state.alpha_blend_op = MTLBlendOperationAdd;
+ this->pipeline_state.rgb_blend_op = MTLBlendOperationAdd;
+ this->pipeline_state.dest_alpha_blend_factor = MTLBlendFactorZero;
+ this->pipeline_state.dest_rgb_blend_factor = MTLBlendFactorZero;
+ this->pipeline_state.src_alpha_blend_factor = MTLBlendFactorOne;
+ this->pipeline_state.src_rgb_blend_factor = MTLBlendFactorOne;
+
+ /* Viewport and scissor. */
+ this->pipeline_state.viewport_offset_x = 0;
+ this->pipeline_state.viewport_offset_y = 0;
+ this->pipeline_state.viewport_width = 0;
+ this->pipeline_state.viewport_height = 0;
+ this->pipeline_state.scissor_x = 0;
+ this->pipeline_state.scissor_y = 0;
+ this->pipeline_state.scissor_width = 0;
+ this->pipeline_state.scissor_height = 0;
+ this->pipeline_state.scissor_enabled = false;
+
+ /* Culling State. */
+ this->pipeline_state.culling_enabled = false;
+ this->pipeline_state.cull_mode = GPU_CULL_NONE;
+ this->pipeline_state.front_face = GPU_COUNTERCLOCKWISE;
+
+ /* DATA and IMAGE access state. */
+ this->pipeline_state.unpack_row_length = 0;
+
+ /* Depth State. */
+ this->pipeline_state.depth_stencil_state.depth_write_enable = false;
+ this->pipeline_state.depth_stencil_state.depth_test_enabled = false;
+ this->pipeline_state.depth_stencil_state.depth_range_near = 0.0;
+ this->pipeline_state.depth_stencil_state.depth_range_far = 1.0;
+ this->pipeline_state.depth_stencil_state.depth_function = MTLCompareFunctionAlways;
+ this->pipeline_state.depth_stencil_state.depth_bias = 0.0;
+ this->pipeline_state.depth_stencil_state.depth_slope_scale = 0.0;
+ this->pipeline_state.depth_stencil_state.depth_bias_enabled_for_points = false;
+ this->pipeline_state.depth_stencil_state.depth_bias_enabled_for_lines = false;
+ this->pipeline_state.depth_stencil_state.depth_bias_enabled_for_tris = false;
+
+ /* Stencil State. */
+ this->pipeline_state.depth_stencil_state.stencil_test_enabled = false;
+ this->pipeline_state.depth_stencil_state.stencil_read_mask = 0xFF;
+ this->pipeline_state.depth_stencil_state.stencil_write_mask = 0xFF;
+ this->pipeline_state.depth_stencil_state.stencil_ref = 0;
+ this->pipeline_state.depth_stencil_state.stencil_func = MTLCompareFunctionAlways;
+ this->pipeline_state.depth_stencil_state.stencil_op_front_stencil_fail = MTLStencilOperationKeep;
+ this->pipeline_state.depth_stencil_state.stencil_op_front_depth_fail = MTLStencilOperationKeep;
+ this->pipeline_state.depth_stencil_state.stencil_op_front_depthstencil_pass =
+ MTLStencilOperationKeep;
+ this->pipeline_state.depth_stencil_state.stencil_op_back_stencil_fail = MTLStencilOperationKeep;
+ this->pipeline_state.depth_stencil_state.stencil_op_back_depth_fail = MTLStencilOperationKeep;
+ this->pipeline_state.depth_stencil_state.stencil_op_back_depthstencil_pass =
+ MTLStencilOperationKeep;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Texture State Management
+ * \{ */
+
+void MTLContext::texture_bind(gpu::MTLTexture *mtl_texture, unsigned int texture_unit)
+{
+ BLI_assert(this);
+ BLI_assert(mtl_texture);
+
+ if (texture_unit < 0 || texture_unit >= GPU_max_textures() ||
+ texture_unit >= MTL_MAX_TEXTURE_SLOTS) {
+ MTL_LOG_WARNING("Attempting to bind texture '%s' to invalid texture unit %d\n",
+ mtl_texture->get_name(),
+ texture_unit);
+ BLI_assert(false);
+ return;
+ }
+
+ /* Bind new texture. */
+ this->pipeline_state.texture_bindings[texture_unit].texture_resource = mtl_texture;
+ this->pipeline_state.texture_bindings[texture_unit].used = true;
+ mtl_texture->is_bound_ = true;
+}
+
+void MTLContext::sampler_bind(MTLSamplerState sampler_state, unsigned int sampler_unit)
+{
+ BLI_assert(this);
+ if (sampler_unit < 0 || sampler_unit >= GPU_max_textures() ||
+ sampler_unit >= MTL_MAX_SAMPLER_SLOTS) {
+ MTL_LOG_WARNING("Attempting to bind sampler to invalid sampler unit %d\n", sampler_unit);
+ BLI_assert(false);
+ return;
+ }
+
+ /* Apply binding. */
+ this->pipeline_state.sampler_bindings[sampler_unit] = {true, sampler_state};
+}
+
+void MTLContext::texture_unbind(gpu::MTLTexture *mtl_texture)
+{
+ BLI_assert(mtl_texture);
+
+ /* Iterate through textures in state and unbind. */
+ for (int i = 0; i < min_uu(GPU_max_textures(), MTL_MAX_TEXTURE_SLOTS); i++) {
+ if (this->pipeline_state.texture_bindings[i].texture_resource == mtl_texture) {
+ this->pipeline_state.texture_bindings[i].texture_resource = nullptr;
+ this->pipeline_state.texture_bindings[i].used = false;
+ }
+ }
+
+ /* Locally unbind texture. */
+ mtl_texture->is_bound_ = false;
+}
+
+void MTLContext::texture_unbind_all()
+{
+ /* Iterate through context's bound textures. */
+ for (int t = 0; t < min_uu(GPU_max_textures(), MTL_MAX_TEXTURE_SLOTS); t++) {
+ if (this->pipeline_state.texture_bindings[t].used &&
+ this->pipeline_state.texture_bindings[t].texture_resource) {
+
+ this->pipeline_state.texture_bindings[t].used = false;
+ this->pipeline_state.texture_bindings[t].texture_resource = nullptr;
+ }
+ }
+}
+
+id<MTLSamplerState> MTLContext::get_sampler_from_state(MTLSamplerState sampler_state)
+{
+ BLI_assert((unsigned int)sampler_state >= 0 && ((unsigned int)sampler_state) < GPU_SAMPLER_MAX);
+ return this->sampler_state_cache_[(unsigned int)sampler_state];
+}
+
+id<MTLSamplerState> MTLContext::generate_sampler_from_state(MTLSamplerState sampler_state)
+{
+ /* Check if sampler already exists for given state. */
+ id<MTLSamplerState> st = this->sampler_state_cache_[(unsigned int)sampler_state];
+ if (st != nil) {
+ return st;
+ }
+ else {
+ MTLSamplerDescriptor *descriptor = [[MTLSamplerDescriptor alloc] init];
+ descriptor.normalizedCoordinates = true;
+
+ MTLSamplerAddressMode clamp_type = (sampler_state.state & GPU_SAMPLER_CLAMP_BORDER) ?
+ MTLSamplerAddressModeClampToBorderColor :
+ MTLSamplerAddressModeClampToEdge;
+ descriptor.rAddressMode = (sampler_state.state & GPU_SAMPLER_REPEAT_R) ?
+ MTLSamplerAddressModeRepeat :
+ clamp_type;
+ descriptor.sAddressMode = (sampler_state.state & GPU_SAMPLER_REPEAT_S) ?
+ MTLSamplerAddressModeRepeat :
+ clamp_type;
+ descriptor.tAddressMode = (sampler_state.state & GPU_SAMPLER_REPEAT_T) ?
+ MTLSamplerAddressModeRepeat :
+ clamp_type;
+ descriptor.borderColor = MTLSamplerBorderColorTransparentBlack;
+ descriptor.minFilter = (sampler_state.state & GPU_SAMPLER_FILTER) ?
+ MTLSamplerMinMagFilterLinear :
+ MTLSamplerMinMagFilterNearest;
+ descriptor.magFilter = (sampler_state.state & GPU_SAMPLER_FILTER) ?
+ MTLSamplerMinMagFilterLinear :
+ MTLSamplerMinMagFilterNearest;
+ descriptor.mipFilter = (sampler_state.state & GPU_SAMPLER_MIPMAP) ?
+ MTLSamplerMipFilterLinear :
+ MTLSamplerMipFilterNotMipmapped;
+ descriptor.lodMinClamp = -1000;
+ descriptor.lodMaxClamp = 1000;
+ float aniso_filter = max_ff(16, U.anisotropic_filter);
+ descriptor.maxAnisotropy = (sampler_state.state & GPU_SAMPLER_MIPMAP) ? aniso_filter : 1;
+ descriptor.compareFunction = (sampler_state.state & GPU_SAMPLER_COMPARE) ?
+ MTLCompareFunctionLessEqual :
+ MTLCompareFunctionAlways;
+ descriptor.supportArgumentBuffers = true;
+
+ id<MTLSamplerState> state = [this->device newSamplerStateWithDescriptor:descriptor];
+ this->sampler_state_cache_[(unsigned int)sampler_state] = state;
+
+ BLI_assert(state != nil);
+ [descriptor autorelease];
+ return state;
+ }
+}
+
+id<MTLSamplerState> MTLContext::get_default_sampler_state()
+{
+ if (this->default_sampler_state_ == nil) {
+ this->default_sampler_state_ = this->get_sampler_from_state(DEFAULT_SAMPLER_STATE);
+ }
+ return this->default_sampler_state_;
+}
+
/** \} */
} // blender::gpu