Obtain supported Vulkan API
This commit is contained in:
parent
5953f4d766
commit
a6c989bc1b
6 changed files with 326 additions and 7 deletions
|
@ -7834,6 +7834,18 @@ void RenderingDeviceVulkan::_flush(bool p_current_frame) {
|
|||
}
|
||||
|
||||
void RenderingDeviceVulkan::initialize(VulkanContext *p_context, bool p_local_device) {
|
||||
// get our device capabilities
|
||||
{
|
||||
device_capabilities.version_major = p_context->get_vulkan_major();
|
||||
device_capabilities.version_minor = p_context->get_vulkan_minor();
|
||||
|
||||
// get info about subgroups
|
||||
VulkanContext::SubgroupCapabilities subgroup_capabilities = p_context->get_subgroup_capabilities();
|
||||
device_capabilities.subgroup_size = subgroup_capabilities.size;
|
||||
device_capabilities.subgroup_in_shaders = subgroup_capabilities.supported_stages_flags_rd();
|
||||
device_capabilities.subgroup_operations = subgroup_capabilities.supported_operations_flags_rd();
|
||||
}
|
||||
|
||||
context = p_context;
|
||||
device = p_context->get_device();
|
||||
if (p_local_device) {
|
||||
|
@ -8253,6 +8265,7 @@ RenderingDevice *RenderingDeviceVulkan::create_local_device() {
|
|||
}
|
||||
|
||||
RenderingDeviceVulkan::RenderingDeviceVulkan() {
|
||||
device_capabilities.device_family = DEVICE_VULKAN;
|
||||
}
|
||||
|
||||
RenderingDeviceVulkan::~RenderingDeviceVulkan() {
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include "core/config/project_settings.h"
|
||||
#include "core/string/ustring.h"
|
||||
#include "core/version.h"
|
||||
#include "servers/rendering/rendering_device.h"
|
||||
|
||||
#include "vk_enum_string_helper.h"
|
||||
|
||||
|
@ -234,6 +235,39 @@ Error VulkanContext::_create_validation_layers() {
|
|||
return OK;
|
||||
}
|
||||
|
||||
typedef VkResult(VKAPI_PTR *_vkEnumerateInstanceVersion)(uint32_t *);
|
||||
|
||||
Error VulkanContext::_obtain_vulkan_version() {
|
||||
// https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/VkApplicationInfo.html#_description
|
||||
// for Vulkan 1.0 vkEnumerateInstanceVersion is not available, including not in the loader we compile against on Android.
|
||||
_vkEnumerateInstanceVersion func = (_vkEnumerateInstanceVersion)vkGetInstanceProcAddr(nullptr, "vkEnumerateInstanceVersion");
|
||||
if (func != nullptr) {
|
||||
uint32_t api_version;
|
||||
VkResult res = func(&api_version);
|
||||
if (res == VK_SUCCESS) {
|
||||
vulkan_major = VK_VERSION_MAJOR(api_version);
|
||||
vulkan_minor = VK_VERSION_MINOR(api_version);
|
||||
uint32_t vulkan_patch = VK_VERSION_PATCH(api_version);
|
||||
|
||||
print_line("Vulkan API " + itos(vulkan_major) + "." + itos(vulkan_minor) + "." + itos(vulkan_patch));
|
||||
} else {
|
||||
// according to the documentation this shouldn't fail with anything except a memory allocation error
|
||||
// in which case we're in deep trouble anyway
|
||||
ERR_FAIL_V(ERR_CANT_CREATE);
|
||||
}
|
||||
} else {
|
||||
print_line("vkEnumerateInstanceVersion not available, assuming Vulkan 1.0");
|
||||
}
|
||||
|
||||
// we don't go above 1.2
|
||||
if ((vulkan_major > 1) || (vulkan_major == 1 && vulkan_minor > 2)) {
|
||||
vulkan_major = 1;
|
||||
vulkan_minor = 2;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
Error VulkanContext::_initialize_extensions() {
|
||||
uint32_t instance_extension_count = 0;
|
||||
|
||||
|
@ -289,12 +323,200 @@ Error VulkanContext::_initialize_extensions() {
|
|||
return OK;
|
||||
}
|
||||
|
||||
typedef void(VKAPI_PTR *_vkGetPhysicalDeviceProperties2)(VkPhysicalDevice, VkPhysicalDeviceProperties2 *);
|
||||
|
||||
uint32_t VulkanContext::SubgroupCapabilities::supported_stages_flags_rd() const {
|
||||
uint32_t flags = 0;
|
||||
|
||||
if (supportedStages & VK_SHADER_STAGE_VERTEX_BIT) {
|
||||
flags += RenderingDevice::ShaderStage::SHADER_STAGE_VERTEX_BIT;
|
||||
}
|
||||
if (supportedStages & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) {
|
||||
flags += RenderingDevice::ShaderStage::SHADER_STAGE_TESSELATION_CONTROL_BIT;
|
||||
}
|
||||
if (supportedStages & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) {
|
||||
flags += RenderingDevice::ShaderStage::SHADER_STAGE_TESSELATION_EVALUATION_BIT;
|
||||
}
|
||||
// if (supportedStages & VK_SHADER_STAGE_GEOMETRY_BIT) {
|
||||
// flags += RenderingDevice::ShaderStage::SHADER_STAGE_GEOMETRY_BIT;
|
||||
// }
|
||||
if (supportedStages & VK_SHADER_STAGE_FRAGMENT_BIT) {
|
||||
flags += RenderingDevice::ShaderStage::SHADER_STAGE_FRAGMENT_BIT;
|
||||
}
|
||||
if (supportedStages & VK_SHADER_STAGE_COMPUTE_BIT) {
|
||||
flags += RenderingDevice::ShaderStage::SHADER_STAGE_COMPUTE_BIT;
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
String VulkanContext::SubgroupCapabilities::supported_stages_desc() const {
|
||||
String res;
|
||||
|
||||
if (supportedStages & VK_SHADER_STAGE_VERTEX_BIT) {
|
||||
res += ", STAGE_VERTEX";
|
||||
}
|
||||
if (supportedStages & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) {
|
||||
res += ", STAGE_TESSELLATION_CONTROL";
|
||||
}
|
||||
if (supportedStages & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) {
|
||||
res += ", STAGE_TESSELLATION_EVALUATION";
|
||||
}
|
||||
if (supportedStages & VK_SHADER_STAGE_GEOMETRY_BIT) {
|
||||
res += ", STAGE_GEOMETRY";
|
||||
}
|
||||
if (supportedStages & VK_SHADER_STAGE_FRAGMENT_BIT) {
|
||||
res += ", STAGE_FRAGMENT";
|
||||
}
|
||||
if (supportedStages & VK_SHADER_STAGE_COMPUTE_BIT) {
|
||||
res += ", STAGE_COMPUTE";
|
||||
}
|
||||
|
||||
/* these are not defined on Android GRMBL */
|
||||
if (supportedStages & 0x00000100 /* VK_SHADER_STAGE_RAYGEN_BIT_KHR */) {
|
||||
res += ", STAGE_RAYGEN_KHR";
|
||||
}
|
||||
if (supportedStages & 0x00000200 /* VK_SHADER_STAGE_ANY_HIT_BIT_KHR */) {
|
||||
res += ", STAGE_ANY_HIT_KHR";
|
||||
}
|
||||
if (supportedStages & 0x00000400 /* VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR */) {
|
||||
res += ", STAGE_CLOSEST_HIT_KHR";
|
||||
}
|
||||
if (supportedStages & 0x00000800 /* VK_SHADER_STAGE_MISS_BIT_KHR */) {
|
||||
res += ", STAGE_MISS_KHR";
|
||||
}
|
||||
if (supportedStages & 0x00001000 /* VK_SHADER_STAGE_INTERSECTION_BIT_KHR */) {
|
||||
res += ", STAGE_INTERSECTION_KHR";
|
||||
}
|
||||
if (supportedStages & 0x00002000 /* VK_SHADER_STAGE_CALLABLE_BIT_KHR */) {
|
||||
res += ", STAGE_CALLABLE_KHR";
|
||||
}
|
||||
if (supportedStages & 0x00000040 /* VK_SHADER_STAGE_TASK_BIT_NV */) {
|
||||
res += ", STAGE_TASK_NV";
|
||||
}
|
||||
if (supportedStages & 0x00000080 /* VK_SHADER_STAGE_MESH_BIT_NV */) {
|
||||
res += ", STAGE_MESH_NV";
|
||||
}
|
||||
|
||||
return res.substr(2); // remove first ", "
|
||||
}
|
||||
|
||||
uint32_t VulkanContext::SubgroupCapabilities::supported_operations_flags_rd() const {
|
||||
uint32_t flags = 0;
|
||||
|
||||
if (supportedOperations & VK_SUBGROUP_FEATURE_BASIC_BIT) {
|
||||
flags += RenderingDevice::SubgroupOperations::SUBGROUP_BASIC_BIT;
|
||||
}
|
||||
if (supportedOperations & VK_SUBGROUP_FEATURE_VOTE_BIT) {
|
||||
flags += RenderingDevice::SubgroupOperations::SUBGROUP_VOTE_BIT;
|
||||
}
|
||||
if (supportedOperations & VK_SUBGROUP_FEATURE_ARITHMETIC_BIT) {
|
||||
flags += RenderingDevice::SubgroupOperations::SUBGROUP_ARITHMETIC_BIT;
|
||||
}
|
||||
if (supportedOperations & VK_SUBGROUP_FEATURE_BALLOT_BIT) {
|
||||
flags += RenderingDevice::SubgroupOperations::SUBGROUP_BALLOT_BIT;
|
||||
}
|
||||
if (supportedOperations & VK_SUBGROUP_FEATURE_SHUFFLE_BIT) {
|
||||
flags += RenderingDevice::SubgroupOperations::SUBGROUP_SHUFFLE_BIT;
|
||||
}
|
||||
if (supportedOperations & VK_SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT) {
|
||||
flags += RenderingDevice::SubgroupOperations::SUBGROUP_SHUFFLE_RELATIVE_BIT;
|
||||
}
|
||||
if (supportedOperations & VK_SUBGROUP_FEATURE_CLUSTERED_BIT) {
|
||||
flags += RenderingDevice::SubgroupOperations::SUBGROUP_CLUSTERED_BIT;
|
||||
}
|
||||
if (supportedOperations & VK_SUBGROUP_FEATURE_QUAD_BIT) {
|
||||
flags += RenderingDevice::SubgroupOperations::SUBGROUP_QUAD_BIT;
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
String VulkanContext::SubgroupCapabilities::supported_operations_desc() const {
|
||||
String res;
|
||||
|
||||
if (supportedOperations & VK_SUBGROUP_FEATURE_BASIC_BIT) {
|
||||
res += ", FEATURE_BASIC";
|
||||
}
|
||||
if (supportedOperations & VK_SUBGROUP_FEATURE_VOTE_BIT) {
|
||||
res += ", FEATURE_VOTE";
|
||||
}
|
||||
if (supportedOperations & VK_SUBGROUP_FEATURE_ARITHMETIC_BIT) {
|
||||
res += ", FEATURE_ARITHMETIC";
|
||||
}
|
||||
if (supportedOperations & VK_SUBGROUP_FEATURE_BALLOT_BIT) {
|
||||
res += ", FEATURE_BALLOT";
|
||||
}
|
||||
if (supportedOperations & VK_SUBGROUP_FEATURE_SHUFFLE_BIT) {
|
||||
res += ", FEATURE_SHUFFLE";
|
||||
}
|
||||
if (supportedOperations & VK_SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT) {
|
||||
res += ", FEATURE_SHUFFLE_RELATIVE";
|
||||
}
|
||||
if (supportedOperations & VK_SUBGROUP_FEATURE_CLUSTERED_BIT) {
|
||||
res += ", FEATURE_CLUSTERED";
|
||||
}
|
||||
if (supportedOperations & VK_SUBGROUP_FEATURE_QUAD_BIT) {
|
||||
res += ", FEATURE_QUAD";
|
||||
}
|
||||
if (supportedOperations & VK_SUBGROUP_FEATURE_PARTITIONED_BIT_NV) {
|
||||
res += ", FEATURE_PARTITIONED_NV";
|
||||
}
|
||||
|
||||
return res.substr(2); // remove first ", "
|
||||
}
|
||||
|
||||
Error VulkanContext::_check_capabilities() {
|
||||
// check subgroups
|
||||
// https://www.khronos.org/blog/vulkan-subgroup-tutorial
|
||||
// for Vulkan 1.0 vkGetPhysicalDeviceProperties2 is not available, including not in the loader we compile against on Android.
|
||||
_vkGetPhysicalDeviceProperties2 func = (_vkGetPhysicalDeviceProperties2)vkGetInstanceProcAddr(inst, "vkGetPhysicalDeviceProperties2");
|
||||
if (func != nullptr) {
|
||||
VkPhysicalDeviceSubgroupProperties subgroupProperties;
|
||||
subgroupProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES;
|
||||
subgroupProperties.pNext = NULL;
|
||||
|
||||
VkPhysicalDeviceProperties2 physicalDeviceProperties;
|
||||
physicalDeviceProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
|
||||
physicalDeviceProperties.pNext = &subgroupProperties;
|
||||
|
||||
func(gpu, &physicalDeviceProperties);
|
||||
|
||||
subgroup_capabilities.size = subgroupProperties.subgroupSize;
|
||||
subgroup_capabilities.supportedStages = subgroupProperties.supportedStages;
|
||||
subgroup_capabilities.supportedOperations = subgroupProperties.supportedOperations;
|
||||
// Note: quadOperationsInAllStages will be true if:
|
||||
// - supportedStages has VK_SHADER_STAGE_ALL_GRAPHICS + VK_SHADER_STAGE_COMPUTE_BIT
|
||||
// - supportedOperations has VK_SUBGROUP_FEATURE_QUAD_BIT
|
||||
subgroup_capabilities.quadOperationsInAllStages = subgroupProperties.quadOperationsInAllStages;
|
||||
|
||||
// only output this when debugging?
|
||||
print_line("- Vulkan subgroup size " + itos(subgroup_capabilities.size));
|
||||
print_line("- Vulkan subgroup stages " + subgroup_capabilities.supported_stages_desc());
|
||||
print_line("- Vulkan subgroup supported ops " + subgroup_capabilities.supported_operations_desc());
|
||||
if (subgroup_capabilities.quadOperationsInAllStages) {
|
||||
print_line("- Vulkan subgroup quad operations in all stages");
|
||||
}
|
||||
} else {
|
||||
subgroup_capabilities.size = 0;
|
||||
subgroup_capabilities.supportedStages = 0;
|
||||
subgroup_capabilities.supportedOperations = 0;
|
||||
subgroup_capabilities.quadOperationsInAllStages = false;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
Error VulkanContext::_create_physical_device() {
|
||||
/* obtain version */
|
||||
_obtain_vulkan_version();
|
||||
|
||||
/* Look for validation layers */
|
||||
if (use_validation_layers) {
|
||||
_create_validation_layers();
|
||||
}
|
||||
|
||||
/* initialise extensions */
|
||||
{
|
||||
Error err = _initialize_extensions();
|
||||
if (err != OK) {
|
||||
|
@ -312,7 +534,7 @@ Error VulkanContext::_create_physical_device() {
|
|||
/*applicationVersion*/ 0,
|
||||
/*pEngineName*/ namecs.get_data(),
|
||||
/*engineVersion*/ 0,
|
||||
/*apiVersion*/ VK_API_VERSION_1_0,
|
||||
/*apiVersion*/ VK_MAKE_VERSION(vulkan_major, vulkan_minor, 0)
|
||||
};
|
||||
VkInstanceCreateInfo inst_info = {
|
||||
/*sType*/ VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
|
||||
|
@ -561,6 +783,14 @@ Error VulkanContext::_create_physical_device() {
|
|||
GET_INSTANCE_PROC_ADDR(inst, GetPhysicalDeviceSurfacePresentModesKHR);
|
||||
GET_INSTANCE_PROC_ADDR(inst, GetSwapchainImagesKHR);
|
||||
|
||||
// get info about what our vulkan driver is capable off
|
||||
{
|
||||
Error res = _check_capabilities();
|
||||
if (res != OK) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -41,6 +41,20 @@
|
|||
#include <vulkan/vulkan.h>
|
||||
|
||||
class VulkanContext {
|
||||
public:
|
||||
struct SubgroupCapabilities {
|
||||
uint32_t size;
|
||||
VkShaderStageFlags supportedStages;
|
||||
VkSubgroupFeatureFlags supportedOperations;
|
||||
VkBool32 quadOperationsInAllStages;
|
||||
|
||||
uint32_t supported_stages_flags_rd() const;
|
||||
String supported_stages_desc() const;
|
||||
uint32_t supported_operations_flags_rd() const;
|
||||
String supported_operations_desc() const;
|
||||
};
|
||||
|
||||
private:
|
||||
enum {
|
||||
MAX_EXTENSIONS = 128,
|
||||
MAX_LAYERS = 64,
|
||||
|
@ -57,6 +71,11 @@ class VulkanContext {
|
|||
bool device_initialized = false;
|
||||
bool inst_initialized = false;
|
||||
|
||||
// Vulkan 1.0 doesn't return version info so we assume this by default until we know otherwise
|
||||
uint32_t vulkan_major = 1;
|
||||
uint32_t vulkan_minor = 0;
|
||||
SubgroupCapabilities subgroup_capabilities;
|
||||
|
||||
String device_vendor;
|
||||
String device_name;
|
||||
String pipeline_cache_id;
|
||||
|
@ -150,8 +169,10 @@ class VulkanContext {
|
|||
|
||||
VkDebugUtilsMessengerEXT dbg_messenger = VK_NULL_HANDLE;
|
||||
|
||||
Error _obtain_vulkan_version();
|
||||
Error _create_validation_layers();
|
||||
Error _initialize_extensions();
|
||||
Error _check_capabilities();
|
||||
|
||||
VkBool32 _check_layers(uint32_t check_count, const char **check_names, uint32_t layer_count, VkLayerProperties *layers);
|
||||
static VKAPI_ATTR VkBool32 VKAPI_CALL _debug_messenger_callback(
|
||||
|
@ -186,6 +207,10 @@ protected:
|
|||
}
|
||||
|
||||
public:
|
||||
uint32_t get_vulkan_major() const { return vulkan_major; };
|
||||
uint32_t get_vulkan_minor() const { return vulkan_minor; };
|
||||
SubgroupCapabilities get_subgroup_capabilities() const { return subgroup_capabilities; };
|
||||
|
||||
VkDevice get_device();
|
||||
VkPhysicalDevice get_physical_device();
|
||||
int get_swapchain_image_count() const;
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
#include <glslang/Include/Types.h>
|
||||
#include <glslang/Public/ShaderLang.h>
|
||||
|
||||
static Vector<uint8_t> _compile_shader_glsl(RenderingDevice::ShaderStage p_stage, const String &p_source_code, RenderingDevice::ShaderLanguage p_language, String *r_error) {
|
||||
static Vector<uint8_t> _compile_shader_glsl(RenderingDevice::ShaderStage p_stage, const String &p_source_code, RenderingDevice::ShaderLanguage p_language, String *r_error, const RenderingDevice::Capabilities *p_capabilities) {
|
||||
Vector<uint8_t> ret;
|
||||
|
||||
ERR_FAIL_COND_V(p_language == RenderingDevice::SHADER_LANGUAGE_HLSL, ret);
|
||||
|
@ -52,17 +52,35 @@ static Vector<uint8_t> _compile_shader_glsl(RenderingDevice::ShaderStage p_stage
|
|||
|
||||
int ClientInputSemanticsVersion = 100; // maps to, say, #define VULKAN 100
|
||||
|
||||
glslang::EShTargetClientVersion VulkanClientVersion = glslang::EShTargetVulkan_1_0;
|
||||
glslang::EShTargetLanguageVersion TargetVersion = glslang::EShTargetSpv_1_3;
|
||||
glslang::EShTargetClientVersion ClientVersion = glslang::EShTargetVulkan_1_2;
|
||||
glslang::EShTargetLanguageVersion TargetVersion = glslang::EShTargetSpv_1_5;
|
||||
glslang::TShader::ForbidIncluder includer;
|
||||
|
||||
if (p_capabilities->device_family == RenderingDevice::DeviceFamily::DEVICE_VULKAN) {
|
||||
if (p_capabilities->version_major == 1 && p_capabilities->version_minor == 0) {
|
||||
ClientVersion = glslang::EShTargetVulkan_1_0;
|
||||
TargetVersion = glslang::EShTargetSpv_1_0;
|
||||
} else if (p_capabilities->version_major == 1 && p_capabilities->version_minor == 1) {
|
||||
ClientVersion = glslang::EShTargetVulkan_1_1;
|
||||
TargetVersion = glslang::EShTargetSpv_1_3;
|
||||
} else {
|
||||
// use defaults
|
||||
}
|
||||
} else {
|
||||
// once we support other backends we'll need to do something here
|
||||
if (r_error) {
|
||||
(*r_error) = "GLSLANG - Unsupported device family";
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
glslang::TShader shader(stages[p_stage]);
|
||||
CharString cs = p_source_code.ascii();
|
||||
const char *cs_strings = cs.get_data();
|
||||
|
||||
shader.setStrings(&cs_strings, 1);
|
||||
shader.setEnvInput(glslang::EShSourceGlsl, stages[p_stage], glslang::EShClientVulkan, ClientInputSemanticsVersion);
|
||||
shader.setEnvClient(glslang::EShClientVulkan, VulkanClientVersion);
|
||||
shader.setEnvClient(glslang::EShClientVulkan, ClientVersion);
|
||||
shader.setEnvTarget(glslang::EShTargetSpv, TargetVersion);
|
||||
|
||||
EShMessages messages = (EShMessages)(EShMsgSpvRules | EShMsgVulkanRules);
|
||||
|
|
|
@ -59,7 +59,7 @@ Vector<uint8_t> RenderingDevice::shader_compile_from_source(ShaderStage p_stage,
|
|||
|
||||
ERR_FAIL_COND_V(!compile_function, Vector<uint8_t>());
|
||||
|
||||
return compile_function(p_stage, p_source_code, p_language, r_error);
|
||||
return compile_function(p_stage, p_source_code, p_language, r_error, &device_capabilities);
|
||||
}
|
||||
|
||||
RID RenderingDevice::_texture_create(const Ref<RDTextureFormat> &p_format, const Ref<RDTextureView> &p_view, const TypedArray<PackedByteArray> &p_data) {
|
||||
|
|
|
@ -51,6 +51,13 @@ class RDPipelineColorBlendState;
|
|||
class RenderingDevice : public Object {
|
||||
GDCLASS(RenderingDevice, Object)
|
||||
public:
|
||||
enum DeviceFamily {
|
||||
DEVICE_UNKNOWN,
|
||||
DEVICE_OPENGL,
|
||||
DEVICE_VULKAN,
|
||||
DEVICE_DIRECTX
|
||||
};
|
||||
|
||||
enum ShaderStage {
|
||||
SHADER_STAGE_VERTEX,
|
||||
SHADER_STAGE_FRAGMENT,
|
||||
|
@ -70,7 +77,29 @@ public:
|
|||
SHADER_LANGUAGE_HLSL
|
||||
};
|
||||
|
||||
typedef Vector<uint8_t> (*ShaderCompileFunction)(ShaderStage p_stage, const String &p_source_code, ShaderLanguage p_language, String *r_error);
|
||||
enum SubgroupOperations {
|
||||
SUBGROUP_BASIC_BIT = 1,
|
||||
SUBGROUP_VOTE_BIT = 2,
|
||||
SUBGROUP_ARITHMETIC_BIT = 4,
|
||||
SUBGROUP_BALLOT_BIT = 8,
|
||||
SUBGROUP_SHUFFLE_BIT = 16,
|
||||
SUBGROUP_SHUFFLE_RELATIVE_BIT = 32,
|
||||
SUBGROUP_CLUSTERED_BIT = 64,
|
||||
SUBGROUP_QUAD_BIT = 128,
|
||||
};
|
||||
|
||||
struct Capabilities {
|
||||
// main device info
|
||||
DeviceFamily device_family = DEVICE_UNKNOWN;
|
||||
uint32_t version_major = 1.0;
|
||||
uint32_t version_minor = 0.0;
|
||||
// subgroup capabilities
|
||||
uint32_t subgroup_size = 0;
|
||||
uint32_t subgroup_in_shaders = 0; // Set flags using SHADER_STAGE_VERTEX_BIT, SHADER_STAGE_FRAGMENT_BIT, etc.
|
||||
uint32_t subgroup_operations = 0; // Set flags, using SubgroupOperations
|
||||
};
|
||||
|
||||
typedef Vector<uint8_t> (*ShaderCompileFunction)(ShaderStage p_stage, const String &p_source_code, ShaderLanguage p_language, String *r_error, const Capabilities *p_capabilities);
|
||||
typedef Vector<uint8_t> (*ShaderCacheFunction)(ShaderStage p_stage, const String &p_source_code, ShaderLanguage p_language);
|
||||
|
||||
private:
|
||||
|
@ -82,6 +111,8 @@ private:
|
|||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
Capabilities device_capabilities;
|
||||
|
||||
public:
|
||||
//base numeric ID for all types
|
||||
enum {
|
||||
|
@ -597,6 +628,8 @@ public:
|
|||
/**** SHADER ****/
|
||||
/****************/
|
||||
|
||||
const Capabilities *get_device_capabilities() const { return &device_capabilities; };
|
||||
|
||||
virtual Vector<uint8_t> shader_compile_from_source(ShaderStage p_stage, const String &p_source_code, ShaderLanguage p_language = SHADER_LANGUAGE_GLSL, String *r_error = nullptr, bool p_allow_cache = true);
|
||||
|
||||
static void shader_set_compile_function(ShaderCompileFunction p_function);
|
||||
|
|
Loading…
Reference in a new issue