mirror of
https://github.com/godotengine/godot.git
synced 2025-04-07 00:44:24 +08:00
Implement support for fragment density maps.
Co-Authored-By: Bastiaan Olij <mux213@gmail.com>
This commit is contained in:
parent
f2cc3f1275
commit
76d709be74
@ -1222,7 +1222,7 @@ RDD::TextureID RenderingDeviceDriverD3D12::texture_create(const TextureFormat &p
|
||||
if ((p_format.usage_bits & TEXTURE_USAGE_STORAGE_BIT)) {
|
||||
resource_desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
|
||||
}
|
||||
if ((p_format.usage_bits & TEXTURE_USAGE_VRS_ATTACHMENT_BIT)) {
|
||||
if ((p_format.usage_bits & TEXTURE_USAGE_VRS_ATTACHMENT_BIT) && (p_format.usage_bits & TEXTURE_USAGE_VRS_FRAGMENT_SHADING_RATE_BIT)) {
|
||||
// For VRS images we can't use the typeless format.
|
||||
resource_desc.Format = DXGI_FORMAT_R8_UINT;
|
||||
}
|
||||
@ -1827,8 +1827,11 @@ static D3D12_BARRIER_ACCESS _rd_texture_layout_access_mask(RDD::TextureLayout p_
|
||||
return D3D12_BARRIER_ACCESS_RESOLVE_SOURCE;
|
||||
case RDD::TEXTURE_LAYOUT_RESOLVE_DST_OPTIMAL:
|
||||
return D3D12_BARRIER_ACCESS_RESOLVE_DEST;
|
||||
case RDD::TEXTURE_LAYOUT_VRS_ATTACHMENT_OPTIMAL:
|
||||
case RDD::TEXTURE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL:
|
||||
return D3D12_BARRIER_ACCESS_SHADING_RATE_SOURCE;
|
||||
case RDD::TEXTURE_LAYOUT_FRAGMENT_DENSITY_MAP_ATTACHMENT_OPTIMAL:
|
||||
DEV_ASSERT(false && "Fragment density maps are not supported in D3D12.");
|
||||
return D3D12_BARRIER_ACCESS_NO_ACCESS;
|
||||
default:
|
||||
return D3D12_BARRIER_ACCESS_NO_ACCESS;
|
||||
}
|
||||
@ -1947,7 +1950,7 @@ static void _rd_stages_to_d3d12(BitField<RDD::PipelineStageBits> p_stages, D3D12
|
||||
r_sync |= D3D12_BARRIER_SYNC_VERTEX_SHADING;
|
||||
}
|
||||
|
||||
if (p_stages.has_flag(RDD::PIPELINE_STAGE_FRAGMENT_SHADER_BIT)) {
|
||||
if (p_stages.has_flag(RDD::PIPELINE_STAGE_FRAGMENT_SHADER_BIT) || p_stages.has_flag(RDD::PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT)) {
|
||||
r_sync |= D3D12_BARRIER_SYNC_PIXEL_SHADING;
|
||||
}
|
||||
|
||||
@ -2042,8 +2045,11 @@ static D3D12_BARRIER_LAYOUT _rd_texture_layout_to_d3d12_barrier_layout(RDD::Text
|
||||
return D3D12_BARRIER_LAYOUT_RESOLVE_SOURCE;
|
||||
case RDD::TEXTURE_LAYOUT_RESOLVE_DST_OPTIMAL:
|
||||
return D3D12_BARRIER_LAYOUT_RESOLVE_DEST;
|
||||
case RDD::TEXTURE_LAYOUT_VRS_ATTACHMENT_OPTIMAL:
|
||||
case RDD::TEXTURE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL:
|
||||
return D3D12_BARRIER_LAYOUT_SHADING_RATE_SOURCE;
|
||||
case RDD::TEXTURE_LAYOUT_FRAGMENT_DENSITY_MAP_ATTACHMENT_OPTIMAL:
|
||||
DEV_ASSERT(false && "Fragment density maps are not supported in D3D12.");
|
||||
return D3D12_BARRIER_LAYOUT_UNDEFINED;
|
||||
default:
|
||||
DEV_ASSERT(false && "Unknown texture layout.");
|
||||
return D3D12_BARRIER_LAYOUT_UNDEFINED;
|
||||
@ -2451,7 +2457,7 @@ RDD::SwapChainID RenderingDeviceDriverD3D12::swap_chain_create(RenderingContextD
|
||||
color_ref.aspect.set_flag(RDD::TEXTURE_ASPECT_COLOR_BIT);
|
||||
subpass.color_references.push_back(color_ref);
|
||||
|
||||
RenderPassID render_pass = render_pass_create(attachment, subpass, {}, 1);
|
||||
RenderPassID render_pass = render_pass_create(attachment, subpass, {}, 1, AttachmentReference());
|
||||
ERR_FAIL_COND_V(!render_pass, SwapChainID());
|
||||
|
||||
// Create the empty swap chain until it is resized.
|
||||
@ -2811,8 +2817,8 @@ RDD::FramebufferID RenderingDeviceDriverD3D12::_framebuffer_create(RenderPassID
|
||||
|
||||
uint32_t vrs_index = UINT32_MAX;
|
||||
for (const Subpass &E : pass_info->subpasses) {
|
||||
if (E.vrs_reference.attachment != AttachmentReference::UNUSED) {
|
||||
vrs_index = E.vrs_reference.attachment;
|
||||
if (E.fragment_shading_rate_reference.attachment != AttachmentReference::UNUSED) {
|
||||
vrs_index = E.fragment_shading_rate_reference.attachment;
|
||||
}
|
||||
}
|
||||
|
||||
@ -4963,7 +4969,9 @@ Vector<uint8_t> RenderingDeviceDriverD3D12::pipeline_cache_serialize() {
|
||||
|
||||
// ----- SUBPASS -----
|
||||
|
||||
RDD::RenderPassID RenderingDeviceDriverD3D12::render_pass_create(VectorView<Attachment> p_attachments, VectorView<Subpass> p_subpasses, VectorView<SubpassDependency> p_subpass_dependencies, uint32_t p_view_count) {
|
||||
RDD::RenderPassID RenderingDeviceDriverD3D12::render_pass_create(VectorView<Attachment> p_attachments, VectorView<Subpass> p_subpasses, VectorView<SubpassDependency> p_subpass_dependencies, uint32_t p_view_count, AttachmentReference p_fragment_density_map_attachment) {
|
||||
ERR_FAIL_COND_V_MSG(p_fragment_density_map_attachment.attachment != AttachmentReference::UNUSED, RenderPassID(), "Fragment density maps are not supported in D3D12.");
|
||||
|
||||
// Pre-bookkeep.
|
||||
RenderPassInfo *pass_info = VersatileResource::allocate<RenderPassInfo>(resources_allocator);
|
||||
|
||||
@ -5064,7 +5072,7 @@ void RenderingDeviceDriverD3D12::command_begin_render_pass(CommandBufferID p_cmd
|
||||
}
|
||||
}
|
||||
|
||||
if (fb_info->vrs_attachment && vrs_capabilities.ss_image_supported) {
|
||||
if (fb_info->vrs_attachment && fsr_capabilities.attachment_supported) {
|
||||
ComPtr<ID3D12GraphicsCommandList5> cmd_list_5;
|
||||
cmd_buf_info->cmd_list->QueryInterface(cmd_list_5.GetAddressOf());
|
||||
if (cmd_list_5) {
|
||||
@ -5184,7 +5192,7 @@ void RenderingDeviceDriverD3D12::command_end_render_pass(CommandBufferID p_cmd_b
|
||||
const FramebufferInfo *fb_info = cmd_buf_info->render_pass_state.fb_info;
|
||||
const RenderPassInfo *pass_info = cmd_buf_info->render_pass_state.pass_info;
|
||||
|
||||
if (vrs_capabilities.ss_image_supported) {
|
||||
if (fsr_capabilities.attachment_supported) {
|
||||
ComPtr<ID3D12GraphicsCommandList5> cmd_list_5;
|
||||
cmd_buf_info->cmd_list->QueryInterface(cmd_list_5.GetAddressOf());
|
||||
if (cmd_list_5) {
|
||||
@ -6244,12 +6252,6 @@ uint64_t RenderingDeviceDriverD3D12::limit_get(Limit p_limit) {
|
||||
return subgroup_capabilities.supported_stages_flags_rd();
|
||||
case LIMIT_SUBGROUP_OPERATIONS:
|
||||
return subgroup_capabilities.supported_operations_flags_rd();
|
||||
case LIMIT_VRS_TEXEL_WIDTH:
|
||||
case LIMIT_VRS_TEXEL_HEIGHT:
|
||||
return vrs_capabilities.ss_image_tile_size;
|
||||
case LIMIT_VRS_MAX_FRAGMENT_WIDTH:
|
||||
case LIMIT_VRS_MAX_FRAGMENT_HEIGHT:
|
||||
return vrs_capabilities.ss_max_fragment_size;
|
||||
case LIMIT_MAX_SHADER_VARYINGS:
|
||||
return MIN(D3D12_VS_OUTPUT_REGISTER_COUNT, D3D12_PS_INPUT_REGISTER_COUNT);
|
||||
default: {
|
||||
@ -6286,12 +6288,8 @@ uint64_t RenderingDeviceDriverD3D12::api_trait_get(ApiTrait p_trait) {
|
||||
|
||||
bool RenderingDeviceDriverD3D12::has_feature(Features p_feature) {
|
||||
switch (p_feature) {
|
||||
case SUPPORTS_MULTIVIEW:
|
||||
return multiview_capabilities.is_supported && multiview_capabilities.max_view_count > 1;
|
||||
case SUPPORTS_FSR_HALF_FLOAT:
|
||||
return shader_capabilities.native_16bit_ops && storage_buffer_capabilities.storage_buffer_16_bit_access_is_supported;
|
||||
case SUPPORTS_ATTACHMENT_VRS:
|
||||
return vrs_capabilities.ss_image_supported;
|
||||
case SUPPORTS_FRAGMENT_SHADER_WITH_ONLY_SIDE_EFFECTS:
|
||||
return true;
|
||||
case SUPPORTS_BUFFER_DEVICE_ADDRESS:
|
||||
@ -6305,6 +6303,14 @@ const RDD::MultiviewCapabilities &RenderingDeviceDriverD3D12::get_multiview_capa
|
||||
return multiview_capabilities;
|
||||
}
|
||||
|
||||
const RDD::FragmentShadingRateCapabilities &RenderingDeviceDriverD3D12::get_fragment_shading_rate_capabilities() {
|
||||
return fsr_capabilities;
|
||||
}
|
||||
|
||||
const RDD::FragmentDensityMapCapabilities &RenderingDeviceDriverD3D12::get_fragment_density_map_capabilities() {
|
||||
return fdm_capabilities;
|
||||
}
|
||||
|
||||
String RenderingDeviceDriverD3D12::get_api_name() const {
|
||||
return "D3D12";
|
||||
}
|
||||
@ -6466,12 +6472,6 @@ Error RenderingDeviceDriverD3D12::_check_capabilities() {
|
||||
device_capabilities.version_minor = feature_level % 10;
|
||||
|
||||
// Assume not supported until proven otherwise.
|
||||
vrs_capabilities.draw_call_supported = false;
|
||||
vrs_capabilities.primitive_supported = false;
|
||||
vrs_capabilities.primitive_in_multiviewport = false;
|
||||
vrs_capabilities.ss_image_supported = false;
|
||||
vrs_capabilities.ss_image_tile_size = 1;
|
||||
vrs_capabilities.additional_rates_supported = false;
|
||||
multiview_capabilities.is_supported = false;
|
||||
multiview_capabilities.geometry_shader_is_supported = false;
|
||||
multiview_capabilities.tessellation_shader_is_supported = false;
|
||||
@ -6562,14 +6562,12 @@ Error RenderingDeviceDriverD3D12::_check_capabilities() {
|
||||
res = device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS6, &options6, sizeof(options6));
|
||||
if (SUCCEEDED(res)) {
|
||||
if (options6.VariableShadingRateTier >= D3D12_VARIABLE_SHADING_RATE_TIER_1) {
|
||||
vrs_capabilities.draw_call_supported = true;
|
||||
fsr_capabilities.pipeline_supported = true;
|
||||
if (options6.VariableShadingRateTier >= D3D12_VARIABLE_SHADING_RATE_TIER_2) {
|
||||
vrs_capabilities.primitive_supported = true;
|
||||
vrs_capabilities.primitive_in_multiviewport = options6.PerPrimitiveShadingRateSupportedWithViewportIndexing;
|
||||
vrs_capabilities.ss_image_supported = true;
|
||||
vrs_capabilities.ss_image_tile_size = options6.ShadingRateImageTileSize;
|
||||
vrs_capabilities.ss_max_fragment_size = 8; // TODO figure out if this is supplied and/or needed
|
||||
vrs_capabilities.additional_rates_supported = options6.AdditionalShadingRatesSupported;
|
||||
fsr_capabilities.primitive_supported = true;
|
||||
fsr_capabilities.attachment_supported = true;
|
||||
fsr_capabilities.min_texel_size = Size2i(options6.ShadingRateImageTileSize, options6.ShadingRateImageTileSize);
|
||||
fsr_capabilities.max_texel_size = Size2i(8, 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -6581,19 +6579,16 @@ Error RenderingDeviceDriverD3D12::_check_capabilities() {
|
||||
barrier_capabilities.enhanced_barriers_supported = options12.EnhancedBarriersSupported;
|
||||
}
|
||||
|
||||
if (vrs_capabilities.draw_call_supported || vrs_capabilities.primitive_supported || vrs_capabilities.ss_image_supported) {
|
||||
if (fsr_capabilities.pipeline_supported || fsr_capabilities.primitive_supported || fsr_capabilities.attachment_supported) {
|
||||
print_verbose("- D3D12 Variable Rate Shading supported:");
|
||||
if (vrs_capabilities.draw_call_supported) {
|
||||
if (fsr_capabilities.pipeline_supported) {
|
||||
print_verbose(" Draw call");
|
||||
}
|
||||
if (vrs_capabilities.primitive_supported) {
|
||||
print_verbose(String(" Per-primitive (multi-viewport: ") + (vrs_capabilities.primitive_in_multiviewport ? "yes" : "no") + ")");
|
||||
if (fsr_capabilities.primitive_supported) {
|
||||
print_verbose(" Primitive");
|
||||
}
|
||||
if (vrs_capabilities.ss_image_supported) {
|
||||
print_verbose(String(" Screen-space image (tile size: ") + itos(vrs_capabilities.ss_image_tile_size) + ")");
|
||||
}
|
||||
if (vrs_capabilities.additional_rates_supported) {
|
||||
print_verbose(String(" Additional rates: ") + (vrs_capabilities.additional_rates_supported ? "yes" : "no"));
|
||||
if (fsr_capabilities.attachment_supported) {
|
||||
print_verbose(String(" Screen-space image (tile size: ") + itos(fsr_capabilities.min_texel_size.x) + ")");
|
||||
}
|
||||
} else {
|
||||
print_verbose("- D3D12 Variable Rate Shading not supported");
|
||||
|
@ -116,16 +116,6 @@ class RenderingDeviceDriverD3D12 : public RenderingDeviceDriver {
|
||||
uint32_t supported_operations_flags_rd() const;
|
||||
};
|
||||
|
||||
struct VRSCapabilities {
|
||||
bool draw_call_supported = false; // We can specify our fragment rate on a draw call level.
|
||||
bool primitive_supported = false; // We can specify our fragment rate on each drawcall.
|
||||
bool primitive_in_multiviewport = false;
|
||||
bool ss_image_supported = false; // We can provide a density map attachment on our framebuffer.
|
||||
uint32_t ss_image_tile_size = 0;
|
||||
uint32_t ss_max_fragment_size = 0;
|
||||
bool additional_rates_supported = false;
|
||||
};
|
||||
|
||||
struct ShaderCapabilities {
|
||||
D3D_SHADER_MODEL shader_model = (D3D_SHADER_MODEL)0;
|
||||
bool native_16bit_ops = false;
|
||||
@ -157,7 +147,8 @@ class RenderingDeviceDriverD3D12 : public RenderingDeviceDriver {
|
||||
uint32_t feature_level = 0; // Major * 10 + minor.
|
||||
SubgroupCapabilities subgroup_capabilities;
|
||||
RDD::MultiviewCapabilities multiview_capabilities;
|
||||
VRSCapabilities vrs_capabilities;
|
||||
FragmentShadingRateCapabilities fsr_capabilities;
|
||||
FragmentDensityMapCapabilities fdm_capabilities;
|
||||
ShaderCapabilities shader_capabilities;
|
||||
StorageBufferCapabilities storage_buffer_capabilities;
|
||||
FormatCapabilities format_capabilities;
|
||||
@ -834,7 +825,7 @@ private:
|
||||
};
|
||||
|
||||
public:
|
||||
virtual RenderPassID render_pass_create(VectorView<Attachment> p_attachments, VectorView<Subpass> p_subpasses, VectorView<SubpassDependency> p_subpass_dependencies, uint32_t p_view_count) override final;
|
||||
virtual RenderPassID render_pass_create(VectorView<Attachment> p_attachments, VectorView<Subpass> p_subpasses, VectorView<SubpassDependency> p_subpass_dependencies, uint32_t p_view_count, AttachmentReference p_fragment_density_map_attachment) override final;
|
||||
virtual void render_pass_free(RenderPassID p_render_pass) override final;
|
||||
|
||||
// ----- COMMANDS -----
|
||||
@ -1002,6 +993,8 @@ public:
|
||||
virtual uint64_t api_trait_get(ApiTrait p_trait) override final;
|
||||
virtual bool has_feature(Features p_feature) override final;
|
||||
virtual const MultiviewCapabilities &get_multiview_capabilities() override final;
|
||||
virtual const FragmentShadingRateCapabilities &get_fragment_shading_rate_capabilities() override final;
|
||||
virtual const FragmentDensityMapCapabilities &get_fragment_density_map_capabilities() override final;
|
||||
virtual String get_api_name() const override final;
|
||||
virtual String get_api_version() const override final;
|
||||
virtual String get_pipeline_cache_uuid() const override final;
|
||||
|
@ -66,6 +66,8 @@ class API_AVAILABLE(macos(11.0), ios(14.0), tvos(14.0)) RenderingDeviceDriverMet
|
||||
|
||||
RDD::Capabilities capabilities;
|
||||
RDD::MultiviewCapabilities multiview_capabilities;
|
||||
RDD::FragmentShadingRateCapabilities fsr_capabilities;
|
||||
RDD::FragmentDensityMapCapabilities fdm_capabilities;
|
||||
|
||||
id<MTLBinaryArchive> archive = nil;
|
||||
uint32_t archive_count = 0;
|
||||
@ -316,7 +318,7 @@ public:
|
||||
|
||||
// ----- SUBPASS -----
|
||||
|
||||
virtual RenderPassID render_pass_create(VectorView<Attachment> p_attachments, VectorView<Subpass> p_subpasses, VectorView<SubpassDependency> p_subpass_dependencies, uint32_t p_view_count) override final;
|
||||
virtual RenderPassID render_pass_create(VectorView<Attachment> p_attachments, VectorView<Subpass> p_subpasses, VectorView<SubpassDependency> p_subpass_dependencies, uint32_t p_view_count, AttachmentReference p_fragment_density_map_attachment) override final;
|
||||
virtual void render_pass_free(RenderPassID p_render_pass) override final;
|
||||
|
||||
// ----- COMMANDS -----
|
||||
@ -421,6 +423,8 @@ public:
|
||||
virtual uint64_t api_trait_get(ApiTrait p_trait) override final;
|
||||
virtual bool has_feature(Features p_feature) override final;
|
||||
virtual const MultiviewCapabilities &get_multiview_capabilities() override final;
|
||||
virtual const FragmentShadingRateCapabilities &get_fragment_shading_rate_capabilities() override final;
|
||||
virtual const FragmentDensityMapCapabilities &get_fragment_density_map_capabilities() override final;
|
||||
virtual String get_api_name() const override final { return "Metal"; }
|
||||
virtual String get_api_version() const override final;
|
||||
virtual String get_pipeline_cache_uuid() const override final;
|
||||
|
@ -974,7 +974,7 @@ RDD::SwapChainID RenderingDeviceDriverMetal::swap_chain_create(RenderingContextD
|
||||
color_ref.aspect.set_flag(RDD::TEXTURE_ASPECT_COLOR_BIT);
|
||||
subpass.color_references.push_back(color_ref);
|
||||
|
||||
RenderPassID render_pass = render_pass_create(attachment, subpass, {}, 1);
|
||||
RenderPassID render_pass = render_pass_create(attachment, subpass, {}, 1, RDD::AttachmentReference());
|
||||
ERR_FAIL_COND_V(!render_pass, SwapChainID());
|
||||
|
||||
// Create the empty swap chain until it is resized.
|
||||
@ -3104,7 +3104,7 @@ Vector<uint8_t> RenderingDeviceDriverMetal::pipeline_cache_serialize() {
|
||||
|
||||
// ----- SUBPASS -----
|
||||
|
||||
RDD::RenderPassID RenderingDeviceDriverMetal::render_pass_create(VectorView<Attachment> p_attachments, VectorView<Subpass> p_subpasses, VectorView<SubpassDependency> p_subpass_dependencies, uint32_t p_view_count) {
|
||||
RDD::RenderPassID RenderingDeviceDriverMetal::render_pass_create(VectorView<Attachment> p_attachments, VectorView<Subpass> p_subpasses, VectorView<SubpassDependency> p_subpass_dependencies, uint32_t p_view_count, AttachmentReference p_fragment_density_map_attachment) {
|
||||
PixelFormats &pf = *pixel_formats;
|
||||
|
||||
size_t subpass_count = p_subpasses.size();
|
||||
@ -4006,10 +4006,6 @@ uint64_t RenderingDeviceDriverMetal::limit_get(Limit p_limit) {
|
||||
return (uint64_t)((1.0 / limits.temporalScalerInputContentMinScale) * 1000'000);
|
||||
case LIMIT_MAX_SHADER_VARYINGS:
|
||||
return limits.maxShaderVaryings;
|
||||
UNKNOWN(LIMIT_VRS_TEXEL_WIDTH);
|
||||
UNKNOWN(LIMIT_VRS_TEXEL_HEIGHT);
|
||||
UNKNOWN(LIMIT_VRS_MAX_FRAGMENT_WIDTH);
|
||||
UNKNOWN(LIMIT_VRS_MAX_FRAGMENT_HEIGHT);
|
||||
default: {
|
||||
#ifdef DEV_ENABLED
|
||||
WARN_PRINT("Returning maximum value for unknown limit " + itos(p_limit) + ".");
|
||||
@ -4032,17 +4028,8 @@ uint64_t RenderingDeviceDriverMetal::api_trait_get(ApiTrait p_trait) {
|
||||
|
||||
bool RenderingDeviceDriverMetal::has_feature(Features p_feature) {
|
||||
switch (p_feature) {
|
||||
case SUPPORTS_MULTIVIEW:
|
||||
return multiview_capabilities.is_supported;
|
||||
case SUPPORTS_FSR_HALF_FLOAT:
|
||||
return true;
|
||||
case SUPPORTS_ATTACHMENT_VRS:
|
||||
// TODO(sgc): Maybe supported via https://developer.apple.com/documentation/metal/render_passes/rendering_at_different_rasterization_rates?language=objc
|
||||
// See also:
|
||||
//
|
||||
// * https://forum.beyond3d.com/threads/variable-rate-shading-vs-variable-rate-rasterization.62243/post-2191363
|
||||
//
|
||||
return false;
|
||||
case SUPPORTS_FRAGMENT_SHADER_WITH_ONLY_SIDE_EFFECTS:
|
||||
return true;
|
||||
case SUPPORTS_BUFFER_DEVICE_ADDRESS:
|
||||
@ -4060,6 +4047,14 @@ const RDD::MultiviewCapabilities &RenderingDeviceDriverMetal::get_multiview_capa
|
||||
return multiview_capabilities;
|
||||
}
|
||||
|
||||
const RDD::FragmentShadingRateCapabilities &RenderingDeviceDriverMetal::get_fragment_shading_rate_capabilities() {
|
||||
return fsr_capabilities;
|
||||
}
|
||||
|
||||
const RDD::FragmentDensityMapCapabilities &RenderingDeviceDriverMetal::get_fragment_density_map_capabilities() {
|
||||
return fdm_capabilities;
|
||||
}
|
||||
|
||||
String RenderingDeviceDriverMetal::get_api_version() const {
|
||||
return vformat("%d.%d", version_major, version_minor);
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -54,6 +54,9 @@ class RenderingDeviceDriverVulkan : public RenderingDeviceDriver {
|
||||
|
||||
struct CommandQueue;
|
||||
struct SwapChain;
|
||||
struct CommandBufferInfo;
|
||||
struct RenderPassInfo;
|
||||
struct Framebuffer;
|
||||
|
||||
struct Queue {
|
||||
VkQueue queue = VK_NULL_HANDLE;
|
||||
@ -76,18 +79,6 @@ class RenderingDeviceDriverVulkan : public RenderingDeviceDriver {
|
||||
String supported_operations_desc() const;
|
||||
};
|
||||
|
||||
struct VRSCapabilities {
|
||||
bool pipeline_vrs_supported = false; // We can specify our fragment rate on a pipeline level.
|
||||
bool primitive_vrs_supported = false; // We can specify our fragment rate on each drawcall.
|
||||
bool attachment_vrs_supported = false; // We can provide a density map attachment on our framebuffer.
|
||||
|
||||
Size2i min_texel_size;
|
||||
Size2i max_texel_size;
|
||||
Size2i max_fragment_size;
|
||||
|
||||
Size2i texel_size; // The texel size we'll use
|
||||
};
|
||||
|
||||
struct ShaderCapabilities {
|
||||
bool shader_float16_is_supported = false;
|
||||
bool shader_int8_is_supported = false;
|
||||
@ -107,6 +98,7 @@ class RenderingDeviceDriverVulkan : public RenderingDeviceDriver {
|
||||
PFN_vkAcquireNextImageKHR AcquireNextImageKHR = nullptr;
|
||||
PFN_vkQueuePresentKHR QueuePresentKHR = nullptr;
|
||||
PFN_vkCreateRenderPass2KHR CreateRenderPass2KHR = nullptr;
|
||||
PFN_vkCmdEndRenderPass2KHR EndRenderPass2KHR = nullptr;
|
||||
|
||||
// Debug marker extensions.
|
||||
PFN_vkCmdDebugMarkerBeginEXT CmdDebugMarkerBeginEXT = nullptr;
|
||||
@ -135,7 +127,8 @@ class RenderingDeviceDriverVulkan : public RenderingDeviceDriver {
|
||||
RDD::Capabilities device_capabilities;
|
||||
SubgroupCapabilities subgroup_capabilities;
|
||||
MultiviewCapabilities multiview_capabilities;
|
||||
VRSCapabilities vrs_capabilities;
|
||||
FragmentShadingRateCapabilities fsr_capabilities;
|
||||
FragmentDensityMapCapabilities fdm_capabilities;
|
||||
ShaderCapabilities shader_capabilities;
|
||||
StorageBufferCapabilities storage_buffer_capabilities;
|
||||
bool buffer_device_address_support = false;
|
||||
@ -155,6 +148,7 @@ class RenderingDeviceDriverVulkan : public RenderingDeviceDriver {
|
||||
Error _initialize_device_extensions();
|
||||
Error _check_device_features();
|
||||
Error _check_device_capabilities();
|
||||
void _choose_vrs_capabilities();
|
||||
Error _add_queue_create_info(LocalVector<VkDeviceQueueCreateInfo> &r_queue_create_info);
|
||||
Error _initialize_device(const LocalVector<VkDeviceQueueCreateInfo> &p_queue_create_info);
|
||||
Error _initialize_allocator();
|
||||
@ -332,6 +326,7 @@ private:
|
||||
struct CommandPool {
|
||||
VkCommandPool vk_command_pool = VK_NULL_HANDLE;
|
||||
CommandBufferType buffer_type = COMMAND_BUFFER_TYPE_PRIMARY;
|
||||
LocalVector<CommandBufferInfo *> command_buffers_created;
|
||||
};
|
||||
|
||||
public:
|
||||
@ -339,8 +334,16 @@ public:
|
||||
virtual bool command_pool_reset(CommandPoolID p_cmd_pool) override final;
|
||||
virtual void command_pool_free(CommandPoolID p_cmd_pool) override final;
|
||||
|
||||
private:
|
||||
// ----- BUFFER -----
|
||||
|
||||
struct CommandBufferInfo {
|
||||
VkCommandBuffer vk_command_buffer = VK_NULL_HANDLE;
|
||||
Framebuffer *active_framebuffer = nullptr;
|
||||
RenderPassInfo *active_render_pass = nullptr;
|
||||
};
|
||||
|
||||
public:
|
||||
virtual CommandBufferID command_buffer_create(CommandPoolID p_cmd_pool) override final;
|
||||
virtual bool command_buffer_begin(CommandBufferID p_cmd_buffer) override final;
|
||||
virtual bool command_buffer_begin_secondary(CommandBufferID p_cmd_buffer, RenderPassID p_render_pass, uint32_t p_subpass, FramebufferID p_framebuffer) override final;
|
||||
@ -382,6 +385,7 @@ public:
|
||||
virtual void swap_chain_set_max_fps(SwapChainID p_swap_chain, int p_max_fps) override final;
|
||||
virtual void swap_chain_free(SwapChainID p_swap_chain) override final;
|
||||
|
||||
private:
|
||||
/*********************/
|
||||
/**** FRAMEBUFFER ****/
|
||||
/*********************/
|
||||
@ -389,12 +393,16 @@ public:
|
||||
struct Framebuffer {
|
||||
VkFramebuffer vk_framebuffer = VK_NULL_HANDLE;
|
||||
|
||||
// Only filled in if the framebuffer uses a fragment density map with offsets. Unused otherwise.
|
||||
uint32_t fragment_density_map_offsets_layers = 0;
|
||||
|
||||
// Only filled in by a framebuffer created by a swap chain. Unused otherwise.
|
||||
VkImage swap_chain_image = VK_NULL_HANDLE;
|
||||
VkImageSubresourceRange swap_chain_image_subresource_range = {};
|
||||
bool swap_chain_acquired = false;
|
||||
};
|
||||
|
||||
public:
|
||||
virtual FramebufferID framebuffer_create(RenderPassID p_render_pass, VectorView<TextureID> p_attachments, uint32_t p_width, uint32_t p_height) override final;
|
||||
virtual void framebuffer_free(FramebufferID p_framebuffer) override final;
|
||||
|
||||
@ -572,9 +580,16 @@ public:
|
||||
/**** RENDERING ****/
|
||||
/*******************/
|
||||
|
||||
private:
|
||||
// ----- SUBPASS -----
|
||||
|
||||
virtual RenderPassID render_pass_create(VectorView<Attachment> p_attachments, VectorView<Subpass> p_subpasses, VectorView<SubpassDependency> p_subpass_dependencies, uint32_t p_view_count) override final;
|
||||
struct RenderPassInfo {
|
||||
VkRenderPass vk_render_pass = VK_NULL_HANDLE;
|
||||
bool uses_fragment_density_map_offsets = false;
|
||||
};
|
||||
|
||||
public:
|
||||
virtual RenderPassID render_pass_create(VectorView<Attachment> p_attachments, VectorView<Subpass> p_subpasses, VectorView<SubpassDependency> p_subpass_dependencies, uint32_t p_view_count, AttachmentReference p_fragment_density_map_attachment) override final;
|
||||
virtual void render_pass_free(RenderPassID p_render_pass) override final;
|
||||
|
||||
// ----- COMMANDS -----
|
||||
@ -692,6 +707,8 @@ public:
|
||||
virtual uint64_t api_trait_get(ApiTrait p_trait) override final;
|
||||
virtual bool has_feature(Features p_feature) override final;
|
||||
virtual const MultiviewCapabilities &get_multiview_capabilities() override final;
|
||||
virtual const FragmentShadingRateCapabilities &get_fragment_shading_rate_capabilities() override final;
|
||||
virtual const FragmentDensityMapCapabilities &get_fragment_density_map_capabilities() override final;
|
||||
virtual String get_api_name() const override final;
|
||||
virtual String get_api_version() const override final;
|
||||
virtual String get_pipeline_cache_uuid() const override final;
|
||||
@ -709,7 +726,9 @@ private:
|
||||
TextureInfo,
|
||||
VertexFormatInfo,
|
||||
ShaderInfo,
|
||||
UniformSetInfo>;
|
||||
UniformSetInfo,
|
||||
RenderPassInfo,
|
||||
CommandBufferInfo>;
|
||||
PagedAllocator<VersatileResource, true> resources_allocator;
|
||||
|
||||
/******************/
|
||||
|
@ -44,6 +44,8 @@ VRS::VRS() {
|
||||
Vector<String> vrs_modes;
|
||||
vrs_modes.push_back("\n"); // VRS_DEFAULT
|
||||
vrs_modes.push_back("\n#define USE_MULTIVIEW\n"); // VRS_MULTIVIEW
|
||||
vrs_modes.push_back("\n#define SPLIT_RG\n"); // VRS_RG
|
||||
vrs_modes.push_back("\n#define SPLIT_RG\n#define USE_MULTIVIEW\n"); // VRS_RG_MULTIVIEW
|
||||
|
||||
vrs_shader.shader.initialize(vrs_modes);
|
||||
|
||||
@ -80,14 +82,16 @@ void VRS::copy_vrs(RID p_source_rd_texture, RID p_dest_framebuffer, bool p_multi
|
||||
|
||||
RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture }));
|
||||
|
||||
int mode = 0;
|
||||
VRSPushConstant push_constant = {};
|
||||
|
||||
int mode = p_multiview ? VRS_MULTIVIEW : VRS_DEFAULT;
|
||||
|
||||
// Set maximum texel factor based on maximum fragment size, some GPUs do not support 8x8 (fragment shading rate approach).
|
||||
if (MIN(RD::get_singleton()->limit_get(RD::LIMIT_VRS_MAX_FRAGMENT_WIDTH), RD::get_singleton()->limit_get(RD::LIMIT_VRS_MAX_FRAGMENT_HEIGHT)) > 4) {
|
||||
push_constant.max_texel_factor = 3.0;
|
||||
bool uses_rg_format = RD::get_singleton()->vrs_get_format() == RD::DATA_FORMAT_R8G8_UNORM;
|
||||
if (uses_rg_format) {
|
||||
mode = p_multiview ? VRS_RG_MULTIVIEW : VRS_RG;
|
||||
} else {
|
||||
mode = p_multiview ? VRS_MULTIVIEW : VRS_DEFAULT;
|
||||
|
||||
// Default to 4x4 as it's not possible to query the max fragment size from RenderingDevice. This can be improved to use the largest size
|
||||
// available if this code is moved over to RenderingDevice at some point.
|
||||
push_constant.max_texel_factor = 2.0;
|
||||
}
|
||||
|
||||
@ -103,18 +107,8 @@ void VRS::copy_vrs(RID p_source_rd_texture, RID p_dest_framebuffer, bool p_multi
|
||||
}
|
||||
|
||||
Size2i VRS::get_vrs_texture_size(const Size2i p_base_size) const {
|
||||
int32_t texel_width = RD::get_singleton()->limit_get(RD::LIMIT_VRS_TEXEL_WIDTH);
|
||||
int32_t texel_height = RD::get_singleton()->limit_get(RD::LIMIT_VRS_TEXEL_HEIGHT);
|
||||
|
||||
int width = p_base_size.x / texel_width;
|
||||
if (p_base_size.x % texel_width != 0) {
|
||||
width++;
|
||||
}
|
||||
int height = p_base_size.y / texel_height;
|
||||
if (p_base_size.y % texel_height != 0) {
|
||||
height++;
|
||||
}
|
||||
return Size2i(width, height);
|
||||
Size2i vrs_texel_size = RD::get_singleton()->vrs_get_texel_size();
|
||||
return Size2i((p_base_size.x + vrs_texel_size.x - 1) / vrs_texel_size.x, (p_base_size.y + vrs_texel_size.y - 1) / vrs_texel_size.y);
|
||||
}
|
||||
|
||||
void VRS::update_vrs_texture(RID p_vrs_fb, RID p_render_target) {
|
||||
|
@ -41,6 +41,8 @@ private:
|
||||
enum VRSMode {
|
||||
VRS_DEFAULT,
|
||||
VRS_MULTIVIEW,
|
||||
VRS_RG,
|
||||
VRS_RG_MULTIVIEW,
|
||||
VRS_MAX,
|
||||
};
|
||||
|
||||
|
@ -167,7 +167,6 @@ RID RenderForwardClustered::RenderBufferDataForwardClustered::get_color_only_fb(
|
||||
|
||||
if (render_buffers->has_texture(RB_SCOPE_VRS, RB_TEXTURE)) {
|
||||
RID vrs_texture = render_buffers->get_texture(RB_SCOPE_VRS, RB_TEXTURE);
|
||||
|
||||
return FramebufferCacheRD::get_singleton()->get_cache_multiview(render_buffers->get_view_count(), color, depth, vrs_texture);
|
||||
} else {
|
||||
return FramebufferCacheRD::get_singleton()->get_cache_multiview(render_buffers->get_view_count(), color, depth);
|
||||
@ -197,7 +196,6 @@ RID RenderForwardClustered::RenderBufferDataForwardClustered::get_color_pass_fb(
|
||||
|
||||
if (render_buffers->has_texture(RB_SCOPE_VRS, RB_TEXTURE)) {
|
||||
RID vrs_texture = render_buffers->get_texture(RB_SCOPE_VRS, RB_TEXTURE);
|
||||
|
||||
return FramebufferCacheRD::get_singleton()->get_cache_multiview(v_count, color, specular, velocity_buffer, depth, vrs_texture);
|
||||
} else {
|
||||
return FramebufferCacheRD::get_singleton()->get_cache_multiview(v_count, color, specular, velocity_buffer, depth);
|
||||
|
@ -208,9 +208,6 @@ RID RenderForwardMobile::RenderBufferDataForwardMobile::get_color_fbs(Framebuffe
|
||||
RD::FramebufferPass pass;
|
||||
pass.color_attachments.push_back(0);
|
||||
pass.depth_attachment = 1;
|
||||
if (vrs_texture.is_valid()) {
|
||||
pass.vrs_attachment = 2;
|
||||
}
|
||||
|
||||
if (use_msaa) {
|
||||
// Add resolve
|
||||
@ -231,9 +228,6 @@ RID RenderForwardMobile::RenderBufferDataForwardMobile::get_color_fbs(Framebuffe
|
||||
RD::FramebufferPass pass;
|
||||
pass.color_attachments.push_back(0);
|
||||
pass.depth_attachment = 1;
|
||||
if (vrs_texture.is_valid()) {
|
||||
pass.vrs_attachment = 2;
|
||||
}
|
||||
|
||||
if (use_msaa) {
|
||||
// add resolve
|
||||
@ -2905,6 +2899,7 @@ static RD::FramebufferFormatID _get_color_framebuffer_format_for_pipeline(RD::Da
|
||||
attachments.push_back(attachment);
|
||||
|
||||
if (p_vrs) {
|
||||
// VRS attachment.
|
||||
attachment.samples = RD::TEXTURE_SAMPLES_1;
|
||||
attachment.format = RenderSceneBuffersRD::get_vrs_format();
|
||||
attachment.usage_flags = RenderSceneBuffersRD::get_vrs_usage_bits();
|
||||
@ -2926,10 +2921,6 @@ static RD::FramebufferFormatID _get_color_framebuffer_format_for_pipeline(RD::Da
|
||||
pass.color_attachments.push_back(0);
|
||||
pass.depth_attachment = 1;
|
||||
|
||||
if (p_vrs) {
|
||||
pass.vrs_attachment = 2;
|
||||
}
|
||||
|
||||
if (multisampling) {
|
||||
pass.resolve_attachments.push_back(attachments.size() - 1);
|
||||
}
|
||||
@ -2955,7 +2946,8 @@ static RD::FramebufferFormatID _get_color_framebuffer_format_for_pipeline(RD::Da
|
||||
passes.push_back(blit_pass);
|
||||
}
|
||||
|
||||
return RD::get_singleton()->framebuffer_format_create_multipass(attachments, passes, p_view_count);
|
||||
int32_t vrs_attachment = p_vrs ? 2 : -1;
|
||||
return RD::get_singleton()->framebuffer_format_create_multipass(attachments, passes, p_view_count, vrs_attachment);
|
||||
}
|
||||
|
||||
static RD::FramebufferFormatID _get_reflection_probe_color_framebuffer_format_for_pipeline() {
|
||||
|
@ -59,7 +59,6 @@ class FramebufferCacheRD : public Object {
|
||||
|
||||
static _FORCE_INLINE_ uint32_t _hash_pass(const RD::FramebufferPass &p, uint32_t h) {
|
||||
h = hash_murmur3_one_32(p.depth_attachment, h);
|
||||
h = hash_murmur3_one_32(p.vrs_attachment, h);
|
||||
|
||||
h = hash_murmur3_one_32(p.color_attachments.size(), h);
|
||||
for (int i = 0; i < p.color_attachments.size(); i++) {
|
||||
@ -84,10 +83,6 @@ class FramebufferCacheRD : public Object {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (a.vrs_attachment != b.vrs_attachment) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (a.color_attachments.size() != b.color_attachments.size()) {
|
||||
return false;
|
||||
}
|
||||
|
@ -59,7 +59,11 @@ layout(location = 0) in vec2 uv_interp;
|
||||
layout(set = 0, binding = 0) uniform sampler2D source_color;
|
||||
#endif /* USE_MULTIVIEW */
|
||||
|
||||
#ifdef SPLIT_RG
|
||||
layout(location = 0) out vec2 frag_color;
|
||||
#else
|
||||
layout(location = 0) out uint frag_color;
|
||||
#endif
|
||||
|
||||
layout(push_constant, std430) uniform Params {
|
||||
float max_texel_factor;
|
||||
@ -79,6 +83,10 @@ void main() {
|
||||
// Input is standardized. R for X, G for Y, 0.0 (0) = 1, 0.33 (85) = 2, 0.66 (170) = 3, 1.0 (255) = 8
|
||||
vec4 color = textureLod(source_color, uv, 0.0);
|
||||
|
||||
#ifdef SPLIT_RG
|
||||
// Density map for VRS according to VK_EXT_fragment_density_map, we can use as is.
|
||||
frag_color = max(vec2(1.0f) - color.rg, vec2(1.0f / 255.0f));
|
||||
#else
|
||||
// Output image shading rate image for VRS according to VK_KHR_fragment_shading_rate.
|
||||
color.r = clamp(floor(color.r * params.max_texel_factor + 0.1), 0.0, params.max_texel_factor);
|
||||
color.g = clamp(floor(color.g * params.max_texel_factor + 0.1), 0.0, params.max_texel_factor);
|
||||
@ -94,4 +102,5 @@ void main() {
|
||||
// Encode to frag_color;
|
||||
frag_color = int(color.r + 0.1) << 2;
|
||||
frag_color += int(color.g + 0.1);
|
||||
#endif
|
||||
}
|
||||
|
@ -756,9 +756,9 @@ uint32_t RenderSceneBuffersRD::get_velocity_usage_bits(bool p_resolve, bool p_ms
|
||||
}
|
||||
|
||||
RD::DataFormat RenderSceneBuffersRD::get_vrs_format() {
|
||||
return RD::DATA_FORMAT_R8_UINT;
|
||||
return RD::get_singleton()->vrs_get_format();
|
||||
}
|
||||
|
||||
uint32_t RenderSceneBuffersRD::get_vrs_usage_bits() {
|
||||
return RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_VRS_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
|
||||
return RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_VRS_ATTACHMENT_BIT;
|
||||
}
|
||||
|
@ -482,17 +482,15 @@ TextureStorage::TextureStorage() {
|
||||
}
|
||||
}
|
||||
|
||||
{ //create default VRS
|
||||
|
||||
{
|
||||
// Create default VRS texture.
|
||||
bool vrs_supported = RD::get_singleton()->has_feature(RD::SUPPORTS_ATTACHMENT_VRS);
|
||||
RD::TextureFormat tformat;
|
||||
tformat.format = RD::DATA_FORMAT_R8_UINT;
|
||||
tformat.format = vrs_supported ? RD::get_singleton()->vrs_get_format() : RD::DATA_FORMAT_R8_UINT;
|
||||
tformat.width = 4;
|
||||
tformat.height = 4;
|
||||
tformat.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT | RD::TEXTURE_USAGE_VRS_ATTACHMENT_BIT;
|
||||
tformat.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT | (vrs_supported ? RD::TEXTURE_USAGE_VRS_ATTACHMENT_BIT : 0);
|
||||
tformat.texture_type = RD::TEXTURE_TYPE_2D;
|
||||
if (!RD::get_singleton()->has_feature(RD::SUPPORTS_ATTACHMENT_VRS)) {
|
||||
tformat.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT;
|
||||
}
|
||||
|
||||
Vector<uint8_t> pv;
|
||||
pv.resize(4 * 4);
|
||||
|
@ -951,22 +951,38 @@ RID RenderingDevice::texture_create(const TextureFormat &p_format, const Texture
|
||||
ERR_FAIL_COND_V_MSG(required_mipmaps < format.mipmaps, RID(),
|
||||
"Too many mipmaps requested for texture format and dimensions (" + itos(format.mipmaps) + "), maximum allowed: (" + itos(required_mipmaps) + ").");
|
||||
|
||||
uint32_t forced_usage_bits = 0;
|
||||
if (p_data.size()) {
|
||||
ERR_FAIL_COND_V_MSG(p_data.size() != (int)format.array_layers, RID(),
|
||||
"Default supplied data for image format is of invalid length (" + itos(p_data.size()) + "), should be (" + itos(format.array_layers) + ").");
|
||||
Vector<Vector<uint8_t>> data = p_data;
|
||||
bool immediate_flush = false;
|
||||
|
||||
// If this is a VRS texture, we make sure that it is created with valid initial data. This prevents a crash on Qualcomm Snapdragon XR2 Gen 1
|
||||
// (used in Quest 2, Quest Pro, Pico 4, HTC Vive XR Elite and others) where the driver will read the texture before we've had time to finish updating it.
|
||||
if (data.is_empty() && (p_format.usage_bits & TEXTURE_USAGE_VRS_ATTACHMENT_BIT)) {
|
||||
immediate_flush = true;
|
||||
for (uint32_t i = 0; i < format.array_layers; i++) {
|
||||
uint32_t required_size = get_image_format_required_size(format.format, format.width, format.height, format.depth, format.mipmaps);
|
||||
Vector<uint8_t> layer;
|
||||
layer.resize(required_size);
|
||||
layer.fill(255);
|
||||
data.push_back(layer);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t forced_usage_bits = _texture_vrs_method_to_usage_bits();
|
||||
if (data.size()) {
|
||||
ERR_FAIL_COND_V_MSG(data.size() != (int)format.array_layers, RID(),
|
||||
"Default supplied data for image format is of invalid length (" + itos(data.size()) + "), should be (" + itos(format.array_layers) + ").");
|
||||
|
||||
for (uint32_t i = 0; i < format.array_layers; i++) {
|
||||
uint32_t required_size = get_image_format_required_size(format.format, format.width, format.height, format.depth, format.mipmaps);
|
||||
ERR_FAIL_COND_V_MSG((uint32_t)p_data[i].size() != required_size, RID(),
|
||||
"Data for slice index " + itos(i) + " (mapped to layer " + itos(i) + ") differs in size (supplied: " + itos(p_data[i].size()) + ") than what is required by the format (" + itos(required_size) + ").");
|
||||
ERR_FAIL_COND_V_MSG((uint32_t)data[i].size() != required_size, RID(),
|
||||
"Data for slice index " + itos(i) + " (mapped to layer " + itos(i) + ") differs in size (supplied: " + itos(data[i].size()) + ") than what is required by the format (" + itos(required_size) + ").");
|
||||
}
|
||||
|
||||
ERR_FAIL_COND_V_MSG(format.usage_bits & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, RID(),
|
||||
"Textures created as depth attachments can't be initialized with data directly. Use RenderingDevice::texture_update() instead.");
|
||||
|
||||
if (!(format.usage_bits & TEXTURE_USAGE_CAN_UPDATE_BIT)) {
|
||||
forced_usage_bits = TEXTURE_USAGE_CAN_UPDATE_BIT;
|
||||
forced_usage_bits |= TEXTURE_USAGE_CAN_UPDATE_BIT;
|
||||
}
|
||||
}
|
||||
|
||||
@ -993,7 +1009,7 @@ RID RenderingDevice::texture_create(const TextureFormat &p_format, const Texture
|
||||
ERR_FAIL_V_MSG(RID(), "Format " + format_text + " does not support usage as atomic storage image.");
|
||||
}
|
||||
if ((format.usage_bits & TEXTURE_USAGE_VRS_ATTACHMENT_BIT) && !supported_usage.has_flag(TEXTURE_USAGE_VRS_ATTACHMENT_BIT)) {
|
||||
ERR_FAIL_V_MSG(RID(), "Format " + format_text + " does not support usage as VRS attachment.");
|
||||
ERR_FAIL_V_MSG(RID(), "Format " + format_text + " does not support usage as variable shading rate attachment.");
|
||||
}
|
||||
}
|
||||
|
||||
@ -1035,7 +1051,7 @@ RID RenderingDevice::texture_create(const TextureFormat &p_format, const Texture
|
||||
texture.usage_flags = format.usage_bits & ~forced_usage_bits;
|
||||
texture.samples = format.samples;
|
||||
texture.allowed_shared_formats = format.shareable_formats;
|
||||
texture.has_initial_data = !p_data.is_empty();
|
||||
texture.has_initial_data = !data.is_empty();
|
||||
|
||||
if ((format.usage_bits & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)) {
|
||||
texture.read_aspect_flags.set_flag(RDD::TEXTURE_ASPECT_DEPTH_BIT);
|
||||
@ -1051,8 +1067,8 @@ RID RenderingDevice::texture_create(const TextureFormat &p_format, const Texture
|
||||
texture.bound = false;
|
||||
|
||||
// Textures are only assumed to be immutable if they have initial data and none of the other bits that indicate write usage are enabled.
|
||||
bool texture_mutable_by_default = texture.usage_flags & (TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | TEXTURE_USAGE_STORAGE_BIT | TEXTURE_USAGE_STORAGE_ATOMIC_BIT | TEXTURE_USAGE_VRS_ATTACHMENT_BIT);
|
||||
if (p_data.is_empty() || texture_mutable_by_default) {
|
||||
bool texture_mutable_by_default = texture.usage_flags & (TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | TEXTURE_USAGE_STORAGE_BIT | TEXTURE_USAGE_STORAGE_ATOMIC_BIT);
|
||||
if (data.is_empty() || texture_mutable_by_default) {
|
||||
_texture_make_mutable(&texture, RID());
|
||||
}
|
||||
|
||||
@ -1063,9 +1079,9 @@ RID RenderingDevice::texture_create(const TextureFormat &p_format, const Texture
|
||||
set_resource_name(id, "RID:" + itos(id.get_id()));
|
||||
#endif
|
||||
|
||||
if (p_data.size()) {
|
||||
if (data.size()) {
|
||||
for (uint32_t i = 0; i < p_format.array_layers; i++) {
|
||||
_texture_initialize(id, i, p_data[i]);
|
||||
_texture_initialize(id, i, data[i], immediate_flush);
|
||||
}
|
||||
|
||||
if (texture.draw_tracker != nullptr) {
|
||||
@ -1399,7 +1415,7 @@ uint32_t RenderingDevice::_texture_alignment(Texture *p_texture) const {
|
||||
return STEPIFY(alignment, driver->api_trait_get(RDD::API_TRAIT_TEXTURE_TRANSFER_ALIGNMENT));
|
||||
}
|
||||
|
||||
Error RenderingDevice::_texture_initialize(RID p_texture, uint32_t p_layer, const Vector<uint8_t> &p_data) {
|
||||
Error RenderingDevice::_texture_initialize(RID p_texture, uint32_t p_layer, const Vector<uint8_t> &p_data, bool p_immediate_flush) {
|
||||
Texture *texture = texture_owner.get_or_null(p_texture);
|
||||
ERR_FAIL_NULL_V(texture, ERR_INVALID_PARAMETER);
|
||||
|
||||
@ -1531,6 +1547,12 @@ Error RenderingDevice::_texture_initialize(RID p_texture, uint32_t p_layer, cons
|
||||
transfer_worker->texture_barriers.push_back(tb);
|
||||
}
|
||||
|
||||
if (p_immediate_flush) {
|
||||
_end_transfer_worker(transfer_worker);
|
||||
_submit_transfer_worker(transfer_worker);
|
||||
_wait_for_transfer_worker(transfer_worker);
|
||||
}
|
||||
|
||||
_release_transfer_worker(transfer_worker);
|
||||
}
|
||||
}
|
||||
@ -1863,6 +1885,17 @@ void RenderingDevice::_texture_create_reinterpret_buffer(Texture *p_texture) {
|
||||
p_texture->shared_fallback->buffer_tracker = tracker;
|
||||
}
|
||||
|
||||
uint32_t RenderingDevice::_texture_vrs_method_to_usage_bits() const {
|
||||
switch (vrs_method) {
|
||||
case VRS_METHOD_FRAGMENT_SHADING_RATE:
|
||||
return RDD::TEXTURE_USAGE_VRS_FRAGMENT_SHADING_RATE_BIT;
|
||||
case VRS_METHOD_FRAGMENT_DENSITY_MAP:
|
||||
return RDD::TEXTURE_USAGE_VRS_FRAGMENT_DENSITY_MAP_BIT;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
Vector<uint8_t> RenderingDevice::_texture_get_data(Texture *tex, uint32_t p_layer, bool p_2d) {
|
||||
uint32_t width, height, depth;
|
||||
uint32_t tight_mip_size = get_image_format_required_size(tex->format, tex->width, tex->height, p_2d ? 1 : tex->depth, tex->mipmaps, &width, &height, &depth);
|
||||
@ -2424,7 +2457,7 @@ bool RenderingDevice::texture_is_format_supported_for_usage(DataFormat p_format,
|
||||
/**** FRAMEBUFFER ****/
|
||||
/*********************/
|
||||
|
||||
RDD::RenderPassID RenderingDevice::_render_pass_create(RenderingDeviceDriver *p_driver, const Vector<AttachmentFormat> &p_attachments, const Vector<FramebufferPass> &p_passes, VectorView<RDD::AttachmentLoadOp> p_load_ops, VectorView<RDD::AttachmentStoreOp> p_store_ops, uint32_t p_view_count, Vector<TextureSamples> *r_samples) {
|
||||
RDD::RenderPassID RenderingDevice::_render_pass_create(RenderingDeviceDriver *p_driver, const Vector<AttachmentFormat> &p_attachments, const Vector<FramebufferPass> &p_passes, VectorView<RDD::AttachmentLoadOp> p_load_ops, VectorView<RDD::AttachmentStoreOp> p_store_ops, uint32_t p_view_count, VRSMethod p_vrs_method, int32_t p_vrs_attachment, Size2i p_vrs_texel_size, Vector<TextureSamples> *r_samples) {
|
||||
// NOTE:
|
||||
// Before the refactor to RenderingDevice-RenderingDeviceDriver, there was commented out code to
|
||||
// specify dependencies to external subpasses. Since it had been unused for a long timel it wasn't ported
|
||||
@ -2464,15 +2497,14 @@ RDD::RenderPassID RenderingDevice::_render_pass_create(RenderingDeviceDriver *p_
|
||||
// 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;
|
||||
|
||||
bool is_vrs = (p_attachments[i].usage_flags & TEXTURE_USAGE_VRS_ATTACHMENT_BIT) && i == p_vrs_attachment;
|
||||
if (is_vrs) {
|
||||
description.load_op = RDD::ATTACHMENT_LOAD_OP_LOAD;
|
||||
description.store_op = RDD::ATTACHMENT_STORE_OP_DONT_CARE;
|
||||
description.stencil_load_op = RDD::ATTACHMENT_LOAD_OP_LOAD;
|
||||
description.stencil_load_op = RDD::ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||
description.stencil_store_op = RDD::ATTACHMENT_STORE_OP_DONT_CARE;
|
||||
description.initial_layout = RDD::TEXTURE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
description.final_layout = RDD::TEXTURE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
description.initial_layout = _vrs_layout_from_method(p_vrs_method);
|
||||
description.final_layout = _vrs_layout_from_method(p_vrs_method);
|
||||
} else {
|
||||
if (p_attachments[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) {
|
||||
description.load_op = p_load_ops[i];
|
||||
@ -2605,14 +2637,15 @@ RDD::RenderPassID RenderingDevice::_render_pass_create(RenderingDeviceDriver *p_
|
||||
subpass.depth_stencil_reference.layout = RDD::TEXTURE_LAYOUT_UNDEFINED;
|
||||
}
|
||||
|
||||
if (pass->vrs_attachment != ATTACHMENT_UNUSED) {
|
||||
int32_t attachment = pass->vrs_attachment;
|
||||
if (p_vrs_method == VRS_METHOD_FRAGMENT_SHADING_RATE && p_vrs_attachment >= 0) {
|
||||
int32_t attachment = p_vrs_attachment;
|
||||
ERR_FAIL_INDEX_V_MSG(attachment, p_attachments.size(), RDD::RenderPassID(), "Invalid framebuffer VRS format attachment(" + itos(attachment) + "), in pass (" + itos(i) + "), VRS attachment.");
|
||||
ERR_FAIL_COND_V_MSG(!(p_attachments[attachment].usage_flags & TEXTURE_USAGE_VRS_ATTACHMENT_BIT), RDD::RenderPassID(), "Invalid framebuffer VRS 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, RDD::RenderPassID(), "Invalid framebuffer VRS attachment(" + itos(attachment) + "), in pass (" + itos(i) + "), it already was used for something else before in this pass.");
|
||||
|
||||
subpass.vrs_reference.attachment = attachment_remap[attachment];
|
||||
subpass.vrs_reference.layout = RDD::TEXTURE_LAYOUT_VRS_ATTACHMENT_OPTIMAL;
|
||||
subpass.fragment_shading_rate_reference.attachment = attachment_remap[attachment];
|
||||
subpass.fragment_shading_rate_reference.layout = RDD::TEXTURE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL;
|
||||
subpass.fragment_shading_rate_texel_size = p_vrs_texel_size;
|
||||
|
||||
attachment_last_pass[attachment] = i;
|
||||
}
|
||||
@ -2647,7 +2680,13 @@ RDD::RenderPassID RenderingDevice::_render_pass_create(RenderingDeviceDriver *p_
|
||||
}
|
||||
}
|
||||
|
||||
RDD::RenderPassID render_pass = p_driver->render_pass_create(attachments, subpasses, subpass_dependencies, p_view_count);
|
||||
RDD::AttachmentReference fragment_density_map_attachment_reference;
|
||||
if (p_vrs_method == VRS_METHOD_FRAGMENT_DENSITY_MAP && p_vrs_attachment >= 0) {
|
||||
fragment_density_map_attachment_reference.attachment = p_vrs_attachment;
|
||||
fragment_density_map_attachment_reference.layout = RDD::TEXTURE_LAYOUT_FRAGMENT_DENSITY_MAP_ATTACHMENT_OPTIMAL;
|
||||
}
|
||||
|
||||
RDD::RenderPassID render_pass = p_driver->render_pass_create(attachments, subpasses, subpass_dependencies, p_view_count, fragment_density_map_attachment_reference);
|
||||
ERR_FAIL_COND_V(!render_pass, RDD::RenderPassID());
|
||||
|
||||
return render_pass;
|
||||
@ -2661,10 +2700,74 @@ RDD::RenderPassID RenderingDevice::_render_pass_create_from_graph(RenderingDevic
|
||||
// resolving the dependencies between commands. This function creates a render pass for the framebuffer accordingly.
|
||||
Framebuffer *framebuffer = (Framebuffer *)(p_user_data);
|
||||
const FramebufferFormatKey &key = framebuffer->rendering_device->framebuffer_formats[framebuffer->format_id].E->key();
|
||||
return _render_pass_create(p_driver, key.attachments, key.passes, p_load_ops, p_store_ops, framebuffer->view_count);
|
||||
return _render_pass_create(p_driver, key.attachments, key.passes, p_load_ops, p_store_ops, framebuffer->view_count, key.vrs_method, key.vrs_attachment, key.vrs_texel_size);
|
||||
}
|
||||
|
||||
RenderingDevice::FramebufferFormatID RenderingDevice::framebuffer_format_create(const Vector<AttachmentFormat> &p_format, uint32_t p_view_count) {
|
||||
RDG::ResourceUsage RenderingDevice::_vrs_usage_from_method(VRSMethod p_method) {
|
||||
switch (p_method) {
|
||||
case VRS_METHOD_FRAGMENT_SHADING_RATE:
|
||||
return RDG::RESOURCE_USAGE_ATTACHMENT_FRAGMENT_SHADING_RATE_READ;
|
||||
case VRS_METHOD_FRAGMENT_DENSITY_MAP:
|
||||
return RDG::RESOURCE_USAGE_ATTACHMENT_FRAGMENT_DENSITY_MAP_READ;
|
||||
default:
|
||||
return RDG::RESOURCE_USAGE_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
RDD::PipelineStageBits RenderingDevice::_vrs_stages_from_method(VRSMethod p_method) {
|
||||
switch (p_method) {
|
||||
case VRS_METHOD_FRAGMENT_SHADING_RATE:
|
||||
return RDD::PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT;
|
||||
case VRS_METHOD_FRAGMENT_DENSITY_MAP:
|
||||
return RDD::PIPELINE_STAGE_FRAGMENT_DENSITY_PROCESS_BIT;
|
||||
default:
|
||||
return RDD::PipelineStageBits(0);
|
||||
}
|
||||
}
|
||||
|
||||
RDD::TextureLayout RenderingDevice::_vrs_layout_from_method(VRSMethod p_method) {
|
||||
switch (p_method) {
|
||||
case VRS_METHOD_FRAGMENT_SHADING_RATE:
|
||||
return RDD::TEXTURE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL;
|
||||
case VRS_METHOD_FRAGMENT_DENSITY_MAP:
|
||||
return RDD::TEXTURE_LAYOUT_FRAGMENT_DENSITY_MAP_ATTACHMENT_OPTIMAL;
|
||||
default:
|
||||
return RDD::TEXTURE_LAYOUT_UNDEFINED;
|
||||
}
|
||||
}
|
||||
|
||||
void RenderingDevice::_vrs_detect_method() {
|
||||
const RDD::FragmentShadingRateCapabilities &fsr_capabilities = driver->get_fragment_shading_rate_capabilities();
|
||||
const RDD::FragmentDensityMapCapabilities &fdm_capabilities = driver->get_fragment_density_map_capabilities();
|
||||
if (fsr_capabilities.attachment_supported) {
|
||||
vrs_method = VRS_METHOD_FRAGMENT_SHADING_RATE;
|
||||
} else if (fdm_capabilities.attachment_supported) {
|
||||
vrs_method = VRS_METHOD_FRAGMENT_DENSITY_MAP;
|
||||
}
|
||||
|
||||
switch (vrs_method) {
|
||||
case VRS_METHOD_FRAGMENT_SHADING_RATE:
|
||||
vrs_format = DATA_FORMAT_R8_UINT;
|
||||
vrs_texel_size = Vector2i(16, 16).clamp(fsr_capabilities.min_texel_size, fsr_capabilities.max_texel_size);
|
||||
break;
|
||||
case VRS_METHOD_FRAGMENT_DENSITY_MAP:
|
||||
vrs_format = DATA_FORMAT_R8G8_UNORM;
|
||||
vrs_texel_size = Vector2i(32, 32).clamp(fdm_capabilities.min_texel_size, fdm_capabilities.max_texel_size);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
RD::DataFormat RenderingDevice::vrs_get_format() const {
|
||||
return vrs_format;
|
||||
}
|
||||
|
||||
Size2i RenderingDevice::vrs_get_texel_size() const {
|
||||
return vrs_texel_size;
|
||||
}
|
||||
|
||||
RenderingDevice::FramebufferFormatID RenderingDevice::framebuffer_format_create(const Vector<AttachmentFormat> &p_format, uint32_t p_view_count, int32_t p_fragment_density_map_attachment) {
|
||||
FramebufferPass pass;
|
||||
for (int i = 0; i < p_format.size(); i++) {
|
||||
if (p_format[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
|
||||
@ -2676,16 +2779,19 @@ RenderingDevice::FramebufferFormatID RenderingDevice::framebuffer_format_create(
|
||||
|
||||
Vector<FramebufferPass> passes;
|
||||
passes.push_back(pass);
|
||||
return framebuffer_format_create_multipass(p_format, passes, p_view_count);
|
||||
return framebuffer_format_create_multipass(p_format, passes, p_view_count, p_fragment_density_map_attachment);
|
||||
}
|
||||
|
||||
RenderingDevice::FramebufferFormatID RenderingDevice::framebuffer_format_create_multipass(const Vector<AttachmentFormat> &p_attachments, const Vector<FramebufferPass> &p_passes, uint32_t p_view_count) {
|
||||
RenderingDevice::FramebufferFormatID RenderingDevice::framebuffer_format_create_multipass(const Vector<AttachmentFormat> &p_attachments, const Vector<FramebufferPass> &p_passes, uint32_t p_view_count, int32_t p_vrs_attachment) {
|
||||
_THREAD_SAFE_METHOD_
|
||||
|
||||
FramebufferFormatKey key;
|
||||
key.attachments = p_attachments;
|
||||
key.passes = p_passes;
|
||||
key.view_count = p_view_count;
|
||||
key.vrs_method = vrs_method;
|
||||
key.vrs_attachment = p_vrs_attachment;
|
||||
key.vrs_texel_size = vrs_texel_size;
|
||||
|
||||
const RBMap<FramebufferFormatKey, FramebufferFormatID>::Element *E = framebuffer_format_cache.find(key);
|
||||
if (E) {
|
||||
@ -2701,7 +2807,7 @@ RenderingDevice::FramebufferFormatID RenderingDevice::framebuffer_format_create_
|
||||
store_ops.push_back(RDD::ATTACHMENT_STORE_OP_STORE);
|
||||
}
|
||||
|
||||
RDD::RenderPassID render_pass = _render_pass_create(driver, p_attachments, p_passes, load_ops, store_ops, p_view_count, &samples); // Actions don't matter for this use case.
|
||||
RDD::RenderPassID render_pass = _render_pass_create(driver, p_attachments, p_passes, load_ops, store_ops, p_view_count, vrs_method, p_vrs_attachment, vrs_texel_size, &samples); // Actions don't matter for this use case.
|
||||
if (!render_pass) { // Was likely invalid.
|
||||
return INVALID_ID;
|
||||
}
|
||||
@ -2741,7 +2847,7 @@ RenderingDevice::FramebufferFormatID RenderingDevice::framebuffer_format_create_
|
||||
LocalVector<RDD::Subpass> subpass;
|
||||
subpass.resize(1);
|
||||
|
||||
RDD::RenderPassID render_pass = driver->render_pass_create({}, subpass, {}, 1);
|
||||
RDD::RenderPassID render_pass = driver->render_pass_create({}, subpass, {}, 1, RDD::AttachmentReference());
|
||||
ERR_FAIL_COND_V(!render_pass, FramebufferFormatID());
|
||||
|
||||
FramebufferFormatID id = FramebufferFormatID(framebuffer_format_cache.size()) | (FramebufferFormatID(ID_TYPE_FRAMEBUFFER_FORMAT) << FramebufferFormatID(ID_BASE_SHIFT));
|
||||
@ -2812,8 +2918,6 @@ RID RenderingDevice::framebuffer_create(const Vector<RID> &p_texture_attachments
|
||||
|
||||
if (texture && texture->usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
|
||||
pass.depth_attachment = i;
|
||||
} else if (texture && texture->usage_flags & TEXTURE_USAGE_VRS_ATTACHMENT_BIT) {
|
||||
pass.vrs_attachment = i;
|
||||
} else {
|
||||
if (texture && texture->is_resolve_buffer) {
|
||||
pass.resolve_attachments.push_back(i);
|
||||
@ -2835,6 +2939,7 @@ RID RenderingDevice::framebuffer_create_multipass(const Vector<RID> &p_texture_a
|
||||
Vector<AttachmentFormat> attachments;
|
||||
LocalVector<RDD::TextureID> textures;
|
||||
LocalVector<RDG::ResourceTracker *> trackers;
|
||||
int32_t vrs_attachment = -1;
|
||||
attachments.resize(p_texture_attachments.size());
|
||||
Size2i size;
|
||||
bool size_set = false;
|
||||
@ -2849,6 +2954,11 @@ RID RenderingDevice::framebuffer_create_multipass(const Vector<RID> &p_texture_a
|
||||
|
||||
_check_transfer_worker_texture(texture);
|
||||
|
||||
if (i != 0 && texture->usage_flags & TEXTURE_USAGE_VRS_ATTACHMENT_BIT) {
|
||||
// Detect if the texture is the fragment density map and it's not the first attachment.
|
||||
vrs_attachment = i;
|
||||
}
|
||||
|
||||
if (!size_set) {
|
||||
size.width = texture->width;
|
||||
size.height = texture->height;
|
||||
@ -2876,7 +2986,7 @@ RID RenderingDevice::framebuffer_create_multipass(const Vector<RID> &p_texture_a
|
||||
|
||||
ERR_FAIL_COND_V_MSG(!size_set, RID(), "All attachments unused.");
|
||||
|
||||
FramebufferFormatID format_id = framebuffer_format_create_multipass(attachments, p_passes, p_view_count);
|
||||
FramebufferFormatID format_id = framebuffer_format_create_multipass(attachments, p_passes, p_view_count, vrs_attachment);
|
||||
if (format_id == INVALID_ID) {
|
||||
return RID();
|
||||
}
|
||||
@ -4259,7 +4369,7 @@ RenderingDevice::DrawListID RenderingDevice::draw_list_begin_for_screen(DisplayS
|
||||
clear_value.color = p_clear_color;
|
||||
|
||||
RDD::RenderPassID render_pass = driver->swap_chain_get_render_pass(sc_it->value);
|
||||
draw_graph.add_draw_list_begin(render_pass, fb_it->value, viewport, RDG::ATTACHMENT_OPERATION_CLEAR, clear_value, true, false, RDD::BreadcrumbMarker::BLIT_PASS, split_swapchain_into_its_own_cmd_buffer);
|
||||
draw_graph.add_draw_list_begin(render_pass, fb_it->value, viewport, RDG::ATTACHMENT_OPERATION_CLEAR, clear_value, RDD::PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, RDD::BreadcrumbMarker::BLIT_PASS, split_swapchain_into_its_own_cmd_buffer);
|
||||
|
||||
draw_graph.add_draw_list_set_viewport(viewport);
|
||||
draw_graph.add_draw_list_set_scissor(viewport);
|
||||
@ -4275,6 +4385,7 @@ RenderingDevice::DrawListID RenderingDevice::draw_list_begin(RID p_framebuffer,
|
||||
Framebuffer *framebuffer = framebuffer_owner.get_or_null(p_framebuffer);
|
||||
ERR_FAIL_NULL_V(framebuffer, INVALID_ID);
|
||||
|
||||
const FramebufferFormatKey &framebuffer_key = framebuffer_formats[framebuffer->format_id].E->key();
|
||||
Point2i viewport_offset;
|
||||
Point2i viewport_size = framebuffer->size;
|
||||
|
||||
@ -4295,12 +4406,12 @@ RenderingDevice::DrawListID RenderingDevice::draw_list_begin(RID p_framebuffer,
|
||||
thread_local LocalVector<RDD::RenderPassClearValue> clear_values;
|
||||
thread_local LocalVector<RDG::ResourceTracker *> resource_trackers;
|
||||
thread_local LocalVector<RDG::ResourceUsage> resource_usages;
|
||||
bool uses_color = false;
|
||||
bool uses_depth = false;
|
||||
BitField<RDD::PipelineStageBits> stages;
|
||||
operations.resize(framebuffer->texture_ids.size());
|
||||
clear_values.resize(framebuffer->texture_ids.size());
|
||||
resource_trackers.clear();
|
||||
resource_usages.clear();
|
||||
stages.clear();
|
||||
|
||||
uint32_t color_index = 0;
|
||||
for (int i = 0; i < framebuffer->texture_ids.size(); i++) {
|
||||
@ -4317,7 +4428,11 @@ RenderingDevice::DrawListID RenderingDevice::draw_list_begin(RID p_framebuffer,
|
||||
|
||||
RDG::AttachmentOperation operation = RDG::ATTACHMENT_OPERATION_DEFAULT;
|
||||
RDD::RenderPassClearValue clear_value;
|
||||
if (texture->usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) {
|
||||
if (framebuffer_key.vrs_attachment == i && (texture->usage_flags & TEXTURE_USAGE_VRS_ATTACHMENT_BIT)) {
|
||||
resource_trackers.push_back(texture->draw_tracker);
|
||||
resource_usages.push_back(_vrs_usage_from_method(framebuffer_key.vrs_method));
|
||||
stages.set_flag(_vrs_stages_from_method(framebuffer_key.vrs_method));
|
||||
} else if (texture->usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) {
|
||||
if (p_draw_flags.has_flag(DrawFlags(DRAW_CLEAR_COLOR_0 << color_index))) {
|
||||
ERR_FAIL_COND_V_MSG(color_index >= p_clear_color_values.size(), INVALID_ID, vformat("Color texture (%d) was specified to be cleared but no color value was provided.", color_index));
|
||||
operation = RDG::ATTACHMENT_OPERATION_CLEAR;
|
||||
@ -4328,7 +4443,7 @@ RenderingDevice::DrawListID RenderingDevice::draw_list_begin(RID p_framebuffer,
|
||||
|
||||
resource_trackers.push_back(texture->draw_tracker);
|
||||
resource_usages.push_back(RDG::RESOURCE_USAGE_ATTACHMENT_COLOR_READ_WRITE);
|
||||
uses_color = true;
|
||||
stages.set_flag(RDD::PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
|
||||
color_index++;
|
||||
} else if (texture->usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
|
||||
if (p_draw_flags.has_flag(DRAW_CLEAR_DEPTH) || p_draw_flags.has_flag(DRAW_CLEAR_STENCIL)) {
|
||||
@ -4341,14 +4456,15 @@ RenderingDevice::DrawListID RenderingDevice::draw_list_begin(RID p_framebuffer,
|
||||
|
||||
resource_trackers.push_back(texture->draw_tracker);
|
||||
resource_usages.push_back(RDG::RESOURCE_USAGE_ATTACHMENT_DEPTH_STENCIL_READ_WRITE);
|
||||
uses_depth = true;
|
||||
stages.set_flag(RDD::PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT);
|
||||
stages.set_flag(RDD::PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT);
|
||||
}
|
||||
|
||||
operations[i] = operation;
|
||||
clear_values[i] = clear_value;
|
||||
}
|
||||
|
||||
draw_graph.add_draw_list_begin(framebuffer->framebuffer_cache, Rect2i(viewport_offset, viewport_size), operations, clear_values, uses_color, uses_depth, p_breadcrumb);
|
||||
draw_graph.add_draw_list_begin(framebuffer->framebuffer_cache, Rect2i(viewport_offset, viewport_size), operations, clear_values, stages, p_breadcrumb);
|
||||
draw_graph.add_draw_list_usages(resource_trackers, resource_usages);
|
||||
|
||||
// Mark textures as bound.
|
||||
@ -4369,9 +4485,7 @@ RenderingDevice::DrawListID RenderingDevice::draw_list_begin(RID p_framebuffer,
|
||||
draw_list_framebuffer_format = framebuffer->format_id;
|
||||
#endif
|
||||
draw_list_current_subpass = 0;
|
||||
|
||||
const FramebufferFormatKey &key = framebuffer_formats[framebuffer->format_id].E->key();
|
||||
draw_list_subpass_count = key.passes.size();
|
||||
draw_list_subpass_count = framebuffer_key.passes.size();
|
||||
|
||||
Rect2i viewport_rect(viewport_offset, viewport_size);
|
||||
draw_graph.add_draw_list_set_viewport(viewport_rect);
|
||||
@ -6832,6 +6946,9 @@ Error RenderingDevice::initialize(RenderingContextDriver *p_context, DisplayServ
|
||||
}
|
||||
}
|
||||
|
||||
// Find the best method available for VRS on the current hardware.
|
||||
_vrs_detect_method();
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
@ -7259,7 +7376,20 @@ RenderingDevice *RenderingDevice::create_local_device() {
|
||||
}
|
||||
|
||||
bool RenderingDevice::has_feature(const Features p_feature) const {
|
||||
return driver->has_feature(p_feature);
|
||||
// Some features can be deduced from the capabilities without querying the driver and looking at the capabilities.
|
||||
switch (p_feature) {
|
||||
case SUPPORTS_MULTIVIEW: {
|
||||
const RDD::MultiviewCapabilities &multiview_capabilities = driver->get_multiview_capabilities();
|
||||
return multiview_capabilities.is_supported && multiview_capabilities.max_view_count > 1;
|
||||
}
|
||||
case SUPPORTS_ATTACHMENT_VRS: {
|
||||
const RDD::FragmentShadingRateCapabilities &fsr_capabilities = driver->get_fragment_shading_rate_capabilities();
|
||||
const RDD::FragmentDensityMapCapabilities &fdm_capabilities = driver->get_fragment_density_map_capabilities();
|
||||
return fsr_capabilities.attachment_supported || fdm_capabilities.attachment_supported;
|
||||
}
|
||||
default:
|
||||
return driver->has_feature(p_feature);
|
||||
}
|
||||
}
|
||||
|
||||
void RenderingDevice::_bind_methods() {
|
||||
|
@ -254,6 +254,8 @@ public:
|
||||
CALLBACK_RESOURCE_USAGE_STORAGE_IMAGE_READ_WRITE,
|
||||
CALLBACK_RESOURCE_USAGE_ATTACHMENT_COLOR_READ_WRITE,
|
||||
CALLBACK_RESOURCE_USAGE_ATTACHMENT_DEPTH_STENCIL_READ_WRITE,
|
||||
CALLBACK_RESOURCE_USAGE_ATTACHMENT_FRAGMENT_SHADING_RATE_READ,
|
||||
CALLBACK_RESOURCE_USAGE_ATTACHMENT_FRAGMENT_DENSITY_MAP_READ,
|
||||
CALLBACK_RESOURCE_USAGE_MAX
|
||||
};
|
||||
|
||||
@ -359,12 +361,13 @@ public:
|
||||
Vector<uint8_t> _texture_get_data(Texture *tex, uint32_t p_layer, bool p_2d = false);
|
||||
uint32_t _texture_layer_count(Texture *p_texture) const;
|
||||
uint32_t _texture_alignment(Texture *p_texture) const;
|
||||
Error _texture_initialize(RID p_texture, uint32_t p_layer, const Vector<uint8_t> &p_data);
|
||||
Error _texture_initialize(RID p_texture, uint32_t p_layer, const Vector<uint8_t> &p_data, bool p_immediate_flush = false);
|
||||
void _texture_check_shared_fallback(Texture *p_texture);
|
||||
void _texture_update_shared_fallback(RID p_texture_rid, Texture *p_texture, bool p_for_writing);
|
||||
void _texture_free_shared_fallback(Texture *p_texture);
|
||||
void _texture_copy_shared(RID p_src_texture_rid, Texture *p_src_texture, RID p_dst_texture_rid, Texture *p_dst_texture);
|
||||
void _texture_create_reinterpret_buffer(Texture *p_texture);
|
||||
uint32_t _texture_vrs_method_to_usage_bits() const;
|
||||
|
||||
struct TextureGetDataRequest {
|
||||
uint32_t frame_local_index = 0;
|
||||
@ -426,6 +429,30 @@ public:
|
||||
void texture_set_discardable(RID p_texture, bool p_discardable);
|
||||
bool texture_is_discardable(RID p_texture);
|
||||
|
||||
private:
|
||||
/*************/
|
||||
/**** VRS ****/
|
||||
/*************/
|
||||
|
||||
enum VRSMethod {
|
||||
VRS_METHOD_NONE,
|
||||
VRS_METHOD_FRAGMENT_SHADING_RATE,
|
||||
VRS_METHOD_FRAGMENT_DENSITY_MAP,
|
||||
};
|
||||
|
||||
VRSMethod vrs_method = VRS_METHOD_NONE;
|
||||
DataFormat vrs_format = DATA_FORMAT_MAX;
|
||||
Size2i vrs_texel_size;
|
||||
|
||||
static RDG::ResourceUsage _vrs_usage_from_method(VRSMethod p_method);
|
||||
static RDD::PipelineStageBits _vrs_stages_from_method(VRSMethod p_method);
|
||||
static RDD::TextureLayout _vrs_layout_from_method(VRSMethod p_method);
|
||||
void _vrs_detect_method();
|
||||
|
||||
public:
|
||||
DataFormat vrs_get_format() const;
|
||||
Size2i vrs_get_texel_size() const;
|
||||
|
||||
/*********************/
|
||||
/**** FRAMEBUFFER ****/
|
||||
/*********************/
|
||||
@ -456,7 +483,6 @@ public:
|
||||
Vector<int32_t> resolve_attachments;
|
||||
Vector<int32_t> preserve_attachments;
|
||||
int32_t depth_attachment = ATTACHMENT_UNUSED;
|
||||
int32_t vrs_attachment = ATTACHMENT_UNUSED; // density map for VRS, only used if supported
|
||||
};
|
||||
|
||||
typedef int64_t FramebufferFormatID;
|
||||
@ -466,8 +492,23 @@ private:
|
||||
Vector<AttachmentFormat> attachments;
|
||||
Vector<FramebufferPass> passes;
|
||||
uint32_t view_count = 1;
|
||||
VRSMethod vrs_method = VRS_METHOD_NONE;
|
||||
int32_t vrs_attachment = ATTACHMENT_UNUSED;
|
||||
Size2i vrs_texel_size;
|
||||
|
||||
bool operator<(const FramebufferFormatKey &p_key) const {
|
||||
if (vrs_texel_size != p_key.vrs_texel_size) {
|
||||
return vrs_texel_size < p_key.vrs_texel_size;
|
||||
}
|
||||
|
||||
if (vrs_attachment != p_key.vrs_attachment) {
|
||||
return vrs_attachment < p_key.vrs_attachment;
|
||||
}
|
||||
|
||||
if (vrs_method != p_key.vrs_method) {
|
||||
return vrs_method < p_key.vrs_method;
|
||||
}
|
||||
|
||||
if (view_count != p_key.view_count) {
|
||||
return view_count < p_key.view_count;
|
||||
}
|
||||
@ -572,7 +613,7 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
static RDD::RenderPassID _render_pass_create(RenderingDeviceDriver *p_driver, const Vector<AttachmentFormat> &p_attachments, const Vector<FramebufferPass> &p_passes, VectorView<RDD::AttachmentLoadOp> p_load_ops, VectorView<RDD::AttachmentStoreOp> p_store_ops, uint32_t p_view_count = 1, Vector<TextureSamples> *r_samples = nullptr);
|
||||
static RDD::RenderPassID _render_pass_create(RenderingDeviceDriver *p_driver, const Vector<AttachmentFormat> &p_attachments, const Vector<FramebufferPass> &p_passes, VectorView<RDD::AttachmentLoadOp> p_load_ops, VectorView<RDD::AttachmentStoreOp> p_store_ops, uint32_t p_view_count = 1, VRSMethod p_vrs_method = VRS_METHOD_NONE, int32_t p_vrs_attachment = -1, Size2i p_vrs_texel_size = Size2i(), Vector<TextureSamples> *r_samples = nullptr);
|
||||
static RDD::RenderPassID _render_pass_create_from_graph(RenderingDeviceDriver *p_driver, VectorView<RDD::AttachmentLoadOp> p_load_ops, VectorView<RDD::AttachmentStoreOp> p_store_ops, void *p_user_data);
|
||||
|
||||
// This is a cache and it's never freed, it ensures
|
||||
@ -603,8 +644,8 @@ private:
|
||||
|
||||
public:
|
||||
// This ID is warranted to be unique for the same formats, does not need to be freed
|
||||
FramebufferFormatID framebuffer_format_create(const Vector<AttachmentFormat> &p_format, uint32_t p_view_count = 1);
|
||||
FramebufferFormatID framebuffer_format_create_multipass(const Vector<AttachmentFormat> &p_attachments, const Vector<FramebufferPass> &p_passes, uint32_t p_view_count = 1);
|
||||
FramebufferFormatID framebuffer_format_create(const Vector<AttachmentFormat> &p_format, uint32_t p_view_count = 1, int32_t p_vrs_attachment = -1);
|
||||
FramebufferFormatID framebuffer_format_create_multipass(const Vector<AttachmentFormat> &p_attachments, const Vector<FramebufferPass> &p_passes, uint32_t p_view_count = 1, int32_t p_vrs_attachment = -1);
|
||||
FramebufferFormatID framebuffer_format_create_empty(TextureSamples p_samples = TEXTURE_SAMPLES_1);
|
||||
TextureSamples framebuffer_format_get_texture_samples(FramebufferFormatID p_format, uint32_t p_pass = 0);
|
||||
|
||||
|
@ -391,6 +391,7 @@ public:
|
||||
// Try to set this bit as much as possible. If you set it, validation doesn't complain
|
||||
// and it works fine on mobile, then go ahead.
|
||||
TEXTURE_USAGE_TRANSIENT_BIT = (1 << 11),
|
||||
TEXTURE_USAGE_MAX_BIT = TEXTURE_USAGE_TRANSIENT_BIT,
|
||||
};
|
||||
|
||||
struct TextureFormat {
|
||||
@ -883,11 +884,7 @@ public:
|
||||
LIMIT_SUBGROUP_MAX_SIZE,
|
||||
LIMIT_SUBGROUP_IN_SHADERS, // Set flags using SHADER_STAGE_VERTEX_BIT, SHADER_STAGE_FRAGMENT_BIT, etc.
|
||||
LIMIT_SUBGROUP_OPERATIONS,
|
||||
LIMIT_VRS_TEXEL_WIDTH,
|
||||
LIMIT_VRS_TEXEL_HEIGHT,
|
||||
LIMIT_VRS_MAX_FRAGMENT_WIDTH,
|
||||
LIMIT_VRS_MAX_FRAGMENT_HEIGHT,
|
||||
LIMIT_METALFX_TEMPORAL_SCALER_MIN_SCALE,
|
||||
LIMIT_METALFX_TEMPORAL_SCALER_MIN_SCALE = 46,
|
||||
LIMIT_METALFX_TEMPORAL_SCALER_MAX_SCALE,
|
||||
LIMIT_MAX_SHADER_VARYINGS,
|
||||
};
|
||||
|
@ -238,7 +238,8 @@ public:
|
||||
TEXTURE_LAYOUT_COPY_DST_OPTIMAL,
|
||||
TEXTURE_LAYOUT_RESOLVE_SRC_OPTIMAL,
|
||||
TEXTURE_LAYOUT_RESOLVE_DST_OPTIMAL,
|
||||
TEXTURE_LAYOUT_VRS_ATTACHMENT_OPTIMAL,
|
||||
TEXTURE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL,
|
||||
TEXTURE_LAYOUT_FRAGMENT_DENSITY_MAP_ATTACHMENT_OPTIMAL,
|
||||
TEXTURE_LAYOUT_MAX
|
||||
};
|
||||
|
||||
@ -249,6 +250,11 @@ public:
|
||||
TEXTURE_ASPECT_MAX
|
||||
};
|
||||
|
||||
enum TextureUsageMethod {
|
||||
TEXTURE_USAGE_VRS_FRAGMENT_SHADING_RATE_BIT = TEXTURE_USAGE_MAX_BIT << 1,
|
||||
TEXTURE_USAGE_VRS_FRAGMENT_DENSITY_MAP_BIT = TEXTURE_USAGE_MAX_BIT << 2,
|
||||
};
|
||||
|
||||
enum TextureAspectBits {
|
||||
TEXTURE_ASPECT_COLOR_BIT = (1 << TEXTURE_ASPECT_COLOR),
|
||||
TEXTURE_ASPECT_DEPTH_BIT = (1 << TEXTURE_ASPECT_DEPTH),
|
||||
@ -335,6 +341,8 @@ public:
|
||||
PIPELINE_STAGE_ALL_GRAPHICS_BIT = (1 << 15),
|
||||
PIPELINE_STAGE_ALL_COMMANDS_BIT = (1 << 16),
|
||||
PIPELINE_STAGE_CLEAR_STORAGE_BIT = (1 << 17),
|
||||
PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT = (1 << 22),
|
||||
PIPELINE_STAGE_FRAGMENT_DENSITY_PROCESS_BIT = (1 << 23),
|
||||
};
|
||||
|
||||
enum BarrierAccessBits {
|
||||
@ -356,8 +364,9 @@ public:
|
||||
BARRIER_ACCESS_MEMORY_READ_BIT = (1 << 15),
|
||||
BARRIER_ACCESS_MEMORY_WRITE_BIT = (1 << 16),
|
||||
BARRIER_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT = (1 << 23),
|
||||
BARRIER_ACCESS_RESOLVE_READ_BIT = (1 << 24),
|
||||
BARRIER_ACCESS_RESOLVE_WRITE_BIT = (1 << 25),
|
||||
BARRIER_ACCESS_FRAGMENT_DENSITY_MAP_ATTACHMENT_READ_BIT = (1 << 24),
|
||||
BARRIER_ACCESS_RESOLVE_READ_BIT = (1 << 25),
|
||||
BARRIER_ACCESS_RESOLVE_WRITE_BIT = (1 << 26),
|
||||
BARRIER_ACCESS_STORAGE_CLEAR_BIT = (1 << 27),
|
||||
};
|
||||
|
||||
@ -629,7 +638,8 @@ public:
|
||||
AttachmentReference depth_stencil_reference;
|
||||
LocalVector<AttachmentReference> resolve_references;
|
||||
LocalVector<uint32_t> preserve_attachments;
|
||||
AttachmentReference vrs_reference;
|
||||
AttachmentReference fragment_shading_rate_reference;
|
||||
Size2i fragment_shading_rate_texel_size;
|
||||
};
|
||||
|
||||
struct SubpassDependency {
|
||||
@ -641,7 +651,7 @@ public:
|
||||
BitField<BarrierAccessBits> dst_access;
|
||||
};
|
||||
|
||||
virtual RenderPassID render_pass_create(VectorView<Attachment> p_attachments, VectorView<Subpass> p_subpasses, VectorView<SubpassDependency> p_subpass_dependencies, uint32_t p_view_count) = 0;
|
||||
virtual RenderPassID render_pass_create(VectorView<Attachment> p_attachments, VectorView<Subpass> p_subpasses, VectorView<SubpassDependency> p_subpass_dependencies, uint32_t p_view_count, AttachmentReference p_fragment_density_map_attachment) = 0;
|
||||
virtual void render_pass_free(RenderPassID p_render_pass) = 0;
|
||||
|
||||
// ----- COMMANDS -----
|
||||
@ -787,6 +797,26 @@ public:
|
||||
uint32_t max_instance_count = 0;
|
||||
};
|
||||
|
||||
struct FragmentShadingRateCapabilities {
|
||||
Size2i min_texel_size;
|
||||
Size2i max_texel_size;
|
||||
Size2i max_fragment_size;
|
||||
bool pipeline_supported = false;
|
||||
bool primitive_supported = false;
|
||||
bool attachment_supported = false;
|
||||
};
|
||||
|
||||
struct FragmentDensityMapCapabilities {
|
||||
Size2i min_texel_size;
|
||||
Size2i max_texel_size;
|
||||
Size2i offset_granularity;
|
||||
bool attachment_supported = false;
|
||||
bool dynamic_attachment_supported = false;
|
||||
bool non_subsampled_images_supported = false;
|
||||
bool invocations_supported = false;
|
||||
bool offset_supported = false;
|
||||
};
|
||||
|
||||
enum ApiTrait {
|
||||
API_TRAIT_HONORS_PIPELINE_BARRIERS,
|
||||
API_TRAIT_SHADER_CHANGE_INVALIDATION,
|
||||
@ -828,6 +858,8 @@ public:
|
||||
virtual uint64_t api_trait_get(ApiTrait p_trait);
|
||||
virtual bool has_feature(Features p_feature) = 0;
|
||||
virtual const MultiviewCapabilities &get_multiview_capabilities() = 0;
|
||||
virtual const FragmentShadingRateCapabilities &get_fragment_shading_rate_capabilities() = 0;
|
||||
virtual const FragmentDensityMapCapabilities &get_fragment_density_map_capabilities() = 0;
|
||||
virtual String get_api_name() const = 0;
|
||||
virtual String get_api_version() const = 0;
|
||||
virtual String get_pipeline_cache_uuid() const = 0;
|
||||
|
@ -98,6 +98,8 @@ bool RenderingDeviceGraph::_is_write_usage(ResourceUsage p_usage) {
|
||||
case RESOURCE_USAGE_INDEX_BUFFER_READ:
|
||||
case RESOURCE_USAGE_TEXTURE_SAMPLE:
|
||||
case RESOURCE_USAGE_STORAGE_IMAGE_READ:
|
||||
case RESOURCE_USAGE_ATTACHMENT_FRAGMENT_SHADING_RATE_READ:
|
||||
case RESOURCE_USAGE_ATTACHMENT_FRAGMENT_DENSITY_MAP_READ:
|
||||
return false;
|
||||
case RESOURCE_USAGE_COPY_TO:
|
||||
case RESOURCE_USAGE_RESOLVE_TO:
|
||||
@ -132,6 +134,10 @@ RDD::TextureLayout RenderingDeviceGraph::_usage_to_image_layout(ResourceUsage p_
|
||||
return RDD::TEXTURE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
case RESOURCE_USAGE_ATTACHMENT_DEPTH_STENCIL_READ_WRITE:
|
||||
return RDD::TEXTURE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||
case RESOURCE_USAGE_ATTACHMENT_FRAGMENT_SHADING_RATE_READ:
|
||||
return RDD::TEXTURE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL;
|
||||
case RESOURCE_USAGE_ATTACHMENT_FRAGMENT_DENSITY_MAP_READ:
|
||||
return RDD::TEXTURE_LAYOUT_FRAGMENT_DENSITY_MAP_ATTACHMENT_OPTIMAL;
|
||||
case RESOURCE_USAGE_NONE:
|
||||
return RDD::TEXTURE_LAYOUT_UNDEFINED;
|
||||
default:
|
||||
@ -176,6 +182,10 @@ RDD::BarrierAccessBits RenderingDeviceGraph::_usage_to_access_bits(ResourceUsage
|
||||
return RDD::BarrierAccessBits(RDD::BARRIER_ACCESS_COLOR_ATTACHMENT_READ_BIT | RDD::BARRIER_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
|
||||
case RESOURCE_USAGE_ATTACHMENT_DEPTH_STENCIL_READ_WRITE:
|
||||
return RDD::BarrierAccessBits(RDD::BARRIER_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | RDD::BARRIER_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT);
|
||||
case RESOURCE_USAGE_ATTACHMENT_FRAGMENT_SHADING_RATE_READ:
|
||||
return RDD::BARRIER_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT;
|
||||
case RESOURCE_USAGE_ATTACHMENT_FRAGMENT_DENSITY_MAP_READ:
|
||||
return RDD::BARRIER_ACCESS_FRAGMENT_DENSITY_MAP_ATTACHMENT_READ_BIT;
|
||||
default:
|
||||
DEV_ASSERT(false && "Invalid usage.");
|
||||
return RDD::BarrierAccessBits(0);
|
||||
@ -918,7 +928,7 @@ void RenderingDeviceGraph::_run_draw_list_command(RDD::CommandBufferID p_command
|
||||
}
|
||||
}
|
||||
|
||||
void RenderingDeviceGraph::_add_draw_list_begin(FramebufferCache *p_framebuffer_cache, RDD::RenderPassID p_render_pass, RDD::FramebufferID p_framebuffer, Rect2i p_region, VectorView<AttachmentOperation> p_attachment_operations, VectorView<RDD::RenderPassClearValue> p_attachment_clear_values, bool p_uses_color, bool p_uses_depth, uint32_t p_breadcrumb, bool p_split_cmd_buffer) {
|
||||
void RenderingDeviceGraph::_add_draw_list_begin(FramebufferCache *p_framebuffer_cache, RDD::RenderPassID p_render_pass, RDD::FramebufferID p_framebuffer, Rect2i p_region, VectorView<AttachmentOperation> p_attachment_operations, VectorView<RDD::RenderPassClearValue> p_attachment_clear_values, BitField<RDD::PipelineStageBits> p_stages, uint32_t p_breadcrumb, bool p_split_cmd_buffer) {
|
||||
DEV_ASSERT(p_attachment_operations.size() == p_attachment_clear_values.size());
|
||||
|
||||
draw_instruction_list.clear();
|
||||
@ -927,6 +937,7 @@ void RenderingDeviceGraph::_add_draw_list_begin(FramebufferCache *p_framebuffer_
|
||||
draw_instruction_list.render_pass = p_render_pass;
|
||||
draw_instruction_list.framebuffer = p_framebuffer;
|
||||
draw_instruction_list.region = p_region;
|
||||
draw_instruction_list.stages = p_stages;
|
||||
draw_instruction_list.attachment_operations.resize(p_attachment_operations.size());
|
||||
draw_instruction_list.attachment_clear_values.resize(p_attachment_clear_values.size());
|
||||
|
||||
@ -935,15 +946,6 @@ void RenderingDeviceGraph::_add_draw_list_begin(FramebufferCache *p_framebuffer_
|
||||
draw_instruction_list.attachment_clear_values[i] = p_attachment_clear_values[i];
|
||||
}
|
||||
|
||||
if (p_uses_color) {
|
||||
draw_instruction_list.stages.set_flag(RDD::PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
|
||||
}
|
||||
|
||||
if (p_uses_depth) {
|
||||
draw_instruction_list.stages.set_flag(RDD::PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT);
|
||||
draw_instruction_list.stages.set_flag(RDD::PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT);
|
||||
}
|
||||
|
||||
draw_instruction_list.split_cmd_buffer = p_split_cmd_buffer;
|
||||
|
||||
#if defined(DEBUG_ENABLED) || defined(DEV_ENABLED)
|
||||
@ -1789,12 +1791,12 @@ void RenderingDeviceGraph::add_compute_list_end() {
|
||||
_add_command_to_graph(compute_instruction_list.command_trackers.ptr(), compute_instruction_list.command_tracker_usages.ptr(), compute_instruction_list.command_trackers.size(), command_index, command);
|
||||
}
|
||||
|
||||
void RenderingDeviceGraph::add_draw_list_begin(FramebufferCache *p_framebuffer_cache, Rect2i p_region, VectorView<AttachmentOperation> p_attachment_operations, VectorView<RDD::RenderPassClearValue> p_attachment_clear_values, bool p_uses_color, bool p_uses_depth, uint32_t p_breadcrumb, bool p_split_cmd_buffer) {
|
||||
_add_draw_list_begin(p_framebuffer_cache, RDD::RenderPassID(), RDD::FramebufferID(), p_region, p_attachment_operations, p_attachment_clear_values, p_uses_color, p_uses_depth, p_breadcrumb, p_split_cmd_buffer);
|
||||
void RenderingDeviceGraph::add_draw_list_begin(FramebufferCache *p_framebuffer_cache, Rect2i p_region, VectorView<AttachmentOperation> p_attachment_operations, VectorView<RDD::RenderPassClearValue> p_attachment_clear_values, BitField<RDD::PipelineStageBits> p_stages, uint32_t p_breadcrumb, bool p_split_cmd_buffer) {
|
||||
_add_draw_list_begin(p_framebuffer_cache, RDD::RenderPassID(), RDD::FramebufferID(), p_region, p_attachment_operations, p_attachment_clear_values, p_stages, p_breadcrumb, p_split_cmd_buffer);
|
||||
}
|
||||
|
||||
void RenderingDeviceGraph::add_draw_list_begin(RDD::RenderPassID p_render_pass, RDD::FramebufferID p_framebuffer, Rect2i p_region, VectorView<AttachmentOperation> p_attachment_operations, VectorView<RDD::RenderPassClearValue> p_attachment_clear_values, bool p_uses_color, bool p_uses_depth, uint32_t p_breadcrumb, bool p_split_cmd_buffer) {
|
||||
_add_draw_list_begin(nullptr, p_render_pass, p_framebuffer, p_region, p_attachment_operations, p_attachment_clear_values, p_uses_color, p_uses_depth, p_breadcrumb, p_split_cmd_buffer);
|
||||
void RenderingDeviceGraph::add_draw_list_begin(RDD::RenderPassID p_render_pass, RDD::FramebufferID p_framebuffer, Rect2i p_region, VectorView<AttachmentOperation> p_attachment_operations, VectorView<RDD::RenderPassClearValue> p_attachment_clear_values, BitField<RDD::PipelineStageBits> p_stages, uint32_t p_breadcrumb, bool p_split_cmd_buffer) {
|
||||
_add_draw_list_begin(nullptr, p_render_pass, p_framebuffer, p_region, p_attachment_operations, p_attachment_clear_values, p_stages, p_breadcrumb, p_split_cmd_buffer);
|
||||
}
|
||||
|
||||
void RenderingDeviceGraph::add_draw_list_bind_index_buffer(RDD::BufferID p_buffer, RDD::IndexBufferFormat p_format, uint32_t p_offset) {
|
||||
|
@ -149,6 +149,8 @@ public:
|
||||
RESOURCE_USAGE_STORAGE_IMAGE_READ_WRITE,
|
||||
RESOURCE_USAGE_ATTACHMENT_COLOR_READ_WRITE,
|
||||
RESOURCE_USAGE_ATTACHMENT_DEPTH_STENCIL_READ_WRITE,
|
||||
RESOURCE_USAGE_ATTACHMENT_FRAGMENT_SHADING_RATE_READ,
|
||||
RESOURCE_USAGE_ATTACHMENT_FRAGMENT_DENSITY_MAP_READ,
|
||||
RESOURCE_USAGE_MAX
|
||||
};
|
||||
|
||||
@ -752,7 +754,7 @@ private:
|
||||
void _run_compute_list_command(RDD::CommandBufferID p_command_buffer, const uint8_t *p_instruction_data, uint32_t p_instruction_data_size);
|
||||
void _get_draw_list_render_pass_and_framebuffer(const RecordedDrawListCommand *p_draw_list_command, RDD::RenderPassID &r_render_pass, RDD::FramebufferID &r_framebuffer);
|
||||
void _run_draw_list_command(RDD::CommandBufferID p_command_buffer, const uint8_t *p_instruction_data, uint32_t p_instruction_data_size);
|
||||
void _add_draw_list_begin(FramebufferCache *p_framebuffer_cache, RDD::RenderPassID p_render_pass, RDD::FramebufferID p_framebuffer, Rect2i p_region, VectorView<AttachmentOperation> p_attachment_operations, VectorView<RDD::RenderPassClearValue> p_attachment_clear_values, bool p_uses_color, bool p_uses_depth, uint32_t p_breadcrumb, bool p_split_cmd_buffer);
|
||||
void _add_draw_list_begin(FramebufferCache *p_framebuffer_cache, RDD::RenderPassID p_render_pass, RDD::FramebufferID p_framebuffer, Rect2i p_region, VectorView<AttachmentOperation> p_attachment_operations, VectorView<RDD::RenderPassClearValue> p_attachment_clear_values, BitField<RDD::PipelineStageBits> p_stages, uint32_t p_breadcrumb, bool p_split_cmd_buffer);
|
||||
void _run_secondary_command_buffer_task(const SecondaryCommandBuffer *p_secondary);
|
||||
void _wait_for_secondary_command_buffer_tasks();
|
||||
void _run_render_commands(int32_t p_level, const RecordedCommandSort *p_sorted_commands, uint32_t p_sorted_commands_count, RDD::CommandBufferID &r_command_buffer, CommandBufferPool &r_command_buffer_pool, int32_t &r_current_label_index, int32_t &r_current_label_level);
|
||||
@ -785,8 +787,8 @@ public:
|
||||
void add_compute_list_usage(ResourceTracker *p_tracker, ResourceUsage p_usage);
|
||||
void add_compute_list_usages(VectorView<ResourceTracker *> p_trackers, VectorView<ResourceUsage> p_usages);
|
||||
void add_compute_list_end();
|
||||
void add_draw_list_begin(FramebufferCache *p_framebuffer_cache, Rect2i p_region, VectorView<AttachmentOperation> p_attachment_operations, VectorView<RDD::RenderPassClearValue> p_attachment_clear_values, bool p_uses_color, bool p_uses_depth, uint32_t p_breadcrumb = 0, bool p_split_cmd_buffer = false);
|
||||
void add_draw_list_begin(RDD::RenderPassID p_render_pass, RDD::FramebufferID p_framebuffer, Rect2i p_region, VectorView<AttachmentOperation> p_attachment_operations, VectorView<RDD::RenderPassClearValue> p_attachment_clear_values, bool p_uses_color, bool p_uses_depth, uint32_t p_breadcrumb = 0, bool p_split_cmd_buffer = false);
|
||||
void add_draw_list_begin(FramebufferCache *p_framebuffer_cache, Rect2i p_region, VectorView<AttachmentOperation> p_attachment_operations, VectorView<RDD::RenderPassClearValue> p_attachment_clear_values, BitField<RDD::PipelineStageBits> p_stages, uint32_t p_breadcrumb = 0, bool p_split_cmd_buffer = false);
|
||||
void add_draw_list_begin(RDD::RenderPassID p_render_pass, RDD::FramebufferID p_framebuffer, Rect2i p_region, VectorView<AttachmentOperation> p_attachment_operations, VectorView<RDD::RenderPassClearValue> p_attachment_clear_values, BitField<RDD::PipelineStageBits> p_stages, uint32_t p_breadcrumb = 0, bool p_split_cmd_buffer = false);
|
||||
void add_draw_list_bind_index_buffer(RDD::BufferID p_buffer, RDD::IndexBufferFormat p_format, uint32_t p_offset);
|
||||
void add_draw_list_bind_pipeline(RDD::PipelineID p_pipeline, BitField<RDD::PipelineStageBits> p_pipeline_stage_bits);
|
||||
void add_draw_list_bind_uniform_set(RDD::ShaderID p_shader, RDD::UniformSetID p_uniform_set, uint32_t set_index);
|
||||
|
@ -104,13 +104,12 @@ void XRVRS::set_vrs_render_region(const Rect2i &p_vrs_render_region) {
|
||||
RID XRVRS::make_vrs_texture(const Size2 &p_target_size, const PackedVector2Array &p_eye_foci) {
|
||||
ERR_FAIL_COND_V(p_eye_foci.is_empty(), RID());
|
||||
|
||||
int32_t texel_width = RD::get_singleton()->limit_get(RD::LIMIT_VRS_TEXEL_WIDTH);
|
||||
int32_t texel_height = RD::get_singleton()->limit_get(RD::LIMIT_VRS_TEXEL_HEIGHT);
|
||||
Size2i texel_size = RD::get_singleton()->vrs_get_texel_size();
|
||||
|
||||
// Should return sensible data or graphics API does not support VRS.
|
||||
ERR_FAIL_COND_V(texel_width < 1 || texel_height < 1, RID());
|
||||
ERR_FAIL_COND_V(texel_size.x < 1 || texel_size.y < 1, RID());
|
||||
|
||||
Size2 vrs_size = Size2(0.5 + p_target_size.x / texel_width, 0.5 + p_target_size.y / texel_height).round();
|
||||
Size2 vrs_size = Size2(0.5 + p_target_size.x / texel_size.x, 0.5 + p_target_size.y / texel_size.y).floor();
|
||||
|
||||
// Make sure we have at least one pixel.
|
||||
vrs_size = vrs_size.maxf(1.0);
|
||||
@ -150,16 +149,18 @@ RID XRVRS::make_vrs_texture(const Size2 &p_target_size, const PackedVector2Array
|
||||
|
||||
Vector2i view_center;
|
||||
view_center.x = int(vrs_size.x * (eye_foci[i].x + 1.0) * region_ratio.x * 0.5) + region_offset.x;
|
||||
view_center.y = int(vrs_size.y * (eye_foci[i].y + 1.0) * region_ratio.y * 0.5) + region_offset.y;
|
||||
view_center.y = int(vrs_size.y * (-eye_foci[i].y + 1.0) * region_ratio.y * 0.5) + region_offset.y;
|
||||
|
||||
int d = 0;
|
||||
for (int y = 0; y < vrs_sizei.y; y++) {
|
||||
for (int x = 0; x < vrs_sizei.x; x++) {
|
||||
// Generate a density map that represents the distance to the view focus point. While this leaves the opportunities
|
||||
// offered by the density map being different in each direction currently unused, it was found to give better tile
|
||||
// distribution on hardware that supports the feature natively. This area is open to improvements in the future.
|
||||
Vector2 offset = Vector2(x - view_center.x, y - view_center.y) / region_ratio;
|
||||
real_t density = 255.0 * MAX(0.0, (Math::abs(offset.x) - min_radius) / outer_radius);
|
||||
data_ptr[d++] = MIN(255, density);
|
||||
density = 255.0 * MAX(0.0, (Math::abs(offset.y) - min_radius) / outer_radius);
|
||||
data_ptr[d++] = MIN(255, density);
|
||||
real_t density = MAX(offset.length() - min_radius, 0.0) / outer_radius;
|
||||
data_ptr[d++] = CLAMP(255.0 * density, 0, 255);
|
||||
data_ptr[d++] = CLAMP(255.0 * density, 0, 255);
|
||||
}
|
||||
}
|
||||
images.push_back(Image::create_from_data(vrs_sizei.x, vrs_sizei.y, false, Image::FORMAT_RG8, data));
|
||||
|
Loading…
x
Reference in New Issue
Block a user