Adding Variable Rate Shading support to Godot
Improve GI renderer and add VRS support Implement render device has_feature and move subgroup settings to limit_get
This commit is contained in:
parent
e3a8ab68ce
commit
d139131aab
|
@ -1968,6 +1968,12 @@
|
||||||
If [code]true[/code], the texture importer will import VRAM-compressed textures using the S3 Texture Compression algorithm. This algorithm is only supported on desktop platforms and consoles.
|
If [code]true[/code], the texture importer will import VRAM-compressed textures using the S3 Texture Compression algorithm. This algorithm is only supported on desktop platforms and consoles.
|
||||||
[b]Note:[/b] Changing this setting does [i]not[/i] impact textures that were already imported before. To make this setting apply to textures that were already imported, exit the editor, remove the [code].godot/imported/[/code] folder located inside the project folder then restart the editor (see [member application/config/use_hidden_project_data_directory]).
|
[b]Note:[/b] Changing this setting does [i]not[/i] impact textures that were already imported before. To make this setting apply to textures that were already imported, exit the editor, remove the [code].godot/imported/[/code] folder located inside the project folder then restart the editor (see [member application/config/use_hidden_project_data_directory]).
|
||||||
</member>
|
</member>
|
||||||
|
<member name="rendering/vrs/mode" type="int" setter="" getter="" default="0">
|
||||||
|
Set the default Variable Rate Shading (VRS) mode for the main viewport. See [member Viewport.vrs_mode] to change this at runtime, and [enum Viewport.VRSMode] for possible values.
|
||||||
|
</member>
|
||||||
|
<member name="rendering/vrs/texture" type="String" setter="" getter="" default="""">
|
||||||
|
If [member rendering/vrs/mode] is set to texture, this is the path to default texture loaded as the VRS image.
|
||||||
|
</member>
|
||||||
<member name="rendering/vulkan/descriptor_pools/max_descriptors_per_pool" type="int" setter="" getter="" default="64">
|
<member name="rendering/vulkan/descriptor_pools/max_descriptors_per_pool" type="int" setter="" getter="" default="64">
|
||||||
</member>
|
</member>
|
||||||
<member name="rendering/vulkan/rendering/back_end" type="int" setter="" getter="" default="0">
|
<member name="rendering/vulkan/rendering/back_end" type="int" setter="" getter="" default="0">
|
||||||
|
|
|
@ -395,7 +395,7 @@
|
||||||
<description>
|
<description>
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
<method name="limit_get">
|
<method name="limit_get" qualifiers="const">
|
||||||
<return type="int" />
|
<return type="int" />
|
||||||
<argument index="0" name="limit" type="int" enum="RenderingDevice.Limit" />
|
<argument index="0" name="limit" type="int" enum="RenderingDevice.Limit" />
|
||||||
<description>
|
<description>
|
||||||
|
|
|
@ -3357,6 +3357,22 @@
|
||||||
If [code]true[/code], the viewport uses augmented or virtual reality technologies. See [XRInterface].
|
If [code]true[/code], the viewport uses augmented or virtual reality technologies. See [XRInterface].
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
|
<method name="viewport_set_vrs_mode">
|
||||||
|
<return type="void" />
|
||||||
|
<argument index="0" name="viewport" type="RID" />
|
||||||
|
<argument index="1" name="mode" type="int" enum="RenderingServer.ViewportVRSMode" />
|
||||||
|
<description>
|
||||||
|
Sets the Variable Rate Shading (VRS) mode for the viewport. Note, if hardware does not support VRS this property is ignored.
|
||||||
|
</description>
|
||||||
|
</method>
|
||||||
|
<method name="viewport_set_vrs_texture">
|
||||||
|
<return type="void" />
|
||||||
|
<argument index="0" name="viewport" type="RID" />
|
||||||
|
<argument index="1" name="texture" type="RID" />
|
||||||
|
<description>
|
||||||
|
Texture to use when the VRS mode is set to [constant RenderingServer.VIEWPORT_VRS_TEXTURE].
|
||||||
|
</description>
|
||||||
|
</method>
|
||||||
<method name="visibility_notifier_create">
|
<method name="visibility_notifier_create">
|
||||||
<return type="RID" />
|
<return type="RID" />
|
||||||
<description>
|
<description>
|
||||||
|
@ -4116,6 +4132,18 @@
|
||||||
</constant>
|
</constant>
|
||||||
<constant name="VIEWPORT_DEBUG_DRAW_MOTION_VECTORS" value="25" enum="ViewportDebugDraw">
|
<constant name="VIEWPORT_DEBUG_DRAW_MOTION_VECTORS" value="25" enum="ViewportDebugDraw">
|
||||||
</constant>
|
</constant>
|
||||||
|
<constant name="VIEWPORT_VRS_DISABLED" value="0" enum="ViewportVRSMode">
|
||||||
|
VRS is disabled.
|
||||||
|
</constant>
|
||||||
|
<constant name="VIEWPORT_VRS_TEXTURE" value="1" enum="ViewportVRSMode">
|
||||||
|
VRS uses a texture. Note, for stereoscopic use a texture atlas with a texture for each view.
|
||||||
|
</constant>
|
||||||
|
<constant name="VIEWPORT_VRS_XR" value="2" enum="ViewportVRSMode">
|
||||||
|
VRS texture is supplied by the primary [XRInterface].
|
||||||
|
</constant>
|
||||||
|
<constant name="VIEWPORT_VRS_MAX" value="3" enum="ViewportVRSMode">
|
||||||
|
Represents the size of the [enum ViewportVRSMode] enum.
|
||||||
|
</constant>
|
||||||
<constant name="SKY_MODE_AUTOMATIC" value="0" enum="SkyMode">
|
<constant name="SKY_MODE_AUTOMATIC" value="0" enum="SkyMode">
|
||||||
</constant>
|
</constant>
|
||||||
<constant name="SKY_MODE_QUALITY" value="1" enum="SkyMode">
|
<constant name="SKY_MODE_QUALITY" value="1" enum="SkyMode">
|
||||||
|
|
|
@ -286,6 +286,12 @@
|
||||||
<member name="use_xr" type="bool" setter="set_use_xr" getter="is_using_xr" default="false">
|
<member name="use_xr" type="bool" setter="set_use_xr" getter="is_using_xr" default="false">
|
||||||
If [code]true[/code], the viewport will use the primary XR interface to render XR output. When applicable this can result in a stereoscopic image and the resulting render being output to a headset.
|
If [code]true[/code], the viewport will use the primary XR interface to render XR output. When applicable this can result in a stereoscopic image and the resulting render being output to a headset.
|
||||||
</member>
|
</member>
|
||||||
|
<member name="vrs_mode" type="int" setter="set_vrs_mode" getter="get_vrs_mode" enum="Viewport.VRSMode" default="0">
|
||||||
|
The Variable Rate Shading (VRS) mode that is used for this viewport. Note, if hardware does not support VRS this property is ignored.
|
||||||
|
</member>
|
||||||
|
<member name="vrs_texture" type="Texture2D" setter="set_vrs_texture" getter="get_vrs_texture">
|
||||||
|
Texture to use when [member vrs_mode] is set to [constant Viewport.VRS_TEXTURE].
|
||||||
|
</member>
|
||||||
<member name="world_2d" type="World2D" setter="set_world_2d" getter="get_world_2d">
|
<member name="world_2d" type="World2D" setter="set_world_2d" getter="get_world_2d">
|
||||||
The custom [World2D] which can be used as 2D environment source.
|
The custom [World2D] which can be used as 2D environment source.
|
||||||
</member>
|
</member>
|
||||||
|
@ -492,5 +498,17 @@
|
||||||
</constant>
|
</constant>
|
||||||
<constant name="SDF_SCALE_MAX" value="3" enum="SDFScale">
|
<constant name="SDF_SCALE_MAX" value="3" enum="SDFScale">
|
||||||
</constant>
|
</constant>
|
||||||
|
<constant name="VRS_DISABLED" value="0" enum="VRSMode">
|
||||||
|
VRS is disabled.
|
||||||
|
</constant>
|
||||||
|
<constant name="VRS_TEXTURE" value="1" enum="VRSMode">
|
||||||
|
VRS uses a texture. Note, for stereoscopic use a texture atlas with a texture for each view.
|
||||||
|
</constant>
|
||||||
|
<constant name="VRS_XR" value="2" enum="VRSMode">
|
||||||
|
VRS texture is supplied by the primary [XRInterface].
|
||||||
|
</constant>
|
||||||
|
<constant name="VRS_MAX" value="3" enum="VRSMode">
|
||||||
|
Represents the size of the [enum VRSMode] enum.
|
||||||
|
</constant>
|
||||||
</constants>
|
</constants>
|
||||||
</class>
|
</class>
|
||||||
|
|
|
@ -106,6 +106,11 @@
|
||||||
Returns the number of views this interface requires, 1 for mono, 2 for stereoscopic.
|
Returns the number of views this interface requires, 1 for mono, 2 for stereoscopic.
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
|
<method name="_get_vrs_texture" qualifiers="virtual">
|
||||||
|
<return type="RID" />
|
||||||
|
<description>
|
||||||
|
</description>
|
||||||
|
</method>
|
||||||
<method name="_initialize" qualifiers="virtual">
|
<method name="_initialize" qualifiers="virtual">
|
||||||
<return type="bool" />
|
<return type="bool" />
|
||||||
<description>
|
<description>
|
||||||
|
|
|
@ -546,6 +546,16 @@ public:
|
||||||
void render_target_copy_to_back_buffer(RID p_render_target, const Rect2i &p_region, bool p_gen_mipmaps);
|
void render_target_copy_to_back_buffer(RID p_render_target, const Rect2i &p_region, bool p_gen_mipmaps);
|
||||||
void render_target_clear_back_buffer(RID p_render_target, const Rect2i &p_region, const Color &p_color);
|
void render_target_clear_back_buffer(RID p_render_target, const Rect2i &p_region, const Color &p_color);
|
||||||
void render_target_gen_back_buffer_mipmaps(RID p_render_target, const Rect2i &p_region);
|
void render_target_gen_back_buffer_mipmaps(RID p_render_target, const Rect2i &p_region);
|
||||||
|
virtual void render_target_set_vrs_mode(RID p_render_target, RS::ViewportVRSMode p_mode) override{};
|
||||||
|
virtual void render_target_set_vrs_texture(RID p_render_target, RID p_texture) override{};
|
||||||
|
|
||||||
|
void bind_framebuffer(GLuint framebuffer) {
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bind_framebuffer_system() {
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, GLES3::TextureStorage::system_fbo);
|
||||||
|
}
|
||||||
|
|
||||||
String get_framebuffer_error(GLenum p_status);
|
String get_framebuffer_error(GLenum p_status);
|
||||||
};
|
};
|
||||||
|
|
|
@ -106,7 +106,7 @@ RenderingDeviceVulkan::Buffer *RenderingDeviceVulkan::_get_buffer_from_owner(RID
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void update_external_dependency_for_store(VkSubpassDependency &dependency, bool is_sampled, bool is_storage, bool is_depth) {
|
static void update_external_dependency_for_store(VkSubpassDependency2KHR &dependency, bool is_sampled, bool is_storage, bool is_depth) {
|
||||||
// Transitioning from write to read, protect the shaders that may use this next
|
// Transitioning from write to read, protect the shaders that may use this next
|
||||||
// Allow for copies/image layout transitions
|
// Allow for copies/image layout transitions
|
||||||
dependency.dstStageMask |= VK_PIPELINE_STAGE_TRANSFER_BIT;
|
dependency.dstStageMask |= VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||||
|
@ -1758,6 +1758,10 @@ RID RenderingDeviceVulkan::texture_create(const TextureFormat &p_format, const T
|
||||||
image_create_info.usage |= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
|
image_create_info.usage |= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (p_format.usage_bits & TEXTURE_USAGE_VRS_ATTACHMENT_BIT) {
|
||||||
|
image_create_info.usage |= VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR;
|
||||||
|
}
|
||||||
|
|
||||||
if (p_format.usage_bits & TEXTURE_USAGE_CAN_UPDATE_BIT) {
|
if (p_format.usage_bits & TEXTURE_USAGE_CAN_UPDATE_BIT) {
|
||||||
image_create_info.usage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
image_create_info.usage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
||||||
}
|
}
|
||||||
|
@ -3362,17 +3366,24 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
|
||||||
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
|
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
|
||||||
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
|
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
|
||||||
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
|
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
|
||||||
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; // From Section 7.1 of Vulkan API Spec v1.1.148
|
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | // From Section 7.1 of Vulkan API Spec v1.1.148
|
||||||
|
VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR;
|
||||||
|
|
||||||
VkPipelineStageFlags reading_stages = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT;
|
VkPipelineStageFlags reading_stages = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||||
VkSubpassDependency dependencies[2] = { { VK_SUBPASS_EXTERNAL, 0, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, 0, default_access_mask, 0 },
|
VkSubpassDependency2KHR dependencies[2] = {
|
||||||
{ 0, VK_SUBPASS_EXTERNAL, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, default_access_mask, 0, 0 } };
|
{ VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2_KHR, nullptr, VK_SUBPASS_EXTERNAL, 0, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, 0, default_access_mask, 0, 0 },
|
||||||
VkSubpassDependency &dependency_from_external = dependencies[0];
|
{ VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2_KHR, nullptr, 0, VK_SUBPASS_EXTERNAL, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, default_access_mask, 0, 0, 0 }
|
||||||
VkSubpassDependency &dependency_to_external = dependencies[1];
|
};
|
||||||
|
VkSubpassDependency2KHR &dependency_from_external = dependencies[0];
|
||||||
|
VkSubpassDependency2KHR &dependency_to_external = dependencies[1];
|
||||||
LocalVector<int32_t> attachment_last_pass;
|
LocalVector<int32_t> attachment_last_pass;
|
||||||
attachment_last_pass.resize(p_attachments.size());
|
attachment_last_pass.resize(p_attachments.size());
|
||||||
|
|
||||||
Vector<VkAttachmentDescription> attachments;
|
// These are only used if we use multiview but we need to define them in scope.
|
||||||
|
const uint32_t view_mask = (1 << p_view_count) - 1;
|
||||||
|
const uint32_t correlation_mask = (1 << p_view_count) - 1;
|
||||||
|
|
||||||
|
Vector<VkAttachmentDescription2KHR> attachments;
|
||||||
Vector<int> attachment_remap;
|
Vector<int> attachment_remap;
|
||||||
|
|
||||||
for (int i = 0; i < p_attachments.size(); i++) {
|
for (int i = 0; i < p_attachments.size(); i++) {
|
||||||
|
@ -3383,10 +3394,12 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
|
||||||
|
|
||||||
ERR_FAIL_INDEX_V(p_attachments[i].format, DATA_FORMAT_MAX, VK_NULL_HANDLE);
|
ERR_FAIL_INDEX_V(p_attachments[i].format, DATA_FORMAT_MAX, VK_NULL_HANDLE);
|
||||||
ERR_FAIL_INDEX_V(p_attachments[i].samples, TEXTURE_SAMPLES_MAX, VK_NULL_HANDLE);
|
ERR_FAIL_INDEX_V(p_attachments[i].samples, TEXTURE_SAMPLES_MAX, VK_NULL_HANDLE);
|
||||||
ERR_FAIL_COND_V_MSG(!(p_attachments[i].usage_flags & (TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | TEXTURE_USAGE_INPUT_ATTACHMENT_BIT)),
|
ERR_FAIL_COND_V_MSG(!(p_attachments[i].usage_flags & (TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | TEXTURE_USAGE_INPUT_ATTACHMENT_BIT | TEXTURE_USAGE_VRS_ATTACHMENT_BIT)),
|
||||||
VK_NULL_HANDLE, "Texture format for index (" + itos(i) + ") requires an attachment (color, depth, input or stencil) bit set.");
|
VK_NULL_HANDLE, "Texture format for index (" + itos(i) + ") requires an attachment (color, depth, input or stencil) bit set.");
|
||||||
|
|
||||||
VkAttachmentDescription description = {};
|
VkAttachmentDescription2KHR description = {};
|
||||||
|
description.sType = VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2_KHR;
|
||||||
|
description.pNext = nullptr;
|
||||||
description.flags = 0;
|
description.flags = 0;
|
||||||
description.format = vulkan_formats[p_attachments[i].format];
|
description.format = vulkan_formats[p_attachments[i].format];
|
||||||
description.samples = rasterization_sample_count[p_attachments[i].samples];
|
description.samples = rasterization_sample_count[p_attachments[i].samples];
|
||||||
|
@ -3395,6 +3408,17 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
|
||||||
bool is_storage = p_attachments[i].usage_flags & TEXTURE_USAGE_STORAGE_BIT;
|
bool is_storage = p_attachments[i].usage_flags & TEXTURE_USAGE_STORAGE_BIT;
|
||||||
bool is_depth = p_attachments[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
|
bool is_depth = p_attachments[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
|
||||||
|
|
||||||
|
// We can setup a framebuffer where we write to our VRS texture to set it up.
|
||||||
|
// We make the assumption here that if our texture is actually used as our VRS attachment,
|
||||||
|
// it is used as such for each subpass. This is fairly certain seeing the restrictions on subpasses.
|
||||||
|
bool is_vrs = p_attachments[i].usage_flags & TEXTURE_USAGE_VRS_ATTACHMENT_BIT && i == p_passes[0].vrs_attachment;
|
||||||
|
|
||||||
|
if (is_vrs) {
|
||||||
|
// For VRS we only read, there is no writing to this texture
|
||||||
|
description.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||||
|
description.initialLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||||
|
description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||||
|
} else {
|
||||||
// For each UNDEFINED, assume the prior use was a *read*, as we'd be discarding the output of a write
|
// For each UNDEFINED, assume the prior use was a *read*, as we'd be discarding the output of a write
|
||||||
// Also, each UNDEFINED will do an immediate layout transition (write), s.t. we must ensure execution synchronization vs.
|
// Also, each UNDEFINED will do an immediate layout transition (write), s.t. we must ensure execution synchronization vs.
|
||||||
// the read. If this is a performance issue, one could track the actual last accessor of each resource, adding only that
|
// the read. If this is a performance issue, one could track the actual last accessor of each resource, adding only that
|
||||||
|
@ -3474,6 +3498,7 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
|
||||||
ERR_FAIL_V(VK_NULL_HANDLE); //should never reach here
|
ERR_FAIL_V(VK_NULL_HANDLE); //should never reach here
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool used_last = false;
|
bool used_last = false;
|
||||||
|
|
||||||
|
@ -3485,6 +3510,10 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
|
||||||
if (p_passes[last_pass].depth_attachment == i) {
|
if (p_passes[last_pass].depth_attachment == i) {
|
||||||
used_last = true;
|
used_last = true;
|
||||||
}
|
}
|
||||||
|
} else if (is_vrs) {
|
||||||
|
if (p_passes[last_pass].vrs_attachment == i) {
|
||||||
|
used_last = true;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (p_passes[last_pass].resolve_attachments.size()) {
|
if (p_passes[last_pass].resolve_attachments.size()) {
|
||||||
//if using resolve attachments, check resolve attachments
|
//if using resolve attachments, check resolve attachments
|
||||||
|
@ -3526,6 +3555,16 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (is_vrs) {
|
||||||
|
// We don't change our VRS texture during this process
|
||||||
|
|
||||||
|
description.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||||
|
description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||||
|
description.finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||||
|
|
||||||
|
// TODO do we need to update our external dependency ?
|
||||||
|
// update_external_dependency_for_store(dependency_to_external, is_sampled, is_storage, false);
|
||||||
|
} else {
|
||||||
switch (is_depth ? final_depth_action : final_action) {
|
switch (is_depth ? final_depth_action : final_action) {
|
||||||
case FINAL_ACTION_READ: {
|
case FINAL_ACTION_READ: {
|
||||||
if (p_attachments[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) {
|
if (p_attachments[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) {
|
||||||
|
@ -3555,9 +3594,9 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
|
||||||
description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||||
description.finalLayout = is_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
|
description.finalLayout = is_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : (is_storage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
|
||||||
} else {
|
} else {
|
||||||
description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
description.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||||
description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||||
description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; //don't care what is there
|
description.finalLayout = VK_IMAGE_LAYOUT_UNDEFINED; //don't care what is there
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case FINAL_ACTION_CONTINUE: {
|
case FINAL_ACTION_CONTINUE: {
|
||||||
|
@ -3570,9 +3609,9 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
|
||||||
description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
|
description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||||
description.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
description.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||||
} else {
|
} else {
|
||||||
description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
description.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||||
description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||||
description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; //don't care what is there
|
description.finalLayout = VK_IMAGE_LAYOUT_UNDEFINED; //don't care what is there
|
||||||
}
|
}
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
|
@ -3580,18 +3619,21 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
|
||||||
ERR_FAIL_V(VK_NULL_HANDLE); //should never reach here
|
ERR_FAIL_V(VK_NULL_HANDLE); //should never reach here
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
attachment_last_pass[i] = -1;
|
attachment_last_pass[i] = -1;
|
||||||
attachment_remap.push_back(attachments.size());
|
attachment_remap.push_back(attachments.size());
|
||||||
attachments.push_back(description);
|
attachments.push_back(description);
|
||||||
}
|
}
|
||||||
|
|
||||||
LocalVector<VkSubpassDescription> subpasses;
|
LocalVector<VkSubpassDescription2KHR> subpasses;
|
||||||
LocalVector<LocalVector<VkAttachmentReference>> color_reference_array;
|
LocalVector<LocalVector<VkAttachmentReference2KHR>> color_reference_array;
|
||||||
LocalVector<LocalVector<VkAttachmentReference>> input_reference_array;
|
LocalVector<LocalVector<VkAttachmentReference2KHR>> input_reference_array;
|
||||||
LocalVector<LocalVector<VkAttachmentReference>> resolve_reference_array;
|
LocalVector<LocalVector<VkAttachmentReference2KHR>> resolve_reference_array;
|
||||||
LocalVector<LocalVector<uint32_t>> preserve_reference_array;
|
LocalVector<LocalVector<uint32_t>> preserve_reference_array;
|
||||||
LocalVector<VkAttachmentReference> depth_reference_array;
|
LocalVector<VkAttachmentReference2KHR> depth_reference_array;
|
||||||
|
LocalVector<VkAttachmentReference2KHR> vrs_reference_array;
|
||||||
|
LocalVector<VkFragmentShadingRateAttachmentInfoKHR> vrs_attachment_info_array;
|
||||||
|
|
||||||
subpasses.resize(p_passes.size());
|
subpasses.resize(p_passes.size());
|
||||||
color_reference_array.resize(p_passes.size());
|
color_reference_array.resize(p_passes.size());
|
||||||
|
@ -3599,20 +3641,25 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
|
||||||
resolve_reference_array.resize(p_passes.size());
|
resolve_reference_array.resize(p_passes.size());
|
||||||
preserve_reference_array.resize(p_passes.size());
|
preserve_reference_array.resize(p_passes.size());
|
||||||
depth_reference_array.resize(p_passes.size());
|
depth_reference_array.resize(p_passes.size());
|
||||||
|
vrs_reference_array.resize(p_passes.size());
|
||||||
|
vrs_attachment_info_array.resize(p_passes.size());
|
||||||
|
|
||||||
LocalVector<VkSubpassDependency> subpass_dependencies;
|
LocalVector<VkSubpassDependency2KHR> subpass_dependencies;
|
||||||
|
|
||||||
for (int i = 0; i < p_passes.size(); i++) {
|
for (int i = 0; i < p_passes.size(); i++) {
|
||||||
const FramebufferPass *pass = &p_passes[i];
|
const FramebufferPass *pass = &p_passes[i];
|
||||||
|
|
||||||
LocalVector<VkAttachmentReference> &color_references = color_reference_array[i];
|
LocalVector<VkAttachmentReference2KHR> &color_references = color_reference_array[i];
|
||||||
|
|
||||||
TextureSamples texture_samples = TEXTURE_SAMPLES_1;
|
TextureSamples texture_samples = TEXTURE_SAMPLES_1;
|
||||||
bool is_multisample_first = true;
|
bool is_multisample_first = true;
|
||||||
|
void *subpass_nextptr = nullptr;
|
||||||
|
|
||||||
for (int j = 0; j < pass->color_attachments.size(); j++) {
|
for (int j = 0; j < pass->color_attachments.size(); j++) {
|
||||||
int32_t attachment = pass->color_attachments[j];
|
int32_t attachment = pass->color_attachments[j];
|
||||||
VkAttachmentReference reference;
|
VkAttachmentReference2KHR reference;
|
||||||
|
reference.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2_KHR;
|
||||||
|
reference.pNext = nullptr;
|
||||||
if (attachment == FramebufferPass::ATTACHMENT_UNUSED) {
|
if (attachment == FramebufferPass::ATTACHMENT_UNUSED) {
|
||||||
reference.attachment = VK_ATTACHMENT_UNUSED;
|
reference.attachment = VK_ATTACHMENT_UNUSED;
|
||||||
reference.layout = VK_IMAGE_LAYOUT_UNDEFINED;
|
reference.layout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||||
|
@ -3631,14 +3678,17 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
|
||||||
reference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
reference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||||
attachment_last_pass[attachment] = i;
|
attachment_last_pass[attachment] = i;
|
||||||
}
|
}
|
||||||
|
reference.aspectMask = 0;
|
||||||
color_references.push_back(reference);
|
color_references.push_back(reference);
|
||||||
}
|
}
|
||||||
|
|
||||||
LocalVector<VkAttachmentReference> &input_references = input_reference_array[i];
|
LocalVector<VkAttachmentReference2KHR> &input_references = input_reference_array[i];
|
||||||
|
|
||||||
for (int j = 0; j < pass->input_attachments.size(); j++) {
|
for (int j = 0; j < pass->input_attachments.size(); j++) {
|
||||||
int32_t attachment = pass->input_attachments[j];
|
int32_t attachment = pass->input_attachments[j];
|
||||||
VkAttachmentReference reference;
|
VkAttachmentReference2KHR reference;
|
||||||
|
reference.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2_KHR;
|
||||||
|
reference.pNext = nullptr;
|
||||||
if (attachment == FramebufferPass::ATTACHMENT_UNUSED) {
|
if (attachment == FramebufferPass::ATTACHMENT_UNUSED) {
|
||||||
reference.attachment = VK_ATTACHMENT_UNUSED;
|
reference.attachment = VK_ATTACHMENT_UNUSED;
|
||||||
reference.layout = VK_IMAGE_LAYOUT_UNDEFINED;
|
reference.layout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||||
|
@ -3650,10 +3700,11 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
|
||||||
reference.layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
reference.layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||||
attachment_last_pass[attachment] = i;
|
attachment_last_pass[attachment] = i;
|
||||||
}
|
}
|
||||||
|
reference.aspectMask = 0; // TODO we need to set this here, possibly VK_IMAGE_ASPECT_COLOR_BIT ??
|
||||||
input_references.push_back(reference);
|
input_references.push_back(reference);
|
||||||
}
|
}
|
||||||
|
|
||||||
LocalVector<VkAttachmentReference> &resolve_references = resolve_reference_array[i];
|
LocalVector<VkAttachmentReference2KHR> &resolve_references = resolve_reference_array[i];
|
||||||
|
|
||||||
if (pass->resolve_attachments.size() > 0) {
|
if (pass->resolve_attachments.size() > 0) {
|
||||||
ERR_FAIL_COND_V_MSG(pass->resolve_attachments.size() != pass->color_attachments.size(), VK_NULL_HANDLE, "The amount of resolve attachments (" + itos(pass->resolve_attachments.size()) + ") must match the number of color attachments (" + itos(pass->color_attachments.size()) + ").");
|
ERR_FAIL_COND_V_MSG(pass->resolve_attachments.size() != pass->color_attachments.size(), VK_NULL_HANDLE, "The amount of resolve attachments (" + itos(pass->resolve_attachments.size()) + ") must match the number of color attachments (" + itos(pass->color_attachments.size()) + ").");
|
||||||
|
@ -3661,7 +3712,9 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
|
||||||
}
|
}
|
||||||
for (int j = 0; j < pass->resolve_attachments.size(); j++) {
|
for (int j = 0; j < pass->resolve_attachments.size(); j++) {
|
||||||
int32_t attachment = pass->resolve_attachments[j];
|
int32_t attachment = pass->resolve_attachments[j];
|
||||||
VkAttachmentReference reference;
|
VkAttachmentReference2KHR reference;
|
||||||
|
reference.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2_KHR;
|
||||||
|
reference.pNext = nullptr;
|
||||||
if (attachment == FramebufferPass::ATTACHMENT_UNUSED) {
|
if (attachment == FramebufferPass::ATTACHMENT_UNUSED) {
|
||||||
reference.attachment = VK_ATTACHMENT_UNUSED;
|
reference.attachment = VK_ATTACHMENT_UNUSED;
|
||||||
reference.layout = VK_IMAGE_LAYOUT_UNDEFINED;
|
reference.layout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||||
|
@ -3676,10 +3729,13 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
|
||||||
reference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; // VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
reference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; // VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||||
attachment_last_pass[attachment] = i;
|
attachment_last_pass[attachment] = i;
|
||||||
}
|
}
|
||||||
|
reference.aspectMask = 0;
|
||||||
resolve_references.push_back(reference);
|
resolve_references.push_back(reference);
|
||||||
}
|
}
|
||||||
|
|
||||||
VkAttachmentReference &depth_stencil_reference = depth_reference_array[i];
|
VkAttachmentReference2KHR &depth_stencil_reference = depth_reference_array[i];
|
||||||
|
depth_stencil_reference.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2_KHR;
|
||||||
|
depth_stencil_reference.pNext = nullptr;
|
||||||
|
|
||||||
if (pass->depth_attachment != FramebufferPass::ATTACHMENT_UNUSED) {
|
if (pass->depth_attachment != FramebufferPass::ATTACHMENT_UNUSED) {
|
||||||
int32_t attachment = pass->depth_attachment;
|
int32_t attachment = pass->depth_attachment;
|
||||||
|
@ -3688,6 +3744,7 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
|
||||||
ERR_FAIL_COND_V_MSG(attachment_last_pass[attachment] == i, VK_NULL_HANDLE, "Invalid framebuffer depth format attachment(" + itos(attachment) + "), in pass (" + itos(i) + "), it already was used for something else before in this pass.");
|
ERR_FAIL_COND_V_MSG(attachment_last_pass[attachment] == i, VK_NULL_HANDLE, "Invalid framebuffer depth format attachment(" + itos(attachment) + "), in pass (" + itos(i) + "), it already was used for something else before in this pass.");
|
||||||
depth_stencil_reference.attachment = attachment_remap[attachment];
|
depth_stencil_reference.attachment = attachment_remap[attachment];
|
||||||
depth_stencil_reference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
depth_stencil_reference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||||
|
depth_stencil_reference.aspectMask = 0;
|
||||||
attachment_last_pass[attachment] = i;
|
attachment_last_pass[attachment] = i;
|
||||||
|
|
||||||
if (is_multisample_first) {
|
if (is_multisample_first) {
|
||||||
|
@ -3702,6 +3759,32 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
|
||||||
depth_stencil_reference.layout = VK_IMAGE_LAYOUT_UNDEFINED;
|
depth_stencil_reference.layout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (context->get_vrs_capabilities().attachment_vrs_supported && pass->vrs_attachment != FramebufferPass::ATTACHMENT_UNUSED) {
|
||||||
|
int32_t attachment = pass->vrs_attachment;
|
||||||
|
ERR_FAIL_INDEX_V_MSG(attachment, p_attachments.size(), VK_NULL_HANDLE, "Invalid framebuffer depth format attachment(" + itos(attachment) + "), in pass (" + itos(i) + "), depth attachment.");
|
||||||
|
ERR_FAIL_COND_V_MSG(!(p_attachments[attachment].usage_flags & TEXTURE_USAGE_VRS_ATTACHMENT_BIT), VK_NULL_HANDLE, "Invalid framebuffer depth format attachment(" + itos(attachment) + "), in pass (" + itos(i) + "), it's marked as vrs, but it's not a vrs attachment.");
|
||||||
|
ERR_FAIL_COND_V_MSG(attachment_last_pass[attachment] == i, VK_NULL_HANDLE, "Invalid framebuffer vrs attachment(" + itos(attachment) + "), in pass (" + itos(i) + "), it already was used for something else before in this pass.");
|
||||||
|
|
||||||
|
VkAttachmentReference2KHR &vrs_reference = vrs_reference_array[i];
|
||||||
|
vrs_reference.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2_KHR;
|
||||||
|
vrs_reference.pNext = nullptr;
|
||||||
|
vrs_reference.attachment = attachment_remap[attachment];
|
||||||
|
vrs_reference.layout = VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR;
|
||||||
|
vrs_reference.aspectMask = 0;
|
||||||
|
|
||||||
|
Size2i texel_size = context->get_vrs_capabilities().max_texel_size;
|
||||||
|
|
||||||
|
VkFragmentShadingRateAttachmentInfoKHR &vrs_attachment_info = vrs_attachment_info_array[i];
|
||||||
|
vrs_attachment_info.sType = VK_STRUCTURE_TYPE_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR;
|
||||||
|
vrs_attachment_info.pNext = nullptr;
|
||||||
|
vrs_attachment_info.pFragmentShadingRateAttachment = &vrs_reference;
|
||||||
|
vrs_attachment_info.shadingRateAttachmentTexelSize = { uint32_t(texel_size.x), uint32_t(texel_size.y) };
|
||||||
|
|
||||||
|
attachment_last_pass[attachment] = i;
|
||||||
|
|
||||||
|
subpass_nextptr = &vrs_attachment_info;
|
||||||
|
}
|
||||||
|
|
||||||
LocalVector<uint32_t> &preserve_references = preserve_reference_array[i];
|
LocalVector<uint32_t> &preserve_references = preserve_reference_array[i];
|
||||||
|
|
||||||
for (int j = 0; j < pass->preserve_attachments.size(); j++) {
|
for (int j = 0; j < pass->preserve_attachments.size(); j++) {
|
||||||
|
@ -3718,9 +3801,12 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VkSubpassDescription &subpass = subpasses[i];
|
VkSubpassDescription2KHR &subpass = subpasses[i];
|
||||||
|
subpass.sType = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2_KHR;
|
||||||
|
subpass.pNext = subpass_nextptr;
|
||||||
subpass.flags = 0;
|
subpass.flags = 0;
|
||||||
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
||||||
|
subpass.viewMask = view_mask;
|
||||||
subpass.inputAttachmentCount = input_references.size();
|
subpass.inputAttachmentCount = input_references.size();
|
||||||
if (input_references.size()) {
|
if (input_references.size()) {
|
||||||
subpass.pInputAttachments = input_references.ptr();
|
subpass.pInputAttachments = input_references.ptr();
|
||||||
|
@ -3757,7 +3843,9 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
VkSubpassDependency dependency;
|
VkSubpassDependency2KHR dependency;
|
||||||
|
dependency.sType = VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2_KHR;
|
||||||
|
dependency.pNext = nullptr;
|
||||||
dependency.srcSubpass = i - 1;
|
dependency.srcSubpass = i - 1;
|
||||||
dependency.dstSubpass = i;
|
dependency.dstSubpass = i;
|
||||||
dependency.srcStageMask = 0;
|
dependency.srcStageMask = 0;
|
||||||
|
@ -3767,6 +3855,7 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
|
||||||
dependency.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
|
dependency.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
|
||||||
dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
|
dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
|
||||||
dependency.dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
|
dependency.dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
|
||||||
|
dependency.viewOffset = 0;
|
||||||
subpass_dependencies.push_back(dependency);
|
subpass_dependencies.push_back(dependency);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
@ -3784,10 +3873,11 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
VkRenderPassCreateInfo render_pass_create_info;
|
VkRenderPassCreateInfo2KHR render_pass_create_info;
|
||||||
render_pass_create_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
|
render_pass_create_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2_KHR;
|
||||||
render_pass_create_info.pNext = nullptr;
|
render_pass_create_info.pNext = nullptr;
|
||||||
render_pass_create_info.flags = 0;
|
render_pass_create_info.flags = 0;
|
||||||
|
|
||||||
render_pass_create_info.attachmentCount = attachments.size();
|
render_pass_create_info.attachmentCount = attachments.size();
|
||||||
render_pass_create_info.pAttachments = attachments.ptr();
|
render_pass_create_info.pAttachments = attachments.ptr();
|
||||||
render_pass_create_info.subpassCount = subpasses.size();
|
render_pass_create_info.subpassCount = subpasses.size();
|
||||||
|
@ -3804,13 +3894,15 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
|
||||||
render_pass_create_info.pDependencies = nullptr;
|
render_pass_create_info.pDependencies = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// These are only used if we use multiview but we need to define them in scope.
|
render_pass_create_info.correlatedViewMaskCount = 1;
|
||||||
const uint32_t view_mask = (1 << p_view_count) - 1;
|
render_pass_create_info.pCorrelatedViewMasks = &correlation_mask;
|
||||||
const uint32_t correlation_mask = (1 << p_view_count) - 1;
|
|
||||||
Vector<uint32_t> view_masks;
|
Vector<uint32_t> view_masks;
|
||||||
VkRenderPassMultiviewCreateInfo render_pass_multiview_create_info;
|
VkRenderPassMultiviewCreateInfo render_pass_multiview_create_info;
|
||||||
|
|
||||||
if (p_view_count > 1) {
|
if (p_view_count > 1) {
|
||||||
|
// this may no longer be needed with the new settings already including this
|
||||||
|
|
||||||
const VulkanContext::MultiviewCapabilities capabilities = context->get_multiview_capabilities();
|
const VulkanContext::MultiviewCapabilities capabilities = context->get_multiview_capabilities();
|
||||||
|
|
||||||
// For now this only works with multiview!
|
// For now this only works with multiview!
|
||||||
|
@ -3837,8 +3929,8 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
|
||||||
}
|
}
|
||||||
|
|
||||||
VkRenderPass render_pass;
|
VkRenderPass render_pass;
|
||||||
VkResult res = vkCreateRenderPass(device, &render_pass_create_info, nullptr, &render_pass);
|
VkResult res = context->vkCreateRenderPass2KHR(device, &render_pass_create_info, nullptr, &render_pass);
|
||||||
ERR_FAIL_COND_V_MSG(res, VK_NULL_HANDLE, "vkCreateRenderPass failed with error " + itos(res) + ".");
|
ERR_FAIL_COND_V_MSG(res, VK_NULL_HANDLE, "vkCreateRenderPass2KHR failed with error " + itos(res) + ".");
|
||||||
|
|
||||||
return render_pass;
|
return render_pass;
|
||||||
}
|
}
|
||||||
|
@ -3899,7 +3991,9 @@ RenderingDevice::FramebufferFormatID RenderingDeviceVulkan::framebuffer_format_c
|
||||||
return E->get();
|
return E->get();
|
||||||
}
|
}
|
||||||
|
|
||||||
VkSubpassDescription subpass;
|
VkSubpassDescription2KHR subpass;
|
||||||
|
subpass.sType = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2_KHR;
|
||||||
|
subpass.pNext = nullptr;
|
||||||
subpass.flags = 0;
|
subpass.flags = 0;
|
||||||
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
||||||
subpass.inputAttachmentCount = 0; //unsupported for now
|
subpass.inputAttachmentCount = 0; //unsupported for now
|
||||||
|
@ -3911,8 +4005,8 @@ RenderingDevice::FramebufferFormatID RenderingDeviceVulkan::framebuffer_format_c
|
||||||
subpass.preserveAttachmentCount = 0;
|
subpass.preserveAttachmentCount = 0;
|
||||||
subpass.pPreserveAttachments = nullptr;
|
subpass.pPreserveAttachments = nullptr;
|
||||||
|
|
||||||
VkRenderPassCreateInfo render_pass_create_info;
|
VkRenderPassCreateInfo2KHR render_pass_create_info;
|
||||||
render_pass_create_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
|
render_pass_create_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2_KHR;
|
||||||
render_pass_create_info.pNext = nullptr;
|
render_pass_create_info.pNext = nullptr;
|
||||||
render_pass_create_info.flags = 0;
|
render_pass_create_info.flags = 0;
|
||||||
render_pass_create_info.attachmentCount = 0;
|
render_pass_create_info.attachmentCount = 0;
|
||||||
|
@ -3923,9 +4017,9 @@ RenderingDevice::FramebufferFormatID RenderingDeviceVulkan::framebuffer_format_c
|
||||||
render_pass_create_info.pDependencies = nullptr;
|
render_pass_create_info.pDependencies = nullptr;
|
||||||
|
|
||||||
VkRenderPass render_pass;
|
VkRenderPass render_pass;
|
||||||
VkResult res = vkCreateRenderPass(device, &render_pass_create_info, nullptr, &render_pass);
|
VkResult res = context->vkCreateRenderPass2KHR(device, &render_pass_create_info, nullptr, &render_pass);
|
||||||
|
|
||||||
ERR_FAIL_COND_V_MSG(res, 0, "vkCreateRenderPass for empty fb failed with error " + itos(res) + ".");
|
ERR_FAIL_COND_V_MSG(res, 0, "vkCreateRenderPass2KHR for empty fb failed with error " + itos(res) + ".");
|
||||||
|
|
||||||
if (render_pass == VK_NULL_HANDLE) { //was likely invalid
|
if (render_pass == VK_NULL_HANDLE) { //was likely invalid
|
||||||
return INVALID_ID;
|
return INVALID_ID;
|
||||||
|
@ -3978,6 +4072,8 @@ RID RenderingDeviceVulkan::framebuffer_create(const Vector<RID> &p_texture_attac
|
||||||
|
|
||||||
if (texture && texture->usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
|
if (texture && texture->usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
|
||||||
pass.depth_attachment = i;
|
pass.depth_attachment = i;
|
||||||
|
} else if (texture && texture->usage_flags & TEXTURE_USAGE_VRS_ATTACHMENT_BIT) {
|
||||||
|
pass.vrs_attachment = i;
|
||||||
} else {
|
} else {
|
||||||
pass.color_attachments.push_back(texture ? i : FramebufferPass::ATTACHMENT_UNUSED);
|
pass.color_attachments.push_back(texture ? i : FramebufferPass::ATTACHMENT_UNUSED);
|
||||||
}
|
}
|
||||||
|
@ -4008,6 +4104,10 @@ RID RenderingDeviceVulkan::framebuffer_create_multipass(const Vector<RID> &p_tex
|
||||||
size.width = texture->width;
|
size.width = texture->width;
|
||||||
size.height = texture->height;
|
size.height = texture->height;
|
||||||
size_set = true;
|
size_set = true;
|
||||||
|
} else if (texture->usage_flags & TEXTURE_USAGE_VRS_ATTACHMENT_BIT) {
|
||||||
|
// If this is not the first attachement we assume this is used as the VRS attachment
|
||||||
|
// in this case this texture will be 1/16th the size of the color attachement.
|
||||||
|
// So we skip the size check
|
||||||
} else {
|
} else {
|
||||||
ERR_FAIL_COND_V_MSG((uint32_t)size.width != texture->width || (uint32_t)size.height != texture->height, RID(),
|
ERR_FAIL_COND_V_MSG((uint32_t)size.width != texture->width || (uint32_t)size.height != texture->height, RID(),
|
||||||
"All textures in a framebuffer should be the same size.");
|
"All textures in a framebuffer should be the same size.");
|
||||||
|
@ -6552,11 +6652,28 @@ RID RenderingDeviceVulkan::render_pipeline_create(RID p_shader, FramebufferForma
|
||||||
dynamic_state_create_info.dynamicStateCount = dynamic_states.size();
|
dynamic_state_create_info.dynamicStateCount = dynamic_states.size();
|
||||||
dynamic_state_create_info.pDynamicStates = dynamic_states.ptr();
|
dynamic_state_create_info.pDynamicStates = dynamic_states.ptr();
|
||||||
|
|
||||||
|
void *graphics_pipeline_nextptr = nullptr;
|
||||||
|
|
||||||
|
VkPipelineFragmentShadingRateStateCreateInfoKHR vrs_create_info;
|
||||||
|
if (context->get_vrs_capabilities().attachment_vrs_supported) {
|
||||||
|
// If VRS is used, this defines how the different VRS types are combined.
|
||||||
|
// combinerOps[0] decides how we use the output of pipeline and primitive (drawcall) VRS
|
||||||
|
// combinerOps[1] decides how we use the output of combinerOps[0] and our attachment VRS
|
||||||
|
|
||||||
|
vrs_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_FRAGMENT_SHADING_RATE_STATE_CREATE_INFO_KHR;
|
||||||
|
vrs_create_info.pNext = nullptr;
|
||||||
|
vrs_create_info.fragmentSize = { 4, 4 };
|
||||||
|
vrs_create_info.combinerOps[0] = VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR; // We don't use pipeline/primitive VRS so this really doesn't matter
|
||||||
|
vrs_create_info.combinerOps[1] = VK_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_KHR; // always use the outcome of attachment VRS if enabled
|
||||||
|
|
||||||
|
graphics_pipeline_nextptr = &vrs_create_info;
|
||||||
|
}
|
||||||
|
|
||||||
//finally, pipeline create info
|
//finally, pipeline create info
|
||||||
VkGraphicsPipelineCreateInfo graphics_pipeline_create_info;
|
VkGraphicsPipelineCreateInfo graphics_pipeline_create_info;
|
||||||
|
|
||||||
graphics_pipeline_create_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
|
graphics_pipeline_create_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
|
||||||
graphics_pipeline_create_info.pNext = nullptr;
|
graphics_pipeline_create_info.pNext = graphics_pipeline_nextptr;
|
||||||
graphics_pipeline_create_info.flags = 0;
|
graphics_pipeline_create_info.flags = 0;
|
||||||
|
|
||||||
Vector<VkPipelineShaderStageCreateInfo> pipeline_stages = shader->pipeline_stages;
|
Vector<VkPipelineShaderStageCreateInfo> pipeline_stages = shader->pipeline_stages;
|
||||||
|
@ -6721,7 +6838,7 @@ RID RenderingDeviceVulkan::compute_pipeline_create(RID p_shader, const Vector<Pi
|
||||||
const PipelineSpecializationConstant &psc = p_specialization_constants[j];
|
const PipelineSpecializationConstant &psc = p_specialization_constants[j];
|
||||||
if (psc.constant_id == sc.constant.constant_id) {
|
if (psc.constant_id == sc.constant.constant_id) {
|
||||||
ERR_FAIL_COND_V_MSG(psc.type != sc.constant.type, RID(), "Specialization constant provided for id (" + itos(sc.constant.constant_id) + ") is of the wrong type.");
|
ERR_FAIL_COND_V_MSG(psc.type != sc.constant.type, RID(), "Specialization constant provided for id (" + itos(sc.constant.constant_id) + ") is of the wrong type.");
|
||||||
data_ptr[i] = sc.constant.int_value;
|
data_ptr[i] = psc.int_value;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6905,10 +7022,12 @@ Error RenderingDeviceVulkan::_draw_list_setup_framebuffer(Framebuffer *p_framebu
|
||||||
Texture *texture = texture_owner.get_or_null(p_framebuffer->texture_ids[i]);
|
Texture *texture = texture_owner.get_or_null(p_framebuffer->texture_ids[i]);
|
||||||
if (texture) {
|
if (texture) {
|
||||||
attachments.push_back(texture->view);
|
attachments.push_back(texture->view);
|
||||||
|
if (!(texture->usage_flags & TEXTURE_USAGE_VRS_ATTACHMENT_BIT)) { // VRS attachment will be a different size.
|
||||||
ERR_FAIL_COND_V(texture->width != p_framebuffer->size.width, ERR_BUG);
|
ERR_FAIL_COND_V(texture->width != p_framebuffer->size.width, ERR_BUG);
|
||||||
ERR_FAIL_COND_V(texture->height != p_framebuffer->size.height, ERR_BUG);
|
ERR_FAIL_COND_V(texture->height != p_framebuffer->size.height, ERR_BUG);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
framebuffer_create_info.attachmentCount = attachments.size();
|
framebuffer_create_info.attachmentCount = attachments.size();
|
||||||
framebuffer_create_info.pAttachments = attachments.ptr();
|
framebuffer_create_info.pAttachments = attachments.ptr();
|
||||||
framebuffer_create_info.width = p_framebuffer->size.width;
|
framebuffer_create_info.width = p_framebuffer->size.width;
|
||||||
|
@ -7134,7 +7253,10 @@ RenderingDevice::DrawListID RenderingDeviceVulkan::draw_list_begin(RID p_framebu
|
||||||
int color_count = 0;
|
int color_count = 0;
|
||||||
for (int i = 0; i < framebuffer->texture_ids.size(); i++) {
|
for (int i = 0; i < framebuffer->texture_ids.size(); i++) {
|
||||||
Texture *texture = texture_owner.get_or_null(framebuffer->texture_ids[i]);
|
Texture *texture = texture_owner.get_or_null(framebuffer->texture_ids[i]);
|
||||||
if (!texture || !(texture->usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)) {
|
// We only check for our VRS usage bit if this is not the first texture id.
|
||||||
|
// If it is the first we're likely populating our VRS texture.
|
||||||
|
// Bit dirty but..
|
||||||
|
if (!texture || (!(texture->usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) && !(i != 0 && texture->usage_flags & TEXTURE_USAGE_VRS_ATTACHMENT_BIT))) {
|
||||||
color_count++;
|
color_count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8995,17 +9117,6 @@ void RenderingDeviceVulkan::initialize(VulkanContext *p_context, bool p_local_de
|
||||||
{
|
{
|
||||||
device_capabilities.version_major = p_context->get_vulkan_major();
|
device_capabilities.version_major = p_context->get_vulkan_major();
|
||||||
device_capabilities.version_minor = p_context->get_vulkan_minor();
|
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();
|
|
||||||
|
|
||||||
// get info about further features
|
|
||||||
VulkanContext::MultiviewCapabilities multiview_capabilies = p_context->get_multiview_capabilities();
|
|
||||||
device_capabilities.supports_multiview = multiview_capabilies.is_supported && multiview_capabilies.max_view_count > 1;
|
|
||||||
device_capabilities.supports_fsr_half_float = p_context->get_shader_capabilities().shader_float16_is_supported && p_context->get_storage_buffer_capabilities().storage_buffer_16_bit_access_is_supported;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
context = p_context;
|
context = p_context;
|
||||||
|
@ -9354,7 +9465,7 @@ String RenderingDeviceVulkan::get_captured_timestamp_name(uint32_t p_index) cons
|
||||||
return frames[frame].timestamp_result_names[p_index];
|
return frames[frame].timestamp_result_names[p_index];
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t RenderingDeviceVulkan::limit_get(Limit p_limit) {
|
uint64_t RenderingDeviceVulkan::limit_get(Limit p_limit) const {
|
||||||
switch (p_limit) {
|
switch (p_limit) {
|
||||||
case LIMIT_MAX_BOUND_UNIFORM_SETS:
|
case LIMIT_MAX_BOUND_UNIFORM_SETS:
|
||||||
return limits.maxBoundDescriptorSets;
|
return limits.maxBoundDescriptorSets;
|
||||||
|
@ -9424,7 +9535,18 @@ uint64_t RenderingDeviceVulkan::limit_get(Limit p_limit) {
|
||||||
return limits.maxComputeWorkGroupSize[1];
|
return limits.maxComputeWorkGroupSize[1];
|
||||||
case LIMIT_MAX_COMPUTE_WORKGROUP_SIZE_Z:
|
case LIMIT_MAX_COMPUTE_WORKGROUP_SIZE_Z:
|
||||||
return limits.maxComputeWorkGroupSize[2];
|
return limits.maxComputeWorkGroupSize[2];
|
||||||
|
case LIMIT_SUBGROUP_SIZE: {
|
||||||
|
VulkanContext::SubgroupCapabilities subgroup_capabilities = context->get_subgroup_capabilities();
|
||||||
|
return subgroup_capabilities.size;
|
||||||
|
}
|
||||||
|
case LIMIT_SUBGROUP_IN_SHADERS: {
|
||||||
|
VulkanContext::SubgroupCapabilities subgroup_capabilities = context->get_subgroup_capabilities();
|
||||||
|
return subgroup_capabilities.supported_stages_flags_rd();
|
||||||
|
}
|
||||||
|
case LIMIT_SUBGROUP_OPERATIONS: {
|
||||||
|
VulkanContext::SubgroupCapabilities subgroup_capabilities = context->get_subgroup_capabilities();
|
||||||
|
return subgroup_capabilities.supported_operations_flags_rd();
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
ERR_FAIL_V(0);
|
ERR_FAIL_V(0);
|
||||||
}
|
}
|
||||||
|
@ -9524,6 +9646,25 @@ RenderingDevice *RenderingDeviceVulkan::create_local_device() {
|
||||||
return rd;
|
return rd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool RenderingDeviceVulkan::has_feature(const Features p_feature) const {
|
||||||
|
switch (p_feature) {
|
||||||
|
case SUPPORTS_MULTIVIEW: {
|
||||||
|
VulkanContext::MultiviewCapabilities multiview_capabilies = context->get_multiview_capabilities();
|
||||||
|
return multiview_capabilies.is_supported && multiview_capabilies.max_view_count > 1;
|
||||||
|
} break;
|
||||||
|
case SUPPORTS_FSR_HALF_FLOAT: {
|
||||||
|
return context->get_shader_capabilities().shader_float16_is_supported && context->get_storage_buffer_capabilities().storage_buffer_16_bit_access_is_supported;
|
||||||
|
} break;
|
||||||
|
case SUPPORTS_ATTACHMENT_VRS: {
|
||||||
|
VulkanContext::VRSCapabilities vrs_capabilities = context->get_vrs_capabilities();
|
||||||
|
return vrs_capabilities.attachment_vrs_supported;
|
||||||
|
} break;
|
||||||
|
default: {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
RenderingDeviceVulkan::RenderingDeviceVulkan() {
|
RenderingDeviceVulkan::RenderingDeviceVulkan() {
|
||||||
device_capabilities.device_family = DEVICE_VULKAN;
|
device_capabilities.device_family = DEVICE_VULKAN;
|
||||||
}
|
}
|
||||||
|
|
|
@ -241,6 +241,7 @@ class RenderingDeviceVulkan : public RenderingDevice {
|
||||||
Vector<AttachmentFormat> attachments;
|
Vector<AttachmentFormat> attachments;
|
||||||
Vector<FramebufferPass> passes;
|
Vector<FramebufferPass> passes;
|
||||||
uint32_t view_count = 1;
|
uint32_t view_count = 1;
|
||||||
|
|
||||||
bool operator<(const FramebufferFormatKey &p_key) const {
|
bool operator<(const FramebufferFormatKey &p_key) const {
|
||||||
if (view_count != p_key.view_count) {
|
if (view_count != p_key.view_count) {
|
||||||
return view_count < p_key.view_count;
|
return view_count < p_key.view_count;
|
||||||
|
@ -1203,7 +1204,7 @@ public:
|
||||||
/**** Limits ****/
|
/**** Limits ****/
|
||||||
/****************/
|
/****************/
|
||||||
|
|
||||||
virtual uint64_t limit_get(Limit p_limit);
|
virtual uint64_t limit_get(Limit p_limit) const;
|
||||||
|
|
||||||
virtual void prepare_screen_for_drawing();
|
virtual void prepare_screen_for_drawing();
|
||||||
void initialize(VulkanContext *p_context, bool p_local_device = false);
|
void initialize(VulkanContext *p_context, bool p_local_device = false);
|
||||||
|
@ -1234,6 +1235,8 @@ public:
|
||||||
|
|
||||||
virtual uint64_t get_driver_resource(DriverResource p_resource, RID p_rid = RID(), uint64_t p_index = 0);
|
virtual uint64_t get_driver_resource(DriverResource p_resource, RID p_rid = RID(), uint64_t p_index = 0);
|
||||||
|
|
||||||
|
virtual bool has_feature(const Features p_feature) const;
|
||||||
|
|
||||||
RenderingDeviceVulkan();
|
RenderingDeviceVulkan();
|
||||||
~RenderingDeviceVulkan();
|
~RenderingDeviceVulkan();
|
||||||
};
|
};
|
||||||
|
|
|
@ -48,6 +48,18 @@
|
||||||
|
|
||||||
VulkanHooks *VulkanContext::vulkan_hooks = nullptr;
|
VulkanHooks *VulkanContext::vulkan_hooks = nullptr;
|
||||||
|
|
||||||
|
VkResult VulkanContext::vkCreateRenderPass2KHR(VkDevice device, const VkRenderPassCreateInfo2 *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkRenderPass *pRenderPass) {
|
||||||
|
if (fpCreateRenderPass2KHR == nullptr) {
|
||||||
|
fpCreateRenderPass2KHR = (PFN_vkCreateRenderPass2KHR)vkGetInstanceProcAddr(inst, "vkCreateRenderPass2KHR");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fpCreateRenderPass2KHR == nullptr) {
|
||||||
|
return VK_ERROR_EXTENSION_NOT_PRESENT;
|
||||||
|
} else {
|
||||||
|
return (fpCreateRenderPass2KHR)(device, pCreateInfo, pAllocator, pRenderPass);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
VKAPI_ATTR VkBool32 VKAPI_CALL VulkanContext::_debug_messenger_callback(
|
VKAPI_ATTR VkBool32 VKAPI_CALL VulkanContext::_debug_messenger_callback(
|
||||||
VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
|
VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
|
||||||
VkDebugUtilsMessageTypeFlagsEXT messageType,
|
VkDebugUtilsMessageTypeFlagsEXT messageType,
|
||||||
|
@ -507,6 +519,9 @@ Error VulkanContext::_check_capabilities() {
|
||||||
// (note that the desktop loader does a better job here but the android loader doesn't)
|
// (note that the desktop loader does a better job here but the android loader doesn't)
|
||||||
|
|
||||||
// assume not supported until proven otherwise
|
// assume not supported until proven otherwise
|
||||||
|
vrs_capabilities.pipeline_vrs_supported = false;
|
||||||
|
vrs_capabilities.primitive_vrs_supported = false;
|
||||||
|
vrs_capabilities.attachment_vrs_supported = false;
|
||||||
multiview_capabilities.is_supported = false;
|
multiview_capabilities.is_supported = false;
|
||||||
multiview_capabilities.geometry_shader_is_supported = false;
|
multiview_capabilities.geometry_shader_is_supported = false;
|
||||||
multiview_capabilities.tessellation_shader_is_supported = false;
|
multiview_capabilities.tessellation_shader_is_supported = false;
|
||||||
|
@ -531,9 +546,17 @@ Error VulkanContext::_check_capabilities() {
|
||||||
}
|
}
|
||||||
if (vkGetPhysicalDeviceFeatures2_func != nullptr) {
|
if (vkGetPhysicalDeviceFeatures2_func != nullptr) {
|
||||||
// check our extended features
|
// check our extended features
|
||||||
|
VkPhysicalDeviceFragmentShadingRateFeaturesKHR vrs_features = {
|
||||||
|
/*sType*/ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_FEATURES_KHR,
|
||||||
|
/*pNext*/ nullptr,
|
||||||
|
/*pipelineFragmentShadingRate*/ false,
|
||||||
|
/*primitiveFragmentShadingRate*/ false,
|
||||||
|
/*attachmentFragmentShadingRate*/ false,
|
||||||
|
};
|
||||||
|
|
||||||
VkPhysicalDeviceShaderFloat16Int8FeaturesKHR shader_features = {
|
VkPhysicalDeviceShaderFloat16Int8FeaturesKHR shader_features = {
|
||||||
/*sType*/ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES_KHR,
|
/*sType*/ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES_KHR,
|
||||||
/*pNext*/ nullptr,
|
/*pNext*/ &vrs_features,
|
||||||
/*shaderFloat16*/ false,
|
/*shaderFloat16*/ false,
|
||||||
/*shaderInt8*/ false,
|
/*shaderInt8*/ false,
|
||||||
};
|
};
|
||||||
|
@ -561,6 +584,10 @@ Error VulkanContext::_check_capabilities() {
|
||||||
|
|
||||||
vkGetPhysicalDeviceFeatures2_func(gpu, &device_features);
|
vkGetPhysicalDeviceFeatures2_func(gpu, &device_features);
|
||||||
|
|
||||||
|
vrs_capabilities.pipeline_vrs_supported = vrs_features.pipelineFragmentShadingRate;
|
||||||
|
vrs_capabilities.primitive_vrs_supported = vrs_features.primitiveFragmentShadingRate;
|
||||||
|
vrs_capabilities.attachment_vrs_supported = vrs_features.attachmentFragmentShadingRate;
|
||||||
|
|
||||||
multiview_capabilities.is_supported = multiview_features.multiview;
|
multiview_capabilities.is_supported = multiview_features.multiview;
|
||||||
multiview_capabilities.geometry_shader_is_supported = multiview_features.multiviewGeometryShader;
|
multiview_capabilities.geometry_shader_is_supported = multiview_features.multiviewGeometryShader;
|
||||||
multiview_capabilities.tessellation_shader_is_supported = multiview_features.multiviewTessellationShader;
|
multiview_capabilities.tessellation_shader_is_supported = multiview_features.multiviewTessellationShader;
|
||||||
|
@ -581,24 +608,33 @@ Error VulkanContext::_check_capabilities() {
|
||||||
device_properties_func = (PFN_vkGetPhysicalDeviceProperties2)vkGetInstanceProcAddr(inst, "vkGetPhysicalDeviceProperties2KHR");
|
device_properties_func = (PFN_vkGetPhysicalDeviceProperties2)vkGetInstanceProcAddr(inst, "vkGetPhysicalDeviceProperties2KHR");
|
||||||
}
|
}
|
||||||
if (device_properties_func != nullptr) {
|
if (device_properties_func != nullptr) {
|
||||||
|
VkPhysicalDeviceFragmentShadingRatePropertiesKHR vrsProperties;
|
||||||
VkPhysicalDeviceMultiviewProperties multiviewProperties;
|
VkPhysicalDeviceMultiviewProperties multiviewProperties;
|
||||||
VkPhysicalDeviceSubgroupProperties subgroupProperties;
|
VkPhysicalDeviceSubgroupProperties subgroupProperties;
|
||||||
VkPhysicalDeviceProperties2 physicalDeviceProperties;
|
VkPhysicalDeviceProperties2 physicalDeviceProperties;
|
||||||
|
void *nextptr = nullptr;
|
||||||
|
|
||||||
subgroupProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES;
|
subgroupProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES;
|
||||||
subgroupProperties.pNext = nullptr;
|
subgroupProperties.pNext = nextptr;
|
||||||
|
nextptr = &subgroupProperties;
|
||||||
physicalDeviceProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
|
|
||||||
|
|
||||||
if (multiview_capabilities.is_supported) {
|
if (multiview_capabilities.is_supported) {
|
||||||
multiviewProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES;
|
multiviewProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES;
|
||||||
multiviewProperties.pNext = &subgroupProperties;
|
multiviewProperties.pNext = nextptr;
|
||||||
|
|
||||||
physicalDeviceProperties.pNext = &multiviewProperties;
|
nextptr = &multiviewProperties;
|
||||||
} else {
|
|
||||||
physicalDeviceProperties.pNext = &subgroupProperties;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (vrs_capabilities.attachment_vrs_supported) {
|
||||||
|
vrsProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_PROPERTIES_KHR;
|
||||||
|
vrsProperties.pNext = nextptr;
|
||||||
|
|
||||||
|
nextptr = &vrsProperties;
|
||||||
|
}
|
||||||
|
|
||||||
|
physicalDeviceProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
|
||||||
|
physicalDeviceProperties.pNext = nextptr;
|
||||||
|
|
||||||
device_properties_func(gpu, &physicalDeviceProperties);
|
device_properties_func(gpu, &physicalDeviceProperties);
|
||||||
|
|
||||||
subgroup_capabilities.size = subgroupProperties.subgroupSize;
|
subgroup_capabilities.size = subgroupProperties.subgroupSize;
|
||||||
|
@ -609,6 +645,28 @@ Error VulkanContext::_check_capabilities() {
|
||||||
// - supportedOperations has VK_SUBGROUP_FEATURE_QUAD_BIT
|
// - supportedOperations has VK_SUBGROUP_FEATURE_QUAD_BIT
|
||||||
subgroup_capabilities.quadOperationsInAllStages = subgroupProperties.quadOperationsInAllStages;
|
subgroup_capabilities.quadOperationsInAllStages = subgroupProperties.quadOperationsInAllStages;
|
||||||
|
|
||||||
|
if (vrs_capabilities.pipeline_vrs_supported || vrs_capabilities.primitive_vrs_supported || vrs_capabilities.attachment_vrs_supported) {
|
||||||
|
print_verbose("- Vulkan Varying Shading Rates supported:");
|
||||||
|
if (vrs_capabilities.pipeline_vrs_supported) {
|
||||||
|
print_verbose(" Pipeline fragment shading rate");
|
||||||
|
}
|
||||||
|
if (vrs_capabilities.primitive_vrs_supported) {
|
||||||
|
print_verbose(" Primitive fragment shading rate");
|
||||||
|
}
|
||||||
|
if (vrs_capabilities.attachment_vrs_supported) {
|
||||||
|
// TODO expose these somehow to the end user
|
||||||
|
vrs_capabilities.min_texel_size.x = vrsProperties.minFragmentShadingRateAttachmentTexelSize.width;
|
||||||
|
vrs_capabilities.min_texel_size.y = vrsProperties.minFragmentShadingRateAttachmentTexelSize.height;
|
||||||
|
vrs_capabilities.max_texel_size.x = vrsProperties.maxFragmentShadingRateAttachmentTexelSize.width;
|
||||||
|
vrs_capabilities.max_texel_size.y = vrsProperties.maxFragmentShadingRateAttachmentTexelSize.height;
|
||||||
|
|
||||||
|
print_verbose(String(" Attachment fragment shading rate") + String(", min texel size: (") + itos(vrs_capabilities.min_texel_size.x) + String(", ") + itos(vrs_capabilities.min_texel_size.y) + String(")") + String(", max texel size: (") + itos(vrs_capabilities.max_texel_size.x) + String(", ") + itos(vrs_capabilities.max_texel_size.y) + String(")"));
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
print_verbose("- Vulkan Varying Shading Rates not supported");
|
||||||
|
}
|
||||||
|
|
||||||
if (multiview_capabilities.is_supported) {
|
if (multiview_capabilities.is_supported) {
|
||||||
multiview_capabilities.max_view_count = multiviewProperties.maxMultiviewViewCount;
|
multiview_capabilities.max_view_count = multiviewProperties.maxMultiviewViewCount;
|
||||||
multiview_capabilities.max_instance_count = multiviewProperties.maxMultiviewInstanceIndex;
|
multiview_capabilities.max_instance_count = multiviewProperties.maxMultiviewInstanceIndex;
|
||||||
|
@ -999,6 +1057,13 @@ Error VulkanContext::_create_physical_device(VkSurfaceKHR p_surface) {
|
||||||
// if multiview is supported, enable it
|
// if multiview is supported, enable it
|
||||||
extension_names[enabled_extension_count++] = VK_KHR_MULTIVIEW_EXTENSION_NAME;
|
extension_names[enabled_extension_count++] = VK_KHR_MULTIVIEW_EXTENSION_NAME;
|
||||||
}
|
}
|
||||||
|
if (!strcmp(VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME, device_extensions[i].extensionName)) {
|
||||||
|
// if shading rate image is supported, enable it
|
||||||
|
extension_names[enabled_extension_count++] = VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME;
|
||||||
|
}
|
||||||
|
if (!strcmp(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME, device_extensions[i].extensionName)) {
|
||||||
|
extension_names[enabled_extension_count++] = VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME;
|
||||||
|
}
|
||||||
if (enabled_extension_count >= MAX_EXTENSIONS) {
|
if (enabled_extension_count >= MAX_EXTENSIONS) {
|
||||||
free(device_extensions);
|
free(device_extensions);
|
||||||
ERR_FAIL_V_MSG(ERR_BUG, "Enabled extension count reaches MAX_EXTENSIONS, BUG");
|
ERR_FAIL_V_MSG(ERR_BUG, "Enabled extension count reaches MAX_EXTENSIONS, BUG");
|
||||||
|
@ -1110,6 +1175,18 @@ Error VulkanContext::_create_device() {
|
||||||
};
|
};
|
||||||
nextptr = &shader_features;
|
nextptr = &shader_features;
|
||||||
|
|
||||||
|
VkPhysicalDeviceFragmentShadingRateFeaturesKHR vrs_features;
|
||||||
|
if (vrs_capabilities.pipeline_vrs_supported || vrs_capabilities.primitive_vrs_supported || vrs_capabilities.attachment_vrs_supported) {
|
||||||
|
// insert into our chain to enable these features if they are available
|
||||||
|
vrs_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_FEATURES_KHR;
|
||||||
|
vrs_features.pNext = nextptr;
|
||||||
|
vrs_features.pipelineFragmentShadingRate = vrs_capabilities.pipeline_vrs_supported;
|
||||||
|
vrs_features.primitiveFragmentShadingRate = vrs_capabilities.primitive_vrs_supported;
|
||||||
|
vrs_features.attachmentFragmentShadingRate = vrs_capabilities.attachment_vrs_supported;
|
||||||
|
|
||||||
|
nextptr = &vrs_features;
|
||||||
|
}
|
||||||
|
|
||||||
VkPhysicalDeviceVulkan11Features vulkan11features;
|
VkPhysicalDeviceVulkan11Features vulkan11features;
|
||||||
VkPhysicalDevice16BitStorageFeaturesKHR storage_feature;
|
VkPhysicalDevice16BitStorageFeaturesKHR storage_feature;
|
||||||
VkPhysicalDeviceMultiviewFeatures multiview_features;
|
VkPhysicalDeviceMultiviewFeatures multiview_features;
|
||||||
|
@ -1725,7 +1802,9 @@ Error VulkanContext::_update_swap_chain(Window *window) {
|
||||||
/******** FRAMEBUFFER ************/
|
/******** FRAMEBUFFER ************/
|
||||||
|
|
||||||
{
|
{
|
||||||
const VkAttachmentDescription attachment = {
|
const VkAttachmentDescription2KHR attachment = {
|
||||||
|
/*sType*/ VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2_KHR,
|
||||||
|
/*pNext*/ nullptr,
|
||||||
/*flags*/ 0,
|
/*flags*/ 0,
|
||||||
/*format*/ format,
|
/*format*/ format,
|
||||||
/*samples*/ VK_SAMPLE_COUNT_1_BIT,
|
/*samples*/ VK_SAMPLE_COUNT_1_BIT,
|
||||||
|
@ -1737,14 +1816,20 @@ Error VulkanContext::_update_swap_chain(Window *window) {
|
||||||
/*finalLayout*/ VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
|
/*finalLayout*/ VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
|
||||||
|
|
||||||
};
|
};
|
||||||
const VkAttachmentReference color_reference = {
|
const VkAttachmentReference2KHR color_reference = {
|
||||||
|
/*sType*/ VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2_KHR,
|
||||||
|
/*pNext*/ nullptr,
|
||||||
/*attachment*/ 0,
|
/*attachment*/ 0,
|
||||||
/*layout*/ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
/*layout*/ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||||
|
/*aspectMask*/ 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
const VkSubpassDescription subpass = {
|
const VkSubpassDescription2KHR subpass = {
|
||||||
|
/*sType*/ VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2_KHR,
|
||||||
|
/*pNext*/ nullptr,
|
||||||
/*flags*/ 0,
|
/*flags*/ 0,
|
||||||
/*pipelineBindPoint*/ VK_PIPELINE_BIND_POINT_GRAPHICS,
|
/*pipelineBindPoint*/ VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||||
|
/*viewMask*/ 1,
|
||||||
/*inputAttachmentCount*/ 0,
|
/*inputAttachmentCount*/ 0,
|
||||||
/*pInputAttachments*/ nullptr,
|
/*pInputAttachments*/ nullptr,
|
||||||
/*colorAttachmentCount*/ 1,
|
/*colorAttachmentCount*/ 1,
|
||||||
|
@ -1754,8 +1839,10 @@ Error VulkanContext::_update_swap_chain(Window *window) {
|
||||||
/*preserveAttachmentCount*/ 0,
|
/*preserveAttachmentCount*/ 0,
|
||||||
/*pPreserveAttachments*/ nullptr,
|
/*pPreserveAttachments*/ nullptr,
|
||||||
};
|
};
|
||||||
const VkRenderPassCreateInfo rp_info = {
|
|
||||||
/*sTyp*/ VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
|
uint32_t view_masks = 1;
|
||||||
|
const VkRenderPassCreateInfo2KHR rp_info = {
|
||||||
|
/*sType*/ VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2_KHR,
|
||||||
/*pNext*/ nullptr,
|
/*pNext*/ nullptr,
|
||||||
/*flags*/ 0,
|
/*flags*/ 0,
|
||||||
/*attachmentCount*/ 1,
|
/*attachmentCount*/ 1,
|
||||||
|
@ -1764,9 +1851,11 @@ Error VulkanContext::_update_swap_chain(Window *window) {
|
||||||
/*pSubpasses*/ &subpass,
|
/*pSubpasses*/ &subpass,
|
||||||
/*dependencyCount*/ 0,
|
/*dependencyCount*/ 0,
|
||||||
/*pDependencies*/ nullptr,
|
/*pDependencies*/ nullptr,
|
||||||
|
/*correlatedViewMaskCount*/ 1,
|
||||||
|
/*pCorrelatedViewMasks*/ &view_masks,
|
||||||
};
|
};
|
||||||
|
|
||||||
err = vkCreateRenderPass(device, &rp_info, nullptr, &window->render_pass);
|
err = vkCreateRenderPass2KHR(device, &rp_info, nullptr, &window->render_pass);
|
||||||
ERR_FAIL_COND_V(err, ERR_CANT_CREATE);
|
ERR_FAIL_COND_V(err, ERR_CANT_CREATE);
|
||||||
|
|
||||||
for (uint32_t i = 0; i < swapchainImageCount; i++) {
|
for (uint32_t i = 0; i < swapchainImageCount; i++) {
|
||||||
|
|
|
@ -69,6 +69,15 @@ public:
|
||||||
uint32_t max_instance_count;
|
uint32_t max_instance_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct VRSCapabilities {
|
||||||
|
bool pipeline_vrs_supported; // We can specify our fragment rate on a pipeline level
|
||||||
|
bool primitive_vrs_supported; // We can specify our fragment rate on each drawcall
|
||||||
|
bool attachment_vrs_supported; // We can provide a density map attachment on our framebuffer
|
||||||
|
|
||||||
|
Size2i min_texel_size;
|
||||||
|
Size2i max_texel_size;
|
||||||
|
};
|
||||||
|
|
||||||
struct ShaderCapabilities {
|
struct ShaderCapabilities {
|
||||||
bool shader_float16_is_supported;
|
bool shader_float16_is_supported;
|
||||||
bool shader_int8_is_supported;
|
bool shader_int8_is_supported;
|
||||||
|
@ -104,6 +113,7 @@ private:
|
||||||
uint32_t vulkan_patch = 0;
|
uint32_t vulkan_patch = 0;
|
||||||
SubgroupCapabilities subgroup_capabilities;
|
SubgroupCapabilities subgroup_capabilities;
|
||||||
MultiviewCapabilities multiview_capabilities;
|
MultiviewCapabilities multiview_capabilities;
|
||||||
|
VRSCapabilities vrs_capabilities;
|
||||||
ShaderCapabilities shader_capabilities;
|
ShaderCapabilities shader_capabilities;
|
||||||
StorageBufferCapabilities storage_buffer_capabilities;
|
StorageBufferCapabilities storage_buffer_capabilities;
|
||||||
|
|
||||||
|
@ -206,6 +216,7 @@ private:
|
||||||
PFN_vkQueuePresentKHR fpQueuePresentKHR = nullptr;
|
PFN_vkQueuePresentKHR fpQueuePresentKHR = nullptr;
|
||||||
PFN_vkGetRefreshCycleDurationGOOGLE fpGetRefreshCycleDurationGOOGLE = nullptr;
|
PFN_vkGetRefreshCycleDurationGOOGLE fpGetRefreshCycleDurationGOOGLE = nullptr;
|
||||||
PFN_vkGetPastPresentationTimingGOOGLE fpGetPastPresentationTimingGOOGLE = nullptr;
|
PFN_vkGetPastPresentationTimingGOOGLE fpGetPastPresentationTimingGOOGLE = nullptr;
|
||||||
|
PFN_vkCreateRenderPass2KHR fpCreateRenderPass2KHR = nullptr;
|
||||||
|
|
||||||
VkDebugUtilsMessengerEXT dbg_messenger = VK_NULL_HANDLE;
|
VkDebugUtilsMessengerEXT dbg_messenger = VK_NULL_HANDLE;
|
||||||
VkDebugReportCallbackEXT dbg_debug_report = VK_NULL_HANDLE;
|
VkDebugReportCallbackEXT dbg_debug_report = VK_NULL_HANDLE;
|
||||||
|
@ -256,10 +267,14 @@ protected:
|
||||||
Error _get_preferred_validation_layers(uint32_t *count, const char *const **names);
|
Error _get_preferred_validation_layers(uint32_t *count, const char *const **names);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
// Extension calls
|
||||||
|
VkResult vkCreateRenderPass2KHR(VkDevice device, const VkRenderPassCreateInfo2 *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkRenderPass *pRenderPass);
|
||||||
|
|
||||||
uint32_t get_vulkan_major() const { return vulkan_major; };
|
uint32_t get_vulkan_major() const { return vulkan_major; };
|
||||||
uint32_t get_vulkan_minor() const { return vulkan_minor; };
|
uint32_t get_vulkan_minor() const { return vulkan_minor; };
|
||||||
SubgroupCapabilities get_subgroup_capabilities() const { return subgroup_capabilities; };
|
SubgroupCapabilities get_subgroup_capabilities() const { return subgroup_capabilities; };
|
||||||
MultiviewCapabilities get_multiview_capabilities() const { return multiview_capabilities; };
|
MultiviewCapabilities get_multiview_capabilities() const { return multiview_capabilities; };
|
||||||
|
VRSCapabilities get_vrs_capabilities() const { return vrs_capabilities; };
|
||||||
ShaderCapabilities get_shader_capabilities() const { return shader_capabilities; };
|
ShaderCapabilities get_shader_capabilities() const { return shader_capabilities; };
|
||||||
StorageBufferCapabilities get_storage_buffer_capabilities() const { return storage_buffer_capabilities; };
|
StorageBufferCapabilities get_storage_buffer_capabilities() const { return storage_buffer_capabilities; };
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,8 @@
|
||||||
#include <glslang/Public/ShaderLang.h>
|
#include <glslang/Public/ShaderLang.h>
|
||||||
#include <glslang/SPIRV/GlslangToSpv.h>
|
#include <glslang/SPIRV/GlslangToSpv.h>
|
||||||
|
|
||||||
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) {
|
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 *p_render_device) {
|
||||||
|
const RD::Capabilities *capabilities = p_render_device->get_device_capabilities();
|
||||||
Vector<uint8_t> ret;
|
Vector<uint8_t> ret;
|
||||||
|
|
||||||
ERR_FAIL_COND_V(p_language == RenderingDevice::SHADER_LANGUAGE_HLSL, ret);
|
ERR_FAIL_COND_V(p_language == RenderingDevice::SHADER_LANGUAGE_HLSL, ret);
|
||||||
|
@ -58,12 +59,12 @@ static Vector<uint8_t> _compile_shader_glsl(RenderingDevice::ShaderStage p_stage
|
||||||
glslang::EShTargetLanguageVersion TargetVersion = glslang::EShTargetSpv_1_5;
|
glslang::EShTargetLanguageVersion TargetVersion = glslang::EShTargetSpv_1_5;
|
||||||
glslang::TShader::ForbidIncluder includer;
|
glslang::TShader::ForbidIncluder includer;
|
||||||
|
|
||||||
if (p_capabilities->device_family == RenderingDevice::DeviceFamily::DEVICE_VULKAN) {
|
if (capabilities->device_family == RenderingDevice::DeviceFamily::DEVICE_VULKAN) {
|
||||||
if (p_capabilities->version_major == 1 && p_capabilities->version_minor == 0) {
|
if (capabilities->version_major == 1 && capabilities->version_minor == 0) {
|
||||||
ClientVersion = glslang::EShTargetVulkan_1_0;
|
ClientVersion = glslang::EShTargetVulkan_1_0;
|
||||||
TargetVersion = glslang::EShTargetSpv_1_0;
|
TargetVersion = glslang::EShTargetSpv_1_0;
|
||||||
check_subgroup_support = false; // subgroups are not supported in Vulkan 1.0
|
check_subgroup_support = false; // subgroups are not supported in Vulkan 1.0
|
||||||
} else if (p_capabilities->version_major == 1 && p_capabilities->version_minor == 1) {
|
} else if (capabilities->version_major == 1 && capabilities->version_minor == 1) {
|
||||||
ClientVersion = glslang::EShTargetVulkan_1_1;
|
ClientVersion = glslang::EShTargetVulkan_1_1;
|
||||||
TargetVersion = glslang::EShTargetSpv_1_3;
|
TargetVersion = glslang::EShTargetSpv_1_3;
|
||||||
} else {
|
} else {
|
||||||
|
@ -90,34 +91,36 @@ static Vector<uint8_t> _compile_shader_glsl(RenderingDevice::ShaderStage p_stage
|
||||||
if (check_subgroup_support) {
|
if (check_subgroup_support) {
|
||||||
uint32_t stage_bit = 1 << p_stage;
|
uint32_t stage_bit = 1 << p_stage;
|
||||||
|
|
||||||
if ((p_capabilities->subgroup_in_shaders & stage_bit) == stage_bit) {
|
uint32_t subgroup_in_shaders = uint32_t(p_render_device->limit_get(RD::LIMIT_SUBGROUP_IN_SHADERS));
|
||||||
|
uint32_t subgroup_operations = uint32_t(p_render_device->limit_get(RD::LIMIT_SUBGROUP_OPERATIONS));
|
||||||
|
if ((subgroup_in_shaders & stage_bit) == stage_bit) {
|
||||||
// stage supports subgroups
|
// stage supports subgroups
|
||||||
preamble += "#define has_GL_KHR_shader_subgroup_basic 1\n";
|
preamble += "#define has_GL_KHR_shader_subgroup_basic 1\n";
|
||||||
if (p_capabilities->subgroup_operations & RenderingDevice::SUBGROUP_VOTE_BIT) {
|
if (subgroup_operations & RenderingDevice::SUBGROUP_VOTE_BIT) {
|
||||||
preamble += "#define has_GL_KHR_shader_subgroup_vote 1\n";
|
preamble += "#define has_GL_KHR_shader_subgroup_vote 1\n";
|
||||||
}
|
}
|
||||||
if (p_capabilities->subgroup_operations & RenderingDevice::SUBGROUP_ARITHMETIC_BIT) {
|
if (subgroup_operations & RenderingDevice::SUBGROUP_ARITHMETIC_BIT) {
|
||||||
preamble += "#define has_GL_KHR_shader_subgroup_arithmetic 1\n";
|
preamble += "#define has_GL_KHR_shader_subgroup_arithmetic 1\n";
|
||||||
}
|
}
|
||||||
if (p_capabilities->subgroup_operations & RenderingDevice::SUBGROUP_BALLOT_BIT) {
|
if (subgroup_operations & RenderingDevice::SUBGROUP_BALLOT_BIT) {
|
||||||
preamble += "#define has_GL_KHR_shader_subgroup_ballot 1\n";
|
preamble += "#define has_GL_KHR_shader_subgroup_ballot 1\n";
|
||||||
}
|
}
|
||||||
if (p_capabilities->subgroup_operations & RenderingDevice::SUBGROUP_SHUFFLE_BIT) {
|
if (subgroup_operations & RenderingDevice::SUBGROUP_SHUFFLE_BIT) {
|
||||||
preamble += "#define has_GL_KHR_shader_subgroup_shuffle 1\n";
|
preamble += "#define has_GL_KHR_shader_subgroup_shuffle 1\n";
|
||||||
}
|
}
|
||||||
if (p_capabilities->subgroup_operations & RenderingDevice::SUBGROUP_SHUFFLE_RELATIVE_BIT) {
|
if (subgroup_operations & RenderingDevice::SUBGROUP_SHUFFLE_RELATIVE_BIT) {
|
||||||
preamble += "#define has_GL_KHR_shader_subgroup_shuffle_relative 1\n";
|
preamble += "#define has_GL_KHR_shader_subgroup_shuffle_relative 1\n";
|
||||||
}
|
}
|
||||||
if (p_capabilities->subgroup_operations & RenderingDevice::SUBGROUP_CLUSTERED_BIT) {
|
if (subgroup_operations & RenderingDevice::SUBGROUP_CLUSTERED_BIT) {
|
||||||
preamble += "#define has_GL_KHR_shader_subgroup_clustered 1\n";
|
preamble += "#define has_GL_KHR_shader_subgroup_clustered 1\n";
|
||||||
}
|
}
|
||||||
if (p_capabilities->subgroup_operations & RenderingDevice::SUBGROUP_QUAD_BIT) {
|
if (subgroup_operations & RenderingDevice::SUBGROUP_QUAD_BIT) {
|
||||||
preamble += "#define has_GL_KHR_shader_subgroup_quad 1\n";
|
preamble += "#define has_GL_KHR_shader_subgroup_quad 1\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p_capabilities->supports_multiview) {
|
if (p_render_device->has_feature(RD::SUPPORTS_MULTIVIEW)) {
|
||||||
preamble += "#define has_VK_KHR_multiview 1\n";
|
preamble += "#define has_VK_KHR_multiview 1\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,9 +187,10 @@ static Vector<uint8_t> _compile_shader_glsl(RenderingDevice::ShaderStage p_stage
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static String _get_cache_key_function_glsl(const RenderingDevice::Capabilities *p_capabilities) {
|
static String _get_cache_key_function_glsl(const RenderingDevice *p_render_device) {
|
||||||
|
const RD::Capabilities *capabilities = p_render_device->get_device_capabilities();
|
||||||
String version;
|
String version;
|
||||||
version = "SpirVGen=" + itos(glslang::GetSpirvGeneratorVersion()) + ", major=" + itos(p_capabilities->version_major) + ", minor=" + itos(p_capabilities->version_minor) + " , subgroup_size=" + itos(p_capabilities->subgroup_operations) + " , subgroup_ops=" + itos(p_capabilities->subgroup_operations) + " , subgroup_in_shaders=" + itos(p_capabilities->subgroup_in_shaders);
|
version = "SpirVGen=" + itos(glslang::GetSpirvGeneratorVersion()) + ", major=" + itos(capabilities->version_major) + ", minor=" + itos(capabilities->version_minor) + " , subgroup_size=" + itos(p_render_device->limit_get(RD::LIMIT_SUBGROUP_SIZE)) + " , subgroup_ops=" + itos(p_render_device->limit_get(RD::LIMIT_SUBGROUP_OPERATIONS)) + " , subgroup_in_shaders=" + itos(p_render_device->limit_get(RD::LIMIT_SUBGROUP_IN_SHADERS));
|
||||||
return version;
|
return version;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
#include "core/debugger/engine_debugger.h"
|
#include "core/debugger/engine_debugger.h"
|
||||||
#include "core/input/input.h"
|
#include "core/input/input.h"
|
||||||
#include "core/io/dir_access.h"
|
#include "core/io/dir_access.h"
|
||||||
|
#include "core/io/image_loader.h"
|
||||||
#include "core/io/marshalls.h"
|
#include "core/io/marshalls.h"
|
||||||
#include "core/io/resource_loader.h"
|
#include "core/io/resource_loader.h"
|
||||||
#include "core/multiplayer/multiplayer_api.h"
|
#include "core/multiplayer/multiplayer_api.h"
|
||||||
|
@ -1446,6 +1447,29 @@ SceneTree::SceneTree() {
|
||||||
bool snap_2d_vertices = GLOBAL_DEF("rendering/2d/snap/snap_2d_vertices_to_pixel", false);
|
bool snap_2d_vertices = GLOBAL_DEF("rendering/2d/snap/snap_2d_vertices_to_pixel", false);
|
||||||
root->set_snap_2d_vertices_to_pixel(snap_2d_vertices);
|
root->set_snap_2d_vertices_to_pixel(snap_2d_vertices);
|
||||||
|
|
||||||
|
// We setup VRS for the main viewport here, in the editor this will have little effect.
|
||||||
|
const int vrs_mode = GLOBAL_DEF("rendering/vrs/mode", 0);
|
||||||
|
ProjectSettings::get_singleton()->set_custom_property_info("rendering/vrs/mode", PropertyInfo(Variant::INT, "rendering/vrs/mode", PROPERTY_HINT_ENUM, String::utf8("Disabled,Texture,XR")));
|
||||||
|
root->set_vrs_mode(Viewport::VRSMode(vrs_mode));
|
||||||
|
const String vrs_texture_path = String(GLOBAL_DEF("rendering/vrs/texture", String())).strip_edges();
|
||||||
|
ProjectSettings::get_singleton()->set_custom_property_info("rendering/vrs/texture",
|
||||||
|
PropertyInfo(Variant::STRING,
|
||||||
|
"rendering/vrs/texture",
|
||||||
|
PROPERTY_HINT_FILE, "*.png"));
|
||||||
|
if (vrs_mode == 1 && !vrs_texture_path.is_empty()) {
|
||||||
|
Ref<Image> vrs_image;
|
||||||
|
vrs_image.instantiate();
|
||||||
|
Error load_err = ImageLoader::load_image(vrs_texture_path, vrs_image);
|
||||||
|
if (load_err) {
|
||||||
|
ERR_PRINT("Non-existing or invalid VRS texture at '" + vrs_texture_path + "'.");
|
||||||
|
} else {
|
||||||
|
Ref<ImageTexture> vrs_texture;
|
||||||
|
vrs_texture.instantiate();
|
||||||
|
vrs_texture->create_from_image(vrs_image);
|
||||||
|
root->set_vrs_texture(vrs_texture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int shadowmap_size = GLOBAL_DEF("rendering/shadows/positional_shadow/atlas_size", 4096);
|
int shadowmap_size = GLOBAL_DEF("rendering/shadows/positional_shadow/atlas_size", 4096);
|
||||||
ProjectSettings::get_singleton()->set_custom_property_info("rendering/shadows/positional_shadow/atlas_size", PropertyInfo(Variant::INT, "rendering/shadows/positional_shadow/atlas_size", PROPERTY_HINT_RANGE, "256,16384"));
|
ProjectSettings::get_singleton()->set_custom_property_info("rendering/shadows/positional_shadow/atlas_size", PropertyInfo(Variant::INT, "rendering/shadows/positional_shadow/atlas_size", PROPERTY_HINT_RANGE, "256,16384"));
|
||||||
GLOBAL_DEF("rendering/shadows/positional_shadow/atlas_size.mobile", 2048);
|
GLOBAL_DEF("rendering/shadows/positional_shadow/atlas_size.mobile", 2048);
|
||||||
|
|
|
@ -3080,6 +3080,41 @@ Viewport::DefaultCanvasItemTextureRepeat Viewport::get_default_canvas_item_textu
|
||||||
return default_canvas_item_texture_repeat;
|
return default_canvas_item_texture_repeat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Viewport::set_vrs_mode(Viewport::VRSMode p_vrs_mode) {
|
||||||
|
// Note, set this even if not supported on this hardware, it will only be used if it is but we want to save the value as set by the user.
|
||||||
|
vrs_mode = p_vrs_mode;
|
||||||
|
|
||||||
|
switch (p_vrs_mode) {
|
||||||
|
case VRS_TEXTURE: {
|
||||||
|
RS::get_singleton()->viewport_set_vrs_mode(viewport, RS::VIEWPORT_VRS_TEXTURE);
|
||||||
|
} break;
|
||||||
|
case VRS_XR: {
|
||||||
|
RS::get_singleton()->viewport_set_vrs_mode(viewport, RS::VIEWPORT_VRS_XR);
|
||||||
|
} break;
|
||||||
|
default: {
|
||||||
|
RS::get_singleton()->viewport_set_vrs_mode(viewport, RS::VIEWPORT_VRS_DISABLED);
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
|
||||||
|
notify_property_list_changed();
|
||||||
|
}
|
||||||
|
|
||||||
|
Viewport::VRSMode Viewport::get_vrs_mode() const {
|
||||||
|
return vrs_mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Viewport::set_vrs_texture(Ref<Texture2D> p_texture) {
|
||||||
|
vrs_texture = p_texture;
|
||||||
|
|
||||||
|
// TODO need to add something here in case the RID changes
|
||||||
|
RID tex = p_texture.is_valid() ? p_texture->get_rid() : RID();
|
||||||
|
RS::get_singleton()->viewport_set_vrs_texture(viewport, tex);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ref<Texture2D> Viewport::get_vrs_texture() const {
|
||||||
|
return vrs_texture;
|
||||||
|
}
|
||||||
|
|
||||||
DisplayServer::WindowID Viewport::get_window_id() const {
|
DisplayServer::WindowID Viewport::get_window_id() const {
|
||||||
return DisplayServer::MAIN_WINDOW_ID;
|
return DisplayServer::MAIN_WINDOW_ID;
|
||||||
}
|
}
|
||||||
|
@ -3741,6 +3776,12 @@ void Viewport::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("set_fsr_mipmap_bias", "fsr_mipmap_bias"), &Viewport::set_fsr_mipmap_bias);
|
ClassDB::bind_method(D_METHOD("set_fsr_mipmap_bias", "fsr_mipmap_bias"), &Viewport::set_fsr_mipmap_bias);
|
||||||
ClassDB::bind_method(D_METHOD("get_fsr_mipmap_bias"), &Viewport::get_fsr_mipmap_bias);
|
ClassDB::bind_method(D_METHOD("get_fsr_mipmap_bias"), &Viewport::get_fsr_mipmap_bias);
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("set_vrs_mode", "mode"), &Viewport::set_vrs_mode);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_vrs_mode"), &Viewport::get_vrs_mode);
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("set_vrs_texture", "texture"), &Viewport::set_vrs_texture);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_vrs_texture"), &Viewport::get_vrs_texture);
|
||||||
|
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "disable_3d"), "set_disable_3d", "is_3d_disabled");
|
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "disable_3d"), "set_disable_3d", "is_3d_disabled");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_xr"), "set_use_xr", "is_using_xr");
|
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_xr"), "set_use_xr", "is_using_xr");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "own_world_3d"), "set_use_own_world_3d", "is_using_own_world_3d");
|
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "own_world_3d"), "set_use_own_world_3d", "is_using_own_world_3d");
|
||||||
|
@ -3766,6 +3807,9 @@ void Viewport::_bind_methods() {
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fsr_mipmap_bias", PROPERTY_HINT_RANGE, "-2,2,0.1"), "set_fsr_mipmap_bias", "get_fsr_mipmap_bias");
|
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fsr_mipmap_bias", PROPERTY_HINT_RANGE, "-2,2,0.1"), "set_fsr_mipmap_bias", "get_fsr_mipmap_bias");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fsr_sharpness", PROPERTY_HINT_RANGE, "0,2,0.1"), "set_fsr_sharpness", "get_fsr_sharpness");
|
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fsr_sharpness", PROPERTY_HINT_RANGE, "0,2,0.1"), "set_fsr_sharpness", "get_fsr_sharpness");
|
||||||
#endif
|
#endif
|
||||||
|
ADD_GROUP("Variable Rate Shading", "vrs_");
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "vrs_mode", PROPERTY_HINT_ENUM, "Disabled,Texture,Depth buffer,XR"), "set_vrs_mode", "get_vrs_mode");
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "vrs_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_vrs_texture", "get_vrs_texture");
|
||||||
ADD_GROUP("Canvas Items", "canvas_item_");
|
ADD_GROUP("Canvas Items", "canvas_item_");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "canvas_item_default_texture_filter", PROPERTY_HINT_ENUM, "Nearest,Linear,Linear Mipmap,Nearest Mipmap"), "set_default_canvas_item_texture_filter", "get_default_canvas_item_texture_filter");
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "canvas_item_default_texture_filter", PROPERTY_HINT_ENUM, "Nearest,Linear,Linear Mipmap,Nearest Mipmap"), "set_default_canvas_item_texture_filter", "get_default_canvas_item_texture_filter");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "canvas_item_default_texture_repeat", PROPERTY_HINT_ENUM, "Disabled,Enabled,Mirror"), "set_default_canvas_item_texture_repeat", "get_default_canvas_item_texture_repeat");
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "canvas_item_default_texture_repeat", PROPERTY_HINT_ENUM, "Disabled,Enabled,Mirror"), "set_default_canvas_item_texture_repeat", "get_default_canvas_item_texture_repeat");
|
||||||
|
@ -3876,6 +3920,17 @@ void Viewport::_bind_methods() {
|
||||||
BIND_ENUM_CONSTANT(SDF_SCALE_50_PERCENT);
|
BIND_ENUM_CONSTANT(SDF_SCALE_50_PERCENT);
|
||||||
BIND_ENUM_CONSTANT(SDF_SCALE_25_PERCENT);
|
BIND_ENUM_CONSTANT(SDF_SCALE_25_PERCENT);
|
||||||
BIND_ENUM_CONSTANT(SDF_SCALE_MAX);
|
BIND_ENUM_CONSTANT(SDF_SCALE_MAX);
|
||||||
|
|
||||||
|
BIND_ENUM_CONSTANT(VRS_DISABLED);
|
||||||
|
BIND_ENUM_CONSTANT(VRS_TEXTURE);
|
||||||
|
BIND_ENUM_CONSTANT(VRS_XR);
|
||||||
|
BIND_ENUM_CONSTANT(VRS_MAX);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Viewport::_validate_property(PropertyInfo &property) const {
|
||||||
|
if (vrs_mode != VRS_TEXTURE && (property.name == "vrs_texture")) {
|
||||||
|
property.usage = PROPERTY_USAGE_NO_EDITOR;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Viewport::Viewport() {
|
Viewport::Viewport() {
|
||||||
|
|
|
@ -197,6 +197,13 @@ public:
|
||||||
SUBWINDOW_CANVAS_LAYER = 1024
|
SUBWINDOW_CANVAS_LAYER = 1024
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum VRSMode {
|
||||||
|
VRS_DISABLED,
|
||||||
|
VRS_TEXTURE,
|
||||||
|
VRS_XR,
|
||||||
|
VRS_MAX
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class ViewportTexture;
|
friend class ViewportTexture;
|
||||||
|
|
||||||
|
@ -333,6 +340,10 @@ private:
|
||||||
RID canvas_item;
|
RID canvas_item;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// VRS
|
||||||
|
VRSMode vrs_mode = VRS_DISABLED;
|
||||||
|
Ref<Texture2D> vrs_texture;
|
||||||
|
|
||||||
struct GUI {
|
struct GUI {
|
||||||
// info used when this is a window
|
// info used when this is a window
|
||||||
|
|
||||||
|
@ -604,6 +615,14 @@ public:
|
||||||
void set_default_canvas_item_texture_repeat(DefaultCanvasItemTextureRepeat p_repeat);
|
void set_default_canvas_item_texture_repeat(DefaultCanvasItemTextureRepeat p_repeat);
|
||||||
DefaultCanvasItemTextureRepeat get_default_canvas_item_texture_repeat() const;
|
DefaultCanvasItemTextureRepeat get_default_canvas_item_texture_repeat() const;
|
||||||
|
|
||||||
|
// VRS
|
||||||
|
|
||||||
|
void set_vrs_mode(VRSMode p_vrs_mode);
|
||||||
|
VRSMode get_vrs_mode() const;
|
||||||
|
|
||||||
|
void set_vrs_texture(Ref<Texture2D> p_texture);
|
||||||
|
Ref<Texture2D> get_vrs_texture() const;
|
||||||
|
|
||||||
virtual DisplayServer::WindowID get_window_id() const = 0;
|
virtual DisplayServer::WindowID get_window_id() const = 0;
|
||||||
|
|
||||||
void set_embedding_subwindows(bool p_embed);
|
void set_embedding_subwindows(bool p_embed);
|
||||||
|
@ -690,6 +709,7 @@ public:
|
||||||
bool is_using_xr();
|
bool is_using_xr();
|
||||||
#endif // _3D_DISABLED
|
#endif // _3D_DISABLED
|
||||||
|
|
||||||
|
virtual void _validate_property(PropertyInfo &property) const override;
|
||||||
Viewport();
|
Viewport();
|
||||||
~Viewport();
|
~Viewport();
|
||||||
};
|
};
|
||||||
|
@ -752,6 +772,7 @@ VARIANT_ENUM_CAST(Viewport::ScreenSpaceAA);
|
||||||
VARIANT_ENUM_CAST(Viewport::DebugDraw);
|
VARIANT_ENUM_CAST(Viewport::DebugDraw);
|
||||||
VARIANT_ENUM_CAST(Viewport::SDFScale);
|
VARIANT_ENUM_CAST(Viewport::SDFScale);
|
||||||
VARIANT_ENUM_CAST(Viewport::SDFOversize);
|
VARIANT_ENUM_CAST(Viewport::SDFOversize);
|
||||||
|
VARIANT_ENUM_CAST(Viewport::VRSMode);
|
||||||
VARIANT_ENUM_CAST(SubViewport::ClearMode);
|
VARIANT_ENUM_CAST(SubViewport::ClearMode);
|
||||||
VARIANT_ENUM_CAST(Viewport::RenderInfo);
|
VARIANT_ENUM_CAST(Viewport::RenderInfo);
|
||||||
VARIANT_ENUM_CAST(Viewport::RenderInfoType);
|
VARIANT_ENUM_CAST(Viewport::RenderInfoType);
|
||||||
|
|
|
@ -169,6 +169,9 @@ public:
|
||||||
virtual void render_target_set_sdf_size_and_scale(RID p_render_target, RS::ViewportSDFOversize p_size, RS::ViewportSDFScale p_scale) override {}
|
virtual void render_target_set_sdf_size_and_scale(RID p_render_target, RS::ViewportSDFOversize p_size, RS::ViewportSDFScale p_scale) override {}
|
||||||
virtual Rect2i render_target_get_sdf_rect(RID p_render_target) const override { return Rect2i(); }
|
virtual Rect2i render_target_get_sdf_rect(RID p_render_target) const override { return Rect2i(); }
|
||||||
virtual void render_target_mark_sdf_enabled(RID p_render_target, bool p_enabled) override {}
|
virtual void render_target_mark_sdf_enabled(RID p_render_target, bool p_enabled) override {}
|
||||||
|
|
||||||
|
virtual void render_target_set_vrs_mode(RID p_render_target, RS::ViewportVRSMode p_mode) override{};
|
||||||
|
virtual void render_target_set_vrs_texture(RID p_render_target, RID p_texture) override{};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace RendererDummy
|
} // namespace RendererDummy
|
||||||
|
|
|
@ -100,11 +100,11 @@ CopyEffects::CopyEffects(bool p_prefer_raster_effects) {
|
||||||
|
|
||||||
{
|
{
|
||||||
Vector<String> copy_modes;
|
Vector<String> copy_modes;
|
||||||
copy_modes.push_back("\n");
|
copy_modes.push_back("\n"); // COPY_TO_FB_COPY
|
||||||
copy_modes.push_back("\n#define MODE_PANORAMA_TO_DP\n");
|
copy_modes.push_back("\n#define MODE_PANORAMA_TO_DP\n"); // COPY_TO_FB_COPY_PANORAMA_TO_DP
|
||||||
copy_modes.push_back("\n#define MODE_TWO_SOURCES\n");
|
copy_modes.push_back("\n#define MODE_TWO_SOURCES\n"); // COPY_TO_FB_COPY2
|
||||||
copy_modes.push_back("\n#define MULTIVIEW\n");
|
copy_modes.push_back("\n#define MULTIVIEW\n"); // COPY_TO_FB_MULTIVIEW
|
||||||
copy_modes.push_back("\n#define MULTIVIEW\n#define MODE_TWO_SOURCES\n");
|
copy_modes.push_back("\n#define MULTIVIEW\n#define MODE_TWO_SOURCES\n"); // COPY_TO_FB_MULTIVIEW_WITH_DEPTH
|
||||||
|
|
||||||
copy_to_fb.shader.initialize(copy_modes);
|
copy_to_fb.shader.initialize(copy_modes);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,171 @@
|
||||||
|
/*************************************************************************/
|
||||||
|
/* vrs.cpp */
|
||||||
|
/*************************************************************************/
|
||||||
|
/* This file is part of: */
|
||||||
|
/* GODOT ENGINE */
|
||||||
|
/* https://godotengine.org */
|
||||||
|
/*************************************************************************/
|
||||||
|
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||||
|
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||||
|
/* */
|
||||||
|
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||||
|
/* a copy of this software and associated documentation files (the */
|
||||||
|
/* "Software"), to deal in the Software without restriction, including */
|
||||||
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||||
|
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||||
|
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||||
|
/* the following conditions: */
|
||||||
|
/* */
|
||||||
|
/* The above copyright notice and this permission notice shall be */
|
||||||
|
/* included in all copies or substantial portions of the Software. */
|
||||||
|
/* */
|
||||||
|
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||||
|
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||||
|
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||||
|
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||||
|
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||||
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||||
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
/*************************************************************************/
|
||||||
|
|
||||||
|
#include "vrs.h"
|
||||||
|
#include "../renderer_compositor_rd.h"
|
||||||
|
#include "../storage_rd/texture_storage.h"
|
||||||
|
#include "../uniform_set_cache_rd.h"
|
||||||
|
#include "servers/xr_server.h"
|
||||||
|
|
||||||
|
using namespace RendererRD;
|
||||||
|
|
||||||
|
VRS::VRS() {
|
||||||
|
{
|
||||||
|
Vector<String> vrs_modes;
|
||||||
|
vrs_modes.push_back("\n"); // VRS_DEFAULT
|
||||||
|
vrs_modes.push_back("\n#define MULTIVIEW\n"); // VRS_MULTIVIEW
|
||||||
|
|
||||||
|
vrs_shader.shader.initialize(vrs_modes);
|
||||||
|
|
||||||
|
if (!RendererCompositorRD::singleton->is_xr_enabled()) {
|
||||||
|
vrs_shader.shader.set_variant_enabled(VRS_MULTIVIEW, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
vrs_shader.shader_version = vrs_shader.shader.version_create();
|
||||||
|
|
||||||
|
//use additive
|
||||||
|
|
||||||
|
for (int i = 0; i < VRS_MAX; i++) {
|
||||||
|
if (vrs_shader.shader.is_variant_enabled(i)) {
|
||||||
|
vrs_shader.pipelines[i].setup(vrs_shader.shader.version_get_shader(vrs_shader.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0);
|
||||||
|
} else {
|
||||||
|
vrs_shader.pipelines[i].clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VRS::~VRS() {
|
||||||
|
vrs_shader.shader.version_free(vrs_shader.shader_version);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VRS::copy_vrs(RID p_source_rd_texture, RID p_dest_framebuffer, bool p_multiview) {
|
||||||
|
UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
|
||||||
|
ERR_FAIL_NULL(uniform_set_cache);
|
||||||
|
MaterialStorage *material_storage = MaterialStorage::get_singleton();
|
||||||
|
ERR_FAIL_NULL(material_storage);
|
||||||
|
|
||||||
|
// setup our uniforms
|
||||||
|
RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
|
||||||
|
|
||||||
|
RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture }));
|
||||||
|
|
||||||
|
VRSMode mode = p_multiview ? VRS_MULTIVIEW : VRS_DEFAULT;
|
||||||
|
|
||||||
|
RID shader = vrs_shader.shader.version_get_shader(vrs_shader.shader_version, mode);
|
||||||
|
ERR_FAIL_COND(shader.is_null());
|
||||||
|
|
||||||
|
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD, Vector<Color>());
|
||||||
|
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, vrs_shader.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
|
||||||
|
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
|
||||||
|
RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
|
||||||
|
// RD::get_singleton()->draw_list_set_push_constant(draw_list, &vrs_shader.push_constant, sizeof(VRSPushConstant));
|
||||||
|
RD::get_singleton()->draw_list_draw(draw_list, true);
|
||||||
|
RD::get_singleton()->draw_list_end();
|
||||||
|
}
|
||||||
|
|
||||||
|
void VRS::create_vrs_texture(const int p_base_width, const int p_base_height, const uint32_t p_view_count, RID &p_vrs_texture, RID &p_vrs_fb) {
|
||||||
|
// TODO find a way to skip this if VRS is not supported, but we don't have access to VulkanContext here, even though we're in vulkan.. hmmm
|
||||||
|
|
||||||
|
// TODO we should find some way to store this properly, we're assuming 16x16 as this seems to be the standard but in our vrs_capacities we
|
||||||
|
// obtain a minimum and maximum size, and we should choose something within this range and then make sure that is consistantly set when creating
|
||||||
|
// our frame buffer. Also it is important that we make the resulting size we calculate down below available to the end user so they know the size
|
||||||
|
// of the VRS buffer to supply.
|
||||||
|
Size2i texel_size = Size2i(16, 16);
|
||||||
|
|
||||||
|
RD::TextureFormat tf;
|
||||||
|
if (p_view_count > 1) {
|
||||||
|
tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
|
||||||
|
} else {
|
||||||
|
tf.texture_type = RD::TEXTURE_TYPE_2D;
|
||||||
|
}
|
||||||
|
tf.format = RD::DATA_FORMAT_R8_UINT;
|
||||||
|
tf.width = p_base_width / texel_size.x;
|
||||||
|
if (p_base_width % texel_size.x != 0) {
|
||||||
|
tf.width++;
|
||||||
|
}
|
||||||
|
tf.height = p_base_height / texel_size.y;
|
||||||
|
if (p_base_height % texel_size.y != 0) {
|
||||||
|
tf.height++;
|
||||||
|
}
|
||||||
|
tf.array_layers = p_view_count; // create a layer for every view
|
||||||
|
tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_VRS_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
|
||||||
|
tf.samples = RD::TEXTURE_SAMPLES_1;
|
||||||
|
|
||||||
|
p_vrs_texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
|
||||||
|
|
||||||
|
// by default VRS is assumed to be our VRS attachment, but if we need to write into it, we need a bit more control
|
||||||
|
Vector<RID> fb;
|
||||||
|
fb.push_back(p_vrs_texture);
|
||||||
|
|
||||||
|
RD::FramebufferPass pass;
|
||||||
|
pass.color_attachments.push_back(0);
|
||||||
|
|
||||||
|
Vector<RD::FramebufferPass> passes;
|
||||||
|
passes.push_back(pass);
|
||||||
|
|
||||||
|
p_vrs_fb = RD::get_singleton()->framebuffer_create_multipass(fb, passes, RenderingDevice::INVALID_ID, p_view_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VRS::update_vrs_texture(RID p_vrs_fb, RID p_render_target) {
|
||||||
|
TextureStorage *texture_storage = TextureStorage::get_singleton();
|
||||||
|
RS::ViewportVRSMode vrs_mode = texture_storage->render_target_get_vrs_mode(p_render_target);
|
||||||
|
|
||||||
|
if (vrs_mode != RS::VIEWPORT_VRS_DISABLED) {
|
||||||
|
RD::get_singleton()->draw_command_begin_label("VRS Setup");
|
||||||
|
|
||||||
|
// TODO figure out if image has changed since it was last copied so we can save some resources..
|
||||||
|
|
||||||
|
if (vrs_mode == RS::VIEWPORT_VRS_TEXTURE) {
|
||||||
|
RID vrs_texture = texture_storage->render_target_get_vrs_texture(p_render_target);
|
||||||
|
if (vrs_texture.is_valid()) {
|
||||||
|
Texture *texture = texture_storage->get_texture(vrs_texture);
|
||||||
|
if (texture) {
|
||||||
|
// Copy into our density buffer
|
||||||
|
copy_vrs(texture->rd_texture, p_vrs_fb, texture->layers > 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (vrs_mode == RS::VIEWPORT_VRS_XR) {
|
||||||
|
Ref<XRInterface> interface = XRServer::get_singleton()->get_primary_interface();
|
||||||
|
if (interface.is_valid()) {
|
||||||
|
RID vrs_texture = interface->get_vrs_texture();
|
||||||
|
if (vrs_texture.is_valid()) {
|
||||||
|
Texture *texture = texture_storage->get_texture(vrs_texture);
|
||||||
|
if (texture) {
|
||||||
|
// Copy into our density buffer
|
||||||
|
copy_vrs(texture->rd_texture, p_vrs_fb, texture->layers > 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RD::get_singleton()->draw_command_end_label();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,75 @@
|
||||||
|
/*************************************************************************/
|
||||||
|
/* vrs.h */
|
||||||
|
/*************************************************************************/
|
||||||
|
/* This file is part of: */
|
||||||
|
/* GODOT ENGINE */
|
||||||
|
/* https://godotengine.org */
|
||||||
|
/*************************************************************************/
|
||||||
|
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||||
|
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||||
|
/* */
|
||||||
|
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||||
|
/* a copy of this software and associated documentation files (the */
|
||||||
|
/* "Software"), to deal in the Software without restriction, including */
|
||||||
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||||
|
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||||
|
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||||
|
/* the following conditions: */
|
||||||
|
/* */
|
||||||
|
/* The above copyright notice and this permission notice shall be */
|
||||||
|
/* included in all copies or substantial portions of the Software. */
|
||||||
|
/* */
|
||||||
|
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||||
|
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||||
|
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||||
|
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||||
|
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||||
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||||
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
/*************************************************************************/
|
||||||
|
|
||||||
|
#ifndef VRS_RD_H
|
||||||
|
#define VRS_RD_H
|
||||||
|
|
||||||
|
#include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
|
||||||
|
#include "servers/rendering/renderer_rd/shaders/effects/vrs.glsl.gen.h"
|
||||||
|
#include "servers/rendering/renderer_scene_render.h"
|
||||||
|
|
||||||
|
#include "servers/rendering_server.h"
|
||||||
|
|
||||||
|
namespace RendererRD {
|
||||||
|
|
||||||
|
class VRS {
|
||||||
|
private:
|
||||||
|
enum VRSMode {
|
||||||
|
VRS_DEFAULT,
|
||||||
|
VRS_MULTIVIEW,
|
||||||
|
VRS_MAX,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* we have no push constant here (yet)
|
||||||
|
struct VRSPushConstant {
|
||||||
|
|
||||||
|
};
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct VRSShader {
|
||||||
|
// VRSPushConstant push_constant;
|
||||||
|
VrsShaderRD shader;
|
||||||
|
RID shader_version;
|
||||||
|
PipelineCacheRD pipelines[VRS_MAX];
|
||||||
|
} vrs_shader;
|
||||||
|
|
||||||
|
public:
|
||||||
|
VRS();
|
||||||
|
~VRS();
|
||||||
|
|
||||||
|
void copy_vrs(RID p_source_rd_texture, RID p_dest_framebuffer, bool p_multiview = false);
|
||||||
|
|
||||||
|
void create_vrs_texture(const int p_base_width, const int p_base_height, const uint32_t p_view_count, RID &p_vrs_texture, RID &p_vrs_fb);
|
||||||
|
void update_vrs_texture(RID p_vrs_fb, RID p_render_target);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace RendererRD
|
||||||
|
|
||||||
|
#endif // !VRS_RD_H
|
|
@ -1309,7 +1309,7 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) {
|
||||||
FSR_upscale_modes.push_back("\n#define MODE_FSR_UPSCALE_FALLBACK\n");
|
FSR_upscale_modes.push_back("\n#define MODE_FSR_UPSCALE_FALLBACK\n");
|
||||||
#else
|
#else
|
||||||
// Everyone else can use normal mode when available.
|
// Everyone else can use normal mode when available.
|
||||||
if (RD::get_singleton()->get_device_capabilities()->supports_fsr_half_float) {
|
if (RD::get_singleton()->has_feature(RD::SUPPORTS_FSR_HALF_FLOAT)) {
|
||||||
FSR_upscale_modes.push_back("\n#define MODE_FSR_UPSCALE_NORMAL\n");
|
FSR_upscale_modes.push_back("\n#define MODE_FSR_UPSCALE_NORMAL\n");
|
||||||
} else {
|
} else {
|
||||||
FSR_upscale_modes.push_back("\n#define MODE_FSR_UPSCALE_FALLBACK\n");
|
FSR_upscale_modes.push_back("\n#define MODE_FSR_UPSCALE_FALLBACK\n");
|
||||||
|
|
|
@ -109,6 +109,7 @@ void GI::voxel_gi_allocate_data(RID p_voxel_gi, const Transform3D &p_to_cell_xfo
|
||||||
Vector<Vector<uint8_t>> s;
|
Vector<Vector<uint8_t>> s;
|
||||||
s.push_back(p_distance_field);
|
s.push_back(p_distance_field);
|
||||||
voxel_gi->sdf_texture = RD::get_singleton()->texture_create(tf, RD::TextureView(), s);
|
voxel_gi->sdf_texture = RD::get_singleton()->texture_create(tf, RD::TextureView(), s);
|
||||||
|
RD::get_singleton()->set_resource_name(voxel_gi->sdf_texture, "VoxelGI SDF Texture");
|
||||||
}
|
}
|
||||||
#if 0
|
#if 0
|
||||||
{
|
{
|
||||||
|
@ -122,6 +123,7 @@ void GI::voxel_gi_allocate_data(RID p_voxel_gi, const Transform3D &p_to_cell_xfo
|
||||||
tf.shareable_formats.push_back(RD::DATA_FORMAT_R8_UNORM);
|
tf.shareable_formats.push_back(RD::DATA_FORMAT_R8_UNORM);
|
||||||
tf.shareable_formats.push_back(RD::DATA_FORMAT_R8_UINT);
|
tf.shareable_formats.push_back(RD::DATA_FORMAT_R8_UINT);
|
||||||
voxel_gi->sdf_texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
|
voxel_gi->sdf_texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
|
||||||
|
RD::get_singleton()->set_resource_name(voxel_gi->sdf_texture, "VoxelGI SDF Texture");
|
||||||
}
|
}
|
||||||
RID shared_tex;
|
RID shared_tex;
|
||||||
{
|
{
|
||||||
|
@ -402,29 +404,38 @@ void GI::SDFGI::create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world
|
||||||
RD::TextureFormat tf_render = tf_sdf;
|
RD::TextureFormat tf_render = tf_sdf;
|
||||||
tf_render.format = RD::DATA_FORMAT_R16_UINT;
|
tf_render.format = RD::DATA_FORMAT_R16_UINT;
|
||||||
render_albedo = RD::get_singleton()->texture_create(tf_render, RD::TextureView());
|
render_albedo = RD::get_singleton()->texture_create(tf_render, RD::TextureView());
|
||||||
|
RD::get_singleton()->set_resource_name(render_albedo, "VoxelGI Render Albedo");
|
||||||
tf_render.format = RD::DATA_FORMAT_R32_UINT;
|
tf_render.format = RD::DATA_FORMAT_R32_UINT;
|
||||||
render_emission = RD::get_singleton()->texture_create(tf_render, RD::TextureView());
|
render_emission = RD::get_singleton()->texture_create(tf_render, RD::TextureView());
|
||||||
|
RD::get_singleton()->set_resource_name(render_emission, "VoxelGI Render Emission");
|
||||||
render_emission_aniso = RD::get_singleton()->texture_create(tf_render, RD::TextureView());
|
render_emission_aniso = RD::get_singleton()->texture_create(tf_render, RD::TextureView());
|
||||||
|
RD::get_singleton()->set_resource_name(render_emission_aniso, "VoxelGI Render Emission Aniso");
|
||||||
|
|
||||||
tf_render.format = RD::DATA_FORMAT_R8_UNORM; //at least its easy to visualize
|
tf_render.format = RD::DATA_FORMAT_R8_UNORM; //at least its easy to visualize
|
||||||
|
|
||||||
for (int i = 0; i < 8; i++) {
|
for (int i = 0; i < 8; i++) {
|
||||||
render_occlusion[i] = RD::get_singleton()->texture_create(tf_render, RD::TextureView());
|
render_occlusion[i] = RD::get_singleton()->texture_create(tf_render, RD::TextureView());
|
||||||
|
RD::get_singleton()->set_resource_name(render_occlusion[i], String("VoxelGI Render Occlusion ") + itos(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
tf_render.format = RD::DATA_FORMAT_R32_UINT;
|
tf_render.format = RD::DATA_FORMAT_R32_UINT;
|
||||||
render_geom_facing = RD::get_singleton()->texture_create(tf_render, RD::TextureView());
|
render_geom_facing = RD::get_singleton()->texture_create(tf_render, RD::TextureView());
|
||||||
|
RD::get_singleton()->set_resource_name(render_geom_facing, "VoxelGI Render Geometry Facing");
|
||||||
|
|
||||||
tf_render.format = RD::DATA_FORMAT_R8G8B8A8_UINT;
|
tf_render.format = RD::DATA_FORMAT_R8G8B8A8_UINT;
|
||||||
render_sdf[0] = RD::get_singleton()->texture_create(tf_render, RD::TextureView());
|
render_sdf[0] = RD::get_singleton()->texture_create(tf_render, RD::TextureView());
|
||||||
|
RD::get_singleton()->set_resource_name(render_sdf[0], "VoxelGI Render SDF 0");
|
||||||
render_sdf[1] = RD::get_singleton()->texture_create(tf_render, RD::TextureView());
|
render_sdf[1] = RD::get_singleton()->texture_create(tf_render, RD::TextureView());
|
||||||
|
RD::get_singleton()->set_resource_name(render_sdf[1], "VoxelGI Render SDF 1");
|
||||||
|
|
||||||
tf_render.width /= 2;
|
tf_render.width /= 2;
|
||||||
tf_render.height /= 2;
|
tf_render.height /= 2;
|
||||||
tf_render.depth /= 2;
|
tf_render.depth /= 2;
|
||||||
|
|
||||||
render_sdf_half[0] = RD::get_singleton()->texture_create(tf_render, RD::TextureView());
|
render_sdf_half[0] = RD::get_singleton()->texture_create(tf_render, RD::TextureView());
|
||||||
|
RD::get_singleton()->set_resource_name(render_sdf_half[0], "VoxelGI Render SDF Half 0");
|
||||||
render_sdf_half[1] = RD::get_singleton()->texture_create(tf_render, RD::TextureView());
|
render_sdf_half[1] = RD::get_singleton()->texture_create(tf_render, RD::TextureView());
|
||||||
|
RD::get_singleton()->set_resource_name(render_sdf_half[1], "VoxelGI Render SDF Half 1");
|
||||||
}
|
}
|
||||||
|
|
||||||
RD::TextureFormat tf_occlusion = tf_sdf;
|
RD::TextureFormat tf_occlusion = tf_sdf;
|
||||||
|
@ -465,7 +476,9 @@ void GI::SDFGI::create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world
|
||||||
tf_probe_average.texture_type = RD::TEXTURE_TYPE_2D;
|
tf_probe_average.texture_type = RD::TEXTURE_TYPE_2D;
|
||||||
|
|
||||||
lightprobe_history_scroll = RD::get_singleton()->texture_create(tf_probe_history, RD::TextureView());
|
lightprobe_history_scroll = RD::get_singleton()->texture_create(tf_probe_history, RD::TextureView());
|
||||||
|
RD::get_singleton()->set_resource_name(lightprobe_history_scroll, "VoxelGI LightProbe History Scroll");
|
||||||
lightprobe_average_scroll = RD::get_singleton()->texture_create(tf_probe_average, RD::TextureView());
|
lightprobe_average_scroll = RD::get_singleton()->texture_create(tf_probe_average, RD::TextureView());
|
||||||
|
RD::get_singleton()->set_resource_name(lightprobe_average_scroll, "VoxelGI LightProbe Average Scroll");
|
||||||
|
|
||||||
{
|
{
|
||||||
//octahedral lightprobes
|
//octahedral lightprobes
|
||||||
|
@ -479,6 +492,7 @@ void GI::SDFGI::create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world
|
||||||
//lightprobe texture is an octahedral texture
|
//lightprobe texture is an octahedral texture
|
||||||
|
|
||||||
lightprobe_data = RD::get_singleton()->texture_create(tf_octprobes, RD::TextureView());
|
lightprobe_data = RD::get_singleton()->texture_create(tf_octprobes, RD::TextureView());
|
||||||
|
RD::get_singleton()->set_resource_name(lightprobe_data, "VoxelGI LightProbe Data");
|
||||||
RD::TextureView tv;
|
RD::TextureView tv;
|
||||||
tv.format_override = RD::DATA_FORMAT_E5B9G9R9_UFLOAT_PACK32;
|
tv.format_override = RD::DATA_FORMAT_E5B9G9R9_UFLOAT_PACK32;
|
||||||
lightprobe_texture = RD::get_singleton()->texture_create_shared(tv, lightprobe_data);
|
lightprobe_texture = RD::get_singleton()->texture_create_shared(tv, lightprobe_data);
|
||||||
|
@ -492,11 +506,13 @@ void GI::SDFGI::create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world
|
||||||
tf_ambient.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
|
tf_ambient.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
|
||||||
//lightprobe texture is an octahedral texture
|
//lightprobe texture is an octahedral texture
|
||||||
ambient_texture = RD::get_singleton()->texture_create(tf_ambient, RD::TextureView());
|
ambient_texture = RD::get_singleton()->texture_create(tf_ambient, RD::TextureView());
|
||||||
|
RD::get_singleton()->set_resource_name(ambient_texture, "VoxelGI Ambient Texture");
|
||||||
}
|
}
|
||||||
|
|
||||||
cascades_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(SDFGI::Cascade::UBO) * SDFGI::MAX_CASCADES);
|
cascades_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(SDFGI::Cascade::UBO) * SDFGI::MAX_CASCADES);
|
||||||
|
|
||||||
occlusion_data = RD::get_singleton()->texture_create(tf_occlusion, RD::TextureView());
|
occlusion_data = RD::get_singleton()->texture_create(tf_occlusion, RD::TextureView());
|
||||||
|
RD::get_singleton()->set_resource_name(occlusion_data, "VoxelGI Occlusion Data");
|
||||||
{
|
{
|
||||||
RD::TextureView tv;
|
RD::TextureView tv;
|
||||||
tv.format_override = RD::DATA_FORMAT_R4G4B4A4_UNORM_PACK16;
|
tv.format_override = RD::DATA_FORMAT_R4G4B4A4_UNORM_PACK16;
|
||||||
|
@ -509,11 +525,15 @@ void GI::SDFGI::create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world
|
||||||
/* 3D Textures */
|
/* 3D Textures */
|
||||||
|
|
||||||
cascade.sdf_tex = RD::get_singleton()->texture_create(tf_sdf, RD::TextureView());
|
cascade.sdf_tex = RD::get_singleton()->texture_create(tf_sdf, RD::TextureView());
|
||||||
|
RD::get_singleton()->set_resource_name(cascade.sdf_tex, "VoxelGI Cascade SDF Texture");
|
||||||
|
|
||||||
cascade.light_data = RD::get_singleton()->texture_create(tf_light, RD::TextureView());
|
cascade.light_data = RD::get_singleton()->texture_create(tf_light, RD::TextureView());
|
||||||
|
RD::get_singleton()->set_resource_name(cascade.light_data, "VoxelGI Cascade Light Data");
|
||||||
|
|
||||||
cascade.light_aniso_0_tex = RD::get_singleton()->texture_create(tf_aniso0, RD::TextureView());
|
cascade.light_aniso_0_tex = RD::get_singleton()->texture_create(tf_aniso0, RD::TextureView());
|
||||||
|
RD::get_singleton()->set_resource_name(cascade.light_aniso_0_tex, "VoxelGI Cascade Light Aniso 0 Texture");
|
||||||
cascade.light_aniso_1_tex = RD::get_singleton()->texture_create(tf_aniso1, RD::TextureView());
|
cascade.light_aniso_1_tex = RD::get_singleton()->texture_create(tf_aniso1, RD::TextureView());
|
||||||
|
RD::get_singleton()->set_resource_name(cascade.light_aniso_1_tex, "VoxelGI Cascade Light Aniso 1 Texture");
|
||||||
|
|
||||||
{
|
{
|
||||||
RD::TextureView tv;
|
RD::TextureView tv;
|
||||||
|
@ -540,9 +560,11 @@ void GI::SDFGI::create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world
|
||||||
/* Probe History */
|
/* Probe History */
|
||||||
|
|
||||||
cascade.lightprobe_history_tex = RD::get_singleton()->texture_create(tf_probe_history, RD::TextureView());
|
cascade.lightprobe_history_tex = RD::get_singleton()->texture_create(tf_probe_history, RD::TextureView());
|
||||||
|
RD::get_singleton()->set_resource_name(cascade.lightprobe_history_tex, "VoxelGI Cascade LightProbe History Texture");
|
||||||
RD::get_singleton()->texture_clear(cascade.lightprobe_history_tex, Color(0, 0, 0, 0), 0, 1, 0, tf_probe_history.array_layers); //needs to be cleared for average to work
|
RD::get_singleton()->texture_clear(cascade.lightprobe_history_tex, Color(0, 0, 0, 0), 0, 1, 0, tf_probe_history.array_layers); //needs to be cleared for average to work
|
||||||
|
|
||||||
cascade.lightprobe_average_tex = RD::get_singleton()->texture_create(tf_probe_average, RD::TextureView());
|
cascade.lightprobe_average_tex = RD::get_singleton()->texture_create(tf_probe_average, RD::TextureView());
|
||||||
|
RD::get_singleton()->set_resource_name(cascade.lightprobe_average_tex, "VoxelGI Cascade LightProbe Average Texture");
|
||||||
RD::get_singleton()->texture_clear(cascade.lightprobe_average_tex, Color(0, 0, 0, 0), 0, 1, 0, 1); //needs to be cleared for average to work
|
RD::get_singleton()->texture_clear(cascade.lightprobe_average_tex, Color(0, 0, 0, 0), 0, 1, 0, 1); //needs to be cleared for average to work
|
||||||
|
|
||||||
/* Buffers */
|
/* Buffers */
|
||||||
|
@ -2444,6 +2466,7 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID
|
||||||
tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
|
tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
|
||||||
|
|
||||||
texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
|
texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
|
||||||
|
RD::get_singleton()->set_resource_name(texture, "VoxelGI Instance Texture");
|
||||||
|
|
||||||
RD::get_singleton()->texture_clear(texture, Color(0, 0, 0, 0), 0, levels.size(), 0, 1);
|
RD::get_singleton()->texture_clear(texture, Color(0, 0, 0, 0), 0, levels.size(), 0, 1);
|
||||||
|
|
||||||
|
@ -2573,6 +2596,7 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID
|
||||||
dtf.usage_bits |= RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
|
dtf.usage_bits |= RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||||
}
|
}
|
||||||
dmap.texture = RD::get_singleton()->texture_create(dtf, RD::TextureView());
|
dmap.texture = RD::get_singleton()->texture_create(dtf, RD::TextureView());
|
||||||
|
RD::get_singleton()->set_resource_name(dmap.texture, "VoxelGI Instance DMap Texture");
|
||||||
|
|
||||||
if (dynamic_maps.size() == 0) {
|
if (dynamic_maps.size() == 0) {
|
||||||
// Render depth for first one.
|
// Render depth for first one.
|
||||||
|
@ -2580,6 +2604,7 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID
|
||||||
dtf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D16_UNORM, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_D16_UNORM : RD::DATA_FORMAT_X8_D24_UNORM_PACK32;
|
dtf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D16_UNORM, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_D16_UNORM : RD::DATA_FORMAT_X8_D24_UNORM_PACK32;
|
||||||
dtf.usage_bits = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
|
dtf.usage_bits = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
|
||||||
dmap.fb_depth = RD::get_singleton()->texture_create(dtf, RD::TextureView());
|
dmap.fb_depth = RD::get_singleton()->texture_create(dtf, RD::TextureView());
|
||||||
|
RD::get_singleton()->set_resource_name(dmap.fb_depth, "VoxelGI Instance DMap FB Depth");
|
||||||
}
|
}
|
||||||
|
|
||||||
//just use depth as-is
|
//just use depth as-is
|
||||||
|
@ -2587,13 +2612,17 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID
|
||||||
dtf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
|
dtf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||||
|
|
||||||
dmap.depth = RD::get_singleton()->texture_create(dtf, RD::TextureView());
|
dmap.depth = RD::get_singleton()->texture_create(dtf, RD::TextureView());
|
||||||
|
RD::get_singleton()->set_resource_name(dmap.depth, "VoxelGI Instance DMap Depth");
|
||||||
|
|
||||||
if (dynamic_maps.size() == 0) {
|
if (dynamic_maps.size() == 0) {
|
||||||
dtf.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
|
dtf.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
|
||||||
dtf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
|
dtf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||||
dmap.albedo = RD::get_singleton()->texture_create(dtf, RD::TextureView());
|
dmap.albedo = RD::get_singleton()->texture_create(dtf, RD::TextureView());
|
||||||
|
RD::get_singleton()->set_resource_name(dmap.albedo, "VoxelGI Instance DMap Albedo");
|
||||||
dmap.normal = RD::get_singleton()->texture_create(dtf, RD::TextureView());
|
dmap.normal = RD::get_singleton()->texture_create(dtf, RD::TextureView());
|
||||||
|
RD::get_singleton()->set_resource_name(dmap.normal, "VoxelGI Instance DMap Normal");
|
||||||
dmap.orm = RD::get_singleton()->texture_create(dtf, RD::TextureView());
|
dmap.orm = RD::get_singleton()->texture_create(dtf, RD::TextureView());
|
||||||
|
RD::get_singleton()->set_resource_name(dmap.orm, "VoxelGI Instance DMap ORM");
|
||||||
|
|
||||||
Vector<RID> fb;
|
Vector<RID> fb;
|
||||||
fb.push_back(dmap.albedo);
|
fb.push_back(dmap.albedo);
|
||||||
|
@ -3342,37 +3371,40 @@ void GI::init(RendererSceneSkyRD *p_sky) {
|
||||||
//calculate tables
|
//calculate tables
|
||||||
String defines = "\n#define SDFGI_OCT_SIZE " + itos(SDFGI::LIGHTPROBE_OCT_SIZE) + "\n";
|
String defines = "\n#define SDFGI_OCT_SIZE " + itos(SDFGI::LIGHTPROBE_OCT_SIZE) + "\n";
|
||||||
Vector<String> gi_modes;
|
Vector<String> gi_modes;
|
||||||
|
|
||||||
gi_modes.push_back("\n#define USE_VOXEL_GI_INSTANCES\n"); // MODE_VOXEL_GI
|
gi_modes.push_back("\n#define USE_VOXEL_GI_INSTANCES\n"); // MODE_VOXEL_GI
|
||||||
gi_modes.push_back("\n#define USE_SDFGI\n"); // MODE_SDFGI
|
gi_modes.push_back("\n#define USE_SDFGI\n"); // MODE_SDFGI
|
||||||
gi_modes.push_back("\n#define USE_SDFGI\n\n#define USE_VOXEL_GI_INSTANCES\n"); // MODE_COMBINED
|
gi_modes.push_back("\n#define USE_SDFGI\n\n#define USE_VOXEL_GI_INSTANCES\n"); // MODE_COMBINED
|
||||||
gi_modes.push_back("\n#define MODE_HALF_RES\n#define USE_VOXEL_GI_INSTANCES\n"); // MODE_HALF_RES_VOXEL_GI
|
|
||||||
gi_modes.push_back("\n#define MODE_HALF_RES\n#define USE_SDFGI\n"); // MODE_HALF_RES_SDFGI
|
|
||||||
gi_modes.push_back("\n#define MODE_HALF_RES\n#define USE_SDFGI\n\n#define USE_VOXEL_GI_INSTANCES\n"); // MODE_HALF_RES_COMBINED
|
|
||||||
|
|
||||||
gi_modes.push_back("\n#define USE_VOXEL_GI_INSTANCES\n#define USE_MULTIVIEW\n"); // MODE_VOXEL_GI_MULTIVIEW
|
|
||||||
gi_modes.push_back("\n#define USE_SDFGI\n#define USE_MULTIVIEW\n"); // MODE_SDFGI_MULTIVIEW
|
|
||||||
gi_modes.push_back("\n#define USE_SDFGI\n\n#define USE_VOXEL_GI_INSTANCES\n#define USE_MULTIVIEW\n"); // MODE_COMBINED_MULTIVIEW
|
|
||||||
gi_modes.push_back("\n#define MODE_HALF_RES\n#define USE_VOXEL_GI_INSTANCES\n#define USE_MULTIVIEW\n"); // MODE_HALF_RES_VOXEL_GI_MULTIVIEW
|
|
||||||
gi_modes.push_back("\n#define MODE_HALF_RES\n#define USE_SDFGI\n#define USE_MULTIVIEW\n"); // MODE_HALF_RES_SDFGI_MULTIVIEW
|
|
||||||
gi_modes.push_back("\n#define MODE_HALF_RES\n#define USE_SDFGI\n\n#define USE_VOXEL_GI_INSTANCES\n#define USE_MULTIVIEW\n"); // MODE_HALF_RES_COMBINED_MULTIVIEW
|
|
||||||
|
|
||||||
shader.initialize(gi_modes, defines);
|
shader.initialize(gi_modes, defines);
|
||||||
|
shader_version = shader.version_create();
|
||||||
|
|
||||||
if (!RendererCompositorRD::singleton->is_xr_enabled()) {
|
Vector<RD::PipelineSpecializationConstant> specialization_constants;
|
||||||
shader.set_variant_enabled(MODE_VOXEL_GI_MULTIVIEW, false);
|
|
||||||
shader.set_variant_enabled(MODE_SDFGI_MULTIVIEW, false);
|
{
|
||||||
shader.set_variant_enabled(MODE_COMBINED_MULTIVIEW, false);
|
RD::PipelineSpecializationConstant sc;
|
||||||
shader.set_variant_enabled(MODE_HALF_RES_VOXEL_GI_MULTIVIEW, false);
|
sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_BOOL;
|
||||||
shader.set_variant_enabled(MODE_HALF_RES_SDFGI_MULTIVIEW, false);
|
sc.constant_id = 0; // SHADER_SPECIALIZATION_HALF_RES
|
||||||
shader.set_variant_enabled(MODE_HALF_RES_COMBINED_MULTIVIEW, false);
|
sc.bool_value = false;
|
||||||
|
specialization_constants.push_back(sc);
|
||||||
|
|
||||||
|
sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_BOOL;
|
||||||
|
sc.constant_id = 1; // SHADER_SPECIALIZATION_USE_FULL_PROJECTION_MATRIX
|
||||||
|
sc.bool_value = false;
|
||||||
|
specialization_constants.push_back(sc);
|
||||||
|
|
||||||
|
sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_BOOL;
|
||||||
|
sc.constant_id = 2; // SHADER_SPECIALIZATION_USE_VRS
|
||||||
|
sc.bool_value = false;
|
||||||
|
specialization_constants.push_back(sc);
|
||||||
}
|
}
|
||||||
|
|
||||||
shader_version = shader.version_create();
|
for (int v = 0; v < SHADER_SPECIALIZATION_VARIATIONS; v++) {
|
||||||
|
specialization_constants.ptrw()[0].bool_value = (v & SHADER_SPECIALIZATION_HALF_RES) ? true : false;
|
||||||
|
specialization_constants.ptrw()[1].bool_value = (v & SHADER_SPECIALIZATION_USE_FULL_PROJECTION_MATRIX) ? true : false;
|
||||||
|
specialization_constants.ptrw()[2].bool_value = (v & SHADER_SPECIALIZATION_USE_VRS) ? true : false;
|
||||||
for (int i = 0; i < MODE_MAX; i++) {
|
for (int i = 0; i < MODE_MAX; i++) {
|
||||||
if (shader.is_variant_enabled(i)) {
|
pipelines[v][i] = RD::get_singleton()->compute_pipeline_create(shader.version_get_shader(shader_version, i), specialization_constants);
|
||||||
pipelines[i] = RD::get_singleton()->compute_pipeline_create(shader.version_get_shader(shader_version, i));
|
|
||||||
} else {
|
|
||||||
pipelines[i] = RID();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3564,25 +3596,17 @@ void GI::RenderBuffersGI::free() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ambient_buffer.is_valid()) {
|
if (ambient_buffer.is_valid()) {
|
||||||
if (view_count == 1) {
|
|
||||||
// Only one view? then these are copies of our main buffers.
|
|
||||||
ambient_view[0] = RID();
|
|
||||||
reflection_view[0] = RID();
|
|
||||||
} else {
|
|
||||||
// Multiple views? free our slices.
|
|
||||||
for (uint32_t v = 0; v < view_count; v++) {
|
|
||||||
RD::get_singleton()->free(ambient_view[v]);
|
|
||||||
RD::get_singleton()->free(reflection_view[v]);
|
|
||||||
ambient_view[v] = RID();
|
|
||||||
reflection_view[v] = RID();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now we can free our buffers.
|
|
||||||
RD::get_singleton()->free(ambient_buffer);
|
RD::get_singleton()->free(ambient_buffer);
|
||||||
RD::get_singleton()->free(reflection_buffer);
|
RD::get_singleton()->free(reflection_buffer);
|
||||||
ambient_buffer = RID();
|
ambient_buffer = RID();
|
||||||
reflection_buffer = RID();
|
reflection_buffer = RID();
|
||||||
|
|
||||||
|
// these are automatically freed when we free the textures, so just reset..
|
||||||
|
for (uint32_t v = 0; v < RendererSceneRender::MAX_RENDER_VIEWS; v++) {
|
||||||
|
ambient_slice[v] = RID();
|
||||||
|
reflection_slice[v] = RID();
|
||||||
|
}
|
||||||
|
|
||||||
view_count = 0;
|
view_count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3592,7 +3616,7 @@ void GI::RenderBuffersGI::free() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GI::process_gi(RID p_render_buffers, RID *p_normal_roughness_views, RID p_voxel_gi_buffer, RID p_environment, uint32_t p_view_count, const CameraMatrix *p_projections, const Vector3 *p_eye_offsets, const Transform3D &p_cam_transform, const PagedArray<RID> &p_voxel_gi_instances, RendererSceneRenderRD *p_scene_render) {
|
void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices, RID p_voxel_gi_buffer, const RID *p_vrs_slices, RID p_environment, uint32_t p_view_count, const CameraMatrix *p_projections, const Vector3 *p_eye_offsets, const Transform3D &p_cam_transform, const PagedArray<RID> &p_voxel_gi_instances, RendererSceneRenderRD *p_scene_render) {
|
||||||
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
|
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
|
||||||
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
|
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
|
||||||
|
|
||||||
|
@ -3606,14 +3630,13 @@ void GI::process_gi(RID p_render_buffers, RID *p_normal_roughness_views, RID p_v
|
||||||
if (rb->rbgi.ambient_buffer.is_null() || rb->rbgi.using_half_size_gi != half_resolution || rb->rbgi.view_count != p_view_count) {
|
if (rb->rbgi.ambient_buffer.is_null() || rb->rbgi.using_half_size_gi != half_resolution || rb->rbgi.view_count != p_view_count) {
|
||||||
// Free our old buffer if applicable
|
// Free our old buffer if applicable
|
||||||
if (rb->rbgi.ambient_buffer.is_valid()) {
|
if (rb->rbgi.ambient_buffer.is_valid()) {
|
||||||
if (rb->rbgi.view_count > 1) {
|
|
||||||
for (uint32_t v = 0; v < rb->rbgi.view_count; v++) {
|
|
||||||
RD::get_singleton()->free(rb->rbgi.ambient_view[v]);
|
|
||||||
RD::get_singleton()->free(rb->rbgi.reflection_view[v]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
RD::get_singleton()->free(rb->rbgi.ambient_buffer);
|
RD::get_singleton()->free(rb->rbgi.ambient_buffer);
|
||||||
RD::get_singleton()->free(rb->rbgi.reflection_buffer);
|
RD::get_singleton()->free(rb->rbgi.reflection_buffer);
|
||||||
|
|
||||||
|
for (uint32_t v = 0; v < RendererSceneRender::MAX_RENDER_VIEWS; v++) {
|
||||||
|
rb->rbgi.ambient_slice[v] = RID();
|
||||||
|
rb->rbgi.reflection_slice[v] = RID();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remember the view count we're using
|
// Remember the view count we're using
|
||||||
|
@ -3637,18 +3660,19 @@ void GI::process_gi(RID p_render_buffers, RID *p_normal_roughness_views, RID p_v
|
||||||
}
|
}
|
||||||
tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
|
tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
|
||||||
rb->rbgi.ambient_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView());
|
rb->rbgi.ambient_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView());
|
||||||
|
RD::get_singleton()->set_resource_name(rb->rbgi.ambient_buffer, "GI Ambient Buffer");
|
||||||
rb->rbgi.reflection_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView());
|
rb->rbgi.reflection_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView());
|
||||||
|
RD::get_singleton()->set_resource_name(rb->rbgi.reflection_buffer, "GI Reflection Buffer");
|
||||||
rb->rbgi.using_half_size_gi = half_resolution;
|
rb->rbgi.using_half_size_gi = half_resolution;
|
||||||
|
|
||||||
if (p_view_count == 1) {
|
if (p_view_count == 1) {
|
||||||
// Just one view? Copy our buffers
|
// Just copy, we don't need to create slices
|
||||||
rb->rbgi.ambient_view[0] = rb->rbgi.ambient_buffer;
|
rb->rbgi.ambient_slice[0] = rb->rbgi.ambient_buffer;
|
||||||
rb->rbgi.reflection_view[0] = rb->rbgi.reflection_buffer;
|
rb->rbgi.reflection_slice[0] = rb->rbgi.reflection_buffer;
|
||||||
} else {
|
} else {
|
||||||
// More then one view? Create slices for each view
|
|
||||||
for (uint32_t v = 0; v < p_view_count; v++) {
|
for (uint32_t v = 0; v < p_view_count; v++) {
|
||||||
rb->rbgi.ambient_view[v] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->rbgi.ambient_buffer, v, 0);
|
rb->rbgi.ambient_slice[v] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->rbgi.ambient_buffer, v, 0);
|
||||||
rb->rbgi.reflection_view[v] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->rbgi.reflection_buffer, v, 0);
|
rb->rbgi.reflection_slice[v] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->rbgi.reflection_buffer, v, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3681,7 +3705,6 @@ void GI::process_gi(RID p_render_buffers, RID *p_normal_roughness_views, RID p_v
|
||||||
// Now compute the contents of our buffers.
|
// Now compute the contents of our buffers.
|
||||||
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(true);
|
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(true);
|
||||||
|
|
||||||
for (uint32_t v = 0; v < p_view_count; v++) {
|
|
||||||
// Render each eye seperately.
|
// Render each eye seperately.
|
||||||
// We need to look into whether we can make our compute shader use Multiview but not sure that works or makes a difference..
|
// We need to look into whether we can make our compute shader use Multiview but not sure that works or makes a difference..
|
||||||
|
|
||||||
|
@ -3689,22 +3712,39 @@ void GI::process_gi(RID p_render_buffers, RID *p_normal_roughness_views, RID p_v
|
||||||
|
|
||||||
PushConstant push_constant;
|
PushConstant push_constant;
|
||||||
|
|
||||||
push_constant.view_index = v;
|
|
||||||
push_constant.orthogonal = p_projections[v].is_orthogonal();
|
|
||||||
push_constant.max_voxel_gi_instances = MIN((uint64_t)MAX_VOXEL_GI_INSTANCES, p_voxel_gi_instances.size());
|
push_constant.max_voxel_gi_instances = MIN((uint64_t)MAX_VOXEL_GI_INSTANCES, p_voxel_gi_instances.size());
|
||||||
push_constant.high_quality_vct = voxel_gi_quality == RS::VOXEL_GI_QUALITY_HIGH;
|
push_constant.high_quality_vct = voxel_gi_quality == RS::VOXEL_GI_QUALITY_HIGH;
|
||||||
|
|
||||||
push_constant.z_near = p_projections[v].get_z_near();
|
// these should be the same for all views
|
||||||
push_constant.z_far = p_projections[v].get_z_far();
|
push_constant.orthogonal = p_projections[0].is_orthogonal();
|
||||||
|
push_constant.z_near = p_projections[0].get_z_near();
|
||||||
|
push_constant.z_far = p_projections[0].get_z_far();
|
||||||
|
|
||||||
push_constant.proj_info[0] = -2.0f / (rb->internal_width * p_projections[v].matrix[0][0]);
|
// these are only used if we have 1 view, else we use the projections in our scene data
|
||||||
push_constant.proj_info[1] = -2.0f / (rb->internal_height * p_projections[v].matrix[1][1]);
|
push_constant.proj_info[0] = -2.0f / (rb->internal_width * p_projections[0].matrix[0][0]);
|
||||||
push_constant.proj_info[2] = (1.0f - p_projections[v].matrix[0][2]) / p_projections[v].matrix[0][0];
|
push_constant.proj_info[1] = -2.0f / (rb->internal_height * p_projections[0].matrix[1][1]);
|
||||||
push_constant.proj_info[3] = (1.0f + p_projections[v].matrix[1][2]) / p_projections[v].matrix[1][1];
|
push_constant.proj_info[2] = (1.0f - p_projections[0].matrix[0][2]) / p_projections[0].matrix[0][0];
|
||||||
|
push_constant.proj_info[3] = (1.0f + p_projections[0].matrix[1][2]) / p_projections[0].matrix[1][1];
|
||||||
|
|
||||||
bool use_sdfgi = rb->sdfgi != nullptr;
|
bool use_sdfgi = rb->sdfgi != nullptr;
|
||||||
bool use_voxel_gi_instances = push_constant.max_voxel_gi_instances > 0;
|
bool use_voxel_gi_instances = push_constant.max_voxel_gi_instances > 0;
|
||||||
|
|
||||||
|
uint32_t pipeline_specialization = 0;
|
||||||
|
if (rb->rbgi.using_half_size_gi) {
|
||||||
|
pipeline_specialization |= SHADER_SPECIALIZATION_HALF_RES;
|
||||||
|
}
|
||||||
|
if (p_view_count > 1) {
|
||||||
|
pipeline_specialization |= SHADER_SPECIALIZATION_USE_FULL_PROJECTION_MATRIX;
|
||||||
|
}
|
||||||
|
if (p_vrs_slices[0].is_valid()) {
|
||||||
|
pipeline_specialization |= SHADER_SPECIALIZATION_USE_VRS;
|
||||||
|
}
|
||||||
|
|
||||||
|
Mode mode = (use_sdfgi && use_voxel_gi_instances) ? MODE_COMBINED : (use_sdfgi ? MODE_SDFGI : MODE_VOXEL_GI);
|
||||||
|
|
||||||
|
for (uint32_t v = 0; v < p_view_count; v++) {
|
||||||
|
push_constant.view_index = v;
|
||||||
|
|
||||||
// setup our uniform set
|
// setup our uniform set
|
||||||
if (rb->rbgi.uniform_set[v].is_null() || !RD::get_singleton()->uniform_set_is_valid(rb->rbgi.uniform_set[v])) {
|
if (rb->rbgi.uniform_set[v].is_null() || !RD::get_singleton()->uniform_set_is_valid(rb->rbgi.uniform_set[v])) {
|
||||||
Vector<RD::Uniform> uniforms;
|
Vector<RD::Uniform> uniforms;
|
||||||
|
@ -3790,7 +3830,7 @@ void GI::process_gi(RID p_render_buffers, RID *p_normal_roughness_views, RID p_v
|
||||||
RD::Uniform u;
|
RD::Uniform u;
|
||||||
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
|
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
|
||||||
u.binding = 9;
|
u.binding = 9;
|
||||||
u.append_id(rb->rbgi.ambient_view[v]);
|
u.append_id(rb->rbgi.ambient_slice[v]);
|
||||||
uniforms.push_back(u);
|
uniforms.push_back(u);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3798,7 +3838,7 @@ void GI::process_gi(RID p_render_buffers, RID *p_normal_roughness_views, RID p_v
|
||||||
RD::Uniform u;
|
RD::Uniform u;
|
||||||
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
|
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
|
||||||
u.binding = 10;
|
u.binding = 10;
|
||||||
u.append_id(rb->rbgi.reflection_view[v]);
|
u.append_id(rb->rbgi.reflection_slice[v]);
|
||||||
uniforms.push_back(u);
|
uniforms.push_back(u);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3824,7 +3864,7 @@ void GI::process_gi(RID p_render_buffers, RID *p_normal_roughness_views, RID p_v
|
||||||
RD::Uniform u;
|
RD::Uniform u;
|
||||||
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
|
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
|
||||||
u.binding = 13;
|
u.binding = 13;
|
||||||
u.append_id(p_normal_roughness_views[v]);
|
u.append_id(p_normal_roughness_slices[v]);
|
||||||
uniforms.push_back(u);
|
uniforms.push_back(u);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
|
@ -3865,27 +3905,19 @@ void GI::process_gi(RID p_render_buffers, RID *p_normal_roughness_views, RID p_v
|
||||||
u.append_id(rb->rbgi.scene_data_ubo);
|
u.append_id(rb->rbgi.scene_data_ubo);
|
||||||
uniforms.push_back(u);
|
uniforms.push_back(u);
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
RD::Uniform u;
|
||||||
|
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
|
||||||
|
u.binding = 19;
|
||||||
|
RID buffer = p_vrs_slices[v].is_valid() ? p_vrs_slices[v] : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_VRS);
|
||||||
|
u.append_id(buffer);
|
||||||
|
uniforms.push_back(u);
|
||||||
|
}
|
||||||
|
|
||||||
rb->rbgi.uniform_set[v] = RD::get_singleton()->uniform_set_create(uniforms, shader.version_get_shader(shader_version, 0), 0);
|
rb->rbgi.uniform_set[v] = RD::get_singleton()->uniform_set_create(uniforms, shader.version_get_shader(shader_version, 0), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Mode mode;
|
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, pipelines[pipeline_specialization][mode]);
|
||||||
|
|
||||||
if (p_view_count > 1) {
|
|
||||||
if (rb->rbgi.using_half_size_gi) {
|
|
||||||
mode = (use_sdfgi && use_voxel_gi_instances) ? MODE_HALF_RES_COMBINED_MULTIVIEW : (use_sdfgi ? MODE_HALF_RES_SDFGI_MULTIVIEW : MODE_HALF_RES_VOXEL_GI_MULTIVIEW);
|
|
||||||
} else {
|
|
||||||
mode = (use_sdfgi && use_voxel_gi_instances) ? MODE_COMBINED_MULTIVIEW : (use_sdfgi ? MODE_SDFGI_MULTIVIEW : MODE_VOXEL_GI_MULTIVIEW);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (rb->rbgi.using_half_size_gi) {
|
|
||||||
mode = (use_sdfgi && use_voxel_gi_instances) ? MODE_HALF_RES_COMBINED : (use_sdfgi ? MODE_HALF_RES_SDFGI : MODE_HALF_RES_VOXEL_GI);
|
|
||||||
} else {
|
|
||||||
mode = (use_sdfgi && use_voxel_gi_instances) ? MODE_COMBINED : (use_sdfgi ? MODE_SDFGI : MODE_VOXEL_GI);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, pipelines[mode]);
|
|
||||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->rbgi.uniform_set[v], 0);
|
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->rbgi.uniform_set[v], 0);
|
||||||
RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(PushConstant));
|
RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(PushConstant));
|
||||||
|
|
||||||
|
|
|
@ -660,13 +660,13 @@ public:
|
||||||
|
|
||||||
/* GI buffers */
|
/* GI buffers */
|
||||||
RID ambient_buffer;
|
RID ambient_buffer;
|
||||||
|
RID ambient_slice[RendererSceneRender::MAX_RENDER_VIEWS];
|
||||||
RID reflection_buffer;
|
RID reflection_buffer;
|
||||||
RID ambient_view[RendererSceneRender::MAX_RENDER_VIEWS];
|
RID reflection_slice[RendererSceneRender::MAX_RENDER_VIEWS];
|
||||||
RID reflection_view[RendererSceneRender::MAX_RENDER_VIEWS];
|
|
||||||
RID uniform_set[RendererSceneRender::MAX_RENDER_VIEWS];
|
|
||||||
bool using_half_size_gi = false;
|
bool using_half_size_gi = false;
|
||||||
uint32_t view_count = 1;
|
uint32_t view_count = 1;
|
||||||
|
|
||||||
|
RID uniform_set[RendererSceneRender::MAX_RENDER_VIEWS];
|
||||||
RID scene_data_ubo;
|
RID scene_data_ubo;
|
||||||
|
|
||||||
void free();
|
void free();
|
||||||
|
@ -729,44 +729,41 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PushConstant {
|
struct PushConstant {
|
||||||
uint32_t view_index;
|
|
||||||
uint32_t max_voxel_gi_instances;
|
uint32_t max_voxel_gi_instances;
|
||||||
uint32_t high_quality_vct;
|
uint32_t high_quality_vct;
|
||||||
uint32_t orthogonal;
|
uint32_t orthogonal;
|
||||||
|
uint32_t view_index;
|
||||||
|
|
||||||
float proj_info[4];
|
float proj_info[4];
|
||||||
|
|
||||||
float z_near;
|
float z_near;
|
||||||
float z_far;
|
float z_far;
|
||||||
float pad1;
|
|
||||||
float pad2;
|
float pad2;
|
||||||
|
float pad3;
|
||||||
};
|
};
|
||||||
|
|
||||||
RID sdfgi_ubo;
|
RID sdfgi_ubo;
|
||||||
|
|
||||||
enum Mode {
|
enum Mode {
|
||||||
MODE_VOXEL_GI,
|
MODE_VOXEL_GI,
|
||||||
MODE_SDFGI,
|
MODE_SDFGI,
|
||||||
MODE_COMBINED,
|
MODE_COMBINED,
|
||||||
MODE_HALF_RES_VOXEL_GI,
|
|
||||||
MODE_HALF_RES_SDFGI,
|
|
||||||
MODE_HALF_RES_COMBINED,
|
|
||||||
|
|
||||||
MODE_VOXEL_GI_MULTIVIEW,
|
|
||||||
MODE_SDFGI_MULTIVIEW,
|
|
||||||
MODE_COMBINED_MULTIVIEW,
|
|
||||||
MODE_HALF_RES_VOXEL_GI_MULTIVIEW,
|
|
||||||
MODE_HALF_RES_SDFGI_MULTIVIEW,
|
|
||||||
MODE_HALF_RES_COMBINED_MULTIVIEW,
|
|
||||||
|
|
||||||
MODE_MAX
|
MODE_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum ShaderSpecializations {
|
||||||
|
SHADER_SPECIALIZATION_HALF_RES = 1 << 0,
|
||||||
|
SHADER_SPECIALIZATION_USE_FULL_PROJECTION_MATRIX = 1 << 1,
|
||||||
|
SHADER_SPECIALIZATION_USE_VRS = 1 << 2,
|
||||||
|
SHADER_SPECIALIZATION_VARIATIONS = 0x07,
|
||||||
|
};
|
||||||
|
|
||||||
RID default_voxel_gi_buffer;
|
RID default_voxel_gi_buffer;
|
||||||
|
|
||||||
bool half_resolution = false;
|
bool half_resolution = false;
|
||||||
GiShaderRD shader;
|
GiShaderRD shader;
|
||||||
RID shader_version;
|
RID shader_version;
|
||||||
RID pipelines[MODE_MAX];
|
RID pipelines[SHADER_SPECIALIZATION_VARIATIONS][MODE_MAX];
|
||||||
|
|
||||||
GI();
|
GI();
|
||||||
~GI();
|
~GI();
|
||||||
|
@ -777,7 +774,7 @@ public:
|
||||||
SDFGI *create_sdfgi(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size);
|
SDFGI *create_sdfgi(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size);
|
||||||
|
|
||||||
void setup_voxel_gi_instances(RID p_render_buffers, const Transform3D &p_transform, const PagedArray<RID> &p_voxel_gi_instances, uint32_t &r_voxel_gi_instances_used, RendererSceneRenderRD *p_scene_render);
|
void setup_voxel_gi_instances(RID p_render_buffers, const Transform3D &p_transform, const PagedArray<RID> &p_voxel_gi_instances, uint32_t &r_voxel_gi_instances_used, RendererSceneRenderRD *p_scene_render);
|
||||||
void process_gi(RID p_render_buffers, RID *p_normal_roughness_views, RID p_voxel_gi_buffer, RID p_environment, uint32_t p_view_count, const CameraMatrix *p_projections, const Vector3 *p_eye_offsets, const Transform3D &p_cam_transform, const PagedArray<RID> &p_voxel_gi_instances, RendererSceneRenderRD *p_scene_render);
|
void process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices, RID p_voxel_gi_buffer, const RID *p_vrs_slices, RID p_environment, uint32_t p_view_count, const CameraMatrix *p_projections, const Vector3 *p_eye_offsets, const Transform3D &p_cam_transform, const PagedArray<RID> &p_voxel_gi_instances, RendererSceneRenderRD *p_scene_render);
|
||||||
|
|
||||||
RID voxel_gi_instance_create(RID p_base);
|
RID voxel_gi_instance_create(RID p_base);
|
||||||
void voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform);
|
void voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform);
|
||||||
|
|
|
@ -171,29 +171,24 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::ensure_voxelgi()
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderForwardClustered::RenderBufferDataForwardClustered::clear() {
|
void RenderForwardClustered::RenderBufferDataForwardClustered::clear() {
|
||||||
|
// note, slices are freed automatically when the parent texture is freed so we just clear them.
|
||||||
|
for (uint32_t v = 0; v < RendererSceneRender::MAX_RENDER_VIEWS; v++) {
|
||||||
|
color_views[v] = RID();
|
||||||
|
depth_views[v] = RID();
|
||||||
|
color_msaa_views[v] = RID();
|
||||||
|
depth_msaa_views[v] = RID();
|
||||||
|
normal_roughness_views[v] = RID();
|
||||||
|
normal_roughness_msaa_views[v] = RID();
|
||||||
|
voxelgi_views[v] = RID();
|
||||||
|
voxelgi_msaa_views[v] = RID();
|
||||||
|
vrs_views[v] = RID();
|
||||||
|
}
|
||||||
|
|
||||||
if (voxelgi_buffer != RID()) {
|
if (voxelgi_buffer != RID()) {
|
||||||
RD::get_singleton()->free(voxelgi_buffer);
|
RD::get_singleton()->free(voxelgi_buffer);
|
||||||
voxelgi_buffer = RID();
|
voxelgi_buffer = RID();
|
||||||
|
|
||||||
if (view_count == 1) {
|
|
||||||
voxelgi_views[0] = RID();
|
|
||||||
} else {
|
|
||||||
for (uint32_t v = 0; v < view_count; v++) {
|
|
||||||
RD::get_singleton()->free(voxelgi_views[v]);
|
|
||||||
voxelgi_views[v] = RID();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (voxelgi_buffer_msaa.is_valid()) {
|
if (voxelgi_buffer_msaa.is_valid()) {
|
||||||
if (view_count == 1) {
|
|
||||||
voxelgi_msaa_views[0] = RID();
|
|
||||||
} else {
|
|
||||||
for (uint32_t v = 0; v < view_count; v++) {
|
|
||||||
RD::get_singleton()->free(voxelgi_msaa_views[v]);
|
|
||||||
voxelgi_msaa_views[v] = RID();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RD::get_singleton()->free(voxelgi_buffer_msaa);
|
RD::get_singleton()->free(voxelgi_buffer_msaa);
|
||||||
voxelgi_buffer_msaa = RID();
|
voxelgi_buffer_msaa = RID();
|
||||||
}
|
}
|
||||||
|
@ -202,35 +197,11 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::clear() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (color_msaa.is_valid()) {
|
if (color_msaa.is_valid()) {
|
||||||
if (view_count == 1) {
|
|
||||||
color_views[0] = RID();
|
|
||||||
color_msaa_views[0] = RID();
|
|
||||||
} else {
|
|
||||||
for (uint32_t v = 0; v < view_count; v++) {
|
|
||||||
RD::get_singleton()->free(color_views[v]);
|
|
||||||
RD::get_singleton()->free(color_msaa_views[v]);
|
|
||||||
color_views[v] = RID();
|
|
||||||
color_msaa_views[v] = RID();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RD::get_singleton()->free(color_msaa);
|
RD::get_singleton()->free(color_msaa);
|
||||||
color_msaa = RID();
|
color_msaa = RID();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (depth_msaa.is_valid()) {
|
if (depth_msaa.is_valid()) {
|
||||||
if (view_count == 1) {
|
|
||||||
depth_views[0] = RID();
|
|
||||||
depth_msaa_views[0] = RID();
|
|
||||||
} else {
|
|
||||||
for (uint32_t v = 0; v < view_count; v++) {
|
|
||||||
RD::get_singleton()->free(depth_views[v]);
|
|
||||||
RD::get_singleton()->free(depth_msaa_views[v]);
|
|
||||||
depth_views[v] = RID();
|
|
||||||
depth_msaa_views[v] = RID();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RD::get_singleton()->free(depth_msaa);
|
RD::get_singleton()->free(depth_msaa);
|
||||||
depth_msaa = RID();
|
depth_msaa = RID();
|
||||||
}
|
}
|
||||||
|
@ -245,33 +216,17 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::clear() {
|
||||||
}
|
}
|
||||||
|
|
||||||
color = RID();
|
color = RID();
|
||||||
|
color_only_fb = RID();
|
||||||
depth = RID();
|
depth = RID();
|
||||||
depth_fb = RID();
|
depth_fb = RID();
|
||||||
|
|
||||||
color_framebuffers.clear(); // Color pass framebuffers are freed automatically by their dependency relations
|
color_framebuffers.clear(); // Color pass framebuffers are freed automatically by their dependency relations
|
||||||
|
|
||||||
if (normal_roughness_buffer.is_valid()) {
|
if (normal_roughness_buffer.is_valid()) {
|
||||||
if (view_count == 1) {
|
|
||||||
normal_roughness_views[0] = RID();
|
|
||||||
} else {
|
|
||||||
for (uint32_t v = 0; v < view_count; v++) {
|
|
||||||
RD::get_singleton()->free(normal_roughness_views[v]);
|
|
||||||
normal_roughness_views[v] = RID();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RD::get_singleton()->free(normal_roughness_buffer);
|
RD::get_singleton()->free(normal_roughness_buffer);
|
||||||
normal_roughness_buffer = RID();
|
normal_roughness_buffer = RID();
|
||||||
|
|
||||||
if (normal_roughness_buffer_msaa.is_valid()) {
|
if (normal_roughness_buffer_msaa.is_valid()) {
|
||||||
if (view_count == 1) {
|
|
||||||
normal_roughness_msaa_views[0] = RID();
|
|
||||||
} else {
|
|
||||||
for (uint32_t v = 0; v < view_count; v++) {
|
|
||||||
RD::get_singleton()->free(normal_roughness_msaa_views[v]);
|
|
||||||
normal_roughness_msaa_views[v] = RID();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
RD::get_singleton()->free(normal_roughness_buffer_msaa);
|
RD::get_singleton()->free(normal_roughness_buffer_msaa);
|
||||||
normal_roughness_buffer_msaa = RID();
|
normal_roughness_buffer_msaa = RID();
|
||||||
}
|
}
|
||||||
|
@ -294,11 +249,12 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::clear() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderForwardClustered::RenderBufferDataForwardClustered::configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, bool p_use_taa, uint32_t p_view_count) {
|
void RenderForwardClustered::RenderBufferDataForwardClustered::configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, bool p_use_taa, uint32_t p_view_count, RID p_vrs_texture) {
|
||||||
clear();
|
clear();
|
||||||
|
|
||||||
msaa = p_msaa;
|
msaa = p_msaa;
|
||||||
use_taa = p_use_taa;
|
use_taa = p_use_taa;
|
||||||
|
vrs = p_vrs_texture;
|
||||||
|
|
||||||
width = p_width;
|
width = p_width;
|
||||||
height = p_height;
|
height = p_height;
|
||||||
|
@ -307,11 +263,26 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::configure(RID p_c
|
||||||
color = p_color_buffer;
|
color = p_color_buffer;
|
||||||
depth = p_depth_buffer;
|
depth = p_depth_buffer;
|
||||||
|
|
||||||
|
if (vrs.is_valid()) {
|
||||||
|
if (view_count == 1) {
|
||||||
|
// just reuse
|
||||||
|
vrs_views[0] = vrs;
|
||||||
|
} else {
|
||||||
|
// create slices
|
||||||
|
for (uint32_t v = 0; v < view_count; v++) {
|
||||||
|
vrs_views[v] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), vrs, v, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (p_msaa == RS::VIEWPORT_MSAA_DISABLED) {
|
if (p_msaa == RS::VIEWPORT_MSAA_DISABLED) {
|
||||||
{
|
{
|
||||||
Vector<RID> fb;
|
Vector<RID> fb;
|
||||||
fb.push_back(p_color_buffer);
|
fb.push_back(p_color_buffer);
|
||||||
fb.push_back(depth);
|
fb.push_back(depth);
|
||||||
|
if (vrs.is_valid()) {
|
||||||
|
fb.push_back(vrs);
|
||||||
|
}
|
||||||
|
|
||||||
color_only_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, view_count);
|
color_only_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, view_count);
|
||||||
}
|
}
|
||||||
|
@ -371,6 +342,9 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::configure(RID p_c
|
||||||
Vector<RID> fb;
|
Vector<RID> fb;
|
||||||
fb.push_back(color_msaa);
|
fb.push_back(color_msaa);
|
||||||
fb.push_back(depth_msaa);
|
fb.push_back(depth_msaa);
|
||||||
|
if (vrs.is_valid()) {
|
||||||
|
fb.push_back(vrs);
|
||||||
|
}
|
||||||
|
|
||||||
color_only_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, view_count);
|
color_only_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, view_count);
|
||||||
}
|
}
|
||||||
|
@ -409,6 +383,10 @@ RID RenderForwardClustered::RenderBufferDataForwardClustered::get_color_pass_fb(
|
||||||
|
|
||||||
fb.push_back(use_msaa ? depth_msaa : depth);
|
fb.push_back(use_msaa ? depth_msaa : depth);
|
||||||
|
|
||||||
|
if (vrs.is_valid()) {
|
||||||
|
fb.push_back(vrs);
|
||||||
|
}
|
||||||
|
|
||||||
int v_count = (p_color_pass_flags & COLOR_PASS_FLAG_MULTIVIEW) ? view_count : 1;
|
int v_count = (p_color_pass_flags & COLOR_PASS_FLAG_MULTIVIEW) ? view_count : 1;
|
||||||
RID framebuffer = RD::get_singleton()->framebuffer_create(fb, RD::INVALID_ID, v_count);
|
RID framebuffer = RD::get_singleton()->framebuffer_create(fb, RD::INVALID_ID, v_count);
|
||||||
color_framebuffers[p_color_pass_flags] = framebuffer;
|
color_framebuffers[p_color_pass_flags] = framebuffer;
|
||||||
|
@ -1673,8 +1651,8 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
|
||||||
continue_depth = !finish_depth;
|
continue_depth = !finish_depth;
|
||||||
}
|
}
|
||||||
|
|
||||||
RID null_rids[2];
|
RID nullrids[RendererSceneRender::MAX_RENDER_VIEWS];
|
||||||
_pre_opaque_render(p_render_data, using_ssao, using_ssil, using_sdfgi || using_voxelgi, render_buffer ? render_buffer->normal_roughness_views : null_rids, render_buffer ? render_buffer->voxelgi_buffer : RID());
|
_pre_opaque_render(p_render_data, using_ssao, using_ssil, using_sdfgi || using_voxelgi, render_buffer ? render_buffer->normal_roughness_views : nullrids, render_buffer ? render_buffer->voxelgi_buffer : RID(), render_buffer ? render_buffer->vrs_views : nullrids);
|
||||||
|
|
||||||
RD::get_singleton()->draw_command_begin_label("Render Opaque Pass");
|
RD::get_singleton()->draw_command_begin_label("Render Opaque Pass");
|
||||||
|
|
||||||
|
|
|
@ -107,11 +107,14 @@ class RenderForwardClustered : public RendererSceneRenderRD {
|
||||||
RID depth_normal_roughness_voxelgi_fb;
|
RID depth_normal_roughness_voxelgi_fb;
|
||||||
RID color_only_fb;
|
RID color_only_fb;
|
||||||
RID specular_only_fb;
|
RID specular_only_fb;
|
||||||
|
|
||||||
|
RID vrs;
|
||||||
|
|
||||||
int width, height;
|
int width, height;
|
||||||
HashMap<uint32_t, RID> color_framebuffers;
|
HashMap<uint32_t, RID> color_framebuffers;
|
||||||
|
|
||||||
// for multiview
|
// for multiview
|
||||||
uint32_t view_count;
|
uint32_t view_count = 1;
|
||||||
RID color_views[RendererSceneRender::MAX_RENDER_VIEWS]; // we should rewrite this so we get access to the existing views in our renderer, something we can address when we reorg this
|
RID color_views[RendererSceneRender::MAX_RENDER_VIEWS]; // we should rewrite this so we get access to the existing views in our renderer, something we can address when we reorg this
|
||||||
RID depth_views[RendererSceneRender::MAX_RENDER_VIEWS]; // we should rewrite this so we get access to the existing views in our renderer, something we can address when we reorg this
|
RID depth_views[RendererSceneRender::MAX_RENDER_VIEWS]; // we should rewrite this so we get access to the existing views in our renderer, something we can address when we reorg this
|
||||||
RID color_msaa_views[RendererSceneRender::MAX_RENDER_VIEWS];
|
RID color_msaa_views[RendererSceneRender::MAX_RENDER_VIEWS];
|
||||||
|
@ -120,13 +123,14 @@ class RenderForwardClustered : public RendererSceneRenderRD {
|
||||||
RID normal_roughness_msaa_views[RendererSceneRender::MAX_RENDER_VIEWS];
|
RID normal_roughness_msaa_views[RendererSceneRender::MAX_RENDER_VIEWS];
|
||||||
RID voxelgi_views[RendererSceneRender::MAX_RENDER_VIEWS];
|
RID voxelgi_views[RendererSceneRender::MAX_RENDER_VIEWS];
|
||||||
RID voxelgi_msaa_views[RendererSceneRender::MAX_RENDER_VIEWS];
|
RID voxelgi_msaa_views[RendererSceneRender::MAX_RENDER_VIEWS];
|
||||||
|
RID vrs_views[RendererSceneRender::MAX_RENDER_VIEWS];
|
||||||
|
|
||||||
RID render_sdfgi_uniform_set;
|
RID render_sdfgi_uniform_set;
|
||||||
void ensure_specular();
|
void ensure_specular();
|
||||||
void ensure_voxelgi();
|
void ensure_voxelgi();
|
||||||
void ensure_velocity();
|
void ensure_velocity();
|
||||||
void clear();
|
void clear();
|
||||||
virtual void configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, bool p_use_taa, uint32_t p_view_count);
|
virtual void configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, bool p_use_taa, uint32_t p_view_count, RID p_vrs_texture);
|
||||||
RID get_color_pass_fb(uint32_t p_color_pass_flags);
|
RID get_color_pass_fb(uint32_t p_color_pass_flags);
|
||||||
|
|
||||||
~RenderBufferDataForwardClustered();
|
~RenderBufferDataForwardClustered();
|
||||||
|
|
|
@ -87,10 +87,11 @@ void RenderForwardMobile::RenderBufferDataForwardMobile::clear() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, bool p_use_taa, uint32_t p_view_count) {
|
void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, bool p_use_taa, uint32_t p_view_count, RID p_vrs_texture) {
|
||||||
clear();
|
clear();
|
||||||
|
|
||||||
msaa = p_msaa;
|
msaa = p_msaa;
|
||||||
|
vrs = p_vrs_texture;
|
||||||
|
|
||||||
Size2i target_size = RD::get_singleton()->texture_size(p_target_buffer);
|
Size2i target_size = RD::get_singleton()->texture_size(p_target_buffer);
|
||||||
|
|
||||||
|
@ -108,6 +109,9 @@ void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_b
|
||||||
Vector<RID> fb;
|
Vector<RID> fb;
|
||||||
fb.push_back(p_color_buffer); // 0 - color buffer
|
fb.push_back(p_color_buffer); // 0 - color buffer
|
||||||
fb.push_back(depth); // 1 - depth buffer
|
fb.push_back(depth); // 1 - depth buffer
|
||||||
|
if (vrs.is_valid()) {
|
||||||
|
fb.push_back(vrs); // 2 - vrs texture
|
||||||
|
}
|
||||||
|
|
||||||
// Now define our subpasses
|
// Now define our subpasses
|
||||||
Vector<RD::FramebufferPass> passes;
|
Vector<RD::FramebufferPass> passes;
|
||||||
|
@ -116,6 +120,9 @@ void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_b
|
||||||
// re-using the same attachments
|
// re-using the same attachments
|
||||||
pass.color_attachments.push_back(0);
|
pass.color_attachments.push_back(0);
|
||||||
pass.depth_attachment = 1;
|
pass.depth_attachment = 1;
|
||||||
|
if (vrs.is_valid()) {
|
||||||
|
pass.vrs_attachment = 2;
|
||||||
|
}
|
||||||
|
|
||||||
// - opaque pass
|
// - opaque pass
|
||||||
passes.push_back(pass);
|
passes.push_back(pass);
|
||||||
|
@ -131,12 +138,13 @@ void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_b
|
||||||
|
|
||||||
if (!is_scaled) {
|
if (!is_scaled) {
|
||||||
// - add blit to 2D pass
|
// - add blit to 2D pass
|
||||||
fb.push_back(p_target_buffer); // 2 - target buffer
|
int target_buffer_id = fb.size();
|
||||||
|
fb.push_back(p_target_buffer); // 2/3 - target buffer
|
||||||
|
|
||||||
RD::FramebufferPass blit_pass;
|
RD::FramebufferPass blit_pass;
|
||||||
blit_pass.color_attachments.push_back(2);
|
blit_pass.color_attachments.push_back(target_buffer_id);
|
||||||
blit_pass.input_attachments.push_back(0);
|
blit_pass.input_attachments.push_back(0);
|
||||||
passes.push_back(blit_pass);
|
passes.push_back(blit_pass); // this doesn't need VRS
|
||||||
|
|
||||||
color_fbs[FB_CONFIG_FOUR_SUBPASSES] = RD::get_singleton()->framebuffer_create_multipass(fb, passes, RenderingDevice::INVALID_ID, view_count);
|
color_fbs[FB_CONFIG_FOUR_SUBPASSES] = RD::get_singleton()->framebuffer_create_multipass(fb, passes, RenderingDevice::INVALID_ID, view_count);
|
||||||
} else {
|
} else {
|
||||||
|
@ -179,6 +187,9 @@ void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_b
|
||||||
Vector<RID> fb;
|
Vector<RID> fb;
|
||||||
fb.push_back(color_msaa); // 0 - msaa color buffer
|
fb.push_back(color_msaa); // 0 - msaa color buffer
|
||||||
fb.push_back(depth_msaa); // 1 - msaa depth buffer
|
fb.push_back(depth_msaa); // 1 - msaa depth buffer
|
||||||
|
if (vrs.is_valid()) {
|
||||||
|
fb.push_back(vrs); // 2 - vrs texture
|
||||||
|
}
|
||||||
|
|
||||||
// Now define our subpasses
|
// Now define our subpasses
|
||||||
Vector<RD::FramebufferPass> passes;
|
Vector<RD::FramebufferPass> passes;
|
||||||
|
@ -187,18 +198,22 @@ void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_b
|
||||||
// re-using the same attachments
|
// re-using the same attachments
|
||||||
pass.color_attachments.push_back(0);
|
pass.color_attachments.push_back(0);
|
||||||
pass.depth_attachment = 1;
|
pass.depth_attachment = 1;
|
||||||
|
if (vrs.is_valid()) {
|
||||||
|
pass.vrs_attachment = 2;
|
||||||
|
}
|
||||||
|
|
||||||
// - opaque pass
|
// - opaque pass
|
||||||
passes.push_back(pass);
|
passes.push_back(pass);
|
||||||
|
|
||||||
// - add sky pass
|
// - add sky pass
|
||||||
fb.push_back(color); // 2 - color buffer
|
int color_buffer_id = fb.size();
|
||||||
|
fb.push_back(color); // color buffer
|
||||||
passes.push_back(pass); // without resolve for our 3 + 4 subpass config
|
passes.push_back(pass); // without resolve for our 3 + 4 subpass config
|
||||||
{
|
{
|
||||||
// but with resolve for our 2 subpass config
|
// but with resolve for our 2 subpass config
|
||||||
Vector<RD::FramebufferPass> two_passes;
|
Vector<RD::FramebufferPass> two_passes;
|
||||||
two_passes.push_back(pass); // opaque subpass without resolve
|
two_passes.push_back(pass); // opaque subpass without resolve
|
||||||
pass.resolve_attachments.push_back(2);
|
pass.resolve_attachments.push_back(color_buffer_id);
|
||||||
two_passes.push_back(pass); // sky subpass with resolve
|
two_passes.push_back(pass); // sky subpass with resolve
|
||||||
|
|
||||||
color_fbs[FB_CONFIG_TWO_SUBPASSES] = RD::get_singleton()->framebuffer_create_multipass(fb, two_passes, RenderingDevice::INVALID_ID, view_count);
|
color_fbs[FB_CONFIG_TWO_SUBPASSES] = RD::get_singleton()->framebuffer_create_multipass(fb, two_passes, RenderingDevice::INVALID_ID, view_count);
|
||||||
|
@ -217,10 +232,11 @@ void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_b
|
||||||
|
|
||||||
if (!is_scaled) {
|
if (!is_scaled) {
|
||||||
// - add blit to 2D pass
|
// - add blit to 2D pass
|
||||||
fb.push_back(p_target_buffer); // 3 - target buffer
|
int target_buffer_id = fb.size();
|
||||||
|
fb.push_back(p_target_buffer); // target buffer
|
||||||
RD::FramebufferPass blit_pass;
|
RD::FramebufferPass blit_pass;
|
||||||
blit_pass.color_attachments.push_back(3);
|
blit_pass.color_attachments.push_back(target_buffer_id);
|
||||||
blit_pass.input_attachments.push_back(2);
|
blit_pass.input_attachments.push_back(color_buffer_id);
|
||||||
passes.push_back(blit_pass);
|
passes.push_back(blit_pass);
|
||||||
|
|
||||||
color_fbs[FB_CONFIG_FOUR_SUBPASSES] = RD::get_singleton()->framebuffer_create_multipass(fb, passes, RenderingDevice::INVALID_ID, view_count);
|
color_fbs[FB_CONFIG_FOUR_SUBPASSES] = RD::get_singleton()->framebuffer_create_multipass(fb, passes, RenderingDevice::INVALID_ID, view_count);
|
||||||
|
@ -675,8 +691,8 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
|
||||||
RD::get_singleton()->draw_command_end_label(); // Setup Sky resolution buffers
|
RD::get_singleton()->draw_command_end_label(); // Setup Sky resolution buffers
|
||||||
}
|
}
|
||||||
|
|
||||||
RID null_rids[2];
|
RID nullrids[RendererSceneRender::MAX_RENDER_VIEWS];
|
||||||
_pre_opaque_render(p_render_data, false, false, false, null_rids, RID());
|
_pre_opaque_render(p_render_data, false, false, false, nullrids, RID(), nullrids);
|
||||||
|
|
||||||
uint32_t spec_constant_base_flags = 0;
|
uint32_t spec_constant_base_flags = 0;
|
||||||
|
|
||||||
|
|
|
@ -131,12 +131,14 @@ protected:
|
||||||
RID depth_msaa;
|
RID depth_msaa;
|
||||||
// RID normal_roughness_buffer_msaa;
|
// RID normal_roughness_buffer_msaa;
|
||||||
|
|
||||||
|
RID vrs;
|
||||||
|
|
||||||
RID color_fbs[FB_CONFIG_MAX];
|
RID color_fbs[FB_CONFIG_MAX];
|
||||||
int width, height;
|
int width, height;
|
||||||
uint32_t view_count;
|
uint32_t view_count;
|
||||||
|
|
||||||
void clear();
|
void clear();
|
||||||
virtual void configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, bool p_use_taa, uint32_t p_view_count);
|
virtual void configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, bool p_use_taa, uint32_t p_view_count, RID p_vrs_texture);
|
||||||
|
|
||||||
~RenderBufferDataForwardMobile();
|
~RenderBufferDataForwardMobile();
|
||||||
};
|
};
|
||||||
|
|
|
@ -1827,6 +1827,16 @@ void RendererSceneRenderRD::_free_render_buffer_data(RenderBuffers *rb) {
|
||||||
rb->sss_texture = RID();
|
rb->sss_texture = RID();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rb->vrs_fb.is_valid()) {
|
||||||
|
RD::get_singleton()->free(rb->vrs_fb);
|
||||||
|
rb->vrs_fb = RID();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rb->vrs_texture.is_valid()) {
|
||||||
|
RD::get_singleton()->free(rb->vrs_texture);
|
||||||
|
rb->vrs_texture = RID();
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < 2; i++) {
|
for (int i = 0; i < 2; i++) {
|
||||||
for (int l = 0; l < rb->blur[i].layers.size(); l++) {
|
for (int l = 0; l < rb->blur[i].layers.size(); l++) {
|
||||||
for (int m = 0; m < rb->blur[i].layers[l].mipmaps.size(); m++) {
|
for (int m = 0; m < rb->blur[i].layers[l].mipmaps.size(); m++) {
|
||||||
|
@ -3151,8 +3161,13 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RS::ViewportVRSMode vrs_mode = texture_storage->render_target_get_vrs_mode(rb->render_target);
|
||||||
|
if (is_vrs_supported() && vrs_mode != RS::VIEWPORT_VRS_DISABLED) {
|
||||||
|
vrs->create_vrs_texture(p_internal_width, p_internal_height, p_view_count, rb->vrs_texture, rb->vrs_fb);
|
||||||
|
}
|
||||||
|
|
||||||
RID target_texture = texture_storage->render_target_get_rd_texture(rb->render_target);
|
RID target_texture = texture_storage->render_target_get_rd_texture(rb->render_target);
|
||||||
rb->data->configure(rb->internal_texture, rb->depth_texture, target_texture, p_internal_width, p_internal_height, p_msaa, p_use_taa, p_view_count);
|
rb->data->configure(rb->internal_texture, rb->depth_texture, target_texture, p_internal_width, p_internal_height, p_msaa, p_use_taa, p_view_count, rb->vrs_texture);
|
||||||
|
|
||||||
if (is_clustered_enabled()) {
|
if (is_clustered_enabled()) {
|
||||||
rb->cluster_builder->setup(Size2i(p_internal_width, p_internal_height), max_cluster_elements, rb->depth_texture, RendererRD::MaterialStorage::get_singleton()->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED), rb->internal_texture);
|
rb->cluster_builder->setup(Size2i(p_internal_width, p_internal_height), max_cluster_elements, rb->depth_texture, RendererRD::MaterialStorage::get_singleton()->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED), rb->internal_texture);
|
||||||
|
@ -4929,7 +4944,7 @@ void RendererSceneRenderRD::_pre_resolve_render(RenderDataRD *p_render_data, boo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool p_use_ssao, bool p_use_ssil, bool p_use_gi, RID *p_normal_roughness_views, RID p_voxel_gi_buffer) {
|
void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool p_use_ssao, bool p_use_ssil, bool p_use_gi, const RID *p_normal_roughness_slices, RID p_voxel_gi_buffer, const RID *p_vrs_slices) {
|
||||||
// Render shadows while GI is rendering, due to how barriers are handled, this should happen at the same time
|
// Render shadows while GI is rendering, due to how barriers are handled, this should happen at the same time
|
||||||
RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton();
|
RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton();
|
||||||
|
|
||||||
|
@ -5004,7 +5019,7 @@ void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool
|
||||||
|
|
||||||
//start GI
|
//start GI
|
||||||
if (render_gi) {
|
if (render_gi) {
|
||||||
gi.process_gi(p_render_data->render_buffers, p_normal_roughness_views, p_voxel_gi_buffer, p_render_data->environment, p_render_data->view_count, p_render_data->view_projection, p_render_data->view_eye_offset, p_render_data->cam_transform, *p_render_data->voxel_gi_instances, this);
|
gi.process_gi(p_render_data->render_buffers, p_normal_roughness_slices, p_voxel_gi_buffer, p_vrs_slices, p_render_data->environment, p_render_data->view_count, p_render_data->view_projection, p_render_data->view_eye_offset, p_render_data->cam_transform, *p_render_data->voxel_gi_instances, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Do shadow rendering (in parallel with GI)
|
//Do shadow rendering (in parallel with GI)
|
||||||
|
@ -5045,13 +5060,13 @@ void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p_use_ssao) {
|
if (p_use_ssao) {
|
||||||
// TODO make these proper stereo and thus use p_normal_roughness_views correctly
|
// TODO make these proper stereo
|
||||||
_process_ssao(p_render_data->render_buffers, p_render_data->environment, p_normal_roughness_views[0], p_render_data->cam_projection);
|
_process_ssao(p_render_data->render_buffers, p_render_data->environment, p_normal_roughness_slices[0], p_render_data->cam_projection);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p_use_ssil) {
|
if (p_use_ssil) {
|
||||||
// TODO make these proper stereo and thus use p_normal_roughness_views correctly
|
// TODO make these proper stereo
|
||||||
_process_ssil(p_render_data->render_buffers, p_render_data->environment, p_normal_roughness_views[0], p_render_data->cam_projection, p_render_data->cam_transform);
|
_process_ssil(p_render_data->render_buffers, p_render_data->environment, p_normal_roughness_slices[0], p_render_data->cam_projection, p_render_data->cam_transform);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5240,6 +5255,11 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData
|
||||||
render_data.cluster_max_elements = current_cluster_builder->get_max_cluster_elements();
|
render_data.cluster_max_elements = current_cluster_builder->get_max_cluster_elements();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rb != nullptr && rb->vrs_fb.is_valid()) {
|
||||||
|
// vrs_fb will only be valid if vrs is enabled
|
||||||
|
vrs->update_vrs_texture(rb->vrs_fb, rb->render_target);
|
||||||
|
}
|
||||||
|
|
||||||
_render_scene(&render_data, clear_color);
|
_render_scene(&render_data, clear_color);
|
||||||
|
|
||||||
if (p_render_buffers.is_valid()) {
|
if (p_render_buffers.is_valid()) {
|
||||||
|
@ -5736,6 +5756,10 @@ int RendererSceneRenderRD::get_max_directional_lights() const {
|
||||||
return cluster.max_directional_lights;
|
return cluster.max_directional_lights;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool RendererSceneRenderRD::is_vrs_supported() const {
|
||||||
|
return RD::get_singleton()->has_feature(RD::SUPPORTS_ATTACHMENT_VRS);
|
||||||
|
}
|
||||||
|
|
||||||
bool RendererSceneRenderRD::is_dynamic_gi_supported() const {
|
bool RendererSceneRenderRD::is_dynamic_gi_supported() const {
|
||||||
// usable by default (unless low end = true)
|
// usable by default (unless low end = true)
|
||||||
return true;
|
return true;
|
||||||
|
@ -5975,6 +5999,7 @@ void fog() {
|
||||||
bokeh_dof = memnew(RendererRD::BokehDOF(!can_use_storage));
|
bokeh_dof = memnew(RendererRD::BokehDOF(!can_use_storage));
|
||||||
copy_effects = memnew(RendererRD::CopyEffects(!can_use_storage));
|
copy_effects = memnew(RendererRD::CopyEffects(!can_use_storage));
|
||||||
tone_mapper = memnew(RendererRD::ToneMapper);
|
tone_mapper = memnew(RendererRD::ToneMapper);
|
||||||
|
vrs = memnew(RendererRD::VRS);
|
||||||
}
|
}
|
||||||
|
|
||||||
RendererSceneRenderRD::~RendererSceneRenderRD() {
|
RendererSceneRenderRD::~RendererSceneRenderRD() {
|
||||||
|
@ -5989,6 +6014,9 @@ RendererSceneRenderRD::~RendererSceneRenderRD() {
|
||||||
if (tone_mapper) {
|
if (tone_mapper) {
|
||||||
memdelete(tone_mapper);
|
memdelete(tone_mapper);
|
||||||
}
|
}
|
||||||
|
if (vrs) {
|
||||||
|
memdelete(vrs);
|
||||||
|
}
|
||||||
|
|
||||||
for (const KeyValue<int, ShadowCubemap> &E : shadow_cubemaps) {
|
for (const KeyValue<int, ShadowCubemap> &E : shadow_cubemaps) {
|
||||||
RD::get_singleton()->free(E.value.cubemap);
|
RD::get_singleton()->free(E.value.cubemap);
|
||||||
|
|
|
@ -38,6 +38,7 @@
|
||||||
#include "servers/rendering/renderer_rd/effects/bokeh_dof.h"
|
#include "servers/rendering/renderer_rd/effects/bokeh_dof.h"
|
||||||
#include "servers/rendering/renderer_rd/effects/copy_effects.h"
|
#include "servers/rendering/renderer_rd/effects/copy_effects.h"
|
||||||
#include "servers/rendering/renderer_rd/effects/tone_mapper.h"
|
#include "servers/rendering/renderer_rd/effects/tone_mapper.h"
|
||||||
|
#include "servers/rendering/renderer_rd/effects/vrs.h"
|
||||||
#include "servers/rendering/renderer_rd/environment/gi.h"
|
#include "servers/rendering/renderer_rd/environment/gi.h"
|
||||||
#include "servers/rendering/renderer_rd/renderer_scene_environment_rd.h"
|
#include "servers/rendering/renderer_rd/renderer_scene_environment_rd.h"
|
||||||
#include "servers/rendering/renderer_rd/renderer_scene_sky_rd.h"
|
#include "servers/rendering/renderer_rd/renderer_scene_sky_rd.h"
|
||||||
|
@ -104,11 +105,12 @@ protected:
|
||||||
RendererRD::BokehDOF *bokeh_dof = nullptr;
|
RendererRD::BokehDOF *bokeh_dof = nullptr;
|
||||||
RendererRD::CopyEffects *copy_effects = nullptr;
|
RendererRD::CopyEffects *copy_effects = nullptr;
|
||||||
RendererRD::ToneMapper *tone_mapper = nullptr;
|
RendererRD::ToneMapper *tone_mapper = nullptr;
|
||||||
|
RendererRD::VRS *vrs = nullptr;
|
||||||
double time = 0.0;
|
double time = 0.0;
|
||||||
double time_step = 0.0;
|
double time_step = 0.0;
|
||||||
|
|
||||||
struct RenderBufferData {
|
struct RenderBufferData {
|
||||||
virtual void configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, bool p_use_taa, uint32_t p_view_count) = 0;
|
virtual void configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, bool p_use_taa, uint32_t p_view_count, RID p_vrs_texture) = 0;
|
||||||
virtual ~RenderBufferData() {}
|
virtual ~RenderBufferData() {}
|
||||||
};
|
};
|
||||||
virtual RenderBufferData *_create_render_buffer_data() = 0;
|
virtual RenderBufferData *_create_render_buffer_data() = 0;
|
||||||
|
@ -149,7 +151,7 @@ protected:
|
||||||
void _post_prepass_render(RenderDataRD *p_render_data, bool p_use_gi);
|
void _post_prepass_render(RenderDataRD *p_render_data, bool p_use_gi);
|
||||||
void _pre_resolve_render(RenderDataRD *p_render_data, bool p_use_gi);
|
void _pre_resolve_render(RenderDataRD *p_render_data, bool p_use_gi);
|
||||||
|
|
||||||
void _pre_opaque_render(RenderDataRD *p_render_data, bool p_use_ssao, bool p_use_ssil, bool p_use_gi, RID *p_normal_roughness_views, RID p_voxel_gi_buffer);
|
void _pre_opaque_render(RenderDataRD *p_render_data, bool p_use_ssao, bool p_use_ssil, bool p_use_gi, const RID *p_normal_roughness_slices, RID p_voxel_gi_buffer, const RID *p_vrs_slices);
|
||||||
|
|
||||||
void _render_buffers_copy_screen_texture(const RenderDataRD *p_render_data);
|
void _render_buffers_copy_screen_texture(const RenderDataRD *p_render_data);
|
||||||
void _render_buffers_copy_depth_texture(const RenderDataRD *p_render_data);
|
void _render_buffers_copy_depth_texture(const RenderDataRD *p_render_data);
|
||||||
|
@ -492,6 +494,8 @@ private:
|
||||||
RID depth_texture; //main depth texture
|
RID depth_texture; //main depth texture
|
||||||
RID texture_fb; // framebuffer for the main texture, ONLY USED FOR MOBILE RENDERER POST EFFECTS, DO NOT USE FOR RENDERING 3D!!!
|
RID texture_fb; // framebuffer for the main texture, ONLY USED FOR MOBILE RENDERER POST EFFECTS, DO NOT USE FOR RENDERING 3D!!!
|
||||||
RID upscale_texture; //used when upscaling internal_texture (This uses the same resource as internal_texture if there is no upscaling)
|
RID upscale_texture; //used when upscaling internal_texture (This uses the same resource as internal_texture if there is no upscaling)
|
||||||
|
RID vrs_texture; // texture for vrs.
|
||||||
|
RID vrs_fb; // framebuffer to write to our vrs texture
|
||||||
|
|
||||||
// Access to the layers for each of our views (specifically needed for applying post effects on stereoscopic images)
|
// Access to the layers for each of our views (specifically needed for applying post effects on stereoscopic images)
|
||||||
struct View {
|
struct View {
|
||||||
|
@ -1503,6 +1507,7 @@ public:
|
||||||
|
|
||||||
virtual void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir) override;
|
virtual void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir) override;
|
||||||
|
|
||||||
|
virtual bool is_vrs_supported() const;
|
||||||
virtual bool is_dynamic_gi_supported() const;
|
virtual bool is_dynamic_gi_supported() const;
|
||||||
virtual bool is_clustered_enabled() const;
|
virtual bool is_clustered_enabled() const;
|
||||||
virtual bool is_volumetric_supported() const;
|
virtual bool is_volumetric_supported() const;
|
||||||
|
|
|
@ -88,7 +88,7 @@ layout(set = 0, binding = 0) uniform sampler2DArray source_color;
|
||||||
layout(set = 1, binding = 0) uniform sampler2DArray source_depth;
|
layout(set = 1, binding = 0) uniform sampler2DArray source_depth;
|
||||||
layout(location = 1) out float depth;
|
layout(location = 1) out float depth;
|
||||||
#endif /* MODE_TWO_SOURCES */
|
#endif /* MODE_TWO_SOURCES */
|
||||||
#else
|
#else /* MULTIVIEW */
|
||||||
layout(set = 0, binding = 0) uniform sampler2D source_color;
|
layout(set = 0, binding = 0) uniform sampler2D source_color;
|
||||||
#ifdef MODE_TWO_SOURCES
|
#ifdef MODE_TWO_SOURCES
|
||||||
layout(set = 1, binding = 0) uniform sampler2D source_color2;
|
layout(set = 1, binding = 0) uniform sampler2D source_color2;
|
||||||
|
@ -139,7 +139,7 @@ void main() {
|
||||||
//uv.y = 1.0 - uv.y;
|
//uv.y = 1.0 - uv.y;
|
||||||
uv = 1.0 - uv;
|
uv = 1.0 - uv;
|
||||||
}
|
}
|
||||||
#endif
|
#endif /* MODE_PANORAMA_TO_DP */
|
||||||
|
|
||||||
#ifdef MULTIVIEW
|
#ifdef MULTIVIEW
|
||||||
vec4 color = textureLod(source_color, uv, 0.0);
|
vec4 color = textureLod(source_color, uv, 0.0);
|
||||||
|
@ -148,12 +148,13 @@ void main() {
|
||||||
depth = textureLod(source_depth, uv, 0.0).r;
|
depth = textureLod(source_depth, uv, 0.0).r;
|
||||||
#endif /* MODE_TWO_SOURCES */
|
#endif /* MODE_TWO_SOURCES */
|
||||||
|
|
||||||
#else
|
#else /* MULTIVIEW */
|
||||||
vec4 color = textureLod(source_color, uv, 0.0);
|
vec4 color = textureLod(source_color, uv, 0.0);
|
||||||
#ifdef MODE_TWO_SOURCES
|
#ifdef MODE_TWO_SOURCES
|
||||||
color += textureLod(source_color2, uv, 0.0);
|
color += textureLod(source_color2, uv, 0.0);
|
||||||
#endif /* MODE_TWO_SOURCES */
|
#endif /* MODE_TWO_SOURCES */
|
||||||
#endif /* MULTIVIEW */
|
#endif /* MULTIVIEW */
|
||||||
|
|
||||||
if (params.force_luminance) {
|
if (params.force_luminance) {
|
||||||
color.rgb = vec3(max(max(color.r, color.g), color.b));
|
color.rgb = vec3(max(max(color.r, color.g), color.b));
|
||||||
}
|
}
|
||||||
|
@ -163,5 +164,6 @@ void main() {
|
||||||
if (params.srgb) {
|
if (params.srgb) {
|
||||||
color.rgb = linear_to_srgb(color.rgb);
|
color.rgb = linear_to_srgb(color.rgb);
|
||||||
}
|
}
|
||||||
|
|
||||||
frag_color = color;
|
frag_color = color;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,72 @@
|
||||||
|
#[vertex]
|
||||||
|
|
||||||
|
#version 450
|
||||||
|
|
||||||
|
#VERSION_DEFINES
|
||||||
|
|
||||||
|
#ifdef MULTIVIEW
|
||||||
|
#ifdef has_VK_KHR_multiview
|
||||||
|
#extension GL_EXT_multiview : enable
|
||||||
|
#define ViewIndex gl_ViewIndex
|
||||||
|
#else // has_VK_KHR_multiview
|
||||||
|
#define ViewIndex 0
|
||||||
|
#endif // has_VK_KHR_multiview
|
||||||
|
#endif //MULTIVIEW
|
||||||
|
|
||||||
|
#ifdef MULTIVIEW
|
||||||
|
layout(location = 0) out vec3 uv_interp;
|
||||||
|
#else
|
||||||
|
layout(location = 0) out vec2 uv_interp;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vec2 base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0));
|
||||||
|
uv_interp.xy = base_arr[gl_VertexIndex];
|
||||||
|
#ifdef MULTIVIEW
|
||||||
|
uv_interp.z = ViewIndex;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
gl_Position = vec4(uv_interp.xy * 2.0 - 1.0, 0.0, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[fragment]
|
||||||
|
|
||||||
|
#version 450
|
||||||
|
|
||||||
|
#VERSION_DEFINES
|
||||||
|
|
||||||
|
#ifdef MULTIVIEW
|
||||||
|
#ifdef has_VK_KHR_multiview
|
||||||
|
#extension GL_EXT_multiview : enable
|
||||||
|
#define ViewIndex gl_ViewIndex
|
||||||
|
#else // has_VK_KHR_multiview
|
||||||
|
#define ViewIndex 0
|
||||||
|
#endif // has_VK_KHR_multiview
|
||||||
|
#endif //MULTIVIEW
|
||||||
|
|
||||||
|
#ifdef MULTIVIEW
|
||||||
|
layout(location = 0) in vec3 uv_interp;
|
||||||
|
layout(set = 0, binding = 0) uniform sampler2DArray source_color;
|
||||||
|
#else /* MULTIVIEW */
|
||||||
|
layout(location = 0) in vec2 uv_interp;
|
||||||
|
layout(set = 0, binding = 0) uniform sampler2D source_color;
|
||||||
|
#endif /* MULTIVIEW */
|
||||||
|
|
||||||
|
layout(location = 0) out uint frag_color;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
#ifdef MULTIVIEW
|
||||||
|
vec3 uv = uv_interp;
|
||||||
|
#else
|
||||||
|
vec2 uv = uv_interp;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MULTIVIEW
|
||||||
|
vec4 color = textureLod(source_color, uv, 0.0);
|
||||||
|
#else /* MULTIVIEW */
|
||||||
|
vec4 color = textureLod(source_color, uv, 0.0);
|
||||||
|
#endif /* MULTIVIEW */
|
||||||
|
|
||||||
|
// See if we can change the sampler to one that returns int...
|
||||||
|
frag_color = uint(color.r * 256.0);
|
||||||
|
}
|
|
@ -8,6 +8,12 @@ layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
|
||||||
|
|
||||||
#define M_PI 3.141592
|
#define M_PI 3.141592
|
||||||
|
|
||||||
|
/* Specialization Constants (Toggles) */
|
||||||
|
|
||||||
|
layout(constant_id = 0) const bool sc_half_res = false;
|
||||||
|
layout(constant_id = 1) const bool sc_use_full_projection_matrix = false;
|
||||||
|
layout(constant_id = 2) const bool sc_use_vrs = false;
|
||||||
|
|
||||||
#define SDFGI_MAX_CASCADES 8
|
#define SDFGI_MAX_CASCADES 8
|
||||||
|
|
||||||
//set 0 for SDFGI and render buffers
|
//set 0 for SDFGI and render buffers
|
||||||
|
@ -97,18 +103,20 @@ layout(set = 0, binding = 18, std140) uniform SceneData {
|
||||||
}
|
}
|
||||||
scene_data;
|
scene_data;
|
||||||
|
|
||||||
|
layout(r8ui, set = 0, binding = 19) uniform restrict readonly uimage2D vrs_buffer;
|
||||||
|
|
||||||
layout(push_constant, std430) uniform Params {
|
layout(push_constant, std430) uniform Params {
|
||||||
uint view_index;
|
|
||||||
uint max_voxel_gi_instances;
|
uint max_voxel_gi_instances;
|
||||||
bool high_quality_vct;
|
bool high_quality_vct;
|
||||||
bool orthogonal;
|
bool orthogonal;
|
||||||
|
uint view_index;
|
||||||
|
|
||||||
vec4 proj_info;
|
vec4 proj_info;
|
||||||
|
|
||||||
float z_near;
|
float z_near;
|
||||||
float z_far;
|
float z_far;
|
||||||
float pad1;
|
|
||||||
float pad2;
|
float pad2;
|
||||||
|
float pad3;
|
||||||
}
|
}
|
||||||
params;
|
params;
|
||||||
|
|
||||||
|
@ -140,7 +148,7 @@ vec4 blend_color(vec4 src, vec4 dst) {
|
||||||
}
|
}
|
||||||
|
|
||||||
vec3 reconstruct_position(ivec2 screen_pos) {
|
vec3 reconstruct_position(ivec2 screen_pos) {
|
||||||
#ifdef USE_MULTIVIEW
|
if (sc_use_full_projection_matrix) {
|
||||||
vec4 pos;
|
vec4 pos;
|
||||||
pos.xy = (2.0 * vec2(screen_pos) / vec2(scene_data.screen_size)) - 1.0;
|
pos.xy = (2.0 * vec2(screen_pos) / vec2(scene_data.screen_size)) - 1.0;
|
||||||
pos.z = texelFetch(sampler2D(depth_buffer, linear_sampler), screen_pos, 0).r * 2.0 - 1.0;
|
pos.z = texelFetch(sampler2D(depth_buffer, linear_sampler), screen_pos, 0).r * 2.0 - 1.0;
|
||||||
|
@ -149,7 +157,7 @@ vec3 reconstruct_position(ivec2 screen_pos) {
|
||||||
pos = scene_data.inv_projection[params.view_index] * pos;
|
pos = scene_data.inv_projection[params.view_index] * pos;
|
||||||
|
|
||||||
return pos.xyz / pos.w;
|
return pos.xyz / pos.w;
|
||||||
#else
|
} else {
|
||||||
vec3 pos;
|
vec3 pos;
|
||||||
pos.z = texelFetch(sampler2D(depth_buffer, linear_sampler), screen_pos, 0).r;
|
pos.z = texelFetch(sampler2D(depth_buffer, linear_sampler), screen_pos, 0).r;
|
||||||
|
|
||||||
|
@ -167,7 +175,7 @@ vec3 reconstruct_position(ivec2 screen_pos) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return pos;
|
return pos;
|
||||||
#endif
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void sdfvoxel_gi_process(uint cascade, vec3 cascade_pos, vec3 cam_pos, vec3 cam_normal, vec3 cam_specular_normal, float roughness, out vec3 diffuse_light, out vec3 specular_light) {
|
void sdfvoxel_gi_process(uint cascade, vec3 cascade_pos, vec3 cam_pos, vec3 cam_normal, vec3 cam_specular_normal, float roughness, out vec3 diffuse_light, out vec3 specular_light) {
|
||||||
|
@ -587,7 +595,6 @@ void voxel_gi_compute(uint index, vec3 position, vec3 normal, vec3 ref_vec, mat3
|
||||||
|
|
||||||
vec4 fetch_normal_and_roughness(ivec2 pos) {
|
vec4 fetch_normal_and_roughness(ivec2 pos) {
|
||||||
vec4 normal_roughness = texelFetch(sampler2D(normal_roughness_buffer, linear_sampler), pos, 0);
|
vec4 normal_roughness = texelFetch(sampler2D(normal_roughness_buffer, linear_sampler), pos, 0);
|
||||||
|
|
||||||
normal_roughness.xyz = normalize(normal_roughness.xyz * 2.0 - 1.0);
|
normal_roughness.xyz = normalize(normal_roughness.xyz * 2.0 - 1.0);
|
||||||
return normal_roughness;
|
return normal_roughness;
|
||||||
}
|
}
|
||||||
|
@ -600,7 +607,7 @@ void process_gi(ivec2 pos, vec3 vertex, inout vec4 ambient_light, inout vec4 ref
|
||||||
if (normal.length() > 0.5) {
|
if (normal.length() > 0.5) {
|
||||||
//valid normal, can do GI
|
//valid normal, can do GI
|
||||||
float roughness = normal_roughness.w;
|
float roughness = normal_roughness.w;
|
||||||
vec3 view = -normalize(mat3(scene_data.cam_transform) * (vertex - scene_data.eye_offset[params.view_index].xyz));
|
vec3 view = -normalize(mat3(scene_data.cam_transform) * (vertex - scene_data.eye_offset[gl_GlobalInvocationID.z].xyz));
|
||||||
vertex = mat3(scene_data.cam_transform) * vertex;
|
vertex = mat3(scene_data.cam_transform) * vertex;
|
||||||
normal = normalize(mat3(scene_data.cam_transform) * normal);
|
normal = normalize(mat3(scene_data.cam_transform) * normal);
|
||||||
vec3 reflection = normalize(reflect(-view, normal));
|
vec3 reflection = normalize(reflect(-view, normal));
|
||||||
|
@ -648,9 +655,35 @@ void process_gi(ivec2 pos, vec3 vertex, inout vec4 ambient_light, inout vec4 ref
|
||||||
void main() {
|
void main() {
|
||||||
ivec2 pos = ivec2(gl_GlobalInvocationID.xy);
|
ivec2 pos = ivec2(gl_GlobalInvocationID.xy);
|
||||||
|
|
||||||
#ifdef MODE_HALF_RES
|
uint vrs_x, vrs_y;
|
||||||
|
if (sc_use_vrs) {
|
||||||
|
ivec2 vrs_pos;
|
||||||
|
|
||||||
|
// Currenty we use a 16x16 texel, possibly some day make this configurable.
|
||||||
|
if (sc_half_res) {
|
||||||
|
vrs_pos = pos >> 3;
|
||||||
|
} else {
|
||||||
|
vrs_pos = pos >> 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint vrs_texel = imageLoad(vrs_buffer, vrs_pos).r;
|
||||||
|
// note, valid values for vrs_x and vrs_y are 1, 2 and 4.
|
||||||
|
vrs_x = 1 << ((vrs_texel >> 2) & 3);
|
||||||
|
vrs_y = 1 << (vrs_texel & 3);
|
||||||
|
|
||||||
|
if (mod(pos.x, vrs_x) != 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mod(pos.y, vrs_y) != 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sc_half_res) {
|
||||||
pos <<= 1;
|
pos <<= 1;
|
||||||
#endif
|
}
|
||||||
|
|
||||||
if (any(greaterThanEqual(pos, scene_data.screen_size))) { //too large, do nothing
|
if (any(greaterThanEqual(pos, scene_data.screen_size))) { //too large, do nothing
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -663,10 +696,69 @@ void main() {
|
||||||
|
|
||||||
process_gi(pos, vertex, ambient_light, reflection_light);
|
process_gi(pos, vertex, ambient_light, reflection_light);
|
||||||
|
|
||||||
#ifdef MODE_HALF_RES
|
if (sc_half_res) {
|
||||||
pos >>= 1;
|
pos >>= 1;
|
||||||
#endif
|
}
|
||||||
|
|
||||||
imageStore(ambient_buffer, pos, ambient_light);
|
imageStore(ambient_buffer, pos, ambient_light);
|
||||||
imageStore(reflection_buffer, pos, reflection_light);
|
imageStore(reflection_buffer, pos, reflection_light);
|
||||||
|
|
||||||
|
if (sc_use_vrs) {
|
||||||
|
if (vrs_x > 1) {
|
||||||
|
imageStore(ambient_buffer, pos + ivec2(1, 0), ambient_light);
|
||||||
|
imageStore(reflection_buffer, pos + ivec2(1, 0), reflection_light);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vrs_x > 2) {
|
||||||
|
imageStore(ambient_buffer, pos + ivec2(2, 0), ambient_light);
|
||||||
|
imageStore(reflection_buffer, pos + ivec2(2, 0), reflection_light);
|
||||||
|
|
||||||
|
imageStore(ambient_buffer, pos + ivec2(3, 0), ambient_light);
|
||||||
|
imageStore(reflection_buffer, pos + ivec2(3, 0), reflection_light);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vrs_y > 1) {
|
||||||
|
imageStore(ambient_buffer, pos + ivec2(0, 1), ambient_light);
|
||||||
|
imageStore(reflection_buffer, pos + ivec2(0, 1), reflection_light);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vrs_y > 1 && vrs_x > 1) {
|
||||||
|
imageStore(ambient_buffer, pos + ivec2(1, 1), ambient_light);
|
||||||
|
imageStore(reflection_buffer, pos + ivec2(1, 1), reflection_light);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vrs_y > 1 && vrs_x > 2) {
|
||||||
|
imageStore(ambient_buffer, pos + ivec2(2, 1), ambient_light);
|
||||||
|
imageStore(reflection_buffer, pos + ivec2(2, 1), reflection_light);
|
||||||
|
|
||||||
|
imageStore(ambient_buffer, pos + ivec2(3, 1), ambient_light);
|
||||||
|
imageStore(reflection_buffer, pos + ivec2(3, 1), reflection_light);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vrs_y > 2) {
|
||||||
|
imageStore(ambient_buffer, pos + ivec2(0, 2), ambient_light);
|
||||||
|
imageStore(reflection_buffer, pos + ivec2(0, 2), reflection_light);
|
||||||
|
imageStore(ambient_buffer, pos + ivec2(0, 3), ambient_light);
|
||||||
|
imageStore(reflection_buffer, pos + ivec2(0, 3), reflection_light);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vrs_y > 2 && vrs_x > 1) {
|
||||||
|
imageStore(ambient_buffer, pos + ivec2(1, 2), ambient_light);
|
||||||
|
imageStore(reflection_buffer, pos + ivec2(1, 2), reflection_light);
|
||||||
|
imageStore(ambient_buffer, pos + ivec2(1, 3), ambient_light);
|
||||||
|
imageStore(reflection_buffer, pos + ivec2(1, 3), reflection_light);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vrs_y > 2 && vrs_x > 2) {
|
||||||
|
imageStore(ambient_buffer, pos + ivec2(2, 2), ambient_light);
|
||||||
|
imageStore(reflection_buffer, pos + ivec2(2, 2), reflection_light);
|
||||||
|
imageStore(ambient_buffer, pos + ivec2(2, 3), ambient_light);
|
||||||
|
imageStore(reflection_buffer, pos + ivec2(2, 3), reflection_light);
|
||||||
|
|
||||||
|
imageStore(ambient_buffer, pos + ivec2(3, 2), ambient_light);
|
||||||
|
imageStore(reflection_buffer, pos + ivec2(3, 2), reflection_light);
|
||||||
|
imageStore(ambient_buffer, pos + ivec2(3, 3), ambient_light);
|
||||||
|
imageStore(reflection_buffer, pos + ivec2(3, 3), reflection_light);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -349,7 +349,6 @@ TextureStorage::TextureStorage() {
|
||||||
|
|
||||||
Vector<uint8_t> pv;
|
Vector<uint8_t> pv;
|
||||||
pv.resize(16 * 4);
|
pv.resize(16 * 4);
|
||||||
|
|
||||||
for (int i = 0; i < 16; i++) {
|
for (int i = 0; i < 16; i++) {
|
||||||
pv.set(i * 4 + 0, 0);
|
pv.set(i * 4 + 0, 0);
|
||||||
pv.set(i * 4 + 1, 0);
|
pv.set(i * 4 + 1, 0);
|
||||||
|
@ -358,7 +357,6 @@ TextureStorage::TextureStorage() {
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
//take the chance and initialize decal atlas to something
|
|
||||||
Vector<Vector<uint8_t>> vpv;
|
Vector<Vector<uint8_t>> vpv;
|
||||||
vpv.push_back(pv);
|
vpv.push_back(pv);
|
||||||
decal_atlas.texture = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
|
decal_atlas.texture = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
|
||||||
|
@ -366,6 +364,29 @@ TextureStorage::TextureStorage() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{ //create default VRS
|
||||||
|
|
||||||
|
RD::TextureFormat tformat;
|
||||||
|
tformat.format = RD::DATA_FORMAT_R8_UINT;
|
||||||
|
tformat.width = 4;
|
||||||
|
tformat.height = 4;
|
||||||
|
tformat.array_layers = 1;
|
||||||
|
tformat.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_VRS_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT;
|
||||||
|
tformat.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
|
||||||
|
|
||||||
|
Vector<uint8_t> pv;
|
||||||
|
pv.resize(4 * 4);
|
||||||
|
for (int i = 0; i < 4 * 4; i++) {
|
||||||
|
pv.set(i, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
Vector<Vector<uint8_t>> vpv;
|
||||||
|
vpv.push_back(pv);
|
||||||
|
default_rd_textures[DEFAULT_RD_TEXTURE_VRS] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
Vector<String> sdf_modes;
|
Vector<String> sdf_modes;
|
||||||
sdf_modes.push_back("\n#define MODE_LOAD\n");
|
sdf_modes.push_back("\n#define MODE_LOAD\n");
|
||||||
|
@ -2751,3 +2772,31 @@ void TextureStorage::render_target_set_backbuffer_uniform_set(RID p_render_targe
|
||||||
ERR_FAIL_COND(!rt);
|
ERR_FAIL_COND(!rt);
|
||||||
rt->backbuffer_uniform_set = p_uniform_set;
|
rt->backbuffer_uniform_set = p_uniform_set;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TextureStorage::render_target_set_vrs_mode(RID p_render_target, RS::ViewportVRSMode p_mode) {
|
||||||
|
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
|
||||||
|
ERR_FAIL_COND(!rt);
|
||||||
|
|
||||||
|
rt->vrs_mode = p_mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextureStorage::render_target_set_vrs_texture(RID p_render_target, RID p_texture) {
|
||||||
|
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
|
||||||
|
ERR_FAIL_COND(!rt);
|
||||||
|
|
||||||
|
rt->vrs_texture = p_texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
RS::ViewportVRSMode TextureStorage::render_target_get_vrs_mode(RID p_render_target) const {
|
||||||
|
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
|
||||||
|
ERR_FAIL_COND_V(!rt, RS::VIEWPORT_VRS_DISABLED);
|
||||||
|
|
||||||
|
return rt->vrs_mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
RID TextureStorage::render_target_get_vrs_texture(RID p_render_target) const {
|
||||||
|
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
|
||||||
|
ERR_FAIL_COND_V(!rt, RID());
|
||||||
|
|
||||||
|
return rt->vrs_texture;
|
||||||
|
}
|
||||||
|
|
|
@ -52,6 +52,7 @@ enum DefaultRDTexture {
|
||||||
DEFAULT_RD_TEXTURE_3D_BLACK,
|
DEFAULT_RD_TEXTURE_3D_BLACK,
|
||||||
DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE,
|
DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE,
|
||||||
DEFAULT_RD_TEXTURE_2D_UINT,
|
DEFAULT_RD_TEXTURE_2D_UINT,
|
||||||
|
DEFAULT_RD_TEXTURE_VRS,
|
||||||
DEFAULT_RD_TEXTURE_MAX
|
DEFAULT_RD_TEXTURE_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -229,6 +230,10 @@ struct RenderTarget {
|
||||||
RS::ViewportSDFScale sdf_scale = RS::VIEWPORT_SDF_SCALE_50_PERCENT;
|
RS::ViewportSDFScale sdf_scale = RS::VIEWPORT_SDF_SCALE_50_PERCENT;
|
||||||
Size2i process_size;
|
Size2i process_size;
|
||||||
|
|
||||||
|
// VRS
|
||||||
|
RS::ViewportVRSMode vrs_mode = RS::VIEWPORT_VRS_DISABLED;
|
||||||
|
RID vrs_texture;
|
||||||
|
|
||||||
//texture generated for this owner (nor RD).
|
//texture generated for this owner (nor RD).
|
||||||
RID texture;
|
RID texture;
|
||||||
bool was_used;
|
bool was_used;
|
||||||
|
@ -549,6 +554,12 @@ public:
|
||||||
virtual void render_target_mark_sdf_enabled(RID p_render_target, bool p_enabled) override;
|
virtual void render_target_mark_sdf_enabled(RID p_render_target, bool p_enabled) override;
|
||||||
bool render_target_is_sdf_enabled(RID p_render_target) const;
|
bool render_target_is_sdf_enabled(RID p_render_target) const;
|
||||||
|
|
||||||
|
virtual void render_target_set_vrs_mode(RID p_render_target, RS::ViewportVRSMode p_mode) override;
|
||||||
|
virtual void render_target_set_vrs_texture(RID p_render_target, RID p_texture) override;
|
||||||
|
|
||||||
|
RS::ViewportVRSMode render_target_get_vrs_mode(RID p_render_target) const;
|
||||||
|
RID render_target_get_vrs_texture(RID p_render_target) const;
|
||||||
|
|
||||||
Size2 render_target_get_size(RID p_render_target);
|
Size2 render_target_get_size(RID p_render_target);
|
||||||
RID render_target_get_rd_framebuffer(RID p_render_target);
|
RID render_target_get_rd_framebuffer(RID p_render_target);
|
||||||
RID render_target_get_rd_texture(RID p_render_target);
|
RID render_target_get_rd_texture(RID p_render_target);
|
||||||
|
|
|
@ -1207,6 +1207,22 @@ RID RendererViewport::viewport_find_from_screen_attachment(DisplayServer::Window
|
||||||
return RID();
|
return RID();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RendererViewport::viewport_set_vrs_mode(RID p_viewport, RS::ViewportVRSMode p_mode) {
|
||||||
|
Viewport *viewport = viewport_owner.get_or_null(p_viewport);
|
||||||
|
ERR_FAIL_COND(!viewport);
|
||||||
|
|
||||||
|
RSG::texture_storage->render_target_set_vrs_mode(viewport->render_target, p_mode);
|
||||||
|
_configure_3d_render_buffers(viewport);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RendererViewport::viewport_set_vrs_texture(RID p_viewport, RID p_texture) {
|
||||||
|
Viewport *viewport = viewport_owner.get_or_null(p_viewport);
|
||||||
|
ERR_FAIL_COND(!viewport);
|
||||||
|
|
||||||
|
RSG::texture_storage->render_target_set_vrs_texture(viewport->render_target, p_texture);
|
||||||
|
_configure_3d_render_buffers(viewport);
|
||||||
|
}
|
||||||
|
|
||||||
bool RendererViewport::free(RID p_rid) {
|
bool RendererViewport::free(RID p_rid) {
|
||||||
if (viewport_owner.owns(p_rid)) {
|
if (viewport_owner.owns(p_rid)) {
|
||||||
Viewport *viewport = viewport_owner.get_or_null(p_rid);
|
Viewport *viewport = viewport_owner.get_or_null(p_rid);
|
||||||
|
|
|
@ -284,6 +284,9 @@ public:
|
||||||
|
|
||||||
virtual RID viewport_find_from_screen_attachment(DisplayServer::WindowID p_id = DisplayServer::MAIN_WINDOW_ID) const;
|
virtual RID viewport_find_from_screen_attachment(DisplayServer::WindowID p_id = DisplayServer::MAIN_WINDOW_ID) const;
|
||||||
|
|
||||||
|
void viewport_set_vrs_mode(RID p_viewport, RS::ViewportVRSMode p_mode);
|
||||||
|
void viewport_set_vrs_texture(RID p_viewport, RID p_texture);
|
||||||
|
|
||||||
void handle_timestamp(String p_timestamp, uint64_t p_cpu_time, uint64_t p_gpu_time);
|
void handle_timestamp(String p_timestamp, uint64_t p_cpu_time, uint64_t p_gpu_time);
|
||||||
|
|
||||||
void set_default_clear_color(const Color &p_color);
|
void set_default_clear_color(const Color &p_color);
|
||||||
|
|
|
@ -64,12 +64,12 @@ Vector<uint8_t> RenderingDevice::shader_compile_spirv_from_source(ShaderStage p_
|
||||||
|
|
||||||
ERR_FAIL_COND_V(!compile_to_spirv_function, Vector<uint8_t>());
|
ERR_FAIL_COND_V(!compile_to_spirv_function, Vector<uint8_t>());
|
||||||
|
|
||||||
return compile_to_spirv_function(p_stage, p_source_code, p_language, r_error, &device_capabilities);
|
return compile_to_spirv_function(p_stage, p_source_code, p_language, r_error, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
String RenderingDevice::shader_get_spirv_cache_key() const {
|
String RenderingDevice::shader_get_spirv_cache_key() const {
|
||||||
if (get_spirv_cache_key_function) {
|
if (get_spirv_cache_key_function) {
|
||||||
return get_spirv_cache_key_function(&device_capabilities);
|
return get_spirv_cache_key_function(this);
|
||||||
}
|
}
|
||||||
return String();
|
return String();
|
||||||
}
|
}
|
||||||
|
@ -279,6 +279,7 @@ static Vector<RenderingDevice::PipelineSpecializationConstant> _get_spec_constan
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
RID RenderingDevice::_render_pipeline_create(RID p_shader, FramebufferFormatID p_framebuffer_format, VertexFormatID p_vertex_format, RenderPrimitive p_render_primitive, const Ref<RDPipelineRasterizationState> &p_rasterization_state, const Ref<RDPipelineMultisampleState> &p_multisample_state, const Ref<RDPipelineDepthStencilState> &p_depth_stencil_state, const Ref<RDPipelineColorBlendState> &p_blend_state, int p_dynamic_state_flags, uint32_t p_for_render_pass, const TypedArray<RDPipelineSpecializationConstant> &p_specialization_constants) {
|
RID RenderingDevice::_render_pipeline_create(RID p_shader, FramebufferFormatID p_framebuffer_format, VertexFormatID p_vertex_format, RenderPrimitive p_render_primitive, const Ref<RDPipelineRasterizationState> &p_rasterization_state, const Ref<RDPipelineMultisampleState> &p_multisample_state, const Ref<RDPipelineDepthStencilState> &p_depth_stencil_state, const Ref<RDPipelineColorBlendState> &p_blend_state, int p_dynamic_state_flags, uint32_t p_for_render_pass, const TypedArray<RDPipelineSpecializationConstant> &p_specialization_constants) {
|
||||||
PipelineRasterizationState rasterization_state;
|
PipelineRasterizationState rasterization_state;
|
||||||
if (p_rasterization_state.is_valid()) {
|
if (p_rasterization_state.is_valid()) {
|
||||||
|
|
|
@ -123,19 +123,10 @@ public:
|
||||||
DeviceFamily device_family = DEVICE_UNKNOWN;
|
DeviceFamily device_family = DEVICE_UNKNOWN;
|
||||||
uint32_t version_major = 1.0;
|
uint32_t version_major = 1.0;
|
||||||
uint32_t version_minor = 0.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
|
|
||||||
|
|
||||||
// features
|
|
||||||
bool supports_multiview = false; // If true this device supports multiview options
|
|
||||||
bool supports_fsr_half_float = false; // If true this device supports FSR scaling 3D in half float mode, otherwise use the fallback mode
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef String (*ShaderSPIRVGetCacheKeyFunction)(const Capabilities *p_capabilities);
|
typedef String (*ShaderSPIRVGetCacheKeyFunction)(const RenderingDevice *p_render_device);
|
||||||
typedef Vector<uint8_t> (*ShaderCompileToSPIRVFunction)(ShaderStage p_stage, const String &p_source_code, ShaderLanguage p_language, String *r_error, const Capabilities *p_capabilities);
|
typedef Vector<uint8_t> (*ShaderCompileToSPIRVFunction)(ShaderStage p_stage, const String &p_source_code, ShaderLanguage p_language, String *r_error, const RenderingDevice *p_render_device);
|
||||||
typedef Vector<uint8_t> (*ShaderCacheFunction)(ShaderStage p_stage, const String &p_source_code, ShaderLanguage p_language);
|
typedef Vector<uint8_t> (*ShaderCacheFunction)(ShaderStage p_stage, const String &p_source_code, ShaderLanguage p_language);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -444,6 +435,7 @@ public:
|
||||||
TEXTURE_USAGE_CAN_COPY_FROM_BIT = (1 << 7),
|
TEXTURE_USAGE_CAN_COPY_FROM_BIT = (1 << 7),
|
||||||
TEXTURE_USAGE_CAN_COPY_TO_BIT = (1 << 8),
|
TEXTURE_USAGE_CAN_COPY_TO_BIT = (1 << 8),
|
||||||
TEXTURE_USAGE_INPUT_ATTACHMENT_BIT = (1 << 9),
|
TEXTURE_USAGE_INPUT_ATTACHMENT_BIT = (1 << 9),
|
||||||
|
TEXTURE_USAGE_VRS_ATTACHMENT_BIT = (1 << 10),
|
||||||
};
|
};
|
||||||
|
|
||||||
enum TextureSwizzle {
|
enum TextureSwizzle {
|
||||||
|
@ -552,6 +544,7 @@ public:
|
||||||
Vector<int32_t> resolve_attachments;
|
Vector<int32_t> resolve_attachments;
|
||||||
Vector<int32_t> preserve_attachments;
|
Vector<int32_t> preserve_attachments;
|
||||||
int32_t depth_attachment = ATTACHMENT_UNUSED;
|
int32_t depth_attachment = ATTACHMENT_UNUSED;
|
||||||
|
int32_t vrs_attachment = ATTACHMENT_UNUSED; // density map for VRS, only used if supported
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual FramebufferFormatID framebuffer_format_create_multipass(const Vector<AttachmentFormat> &p_attachments, Vector<FramebufferPass> &p_passes, uint32_t p_view_count = 1) = 0;
|
virtual FramebufferFormatID framebuffer_format_create_multipass(const Vector<AttachmentFormat> &p_attachments, Vector<FramebufferPass> &p_passes, uint32_t p_view_count = 1) = 0;
|
||||||
|
@ -675,6 +668,13 @@ public:
|
||||||
|
|
||||||
const Capabilities *get_device_capabilities() const { return &device_capabilities; };
|
const Capabilities *get_device_capabilities() const { return &device_capabilities; };
|
||||||
|
|
||||||
|
enum Features {
|
||||||
|
SUPPORTS_MULTIVIEW,
|
||||||
|
SUPPORTS_FSR_HALF_FLOAT,
|
||||||
|
SUPPORTS_ATTACHMENT_VRS,
|
||||||
|
};
|
||||||
|
virtual bool has_feature(const Features p_feature) const = 0;
|
||||||
|
|
||||||
virtual Vector<uint8_t> shader_compile_spirv_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);
|
virtual Vector<uint8_t> shader_compile_spirv_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);
|
||||||
virtual String shader_get_spirv_cache_key() const;
|
virtual String shader_get_spirv_cache_key() const;
|
||||||
|
|
||||||
|
@ -1221,9 +1221,12 @@ public:
|
||||||
LIMIT_MAX_COMPUTE_WORKGROUP_SIZE_X,
|
LIMIT_MAX_COMPUTE_WORKGROUP_SIZE_X,
|
||||||
LIMIT_MAX_COMPUTE_WORKGROUP_SIZE_Y,
|
LIMIT_MAX_COMPUTE_WORKGROUP_SIZE_Y,
|
||||||
LIMIT_MAX_COMPUTE_WORKGROUP_SIZE_Z,
|
LIMIT_MAX_COMPUTE_WORKGROUP_SIZE_Z,
|
||||||
|
LIMIT_SUBGROUP_SIZE,
|
||||||
|
LIMIT_SUBGROUP_IN_SHADERS, // Set flags using SHADER_STAGE_VERTEX_BIT, SHADER_STAGE_FRAGMENT_BIT, etc.
|
||||||
|
LIMIT_SUBGROUP_OPERATIONS,
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual uint64_t limit_get(Limit p_limit) = 0;
|
virtual uint64_t limit_get(Limit p_limit) const = 0;
|
||||||
|
|
||||||
//methods below not exposed, used by RenderingDeviceRD
|
//methods below not exposed, used by RenderingDeviceRD
|
||||||
virtual void prepare_screen_for_drawing() = 0;
|
virtual void prepare_screen_for_drawing() = 0;
|
||||||
|
@ -1324,6 +1327,7 @@ VARIANT_ENUM_CAST(RenderingDevice::InitialAction)
|
||||||
VARIANT_ENUM_CAST(RenderingDevice::FinalAction)
|
VARIANT_ENUM_CAST(RenderingDevice::FinalAction)
|
||||||
VARIANT_ENUM_CAST(RenderingDevice::Limit)
|
VARIANT_ENUM_CAST(RenderingDevice::Limit)
|
||||||
VARIANT_ENUM_CAST(RenderingDevice::MemoryType)
|
VARIANT_ENUM_CAST(RenderingDevice::MemoryType)
|
||||||
|
VARIANT_ENUM_CAST(RenderingDevice::Features)
|
||||||
|
|
||||||
typedef RenderingDevice RD;
|
typedef RenderingDevice RD;
|
||||||
|
|
||||||
|
|
|
@ -637,6 +637,9 @@ public:
|
||||||
|
|
||||||
FUNC2(call_set_vsync_mode, DisplayServer::VSyncMode, DisplayServer::WindowID)
|
FUNC2(call_set_vsync_mode, DisplayServer::VSyncMode, DisplayServer::WindowID)
|
||||||
|
|
||||||
|
FUNC2(viewport_set_vrs_mode, RID, ViewportVRSMode)
|
||||||
|
FUNC2(viewport_set_vrs_texture, RID, RID)
|
||||||
|
|
||||||
/* ENVIRONMENT API */
|
/* ENVIRONMENT API */
|
||||||
|
|
||||||
#undef server_name
|
#undef server_name
|
||||||
|
|
|
@ -143,6 +143,9 @@ public:
|
||||||
virtual void render_target_set_sdf_size_and_scale(RID p_render_target, RS::ViewportSDFOversize p_size, RS::ViewportSDFScale p_scale) = 0;
|
virtual void render_target_set_sdf_size_and_scale(RID p_render_target, RS::ViewportSDFOversize p_size, RS::ViewportSDFScale p_scale) = 0;
|
||||||
virtual Rect2i render_target_get_sdf_rect(RID p_render_target) const = 0;
|
virtual Rect2i render_target_get_sdf_rect(RID p_render_target) const = 0;
|
||||||
virtual void render_target_mark_sdf_enabled(RID p_render_target, bool p_enabled) = 0;
|
virtual void render_target_mark_sdf_enabled(RID p_render_target, bool p_enabled) = 0;
|
||||||
|
|
||||||
|
virtual void render_target_set_vrs_mode(RID p_render_target, RS::ViewportVRSMode p_mode) = 0;
|
||||||
|
virtual void render_target_set_vrs_texture(RID p_render_target, RID p_texture) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // !TEXTURE_STORAGE_H
|
#endif // !TEXTURE_STORAGE_H
|
||||||
|
|
|
@ -2225,6 +2225,9 @@ void RenderingServer::_bind_methods() {
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("viewport_get_measured_render_time_gpu", "viewport"), &RenderingServer::viewport_get_measured_render_time_gpu);
|
ClassDB::bind_method(D_METHOD("viewport_get_measured_render_time_gpu", "viewport"), &RenderingServer::viewport_get_measured_render_time_gpu);
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("viewport_set_vrs_mode", "viewport", "mode"), &RenderingServer::viewport_set_vrs_mode);
|
||||||
|
ClassDB::bind_method(D_METHOD("viewport_set_vrs_texture", "viewport", "texture"), &RenderingServer::viewport_set_vrs_texture);
|
||||||
|
|
||||||
BIND_ENUM_CONSTANT(VIEWPORT_SCALING_3D_MODE_BILINEAR);
|
BIND_ENUM_CONSTANT(VIEWPORT_SCALING_3D_MODE_BILINEAR);
|
||||||
BIND_ENUM_CONSTANT(VIEWPORT_SCALING_3D_MODE_FSR);
|
BIND_ENUM_CONSTANT(VIEWPORT_SCALING_3D_MODE_FSR);
|
||||||
BIND_ENUM_CONSTANT(VIEWPORT_SCALING_3D_MODE_MAX);
|
BIND_ENUM_CONSTANT(VIEWPORT_SCALING_3D_MODE_MAX);
|
||||||
|
@ -2300,6 +2303,11 @@ void RenderingServer::_bind_methods() {
|
||||||
BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_OCCLUDERS);
|
BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_OCCLUDERS);
|
||||||
BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_MOTION_VECTORS);
|
BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_MOTION_VECTORS);
|
||||||
|
|
||||||
|
BIND_ENUM_CONSTANT(VIEWPORT_VRS_DISABLED);
|
||||||
|
BIND_ENUM_CONSTANT(VIEWPORT_VRS_TEXTURE);
|
||||||
|
BIND_ENUM_CONSTANT(VIEWPORT_VRS_XR);
|
||||||
|
BIND_ENUM_CONSTANT(VIEWPORT_VRS_MAX);
|
||||||
|
|
||||||
/* SKY API */
|
/* SKY API */
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("sky_create"), &RenderingServer::sky_create);
|
ClassDB::bind_method(D_METHOD("sky_create"), &RenderingServer::sky_create);
|
||||||
|
|
|
@ -946,6 +946,16 @@ public:
|
||||||
|
|
||||||
virtual RID viewport_find_from_screen_attachment(DisplayServer::WindowID p_id = DisplayServer::MAIN_WINDOW_ID) const = 0;
|
virtual RID viewport_find_from_screen_attachment(DisplayServer::WindowID p_id = DisplayServer::MAIN_WINDOW_ID) const = 0;
|
||||||
|
|
||||||
|
enum ViewportVRSMode {
|
||||||
|
VIEWPORT_VRS_DISABLED,
|
||||||
|
VIEWPORT_VRS_TEXTURE,
|
||||||
|
VIEWPORT_VRS_XR,
|
||||||
|
VIEWPORT_VRS_MAX,
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual void viewport_set_vrs_mode(RID p_viewport, ViewportVRSMode p_mode) = 0;
|
||||||
|
virtual void viewport_set_vrs_texture(RID p_viewport, RID p_texture) = 0;
|
||||||
|
|
||||||
/* SKY API */
|
/* SKY API */
|
||||||
|
|
||||||
enum SkyMode {
|
enum SkyMode {
|
||||||
|
@ -1609,6 +1619,7 @@ VARIANT_ENUM_CAST(RenderingServer::ViewportDebugDraw);
|
||||||
VARIANT_ENUM_CAST(RenderingServer::ViewportOcclusionCullingBuildQuality);
|
VARIANT_ENUM_CAST(RenderingServer::ViewportOcclusionCullingBuildQuality);
|
||||||
VARIANT_ENUM_CAST(RenderingServer::ViewportSDFOversize);
|
VARIANT_ENUM_CAST(RenderingServer::ViewportSDFOversize);
|
||||||
VARIANT_ENUM_CAST(RenderingServer::ViewportSDFScale);
|
VARIANT_ENUM_CAST(RenderingServer::ViewportSDFScale);
|
||||||
|
VARIANT_ENUM_CAST(RenderingServer::ViewportVRSMode);
|
||||||
VARIANT_ENUM_CAST(RenderingServer::SkyMode);
|
VARIANT_ENUM_CAST(RenderingServer::SkyMode);
|
||||||
VARIANT_ENUM_CAST(RenderingServer::EnvironmentBG);
|
VARIANT_ENUM_CAST(RenderingServer::EnvironmentBG);
|
||||||
VARIANT_ENUM_CAST(RenderingServer::EnvironmentAmbientSource);
|
VARIANT_ENUM_CAST(RenderingServer::EnvironmentAmbientSource);
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
/*************************************************************************/
|
/*************************************************************************/
|
||||||
|
|
||||||
#include "xr_interface.h"
|
#include "xr_interface.h"
|
||||||
// #include "servers/rendering/renderer_compositor.h"
|
#include "servers/rendering/renderer_compositor.h"
|
||||||
|
|
||||||
void XRInterface::_bind_methods() {
|
void XRInterface::_bind_methods() {
|
||||||
ADD_SIGNAL(MethodInfo("play_area_changed", PropertyInfo(Variant::INT, "mode")));
|
ADD_SIGNAL(MethodInfo("play_area_changed", PropertyInfo(Variant::INT, "mode")));
|
||||||
|
@ -114,7 +114,12 @@ void XRInterface::set_primary(bool p_primary) {
|
||||||
|
|
||||||
XRInterface::XRInterface() {}
|
XRInterface::XRInterface() {}
|
||||||
|
|
||||||
XRInterface::~XRInterface() {}
|
XRInterface::~XRInterface() {
|
||||||
|
if (vrs.vrs_texture.is_valid()) {
|
||||||
|
RS::get_singleton()->free(vrs.vrs_texture);
|
||||||
|
vrs.vrs_texture = RID();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// query if this interface supports this play area mode
|
// query if this interface supports this play area mode
|
||||||
bool XRInterface::supports_play_area_mode(XRInterface::PlayAreaMode p_mode) {
|
bool XRInterface::supports_play_area_mode(XRInterface::PlayAreaMode p_mode) {
|
||||||
|
@ -151,6 +156,85 @@ int XRInterface::get_camera_feed_id() {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RID XRInterface::get_vrs_texture() {
|
||||||
|
// Default logic will return a standard VRS image based on our target size and default projections.
|
||||||
|
// Note that this only gets called if VRS is supported on the hardware.
|
||||||
|
|
||||||
|
Size2 texel_size = Size2(16.0, 16.0); // For now we assume we always use 16x16 texels, seems to be the standard.
|
||||||
|
int view_count = get_view_count();
|
||||||
|
Size2 target_size = get_render_target_size();
|
||||||
|
real_t aspect = target_size.x / target_size.y; // is this y/x ?
|
||||||
|
Size2 vrs_size = Size2(round(0.5 + target_size.x / texel_size.x), round(0.5 + target_size.y / texel_size.y));
|
||||||
|
real_t radius = vrs_size.length() * 0.5;
|
||||||
|
Size2 vrs_sizei = vrs_size;
|
||||||
|
|
||||||
|
if (vrs.size != vrs_sizei) {
|
||||||
|
const uint8_t densities[] = {
|
||||||
|
0, // 1x1
|
||||||
|
1, // 1x2
|
||||||
|
// 4, // 2x1
|
||||||
|
5, // 2x2
|
||||||
|
6, // 2x4
|
||||||
|
// 9, // 4x2
|
||||||
|
10, // 4x4
|
||||||
|
};
|
||||||
|
|
||||||
|
// out with the old
|
||||||
|
if (vrs.vrs_texture.is_valid()) {
|
||||||
|
RS::get_singleton()->free(vrs.vrs_texture);
|
||||||
|
vrs.vrs_texture = RID();
|
||||||
|
}
|
||||||
|
|
||||||
|
// in with the new
|
||||||
|
Vector<Ref<Image>> images;
|
||||||
|
vrs.size = vrs_sizei;
|
||||||
|
|
||||||
|
for (int i = 0; i < view_count && i < 2; i++) {
|
||||||
|
PackedByteArray data;
|
||||||
|
data.resize(vrs_sizei.x * vrs_sizei.y);
|
||||||
|
uint8_t *data_ptr = data.ptrw();
|
||||||
|
|
||||||
|
// Our near and far don't matter much for what we're doing here, but there are some interfaces that will remember this as the near and far and may fail as a result...
|
||||||
|
CameraMatrix cm = get_projection_for_view(i, aspect, 0.1, 1000.0);
|
||||||
|
Vector3 center = cm.xform(Vector3(0.0, 0.0, 999.0));
|
||||||
|
|
||||||
|
Vector2i view_center;
|
||||||
|
view_center.x = int(vrs_size.x * (center.x + 1.0) * 0.5);
|
||||||
|
view_center.y = int(vrs_size.y * (center.y + 1.0) * 0.5);
|
||||||
|
|
||||||
|
int d = 0;
|
||||||
|
for (int y = 0; y < vrs_sizei.y; y++) {
|
||||||
|
for (int x = 0; x < vrs_sizei.x; x++) {
|
||||||
|
Vector2 offset = Vector2(x - view_center.x, y - view_center.y);
|
||||||
|
offset.y *= aspect;
|
||||||
|
real_t distance = offset.length();
|
||||||
|
int idx = round(5.0 * distance / radius);
|
||||||
|
if (idx > 4) {
|
||||||
|
idx = 4;
|
||||||
|
}
|
||||||
|
uint8_t density = densities[idx];
|
||||||
|
|
||||||
|
data_ptr[d++] = density;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ref<Image> image;
|
||||||
|
image.instantiate();
|
||||||
|
image->create_from_data(vrs_sizei.x, vrs_sizei.y, false, Image::FORMAT_R8, data);
|
||||||
|
|
||||||
|
images.push_back(image);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (images.size() == 1) {
|
||||||
|
vrs.vrs_texture = RS::get_singleton()->texture_2d_create(images[0]);
|
||||||
|
} else {
|
||||||
|
vrs.vrs_texture = RS::get_singleton()->texture_2d_layered_create(images, RS::TEXTURE_LAYERED_2D_ARRAY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return vrs.vrs_texture;
|
||||||
|
}
|
||||||
|
|
||||||
/** these are optional, so we want dummies **/
|
/** these are optional, so we want dummies **/
|
||||||
PackedStringArray XRInterface::get_suggested_tracker_names() const {
|
PackedStringArray XRInterface::get_suggested_tracker_names() const {
|
||||||
PackedStringArray arr;
|
PackedStringArray arr;
|
||||||
|
|
|
@ -120,6 +120,7 @@ public:
|
||||||
virtual Transform3D get_camera_transform() = 0; /* returns the position of our camera for updating our camera node. For monoscopic this is equal to the views transform, for stereoscopic this should be an average */
|
virtual Transform3D get_camera_transform() = 0; /* returns the position of our camera for updating our camera node. For monoscopic this is equal to the views transform, for stereoscopic this should be an average */
|
||||||
virtual Transform3D get_transform_for_view(uint32_t p_view, const Transform3D &p_cam_transform) = 0; /* get each views transform */
|
virtual Transform3D get_transform_for_view(uint32_t p_view, const Transform3D &p_cam_transform) = 0; /* get each views transform */
|
||||||
virtual CameraMatrix get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) = 0; /* get each view projection matrix */
|
virtual CameraMatrix get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) = 0; /* get each view projection matrix */
|
||||||
|
virtual RID get_vrs_texture(); /* obtain VRS texture */
|
||||||
|
|
||||||
// note, external color/depth/vrs texture support will be added here soon.
|
// note, external color/depth/vrs texture support will be added here soon.
|
||||||
|
|
||||||
|
@ -133,6 +134,12 @@ public:
|
||||||
|
|
||||||
XRInterface();
|
XRInterface();
|
||||||
~XRInterface();
|
~XRInterface();
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct VRSData {
|
||||||
|
RID vrs_texture;
|
||||||
|
Size2i size;
|
||||||
|
} vrs;
|
||||||
};
|
};
|
||||||
|
|
||||||
VARIANT_ENUM_CAST(XRInterface::Capabilities);
|
VARIANT_ENUM_CAST(XRInterface::Capabilities);
|
||||||
|
|
|
@ -50,6 +50,7 @@ void XRInterfaceExtension::_bind_methods() {
|
||||||
GDVIRTUAL_BIND(_get_camera_transform);
|
GDVIRTUAL_BIND(_get_camera_transform);
|
||||||
GDVIRTUAL_BIND(_get_transform_for_view, "view", "cam_transform");
|
GDVIRTUAL_BIND(_get_transform_for_view, "view", "cam_transform");
|
||||||
GDVIRTUAL_BIND(_get_projection_for_view, "view", "aspect", "z_near", "z_far");
|
GDVIRTUAL_BIND(_get_projection_for_view, "view", "aspect", "z_near", "z_far");
|
||||||
|
GDVIRTUAL_BIND(_get_vrs_texture);
|
||||||
|
|
||||||
GDVIRTUAL_BIND(_process);
|
GDVIRTUAL_BIND(_process);
|
||||||
GDVIRTUAL_BIND(_pre_render);
|
GDVIRTUAL_BIND(_pre_render);
|
||||||
|
@ -273,6 +274,15 @@ CameraMatrix XRInterfaceExtension::get_projection_for_view(uint32_t p_view, doub
|
||||||
return CameraMatrix();
|
return CameraMatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RID XRInterfaceExtension::get_vrs_texture() {
|
||||||
|
RID vrs_texture;
|
||||||
|
if (GDVIRTUAL_CALL(_get_vrs_texture, vrs_texture)) {
|
||||||
|
return vrs_texture;
|
||||||
|
} else {
|
||||||
|
return XRInterface::get_vrs_texture();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void XRInterfaceExtension::add_blit(RID p_render_target, Rect2 p_src_rect, Rect2i p_dst_rect, bool p_use_layer, uint32_t p_layer, bool p_apply_lens_distortion, Vector2 p_eye_center, double p_k1, double p_k2, double p_upscale, double p_aspect_ratio) {
|
void XRInterfaceExtension::add_blit(RID p_render_target, Rect2 p_src_rect, Rect2i p_dst_rect, bool p_use_layer, uint32_t p_layer, bool p_apply_lens_distortion, Vector2 p_eye_center, double p_k1, double p_k2, double p_upscale, double p_aspect_ratio) {
|
||||||
BlitToScreen blit;
|
BlitToScreen blit;
|
||||||
|
|
||||||
|
|
|
@ -101,12 +101,14 @@ public:
|
||||||
virtual Transform3D get_camera_transform() override;
|
virtual Transform3D get_camera_transform() override;
|
||||||
virtual Transform3D get_transform_for_view(uint32_t p_view, const Transform3D &p_cam_transform) override;
|
virtual Transform3D get_transform_for_view(uint32_t p_view, const Transform3D &p_cam_transform) override;
|
||||||
virtual CameraMatrix get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) override;
|
virtual CameraMatrix get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) override;
|
||||||
|
virtual RID get_vrs_texture() override;
|
||||||
|
|
||||||
GDVIRTUAL0R(Size2, _get_render_target_size);
|
GDVIRTUAL0R(Size2, _get_render_target_size);
|
||||||
GDVIRTUAL0R(uint32_t, _get_view_count);
|
GDVIRTUAL0R(uint32_t, _get_view_count);
|
||||||
GDVIRTUAL0R(Transform3D, _get_camera_transform);
|
GDVIRTUAL0R(Transform3D, _get_camera_transform);
|
||||||
GDVIRTUAL2R(Transform3D, _get_transform_for_view, uint32_t, const Transform3D &);
|
GDVIRTUAL2R(Transform3D, _get_transform_for_view, uint32_t, const Transform3D &);
|
||||||
GDVIRTUAL4R(PackedFloat64Array, _get_projection_for_view, uint32_t, double, double, double);
|
GDVIRTUAL4R(PackedFloat64Array, _get_projection_for_view, uint32_t, double, double, double);
|
||||||
|
GDVIRTUAL0R(RID, _get_vrs_texture);
|
||||||
|
|
||||||
void add_blit(RID p_render_target, Rect2 p_src_rect, Rect2i p_dst_rect, bool p_use_layer = false, uint32_t p_layer = 0, bool p_apply_lens_distortion = false, Vector2 p_eye_center = Vector2(), double p_k1 = 0.0, double p_k2 = 0.0, double p_upscale = 1.0, double p_aspect_ratio = 1.0);
|
void add_blit(RID p_render_target, Rect2 p_src_rect, Rect2i p_dst_rect, bool p_use_layer = false, uint32_t p_layer = 0, bool p_apply_lens_distortion = false, Vector2 p_eye_center = Vector2(), double p_k1 = 0.0, double p_k2 = 0.0, double p_upscale = 1.0, double p_aspect_ratio = 1.0);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue