Skip to content

Commit efda589

Browse files
DarioSamoBastiaanOlij
authored andcommitted
Implement support for fragment density maps.
Co-Authored-By: Bastiaan Olij <mux213@gmail.com>
1 parent f2cc3f1 commit efda589

21 files changed

+737
-359
lines changed

drivers/d3d12/rendering_device_driver_d3d12.cpp

+37-42
Original file line numberDiff line numberDiff line change
@@ -1222,7 +1222,7 @@ RDD::TextureID RenderingDeviceDriverD3D12::texture_create(const TextureFormat &p
12221222
if ((p_format.usage_bits & TEXTURE_USAGE_STORAGE_BIT)) {
12231223
resource_desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
12241224
}
1225-
if ((p_format.usage_bits & TEXTURE_USAGE_VRS_ATTACHMENT_BIT)) {
1225+
if ((p_format.usage_bits & TEXTURE_USAGE_VRS_ATTACHMENT_BIT) && (p_format.usage_bits & TEXTURE_USAGE_VRS_FRAGMENT_SHADING_RATE_BIT)) {
12261226
// For VRS images we can't use the typeless format.
12271227
resource_desc.Format = DXGI_FORMAT_R8_UINT;
12281228
}
@@ -1827,8 +1827,11 @@ static D3D12_BARRIER_ACCESS _rd_texture_layout_access_mask(RDD::TextureLayout p_
18271827
return D3D12_BARRIER_ACCESS_RESOLVE_SOURCE;
18281828
case RDD::TEXTURE_LAYOUT_RESOLVE_DST_OPTIMAL:
18291829
return D3D12_BARRIER_ACCESS_RESOLVE_DEST;
1830-
case RDD::TEXTURE_LAYOUT_VRS_ATTACHMENT_OPTIMAL:
1830+
case RDD::TEXTURE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL:
18311831
return D3D12_BARRIER_ACCESS_SHADING_RATE_SOURCE;
1832+
case RDD::TEXTURE_LAYOUT_FRAGMENT_DENSITY_MAP_ATTACHMENT_OPTIMAL:
1833+
DEV_ASSERT(false && "Fragment density maps are not supported in D3D12.");
1834+
return D3D12_BARRIER_ACCESS_NO_ACCESS;
18321835
default:
18331836
return D3D12_BARRIER_ACCESS_NO_ACCESS;
18341837
}
@@ -1947,7 +1950,7 @@ static void _rd_stages_to_d3d12(BitField<RDD::PipelineStageBits> p_stages, D3D12
19471950
r_sync |= D3D12_BARRIER_SYNC_VERTEX_SHADING;
19481951
}
19491952

1950-
if (p_stages.has_flag(RDD::PIPELINE_STAGE_FRAGMENT_SHADER_BIT)) {
1953+
if (p_stages.has_flag(RDD::PIPELINE_STAGE_FRAGMENT_SHADER_BIT) || p_stages.has_flag(RDD::PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT)) {
19511954
r_sync |= D3D12_BARRIER_SYNC_PIXEL_SHADING;
19521955
}
19531956

@@ -2042,8 +2045,11 @@ static D3D12_BARRIER_LAYOUT _rd_texture_layout_to_d3d12_barrier_layout(RDD::Text
20422045
return D3D12_BARRIER_LAYOUT_RESOLVE_SOURCE;
20432046
case RDD::TEXTURE_LAYOUT_RESOLVE_DST_OPTIMAL:
20442047
return D3D12_BARRIER_LAYOUT_RESOLVE_DEST;
2045-
case RDD::TEXTURE_LAYOUT_VRS_ATTACHMENT_OPTIMAL:
2048+
case RDD::TEXTURE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL:
20462049
return D3D12_BARRIER_LAYOUT_SHADING_RATE_SOURCE;
2050+
case RDD::TEXTURE_LAYOUT_FRAGMENT_DENSITY_MAP_ATTACHMENT_OPTIMAL:
2051+
DEV_ASSERT(false && "Fragment density maps are not supported in D3D12.");
2052+
return D3D12_BARRIER_LAYOUT_UNDEFINED;
20472053
default:
20482054
DEV_ASSERT(false && "Unknown texture layout.");
20492055
return D3D12_BARRIER_LAYOUT_UNDEFINED;
@@ -2451,7 +2457,7 @@ RDD::SwapChainID RenderingDeviceDriverD3D12::swap_chain_create(RenderingContextD
24512457
color_ref.aspect.set_flag(RDD::TEXTURE_ASPECT_COLOR_BIT);
24522458
subpass.color_references.push_back(color_ref);
24532459

2454-
RenderPassID render_pass = render_pass_create(attachment, subpass, {}, 1);
2460+
RenderPassID render_pass = render_pass_create(attachment, subpass, {}, 1, AttachmentReference());
24552461
ERR_FAIL_COND_V(!render_pass, SwapChainID());
24562462

24572463
// Create the empty swap chain until it is resized.
@@ -2811,8 +2817,8 @@ RDD::FramebufferID RenderingDeviceDriverD3D12::_framebuffer_create(RenderPassID
28112817

28122818
uint32_t vrs_index = UINT32_MAX;
28132819
for (const Subpass &E : pass_info->subpasses) {
2814-
if (E.vrs_reference.attachment != AttachmentReference::UNUSED) {
2815-
vrs_index = E.vrs_reference.attachment;
2820+
if (E.fragment_shading_rate_reference.attachment != AttachmentReference::UNUSED) {
2821+
vrs_index = E.fragment_shading_rate_reference.attachment;
28162822
}
28172823
}
28182824

@@ -4963,7 +4969,9 @@ Vector<uint8_t> RenderingDeviceDriverD3D12::pipeline_cache_serialize() {
49634969

49644970
// ----- SUBPASS -----
49654971

4966-
RDD::RenderPassID RenderingDeviceDriverD3D12::render_pass_create(VectorView<Attachment> p_attachments, VectorView<Subpass> p_subpasses, VectorView<SubpassDependency> p_subpass_dependencies, uint32_t p_view_count) {
4972+
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) {
4973+
ERR_FAIL_COND_V_MSG(p_fragment_density_map_attachment.attachment != AttachmentReference::UNUSED, RenderPassID(), "Fragment density maps are not supported in D3D12.");
4974+
49674975
// Pre-bookkeep.
49684976
RenderPassInfo *pass_info = VersatileResource::allocate<RenderPassInfo>(resources_allocator);
49694977

@@ -5064,7 +5072,7 @@ void RenderingDeviceDriverD3D12::command_begin_render_pass(CommandBufferID p_cmd
50645072
}
50655073
}
50665074

5067-
if (fb_info->vrs_attachment && vrs_capabilities.ss_image_supported) {
5075+
if (fb_info->vrs_attachment && fsr_capabilities.attachment_supported) {
50685076
ComPtr<ID3D12GraphicsCommandList5> cmd_list_5;
50695077
cmd_buf_info->cmd_list->QueryInterface(cmd_list_5.GetAddressOf());
50705078
if (cmd_list_5) {
@@ -5184,7 +5192,7 @@ void RenderingDeviceDriverD3D12::command_end_render_pass(CommandBufferID p_cmd_b
51845192
const FramebufferInfo *fb_info = cmd_buf_info->render_pass_state.fb_info;
51855193
const RenderPassInfo *pass_info = cmd_buf_info->render_pass_state.pass_info;
51865194

5187-
if (vrs_capabilities.ss_image_supported) {
5195+
if (fsr_capabilities.attachment_supported) {
51885196
ComPtr<ID3D12GraphicsCommandList5> cmd_list_5;
51895197
cmd_buf_info->cmd_list->QueryInterface(cmd_list_5.GetAddressOf());
51905198
if (cmd_list_5) {
@@ -6244,12 +6252,6 @@ uint64_t RenderingDeviceDriverD3D12::limit_get(Limit p_limit) {
62446252
return subgroup_capabilities.supported_stages_flags_rd();
62456253
case LIMIT_SUBGROUP_OPERATIONS:
62466254
return subgroup_capabilities.supported_operations_flags_rd();
6247-
case LIMIT_VRS_TEXEL_WIDTH:
6248-
case LIMIT_VRS_TEXEL_HEIGHT:
6249-
return vrs_capabilities.ss_image_tile_size;
6250-
case LIMIT_VRS_MAX_FRAGMENT_WIDTH:
6251-
case LIMIT_VRS_MAX_FRAGMENT_HEIGHT:
6252-
return vrs_capabilities.ss_max_fragment_size;
62536255
case LIMIT_MAX_SHADER_VARYINGS:
62546256
return MIN(D3D12_VS_OUTPUT_REGISTER_COUNT, D3D12_PS_INPUT_REGISTER_COUNT);
62556257
default: {
@@ -6286,12 +6288,8 @@ uint64_t RenderingDeviceDriverD3D12::api_trait_get(ApiTrait p_trait) {
62866288

62876289
bool RenderingDeviceDriverD3D12::has_feature(Features p_feature) {
62886290
switch (p_feature) {
6289-
case SUPPORTS_MULTIVIEW:
6290-
return multiview_capabilities.is_supported && multiview_capabilities.max_view_count > 1;
62916291
case SUPPORTS_FSR_HALF_FLOAT:
62926292
return shader_capabilities.native_16bit_ops && storage_buffer_capabilities.storage_buffer_16_bit_access_is_supported;
6293-
case SUPPORTS_ATTACHMENT_VRS:
6294-
return vrs_capabilities.ss_image_supported;
62956293
case SUPPORTS_FRAGMENT_SHADER_WITH_ONLY_SIDE_EFFECTS:
62966294
return true;
62976295
case SUPPORTS_BUFFER_DEVICE_ADDRESS:
@@ -6305,6 +6303,14 @@ const RDD::MultiviewCapabilities &RenderingDeviceDriverD3D12::get_multiview_capa
63056303
return multiview_capabilities;
63066304
}
63076305

6306+
const RDD::FragmentShadingRateCapabilities &RenderingDeviceDriverD3D12::get_fragment_shading_rate_capabilities() {
6307+
return fsr_capabilities;
6308+
}
6309+
6310+
const RDD::FragmentDensityMapCapabilities &RenderingDeviceDriverD3D12::get_fragment_density_map_capabilities() {
6311+
return fdm_capabilities;
6312+
}
6313+
63086314
String RenderingDeviceDriverD3D12::get_api_name() const {
63096315
return "D3D12";
63106316
}
@@ -6466,12 +6472,6 @@ Error RenderingDeviceDriverD3D12::_check_capabilities() {
64666472
device_capabilities.version_minor = feature_level % 10;
64676473

64686474
// Assume not supported until proven otherwise.
6469-
vrs_capabilities.draw_call_supported = false;
6470-
vrs_capabilities.primitive_supported = false;
6471-
vrs_capabilities.primitive_in_multiviewport = false;
6472-
vrs_capabilities.ss_image_supported = false;
6473-
vrs_capabilities.ss_image_tile_size = 1;
6474-
vrs_capabilities.additional_rates_supported = false;
64756475
multiview_capabilities.is_supported = false;
64766476
multiview_capabilities.geometry_shader_is_supported = false;
64776477
multiview_capabilities.tessellation_shader_is_supported = false;
@@ -6562,14 +6562,12 @@ Error RenderingDeviceDriverD3D12::_check_capabilities() {
65626562
res = device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS6, &options6, sizeof(options6));
65636563
if (SUCCEEDED(res)) {
65646564
if (options6.VariableShadingRateTier >= D3D12_VARIABLE_SHADING_RATE_TIER_1) {
6565-
vrs_capabilities.draw_call_supported = true;
6565+
fsr_capabilities.pipeline_supported = true;
65666566
if (options6.VariableShadingRateTier >= D3D12_VARIABLE_SHADING_RATE_TIER_2) {
6567-
vrs_capabilities.primitive_supported = true;
6568-
vrs_capabilities.primitive_in_multiviewport = options6.PerPrimitiveShadingRateSupportedWithViewportIndexing;
6569-
vrs_capabilities.ss_image_supported = true;
6570-
vrs_capabilities.ss_image_tile_size = options6.ShadingRateImageTileSize;
6571-
vrs_capabilities.ss_max_fragment_size = 8; // TODO figure out if this is supplied and/or needed
6572-
vrs_capabilities.additional_rates_supported = options6.AdditionalShadingRatesSupported;
6567+
fsr_capabilities.primitive_supported = true;
6568+
fsr_capabilities.attachment_supported = true;
6569+
fsr_capabilities.min_texel_size = Size2i(options6.ShadingRateImageTileSize, options6.ShadingRateImageTileSize);
6570+
fsr_capabilities.max_texel_size = Size2i(8, 8);
65736571
}
65746572
}
65756573
}
@@ -6581,19 +6579,16 @@ Error RenderingDeviceDriverD3D12::_check_capabilities() {
65816579
barrier_capabilities.enhanced_barriers_supported = options12.EnhancedBarriersSupported;
65826580
}
65836581

6584-
if (vrs_capabilities.draw_call_supported || vrs_capabilities.primitive_supported || vrs_capabilities.ss_image_supported) {
6582+
if (fsr_capabilities.pipeline_supported || fsr_capabilities.primitive_supported || fsr_capabilities.attachment_supported) {
65856583
print_verbose("- D3D12 Variable Rate Shading supported:");
6586-
if (vrs_capabilities.draw_call_supported) {
6584+
if (fsr_capabilities.pipeline_supported) {
65876585
print_verbose(" Draw call");
65886586
}
6589-
if (vrs_capabilities.primitive_supported) {
6590-
print_verbose(String(" Per-primitive (multi-viewport: ") + (vrs_capabilities.primitive_in_multiviewport ? "yes" : "no") + ")");
6591-
}
6592-
if (vrs_capabilities.ss_image_supported) {
6593-
print_verbose(String(" Screen-space image (tile size: ") + itos(vrs_capabilities.ss_image_tile_size) + ")");
6587+
if (fsr_capabilities.primitive_supported) {
6588+
print_verbose(" Primitive");
65946589
}
6595-
if (vrs_capabilities.additional_rates_supported) {
6596-
print_verbose(String(" Additional rates: ") + (vrs_capabilities.additional_rates_supported ? "yes" : "no"));
6590+
if (fsr_capabilities.attachment_supported) {
6591+
print_verbose(String(" Screen-space image (tile size: ") + itos(fsr_capabilities.min_texel_size.x) + ")");
65976592
}
65986593
} else {
65996594
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;
@@ -834,7 +825,7 @@ class RenderingDeviceDriverD3D12 : public RenderingDeviceDriver {
834825
};
835826

836827
public:
837-
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;
828+
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;
838829
virtual void render_pass_free(RenderPassID p_render_pass) override final;
839830

840831
// ----- COMMANDS -----
@@ -1002,6 +993,8 @@ class RenderingDeviceDriverD3D12 : public RenderingDeviceDriver {
1002993
virtual uint64_t api_trait_get(ApiTrait p_trait) override final;
1003994
virtual bool has_feature(Features p_feature) override final;
1004995
virtual const MultiviewCapabilities &get_multiview_capabilities() override final;
996+
virtual const FragmentShadingRateCapabilities &get_fragment_shading_rate_capabilities() override final;
997+
virtual const FragmentDensityMapCapabilities &get_fragment_density_map_capabilities() override final;
1005998
virtual String get_api_name() const override final;
1006999
virtual String get_api_version() const override final;
10071000
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
@@ -66,6 +66,8 @@ class API_AVAILABLE(macos(11.0), ios(14.0), tvos(14.0)) RenderingDeviceDriverMet
6666

6767
RDD::Capabilities capabilities;
6868
RDD::MultiviewCapabilities multiview_capabilities;
69+
RDD::FragmentShadingRateCapabilities fsr_capabilities;
70+
RDD::FragmentDensityMapCapabilities fdm_capabilities;
6971

7072
id<MTLBinaryArchive> archive = nil;
7173
uint32_t archive_count = 0;
@@ -316,7 +318,7 @@ class API_AVAILABLE(macos(11.0), ios(14.0), tvos(14.0)) RenderingDeviceDriverMet
316318

317319
// ----- SUBPASS -----
318320

319-
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;
321+
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;
320322
virtual void render_pass_free(RenderPassID p_render_pass) override final;
321323

322324
// ----- COMMANDS -----
@@ -421,6 +423,8 @@ class API_AVAILABLE(macos(11.0), ios(14.0), tvos(14.0)) RenderingDeviceDriverMet
421423
virtual uint64_t api_trait_get(ApiTrait p_trait) override final;
422424
virtual bool has_feature(Features p_feature) override final;
423425
virtual const MultiviewCapabilities &get_multiview_capabilities() override final;
426+
virtual const FragmentShadingRateCapabilities &get_fragment_shading_rate_capabilities() override final;
427+
virtual const FragmentDensityMapCapabilities &get_fragment_density_map_capabilities() override final;
424428
virtual String get_api_name() const override final { return "Metal"; }
425429
virtual String get_api_version() const override final;
426430
virtual String get_pipeline_cache_uuid() const override final;

drivers/metal/rendering_device_driver_metal.mm

+10-15
Original file line numberDiff line numberDiff line change
@@ -974,7 +974,7 @@ static const API_AVAILABLE(macos(11.0), ios(14.0), tvos(14.0)) MTLSamplerBorderC
974974
color_ref.aspect.set_flag(RDD::TEXTURE_ASPECT_COLOR_BIT);
975975
subpass.color_references.push_back(color_ref);
976976

977-
RenderPassID render_pass = render_pass_create(attachment, subpass, {}, 1);
977+
RenderPassID render_pass = render_pass_create(attachment, subpass, {}, 1, RDD::AttachmentReference());
978978
ERR_FAIL_COND_V(!render_pass, SwapChainID());
979979

980980
// Create the empty swap chain until it is resized.
@@ -3104,7 +3104,7 @@ bool isArrayTexture(MTLTextureType p_type) {
31043104

31053105
// ----- SUBPASS -----
31063106

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

31103110
size_t subpass_count = p_subpasses.size();
@@ -4006,10 +4006,6 @@ bool isArrayTexture(MTLTextureType p_type) {
40064006
return (uint64_t)((1.0 / limits.temporalScalerInputContentMinScale) * 1000'000);
40074007
case LIMIT_MAX_SHADER_VARYINGS:
40084008
return limits.maxShaderVaryings;
4009-
UNKNOWN(LIMIT_VRS_TEXEL_WIDTH);
4010-
UNKNOWN(LIMIT_VRS_TEXEL_HEIGHT);
4011-
UNKNOWN(LIMIT_VRS_MAX_FRAGMENT_WIDTH);
4012-
UNKNOWN(LIMIT_VRS_MAX_FRAGMENT_HEIGHT);
40134009
default: {
40144010
#ifdef DEV_ENABLED
40154011
WARN_PRINT("Returning maximum value for unknown limit " + itos(p_limit) + ".");
@@ -4032,17 +4028,8 @@ bool isArrayTexture(MTLTextureType p_type) {
40324028

40334029
bool RenderingDeviceDriverMetal::has_feature(Features p_feature) {
40344030
switch (p_feature) {
4035-
case SUPPORTS_MULTIVIEW:
4036-
return multiview_capabilities.is_supported;
40374031
case SUPPORTS_FSR_HALF_FLOAT:
40384032
return true;
4039-
case SUPPORTS_ATTACHMENT_VRS:
4040-
// TODO(sgc): Maybe supported via https://developer.apple.com/documentation/metal/render_passes/rendering_at_different_rasterization_rates?language=objc
4041-
// See also:
4042-
//
4043-
// * https://forum.beyond3d.com/threads/variable-rate-shading-vs-variable-rate-rasterization.62243/post-2191363
4044-
//
4045-
return false;
40464033
case SUPPORTS_FRAGMENT_SHADER_WITH_ONLY_SIDE_EFFECTS:
40474034
return true;
40484035
case SUPPORTS_BUFFER_DEVICE_ADDRESS:
@@ -4060,6 +4047,14 @@ bool isArrayTexture(MTLTextureType p_type) {
40604047
return multiview_capabilities;
40614048
}
40624049

4050+
const RDD::FragmentShadingRateCapabilities &RenderingDeviceDriverMetal::get_fragment_shading_rate_capabilities() {
4051+
return fsr_capabilities;
4052+
}
4053+
4054+
const RDD::FragmentDensityMapCapabilities &RenderingDeviceDriverMetal::get_fragment_density_map_capabilities() {
4055+
return fdm_capabilities;
4056+
}
4057+
40634058
String RenderingDeviceDriverMetal::get_api_version() const {
40644059
return vformat("%d.%d", version_major, version_minor);
40654060
}

0 commit comments

Comments
 (0)