Skip to content

Commit 206e8d6

Browse files
Implement support for fragment density maps.
Co-Authored-By: Bastiaan Olij <mux213@gmail.com>
1 parent 0eadbdb commit 206e8d6

21 files changed

+481
-278
lines changed

drivers/d3d12/rendering_device_driver_d3d12.cpp

+37-42
Original file line numberDiff line numberDiff line change
@@ -1203,7 +1203,7 @@ RDD::TextureID RenderingDeviceDriverD3D12::texture_create(const TextureFormat &p
12031203
if ((p_format.usage_bits & TEXTURE_USAGE_STORAGE_BIT)) {
12041204
resource_desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
12051205
}
1206-
if ((p_format.usage_bits & TEXTURE_USAGE_VRS_ATTACHMENT_BIT)) {
1206+
if ((p_format.usage_bits & TEXTURE_USAGE_VRS_ATTACHMENT_BIT) && (p_format.usage_bits & TEXTURE_USAGE_VRS_FRAGMENT_SHADING_RATE_BIT)) {
12071207
// For VRS images we can't use the typeless format.
12081208
resource_desc.Format = DXGI_FORMAT_R8_UINT;
12091209
}
@@ -1808,8 +1808,11 @@ static D3D12_BARRIER_ACCESS _rd_texture_layout_access_mask(RDD::TextureLayout p_
18081808
return D3D12_BARRIER_ACCESS_RESOLVE_SOURCE;
18091809
case RDD::TEXTURE_LAYOUT_RESOLVE_DST_OPTIMAL:
18101810
return D3D12_BARRIER_ACCESS_RESOLVE_DEST;
1811-
case RDD::TEXTURE_LAYOUT_VRS_ATTACHMENT_OPTIMAL:
1811+
case RDD::TEXTURE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL:
18121812
return D3D12_BARRIER_ACCESS_SHADING_RATE_SOURCE;
1813+
case RDD::TEXTURE_LAYOUT_FRAGMENT_DENSITY_MAP_ATTACHMENT_OPTIMAL:
1814+
DEV_ASSERT(false && "Fragment density maps are not supported in D3D12.");
1815+
return D3D12_BARRIER_ACCESS_NO_ACCESS;
18131816
default:
18141817
return D3D12_BARRIER_ACCESS_NO_ACCESS;
18151818
}
@@ -1928,7 +1931,7 @@ static void _rd_stages_to_d3d12(BitField<RDD::PipelineStageBits> p_stages, D3D12
19281931
r_sync |= D3D12_BARRIER_SYNC_VERTEX_SHADING;
19291932
}
19301933

1931-
if (p_stages.has_flag(RDD::PIPELINE_STAGE_FRAGMENT_SHADER_BIT)) {
1934+
if (p_stages.has_flag(RDD::PIPELINE_STAGE_FRAGMENT_SHADER_BIT) || p_stages.has_flag(RDD::PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT)) {
19321935
r_sync |= D3D12_BARRIER_SYNC_PIXEL_SHADING;
19331936
}
19341937

@@ -2023,8 +2026,11 @@ static D3D12_BARRIER_LAYOUT _rd_texture_layout_to_d3d12_barrier_layout(RDD::Text
20232026
return D3D12_BARRIER_LAYOUT_RESOLVE_SOURCE;
20242027
case RDD::TEXTURE_LAYOUT_RESOLVE_DST_OPTIMAL:
20252028
return D3D12_BARRIER_LAYOUT_RESOLVE_DEST;
2026-
case RDD::TEXTURE_LAYOUT_VRS_ATTACHMENT_OPTIMAL:
2029+
case RDD::TEXTURE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL:
20272030
return D3D12_BARRIER_LAYOUT_SHADING_RATE_SOURCE;
2031+
case RDD::TEXTURE_LAYOUT_FRAGMENT_DENSITY_MAP_ATTACHMENT_OPTIMAL:
2032+
DEV_ASSERT(false && "Fragment density maps are not supported in D3D12.");
2033+
return D3D12_BARRIER_LAYOUT_UNDEFINED;
20282034
default:
20292035
DEV_ASSERT(false && "Unknown texture layout.");
20302036
return D3D12_BARRIER_LAYOUT_UNDEFINED;
@@ -2412,7 +2418,7 @@ RDD::SwapChainID RenderingDeviceDriverD3D12::swap_chain_create(RenderingContextD
24122418
color_ref.aspect.set_flag(RDD::TEXTURE_ASPECT_COLOR_BIT);
24132419
subpass.color_references.push_back(color_ref);
24142420

2415-
RenderPassID render_pass = render_pass_create(attachment, subpass, {}, 1);
2421+
RenderPassID render_pass = render_pass_create(attachment, subpass, {}, 1, AttachmentReference());
24162422
ERR_FAIL_COND_V(!render_pass, SwapChainID());
24172423

24182424
// Create the empty swap chain until it is resized.
@@ -2772,8 +2778,8 @@ RDD::FramebufferID RenderingDeviceDriverD3D12::_framebuffer_create(RenderPassID
27722778

27732779
uint32_t vrs_index = UINT32_MAX;
27742780
for (const Subpass &E : pass_info->subpasses) {
2775-
if (E.vrs_reference.attachment != AttachmentReference::UNUSED) {
2776-
vrs_index = E.vrs_reference.attachment;
2781+
if (E.fragment_shading_rate_reference.attachment != AttachmentReference::UNUSED) {
2782+
vrs_index = E.fragment_shading_rate_reference.attachment;
27772783
}
27782784
}
27792785

@@ -4922,7 +4928,9 @@ Vector<uint8_t> RenderingDeviceDriverD3D12::pipeline_cache_serialize() {
49224928

49234929
// ----- SUBPASS -----
49244930

4925-
RDD::RenderPassID RenderingDeviceDriverD3D12::render_pass_create(VectorView<Attachment> p_attachments, VectorView<Subpass> p_subpasses, VectorView<SubpassDependency> p_subpass_dependencies, uint32_t p_view_count) {
4931+
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) {
4932+
ERR_FAIL_COND_V_MSG(p_fragment_density_map_attachment.attachment != AttachmentReference::UNUSED, RenderPassID(), "Fragment density maps are not supported in D3D12.");
4933+
49264934
// Pre-bookkeep.
49274935
RenderPassInfo *pass_info = VersatileResource::allocate<RenderPassInfo>(resources_allocator);
49284936

@@ -5023,7 +5031,7 @@ void RenderingDeviceDriverD3D12::command_begin_render_pass(CommandBufferID p_cmd
50235031
}
50245032
}
50255033

5026-
if (fb_info->vrs_attachment && vrs_capabilities.ss_image_supported) {
5034+
if (fb_info->vrs_attachment && fsr_capabilities.attachment_supported) {
50275035
ComPtr<ID3D12GraphicsCommandList5> cmd_list_5;
50285036
cmd_buf_info->cmd_list->QueryInterface(cmd_list_5.GetAddressOf());
50295037
if (cmd_list_5) {
@@ -5143,7 +5151,7 @@ void RenderingDeviceDriverD3D12::command_end_render_pass(CommandBufferID p_cmd_b
51435151
const FramebufferInfo *fb_info = cmd_buf_info->render_pass_state.fb_info;
51445152
const RenderPassInfo *pass_info = cmd_buf_info->render_pass_state.pass_info;
51455153

5146-
if (vrs_capabilities.ss_image_supported) {
5154+
if (fsr_capabilities.attachment_supported) {
51475155
ComPtr<ID3D12GraphicsCommandList5> cmd_list_5;
51485156
cmd_buf_info->cmd_list->QueryInterface(cmd_list_5.GetAddressOf());
51495157
if (cmd_list_5) {
@@ -6173,12 +6181,6 @@ uint64_t RenderingDeviceDriverD3D12::limit_get(Limit p_limit) {
61736181
return subgroup_capabilities.supported_stages_flags_rd();
61746182
case LIMIT_SUBGROUP_OPERATIONS:
61756183
return subgroup_capabilities.supported_operations_flags_rd();
6176-
case LIMIT_VRS_TEXEL_WIDTH:
6177-
case LIMIT_VRS_TEXEL_HEIGHT:
6178-
return vrs_capabilities.ss_image_tile_size;
6179-
case LIMIT_VRS_MAX_FRAGMENT_WIDTH:
6180-
case LIMIT_VRS_MAX_FRAGMENT_HEIGHT:
6181-
return vrs_capabilities.ss_max_fragment_size;
61826184
default: {
61836185
#ifdef DEV_ENABLED
61846186
WARN_PRINT("Returning maximum value for unknown limit " + itos(p_limit) + ".");
@@ -6213,12 +6215,8 @@ uint64_t RenderingDeviceDriverD3D12::api_trait_get(ApiTrait p_trait) {
62136215

62146216
bool RenderingDeviceDriverD3D12::has_feature(Features p_feature) {
62156217
switch (p_feature) {
6216-
case SUPPORTS_MULTIVIEW:
6217-
return multiview_capabilities.is_supported && multiview_capabilities.max_view_count > 1;
62186218
case SUPPORTS_FSR_HALF_FLOAT:
62196219
return shader_capabilities.native_16bit_ops && storage_buffer_capabilities.storage_buffer_16_bit_access_is_supported;
6220-
case SUPPORTS_ATTACHMENT_VRS:
6221-
return vrs_capabilities.ss_image_supported;
62226220
case SUPPORTS_FRAGMENT_SHADER_WITH_ONLY_SIDE_EFFECTS:
62236221
return true;
62246222
default:
@@ -6230,6 +6228,14 @@ const RDD::MultiviewCapabilities &RenderingDeviceDriverD3D12::get_multiview_capa
62306228
return multiview_capabilities;
62316229
}
62326230

6231+
const RDD::FragmentShadingRateCapabilities &RenderingDeviceDriverD3D12::get_fragment_shading_rate_capabilities() {
6232+
return fsr_capabilities;
6233+
}
6234+
6235+
const RDD::FragmentDensityMapCapabilities &RenderingDeviceDriverD3D12::get_fragment_density_map_capabilities() {
6236+
return fdm_capabilities;
6237+
}
6238+
62336239
String RenderingDeviceDriverD3D12::get_api_name() const {
62346240
return "D3D12";
62356241
}
@@ -6391,12 +6397,6 @@ Error RenderingDeviceDriverD3D12::_check_capabilities() {
63916397
device_capabilities.version_minor = feature_level % 10;
63926398

63936399
// Assume not supported until proven otherwise.
6394-
vrs_capabilities.draw_call_supported = false;
6395-
vrs_capabilities.primitive_supported = false;
6396-
vrs_capabilities.primitive_in_multiviewport = false;
6397-
vrs_capabilities.ss_image_supported = false;
6398-
vrs_capabilities.ss_image_tile_size = 1;
6399-
vrs_capabilities.additional_rates_supported = false;
64006400
multiview_capabilities.is_supported = false;
64016401
multiview_capabilities.geometry_shader_is_supported = false;
64026402
multiview_capabilities.tessellation_shader_is_supported = false;
@@ -6487,14 +6487,12 @@ Error RenderingDeviceDriverD3D12::_check_capabilities() {
64876487
res = device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS6, &options6, sizeof(options6));
64886488
if (SUCCEEDED(res)) {
64896489
if (options6.VariableShadingRateTier >= D3D12_VARIABLE_SHADING_RATE_TIER_1) {
6490-
vrs_capabilities.draw_call_supported = true;
6490+
fsr_capabilities.pipeline_supported = true;
64916491
if (options6.VariableShadingRateTier >= D3D12_VARIABLE_SHADING_RATE_TIER_2) {
6492-
vrs_capabilities.primitive_supported = true;
6493-
vrs_capabilities.primitive_in_multiviewport = options6.PerPrimitiveShadingRateSupportedWithViewportIndexing;
6494-
vrs_capabilities.ss_image_supported = true;
6495-
vrs_capabilities.ss_image_tile_size = options6.ShadingRateImageTileSize;
6496-
vrs_capabilities.ss_max_fragment_size = 8; // TODO figure out if this is supplied and/or needed
6497-
vrs_capabilities.additional_rates_supported = options6.AdditionalShadingRatesSupported;
6492+
fsr_capabilities.primitive_supported = true;
6493+
fsr_capabilities.attachment_supported = true;
6494+
fsr_capabilities.min_texel_size = Size2i(options6.ShadingRateImageTileSize, options6.ShadingRateImageTileSize);
6495+
fsr_capabilities.max_texel_size = Size2i(8, 8);
64986496
}
64996497
}
65006498
}
@@ -6506,19 +6504,16 @@ Error RenderingDeviceDriverD3D12::_check_capabilities() {
65066504
barrier_capabilities.enhanced_barriers_supported = options12.EnhancedBarriersSupported;
65076505
}
65086506

6509-
if (vrs_capabilities.draw_call_supported || vrs_capabilities.primitive_supported || vrs_capabilities.ss_image_supported) {
6507+
if (fsr_capabilities.pipeline_supported || fsr_capabilities.primitive_supported || fsr_capabilities.attachment_supported) {
65106508
print_verbose("- D3D12 Variable Rate Shading supported:");
6511-
if (vrs_capabilities.draw_call_supported) {
6509+
if (fsr_capabilities.pipeline_supported) {
65126510
print_verbose(" Draw call");
65136511
}
6514-
if (vrs_capabilities.primitive_supported) {
6515-
print_verbose(String(" Per-primitive (multi-viewport: ") + (vrs_capabilities.primitive_in_multiviewport ? "yes" : "no") + ")");
6516-
}
6517-
if (vrs_capabilities.ss_image_supported) {
6518-
print_verbose(String(" Screen-space image (tile size: ") + itos(vrs_capabilities.ss_image_tile_size) + ")");
6512+
if (fsr_capabilities.primitive_supported) {
6513+
print_verbose(" Primitive");
65196514
}
6520-
if (vrs_capabilities.additional_rates_supported) {
6521-
print_verbose(String(" Additional rates: ") + (vrs_capabilities.additional_rates_supported ? "yes" : "no"));
6515+
if (fsr_capabilities.attachment_supported) {
6516+
print_verbose(String(" Screen-space image (tile size: ") + itos(fsr_capabilities.min_texel_size.x) + ")");
65226517
}
65236518
} else {
65246519
print_verbose("- D3D12 Variable Rate Shading not supported");

drivers/d3d12/rendering_device_driver_d3d12.h

+5-12
Original file line numberDiff line numberDiff line change
@@ -116,16 +116,6 @@ class RenderingDeviceDriverD3D12 : public RenderingDeviceDriver {
116116
uint32_t supported_operations_flags_rd() const;
117117
};
118118

119-
struct VRSCapabilities {
120-
bool draw_call_supported = false; // We can specify our fragment rate on a draw call level.
121-
bool primitive_supported = false; // We can specify our fragment rate on each drawcall.
122-
bool primitive_in_multiviewport = false;
123-
bool ss_image_supported = false; // We can provide a density map attachment on our framebuffer.
124-
uint32_t ss_image_tile_size = 0;
125-
uint32_t ss_max_fragment_size = 0;
126-
bool additional_rates_supported = false;
127-
};
128-
129119
struct ShaderCapabilities {
130120
D3D_SHADER_MODEL shader_model = (D3D_SHADER_MODEL)0;
131121
bool native_16bit_ops = false;
@@ -157,7 +147,8 @@ class RenderingDeviceDriverD3D12 : public RenderingDeviceDriver {
157147
uint32_t feature_level = 0; // Major * 10 + minor.
158148
SubgroupCapabilities subgroup_capabilities;
159149
RDD::MultiviewCapabilities multiview_capabilities;
160-
VRSCapabilities vrs_capabilities;
150+
FragmentShadingRateCapabilities fsr_capabilities;
151+
FragmentDensityMapCapabilities fdm_capabilities;
161152
ShaderCapabilities shader_capabilities;
162153
StorageBufferCapabilities storage_buffer_capabilities;
163154
FormatCapabilities format_capabilities;
@@ -825,7 +816,7 @@ class RenderingDeviceDriverD3D12 : public RenderingDeviceDriver {
825816
};
826817

827818
public:
828-
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;
819+
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;
829820
virtual void render_pass_free(RenderPassID p_render_pass) override final;
830821

831822
// ----- COMMANDS -----
@@ -990,6 +981,8 @@ class RenderingDeviceDriverD3D12 : public RenderingDeviceDriver {
990981
virtual uint64_t api_trait_get(ApiTrait p_trait) override final;
991982
virtual bool has_feature(Features p_feature) override final;
992983
virtual const MultiviewCapabilities &get_multiview_capabilities() override final;
984+
virtual const FragmentShadingRateCapabilities &get_fragment_shading_rate_capabilities() override final;
985+
virtual const FragmentDensityMapCapabilities &get_fragment_density_map_capabilities() override final;
993986
virtual String get_api_name() const override final;
994987
virtual String get_api_version() const override final;
995988
virtual String get_pipeline_cache_uuid() const override final;

drivers/metal/rendering_device_driver_metal.h

+5-1
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ class API_AVAILABLE(macos(11.0), ios(14.0)) RenderingDeviceDriverMetal : public
6767

6868
RDD::Capabilities capabilities;
6969
RDD::MultiviewCapabilities multiview_capabilities;
70+
RDD::FragmentShadingRateCapabilities fsr_capabilities;
71+
RDD::FragmentDensityMapCapabilities fdm_capabilities;
7072

7173
id<MTLBinaryArchive> archive = nil;
7274
uint32_t archive_count = 0;
@@ -315,7 +317,7 @@ class API_AVAILABLE(macos(11.0), ios(14.0)) RenderingDeviceDriverMetal : public
315317

316318
// ----- SUBPASS -----
317319

318-
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;
320+
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;
319321
virtual void render_pass_free(RenderPassID p_render_pass) override final;
320322

321323
// ----- COMMANDS -----
@@ -417,6 +419,8 @@ class API_AVAILABLE(macos(11.0), ios(14.0)) RenderingDeviceDriverMetal : public
417419
virtual uint64_t api_trait_get(ApiTrait p_trait) override final;
418420
virtual bool has_feature(Features p_feature) override final;
419421
virtual const MultiviewCapabilities &get_multiview_capabilities() override final;
422+
virtual const FragmentShadingRateCapabilities &get_fragment_shading_rate_capabilities() override final;
423+
virtual const FragmentDensityMapCapabilities &get_fragment_density_map_capabilities() override final;
420424
virtual String get_api_name() const override final { return "Metal"; }
421425
virtual String get_api_version() const override final;
422426
virtual String get_pipeline_cache_uuid() const override final;

drivers/metal/rendering_device_driver_metal.mm

+10-13
Original file line numberDiff line numberDiff line change
@@ -933,7 +933,7 @@ static const API_AVAILABLE(macos(11.0), ios(14.0)) MTLSamplerBorderColor SAMPLER
933933
color_ref.aspect.set_flag(RDD::TEXTURE_ASPECT_COLOR_BIT);
934934
subpass.color_references.push_back(color_ref);
935935

936-
RenderPassID render_pass = render_pass_create(attachment, subpass, {}, 1);
936+
RenderPassID render_pass = render_pass_create(attachment, subpass, {}, 1, RDD::AttachmentReference());
937937
ERR_FAIL_COND_V(!render_pass, SwapChainID());
938938

939939
// Create the empty swap chain until it is resized.
@@ -2992,7 +2992,7 @@ bool isArrayTexture(MTLTextureType p_type) {
29922992

29932993
// ----- SUBPASS -----
29942994

2995-
RDD::RenderPassID RenderingDeviceDriverMetal::render_pass_create(VectorView<Attachment> p_attachments, VectorView<Subpass> p_subpasses, VectorView<SubpassDependency> p_subpass_dependencies, uint32_t p_view_count) {
2995+
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) {
29962996
PixelFormats &pf = *pixel_formats;
29972997

29982998
size_t subpass_count = p_subpasses.size();
@@ -3872,8 +3872,6 @@ bool isArrayTexture(MTLTextureType p_type) {
38723872
return (int64_t)limits.subgroupSupportedShaderStages;
38733873
case LIMIT_SUBGROUP_OPERATIONS:
38743874
return (int64_t)limits.subgroupSupportedOperations;
3875-
UNKNOWN(LIMIT_VRS_TEXEL_WIDTH);
3876-
UNKNOWN(LIMIT_VRS_TEXEL_HEIGHT);
38773875
default:
38783876
ERR_FAIL_V(0);
38793877
}
@@ -3892,17 +3890,8 @@ bool isArrayTexture(MTLTextureType p_type) {
38923890

38933891
bool RenderingDeviceDriverMetal::has_feature(Features p_feature) {
38943892
switch (p_feature) {
3895-
case SUPPORTS_MULTIVIEW:
3896-
return multiview_capabilities.is_supported;
38973893
case SUPPORTS_FSR_HALF_FLOAT:
38983894
return true;
3899-
case SUPPORTS_ATTACHMENT_VRS:
3900-
// TODO(sgc): Maybe supported via https://developer.apple.com/documentation/metal/render_passes/rendering_at_different_rasterization_rates?language=objc
3901-
// See also:
3902-
//
3903-
// * https://forum.beyond3d.com/threads/variable-rate-shading-vs-variable-rate-rasterization.62243/post-2191363
3904-
//
3905-
return false;
39063895
case SUPPORTS_FRAGMENT_SHADER_WITH_ONLY_SIDE_EFFECTS:
39073896
return true;
39083897
default:
@@ -3914,6 +3903,14 @@ bool isArrayTexture(MTLTextureType p_type) {
39143903
return multiview_capabilities;
39153904
}
39163905

3906+
const RDD::FragmentShadingRateCapabilities &RenderingDeviceDriverMetal::get_fragment_shading_rate_capabilities() {
3907+
return fsr_capabilities;
3908+
}
3909+
3910+
const RDD::FragmentDensityMapCapabilities &RenderingDeviceDriverMetal::get_fragment_density_map_capabilities() {
3911+
return fdm_capabilities;
3912+
}
3913+
39173914
String RenderingDeviceDriverMetal::get_api_version() const {
39183915
return vformat("%d.%d", version_major, version_minor);
39193916
}

0 commit comments

Comments
 (0)