Path: blob/master/drivers/metal/rendering_shader_container_metal.h
21826 views
/**************************************************************************/1/* rendering_shader_container_metal.h */2/**************************************************************************/3/* This file is part of: */4/* GODOT ENGINE */5/* https://godotengine.org */6/**************************************************************************/7/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */8/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */9/* */10/* Permission is hereby granted, free of charge, to any person obtaining */11/* a copy of this software and associated documentation files (the */12/* "Software"), to deal in the Software without restriction, including */13/* without limitation the rights to use, copy, modify, merge, publish, */14/* distribute, sublicense, and/or sell copies of the Software, and to */15/* permit persons to whom the Software is furnished to do so, subject to */16/* the following conditions: */17/* */18/* The above copyright notice and this permission notice shall be */19/* included in all copies or substantial portions of the Software. */20/* */21/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */22/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */23/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */24/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */25/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */26/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */27/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */28/**************************************************************************/2930#pragma once3132#include "metal_device_profile.h"33#include "sha256_digest.h"3435#include "servers/rendering/rendering_device_driver.h"36#include "servers/rendering/rendering_shader_container.h"3738constexpr uint32_t R32UI_ALIGNMENT_CONSTANT_ID = 65535;39/// Metal buffer index for the view mask when rendering multi-view.40const uint32_t VIEW_MASK_BUFFER_INDEX = 24;4142class RenderingShaderContainerFormatMetal;4344class RenderingShaderContainerMetal : public RenderingShaderContainer {45GDSOFTCLASS(RenderingShaderContainerMetal, RenderingShaderContainer);4647public:48struct HeaderData {49enum Flags : uint32_t {50NONE = 0,51NEEDS_VIEW_MASK_BUFFER = 1 << 0,52USES_ARGUMENT_BUFFERS = 1 << 1,53NEEDS_DEBUG_LOGGING = 1 << 2,54};5556/// The base profile that was used to generate this shader.57MetalDeviceProfile profile;5859/// The Metal language version specified when compiling SPIR-V to MSL.60/// Format is major * 10000 + minor * 100 + patch.61uint32_t msl_version = UINT32_MAX;62/*! @brief The minimum supported OS version for shaders baked to a `.metallib`.63*64* NOTE: This property is only valid when shaders are baked to a .metalllib65*66* Format is major * 10000 + minor * 100 + patch.67*/68MinOsVersion os_min_version;69uint32_t flags = NONE;70uint32_t push_constant_binding = UINT32_MAX; ///< Metal binding slot for the push constant data7172/// @brief Returns `true` if the shader is compiled with multi-view support.73bool needs_view_mask_buffer() const {74return flags & NEEDS_VIEW_MASK_BUFFER;75}7677void set_needs_view_mask_buffer(bool p_value) {78if (p_value) {79flags |= NEEDS_VIEW_MASK_BUFFER;80} else {81flags &= ~NEEDS_VIEW_MASK_BUFFER;82}83}8485/// @brief Returns `true` if the shader was compiled with argument buffer support.86bool uses_argument_buffers() const {87return flags & USES_ARGUMENT_BUFFERS;88}8990void set_uses_argument_buffers(bool p_value) {91if (p_value) {92flags |= USES_ARGUMENT_BUFFERS;93} else {94flags &= ~USES_ARGUMENT_BUFFERS;95}96}9798/// Returns `true` if the shader was compiled with the GL_EXT_debug_printf extension enabled.99bool needs_debug_logging() const {100return flags & NEEDS_DEBUG_LOGGING;101}102103void set_needs_debug_logging(bool p_value) {104if (p_value) {105flags |= NEEDS_DEBUG_LOGGING;106} else {107flags &= ~NEEDS_DEBUG_LOGGING;108}109}110};111112struct StageData {113uint32_t vertex_input_binding_mask = 0;114uint32_t is_position_invariant = 0; ///< <c>true</c> if the position output is invariant115uint32_t supports_fast_math = 0;116SHA256Digest hash; ///< SHA 256 hash of the shader code117uint32_t source_size = 0; ///< size of the source code in the returned bytes118uint32_t library_size = 0; ///< size of the compiled library in the returned bytes, 0 if it is not compiled119};120121struct UniformData {122uint32_t active_stages = 0;123uint32_t uniform_type = 0; // UniformType124uint32_t data_type = 0; // MTLDataTypeNone125uint32_t access = 0; // MTLBindingAccessReadOnly126uint32_t usage = 0; // MTLResourceUsage (none)127uint32_t texture_type = 2; // MTLTextureType2D128uint32_t image_format = 0;129uint32_t array_length = 0;130uint32_t is_multisampled = 0;131132struct Indexes {133uint32_t buffer = UINT32_MAX;134uint32_t texture = UINT32_MAX;135uint32_t sampler = UINT32_MAX;136};137Indexes slot;138Indexes arg_buffer;139140enum class IndexType {141SLOT,142ARG,143};144145_FORCE_INLINE_ Indexes &get_indexes(IndexType p_type) {146switch (p_type) {147case IndexType::SLOT:148return slot;149case IndexType::ARG:150return arg_buffer;151}152}153};154155HeaderData mtl_reflection_data; // compliment to reflection_data156Vector<StageData> mtl_shaders; // compliment to shaders157158private:159struct ToolchainProperties {160MinOsVersion os_version_min_required;161uint32_t metal_version = UINT32_MAX;162163_FORCE_INLINE_ bool is_null() const { return os_version_min_required.is_null() || metal_version == UINT32_MAX; }164_FORCE_INLINE_ bool is_valid() const { return !is_null(); }165};166167ToolchainProperties compiler_props;168169void _initialize_toolchain_properties();170171private:172const MetalDeviceProfile *device_profile = nullptr;173bool export_mode = false;174175Vector<UniformData> mtl_reflection_binding_set_uniforms_data; // compliment to reflection_binding_set_uniforms_data176177Error compile_metal_source(const char *p_source, const StageData &p_stage_data, Vector<uint8_t> &r_binary_data);178179Error reflect_spirv(const ReflectShader &p_shader);180181public:182static constexpr uint32_t FORMAT_VERSION = 2;183184void set_export_mode(bool p_export_mode) { export_mode = p_export_mode; }185void set_device_profile(const MetalDeviceProfile *p_device_profile) { device_profile = p_device_profile; }186187struct MetalShaderReflection {188Vector<Vector<UniformData>> uniform_sets;189};190191MetalShaderReflection get_metal_shader_reflection() const;192193protected:194virtual uint32_t _from_bytes_reflection_extra_data(const uint8_t *p_bytes) override;195virtual uint32_t _from_bytes_reflection_binding_uniform_extra_data_start(const uint8_t *p_bytes) override;196virtual uint32_t _from_bytes_reflection_binding_uniform_extra_data(const uint8_t *p_bytes, uint32_t p_index) override;197virtual uint32_t _from_bytes_shader_extra_data_start(const uint8_t *p_bytes) override;198virtual uint32_t _from_bytes_shader_extra_data(const uint8_t *p_bytes, uint32_t p_index) override;199200virtual uint32_t _to_bytes_reflection_extra_data(uint8_t *p_bytes) const override;201virtual uint32_t _to_bytes_reflection_binding_uniform_extra_data(uint8_t *p_bytes, uint32_t p_index) const override;202virtual uint32_t _to_bytes_shader_extra_data(uint8_t *p_bytes, uint32_t p_index) const override;203204virtual uint32_t _format() const override;205virtual uint32_t _format_version() const override;206virtual bool _set_code_from_spirv(const ReflectShader &p_shader) override;207};208209class RenderingShaderContainerFormatMetal : public RenderingShaderContainerFormat {210bool export_mode = false;211212const MetalDeviceProfile *device_profile = nullptr;213214public:215virtual Ref<RenderingShaderContainer> create_container() const override;216virtual ShaderLanguageVersion get_shader_language_version() const override;217virtual ShaderSpirvVersion get_shader_spirv_version() const override;218RenderingShaderContainerFormatMetal(const MetalDeviceProfile *p_device_profile, bool p_export = false);219virtual ~RenderingShaderContainerFormatMetal() = default;220};221222223