Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Fragment density map support. #99551

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 37 additions & 42 deletions drivers/d3d12/rendering_device_driver_d3d12.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1203,7 +1203,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;
}
Expand Down Expand Up @@ -1808,8 +1808,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;
}
Expand Down Expand Up @@ -1928,7 +1931,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;
}

Expand Down Expand Up @@ -2023,8 +2026,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;
Expand Down Expand Up @@ -2412,7 +2418,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.
Expand Down Expand Up @@ -2772,8 +2778,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;
}
}

Expand Down Expand Up @@ -4922,7 +4928,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);

Expand Down Expand Up @@ -5023,7 +5031,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) {
Expand Down Expand Up @@ -5143,7 +5151,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) {
Expand Down Expand Up @@ -6173,12 +6181,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;
default: {
#ifdef DEV_ENABLED
WARN_PRINT("Returning maximum value for unknown limit " + itos(p_limit) + ".");
Expand Down Expand Up @@ -6213,12 +6215,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;
default:
Expand All @@ -6230,6 +6228,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";
}
Expand Down Expand Up @@ -6391,12 +6397,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;
Expand Down Expand Up @@ -6487,14 +6487,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);
}
}
}
Expand All @@ -6506,19 +6504,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 (vrs_capabilities.ss_image_supported) {
print_verbose(String(" Screen-space image (tile size: ") + itos(vrs_capabilities.ss_image_tile_size) + ")");
if (fsr_capabilities.primitive_supported) {
print_verbose(" Primitive");
}
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");
Expand Down
17 changes: 5 additions & 12 deletions drivers/d3d12/rendering_device_driver_d3d12.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -825,7 +816,7 @@ class RenderingDeviceDriverD3D12 : public RenderingDeviceDriver {
};

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;
DarioSamo marked this conversation as resolved.
Show resolved Hide resolved
virtual void render_pass_free(RenderPassID p_render_pass) override final;

// ----- COMMANDS -----
Expand Down Expand Up @@ -990,6 +981,8 @@ class RenderingDeviceDriverD3D12 : public RenderingDeviceDriver {
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;
Expand Down
6 changes: 5 additions & 1 deletion drivers/metal/rendering_device_driver_metal.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ class API_AVAILABLE(macos(11.0), ios(14.0)) RenderingDeviceDriverMetal : public

RDD::Capabilities capabilities;
RDD::MultiviewCapabilities multiview_capabilities;
RDD::FragmentShadingRateCapabilities fsr_capabilities;
RDD::FragmentDensityMapCapabilities fdm_capabilities;

id<MTLBinaryArchive> archive = nil;
uint32_t archive_count = 0;
Expand Down Expand Up @@ -315,7 +317,7 @@ class API_AVAILABLE(macos(11.0), ios(14.0)) RenderingDeviceDriverMetal : 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 -----
Expand Down Expand Up @@ -417,6 +419,8 @@ class API_AVAILABLE(macos(11.0), ios(14.0)) RenderingDeviceDriverMetal : 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;
Expand Down
23 changes: 10 additions & 13 deletions drivers/metal/rendering_device_driver_metal.mm
Original file line number Diff line number Diff line change
Expand Up @@ -947,7 +947,7 @@ static const API_AVAILABLE(macos(11.0), ios(14.0)) MTLSamplerBorderColor SAMPLER
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.
Expand Down Expand Up @@ -3006,7 +3006,7 @@ bool isArrayTexture(MTLTextureType p_type) {

// ----- 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();
Expand Down Expand Up @@ -3886,8 +3886,6 @@ bool isArrayTexture(MTLTextureType p_type) {
return (int64_t)limits.subgroupSupportedShaderStages;
case LIMIT_SUBGROUP_OPERATIONS:
return (int64_t)limits.subgroupSupportedOperations;
UNKNOWN(LIMIT_VRS_TEXEL_WIDTH);
UNKNOWN(LIMIT_VRS_TEXEL_HEIGHT);
default:
ERR_FAIL_V(0);
}
Expand All @@ -3906,17 +3904,8 @@ bool isArrayTexture(MTLTextureType p_type) {

bool RenderingDeviceDriverMetal::has_feature(Features p_feature) {
switch (p_feature) {
case SUPPORTS_MULTIVIEW:
BastiaanOlij marked this conversation as resolved.
Show resolved Hide resolved
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;
default:
Expand All @@ -3928,6 +3917,14 @@ bool isArrayTexture(MTLTextureType p_type) {
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);
}
Expand Down
Loading