1
0
mirror of https://github.com/godotengine/godot.git synced 2025-12-02 16:48:55 +00:00

Move D3D12's automatic texture clears to RenderingDevice.

This commit is contained in:
Dario
2025-07-22 11:38:36 -03:00
parent 369afc7b46
commit d17ea061bc
6 changed files with 97 additions and 42 deletions

View File

@@ -1646,12 +1646,6 @@ RDD::TextureID RenderingDeviceDriverD3D12::texture_create(const TextureFormat &p
tex_info->view_descs.srv = srv_desc; tex_info->view_descs.srv = srv_desc;
tex_info->view_descs.uav = uav_desc; tex_info->view_descs.uav = uav_desc;
if (!barrier_capabilities.enhanced_barriers_supported && (p_format.usage_bits & (TEXTURE_USAGE_STORAGE_BIT | TEXTURE_USAGE_COLOR_ATTACHMENT_BIT))) {
// Fallback to clear resources when they're first used in a uniform set. Not necessary if enhanced barriers
// are supported, as the discard flag will be used instead when transitioning from an undefined layout.
textures_pending_clear.add(&tex_info->pending_clear);
}
return TextureID(tex_info); return TextureID(tex_info);
} }
@@ -3885,21 +3879,6 @@ void RenderingDeviceDriverD3D12::command_uniform_set_prepare_for_use(CommandBuff
return; return;
} }
// Perform pending blackouts.
{
SelfList<TextureInfo> *E = textures_pending_clear.first();
while (E) {
TextureSubresourceRange subresources;
subresources.layer_count = E->self()->layers;
subresources.mipmap_count = E->self()->mipmaps;
command_clear_color_texture(p_cmd_buffer, TextureID(E->self()), TEXTURE_LAYOUT_UNDEFINED, Color(), subresources);
SelfList<TextureInfo> *next = E->next();
E->remove_from_list();
E = next;
}
}
CommandBufferInfo *cmd_buf_info = (CommandBufferInfo *)p_cmd_buffer.id; CommandBufferInfo *cmd_buf_info = (CommandBufferInfo *)p_cmd_buffer.id;
const UniformSetInfo *uniform_set_info = (const UniformSetInfo *)p_uniform_set.id; const UniformSetInfo *uniform_set_info = (const UniformSetInfo *)p_uniform_set.id;
const ShaderInfo *shader_info_in = (const ShaderInfo *)p_shader.id; const ShaderInfo *shader_info_in = (const ShaderInfo *)p_shader.id;
@@ -4889,7 +4868,6 @@ void RenderingDeviceDriverD3D12::command_begin_render_pass(CommandBufferID p_cmd
if (pass_info->attachments[i].load_op == ATTACHMENT_LOAD_OP_CLEAR) { if (pass_info->attachments[i].load_op == ATTACHMENT_LOAD_OP_CLEAR) {
clear.aspect.set_flag(TEXTURE_ASPECT_COLOR_BIT); clear.aspect.set_flag(TEXTURE_ASPECT_COLOR_BIT);
clear.color_attachment = i; clear.color_attachment = i;
tex_info->pending_clear.remove_from_list();
} }
} else if ((tex_info->desc.Flags & D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL)) { } else if ((tex_info->desc.Flags & D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL)) {
if (pass_info->attachments[i].load_op == ATTACHMENT_LOAD_OP_CLEAR) { if (pass_info->attachments[i].load_op == ATTACHMENT_LOAD_OP_CLEAR) {
@@ -6234,6 +6212,8 @@ uint64_t RenderingDeviceDriverD3D12::api_trait_get(ApiTrait p_trait) {
return true; return true;
case API_TRAIT_BUFFERS_REQUIRE_TRANSITIONS: case API_TRAIT_BUFFERS_REQUIRE_TRANSITIONS:
return !barrier_capabilities.enhanced_barriers_supported; return !barrier_capabilities.enhanced_barriers_supported;
case API_TRAIT_TEXTURE_OUTPUTS_REQUIRE_CLEARS:
return true;
default: default:
return RenderingDeviceDriver::api_trait_get(p_trait); return RenderingDeviceDriver::api_trait_get(p_trait);
} }

View File

@@ -365,12 +365,10 @@ private:
TextureInfo *main_texture = nullptr; TextureInfo *main_texture = nullptr;
UINT mapped_subresource = UINT_MAX; UINT mapped_subresource = UINT_MAX;
SelfList<TextureInfo> pending_clear{ this };
#ifdef DEBUG_ENABLED #ifdef DEBUG_ENABLED
bool created_from_extension = false; bool created_from_extension = false;
#endif #endif
}; };
SelfList<TextureInfo>::List textures_pending_clear;
HashMap<DXGI_FORMAT, uint32_t> format_sample_counts_mask_cache; HashMap<DXGI_FORMAT, uint32_t> format_sample_counts_mask_cache;
Mutex format_sample_counts_mask_cache_mutex; Mutex format_sample_counts_mask_cache_mutex;

View File

@@ -1079,6 +1079,11 @@ RID RenderingDevice::texture_create(const TextureFormat &p_format, const Texture
texture.allowed_shared_formats = format.shareable_formats; texture.allowed_shared_formats = format.shareable_formats;
texture.has_initial_data = !data.is_empty(); texture.has_initial_data = !data.is_empty();
if (driver->api_trait_get(RDD::API_TRAIT_TEXTURE_OUTPUTS_REQUIRE_CLEARS)) {
// Check if a clear for this texture must be performed the first time it's used if the driver requires explicit clears after initialization.
texture.pending_clear = !texture.has_initial_data && (format.usage_bits & (TEXTURE_USAGE_STORAGE_BIT | TEXTURE_USAGE_COLOR_ATTACHMENT_BIT));
}
if ((format.usage_bits & (TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | TEXTURE_USAGE_DEPTH_RESOLVE_ATTACHMENT_BIT))) { if ((format.usage_bits & (TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | TEXTURE_USAGE_DEPTH_RESOLVE_ATTACHMENT_BIT))) {
texture.read_aspect_flags.set_flag(RDD::TEXTURE_ASPECT_DEPTH_BIT); texture.read_aspect_flags.set_flag(RDD::TEXTURE_ASPECT_DEPTH_BIT);
texture.barrier_aspect_flags.set_flag(RDD::TEXTURE_ASPECT_DEPTH_BIT); texture.barrier_aspect_flags.set_flag(RDD::TEXTURE_ASPECT_DEPTH_BIT);
@@ -1931,6 +1936,50 @@ uint32_t RenderingDevice::_texture_vrs_method_to_usage_bits() const {
} }
} }
void RenderingDevice::_texture_check_pending_clear(RID p_texture_rid, Texture *p_texture) {
DEV_ASSERT(p_texture != nullptr);
if (!p_texture->pending_clear) {
return;
}
bool clear = true;
p_texture->pending_clear = false;
if (p_texture->owner.is_valid()) {
// Check the owner texture instead if it exists.
p_texture_rid = p_texture->owner;
p_texture = texture_owner.get_or_null(p_texture_rid);
clear = p_texture->pending_clear;
}
if (p_texture != nullptr && clear) {
_texture_clear(p_texture_rid, p_texture, Color(), 0, p_texture->mipmaps, 0, p_texture->layers);
p_texture->pending_clear = false;
}
}
void RenderingDevice::_texture_clear(RID p_texture_rid, Texture *p_texture, const Color &p_color, uint32_t p_base_mipmap, uint32_t p_mipmaps, uint32_t p_base_layer, uint32_t p_layers) {
_check_transfer_worker_texture(p_texture);
RDD::TextureSubresourceRange range;
range.aspect = p_texture->read_aspect_flags;
range.base_mipmap = p_texture->base_mipmap + p_base_mipmap;
range.mipmap_count = p_mipmaps;
range.base_layer = p_texture->base_layer + p_base_layer;
range.layer_count = p_layers;
// Indicate the texture will get modified for the shared texture fallback.
_texture_update_shared_fallback(p_texture_rid, p_texture, true);
if (_texture_make_mutable(p_texture, p_texture_rid)) {
// The texture must be mutable to be used as a clear destination.
draw_graph.add_synchronization();
}
draw_graph.add_texture_clear(p_texture->driver_id, p_texture->draw_tracker, p_color, range);
}
Vector<uint8_t> RenderingDevice::texture_get_data(RID p_texture, uint32_t p_layer) { Vector<uint8_t> RenderingDevice::texture_get_data(RID p_texture, uint32_t p_layer) {
ERR_RENDER_THREAD_GUARD_V(Vector<uint8_t>()); ERR_RENDER_THREAD_GUARD_V(Vector<uint8_t>());
@@ -2391,24 +2440,7 @@ Error RenderingDevice::texture_clear(RID p_texture, const Color &p_color, uint32
ERR_FAIL_COND_V(p_base_mipmap + p_mipmaps > src_tex->mipmaps, ERR_INVALID_PARAMETER); ERR_FAIL_COND_V(p_base_mipmap + p_mipmaps > src_tex->mipmaps, ERR_INVALID_PARAMETER);
ERR_FAIL_COND_V(p_base_layer + p_layers > src_tex->layers, ERR_INVALID_PARAMETER); ERR_FAIL_COND_V(p_base_layer + p_layers > src_tex->layers, ERR_INVALID_PARAMETER);
_check_transfer_worker_texture(src_tex); _texture_clear(p_texture, src_tex, p_color, p_base_mipmap, p_mipmaps, p_base_layer, p_layers);
RDD::TextureSubresourceRange range;
range.aspect = src_tex->read_aspect_flags;
range.base_mipmap = src_tex->base_mipmap + p_base_mipmap;
range.mipmap_count = p_mipmaps;
range.base_layer = src_tex->base_layer + p_base_layer;
range.layer_count = p_layers;
// Indicate the texture will get modified for the shared texture fallback.
_texture_update_shared_fallback(p_texture, src_tex, true);
if (_texture_make_mutable(src_tex, p_texture)) {
// The texture must be mutable to be used as a clear destination.
draw_graph.add_synchronization();
}
draw_graph.add_texture_clear(src_tex->driver_id, src_tex->draw_tracker, p_color, range);
return OK; return OK;
} }
@@ -3584,6 +3616,21 @@ void RenderingDevice::_uniform_set_update_shared(UniformSet *p_uniform_set) {
} }
} }
void RenderingDevice::_uniform_set_update_clears(UniformSet *p_uniform_set) {
if (p_uniform_set->pending_clear_textures.is_empty()) {
return;
}
for (RID texture_id : p_uniform_set->pending_clear_textures) {
Texture *texture = texture_owner.get_or_null(texture_id);
if (texture != nullptr) {
_texture_check_pending_clear(texture_id, texture);
}
}
p_uniform_set->pending_clear_textures.clear();
}
RID RenderingDevice::uniform_set_create(const VectorView<RD::Uniform> &p_uniforms, RID p_shader, uint32_t p_shader_set, bool p_linear_pool) { RID RenderingDevice::uniform_set_create(const VectorView<RD::Uniform> &p_uniforms, RID p_shader, uint32_t p_shader_set, bool p_linear_pool) {
_THREAD_SAFE_METHOD_ _THREAD_SAFE_METHOD_
@@ -3613,6 +3660,7 @@ RID RenderingDevice::uniform_set_create(const VectorView<RD::Uniform> &p_uniform
Vector<RDG::ResourceUsage> draw_trackers_usage; Vector<RDG::ResourceUsage> draw_trackers_usage;
HashMap<RID, RDG::ResourceUsage> untracked_usage; HashMap<RID, RDG::ResourceUsage> untracked_usage;
Vector<UniformSet::SharedTexture> shared_textures_to_update; Vector<UniformSet::SharedTexture> shared_textures_to_update;
LocalVector<RID> pending_clear_textures;
for (uint32_t i = 0; i < set_uniform_count; i++) { for (uint32_t i = 0; i < set_uniform_count; i++) {
const ShaderUniform &set_uniform = set_uniforms[i]; const ShaderUniform &set_uniform = set_uniforms[i];
@@ -3682,6 +3730,10 @@ RID RenderingDevice::uniform_set_create(const VectorView<RD::Uniform> &p_uniform
attachable_textures.push_back(attachable_texture); attachable_textures.push_back(attachable_texture);
} }
if (texture->pending_clear) {
pending_clear_textures.push_back(texture_id);
}
RDD::TextureID driver_id = texture->driver_id; RDD::TextureID driver_id = texture->driver_id;
RDG::ResourceTracker *tracker = texture->draw_tracker; RDG::ResourceTracker *tracker = texture->draw_tracker;
if (texture->shared_fallback != nullptr && texture->shared_fallback->texture.id != 0) { if (texture->shared_fallback != nullptr && texture->shared_fallback->texture.id != 0) {
@@ -3728,6 +3780,10 @@ RID RenderingDevice::uniform_set_create(const VectorView<RD::Uniform> &p_uniform
attachable_textures.push_back(attachable_texture); attachable_textures.push_back(attachable_texture);
} }
if (texture->pending_clear) {
pending_clear_textures.push_back(texture_id);
}
RDD::TextureID driver_id = texture->driver_id; RDD::TextureID driver_id = texture->driver_id;
RDG::ResourceTracker *tracker = texture->draw_tracker; RDG::ResourceTracker *tracker = texture->draw_tracker;
if (texture->shared_fallback != nullptr && texture->shared_fallback->texture.id != 0) { if (texture->shared_fallback != nullptr && texture->shared_fallback->texture.id != 0) {
@@ -3772,6 +3828,10 @@ RID RenderingDevice::uniform_set_create(const VectorView<RD::Uniform> &p_uniform
shared_textures_to_update.push_back({ true, texture_id }); shared_textures_to_update.push_back({ true, texture_id });
} }
if (texture->pending_clear) {
pending_clear_textures.push_back(texture_id);
}
if (_texture_make_mutable(texture, texture_id)) { if (_texture_make_mutable(texture, texture_id)) {
// The texture must be mutable as a layout transition will be required. // The texture must be mutable as a layout transition will be required.
draw_graph.add_synchronization(); draw_graph.add_synchronization();
@@ -3966,6 +4026,7 @@ RID RenderingDevice::uniform_set_create(const VectorView<RD::Uniform> &p_uniform
uniform_set.draw_trackers_usage = draw_trackers_usage; uniform_set.draw_trackers_usage = draw_trackers_usage;
uniform_set.untracked_usage = untracked_usage; uniform_set.untracked_usage = untracked_usage;
uniform_set.shared_textures_to_update = shared_textures_to_update; uniform_set.shared_textures_to_update = shared_textures_to_update;
uniform_set.pending_clear_textures = pending_clear_textures;
uniform_set.shader_set = p_shader_set; uniform_set.shader_set = p_shader_set;
uniform_set.shader_id = p_shader; uniform_set.shader_id = p_shader;
@@ -4482,6 +4543,9 @@ RenderingDevice::DrawListID RenderingDevice::draw_list_begin(RID p_framebuffer,
continue; continue;
} }
// Clear the texture if the driver requires it during its first use.
_texture_check_pending_clear(texture_rid, texture);
// Indicate the texture will get modified for the shared texture fallback. // Indicate the texture will get modified for the shared texture fallback.
_texture_update_shared_fallback(texture_rid, texture, true); _texture_update_shared_fallback(texture_rid, texture, true);
@@ -4965,6 +5029,8 @@ void RenderingDevice::draw_list_draw(DrawListID p_list, bool p_use_indices, uint
UniformSet *uniform_set = uniform_set_owner.get_or_null(draw_list.state.sets[i].uniform_set); UniformSet *uniform_set = uniform_set_owner.get_or_null(draw_list.state.sets[i].uniform_set);
_uniform_set_update_shared(uniform_set); _uniform_set_update_shared(uniform_set);
_uniform_set_update_clears(uniform_set);
draw_graph.add_draw_list_usages(uniform_set->draw_trackers, uniform_set->draw_trackers_usage); draw_graph.add_draw_list_usages(uniform_set->draw_trackers, uniform_set->draw_trackers_usage);
draw_list.state.sets[i].bound = true; draw_list.state.sets[i].bound = true;
@@ -5105,6 +5171,7 @@ void RenderingDevice::draw_list_draw_indirect(DrawListID p_list, bool p_use_indi
UniformSet *uniform_set = uniform_set_owner.get_or_null(draw_list.state.sets[i].uniform_set); UniformSet *uniform_set = uniform_set_owner.get_or_null(draw_list.state.sets[i].uniform_set);
_uniform_set_update_shared(uniform_set); _uniform_set_update_shared(uniform_set);
_uniform_set_update_clears(uniform_set);
draw_graph.add_draw_list_usages(uniform_set->draw_trackers, uniform_set->draw_trackers_usage); draw_graph.add_draw_list_usages(uniform_set->draw_trackers, uniform_set->draw_trackers_usage);
@@ -5502,6 +5569,7 @@ void RenderingDevice::compute_list_dispatch(ComputeListID p_list, uint32_t p_x_g
} }
UniformSet *uniform_set = uniform_set_owner.get_or_null(compute_list.state.sets[i].uniform_set); UniformSet *uniform_set = uniform_set_owner.get_or_null(compute_list.state.sets[i].uniform_set);
_uniform_set_update_shared(uniform_set); _uniform_set_update_shared(uniform_set);
_uniform_set_update_clears(uniform_set);
draw_graph.add_compute_list_usages(uniform_set->draw_trackers, uniform_set->draw_trackers_usage); draw_graph.add_compute_list_usages(uniform_set->draw_trackers, uniform_set->draw_trackers_usage);
compute_list.state.sets[i].bound = true; compute_list.state.sets[i].bound = true;
@@ -5638,6 +5706,7 @@ void RenderingDevice::compute_list_dispatch_indirect(ComputeListID p_list, RID p
UniformSet *uniform_set = uniform_set_owner.get_or_null(compute_list.state.sets[i].uniform_set); UniformSet *uniform_set = uniform_set_owner.get_or_null(compute_list.state.sets[i].uniform_set);
_uniform_set_update_shared(uniform_set); _uniform_set_update_shared(uniform_set);
_uniform_set_update_clears(uniform_set);
draw_graph.add_compute_list_usages(uniform_set->draw_trackers, uniform_set->draw_trackers_usage); draw_graph.add_compute_list_usages(uniform_set->draw_trackers, uniform_set->draw_trackers_usage);
compute_list.state.sets[i].bound = true; compute_list.state.sets[i].bound = true;

View File

@@ -349,6 +349,7 @@ public:
bool is_resolve_buffer = false; bool is_resolve_buffer = false;
bool is_discardable = false; bool is_discardable = false;
bool has_initial_data = false; bool has_initial_data = false;
bool pending_clear = false;
BitField<RDD::TextureAspectBits> read_aspect_flags = {}; BitField<RDD::TextureAspectBits> read_aspect_flags = {};
BitField<RDD::TextureAspectBits> barrier_aspect_flags = {}; BitField<RDD::TextureAspectBits> barrier_aspect_flags = {};
@@ -401,6 +402,8 @@ public:
void _texture_free_shared_fallback(Texture *p_texture); 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_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); void _texture_create_reinterpret_buffer(Texture *p_texture);
void _texture_check_pending_clear(RID p_texture_rid, Texture *p_texture);
void _texture_clear(RID p_texture_rid, Texture *p_texture, const Color &p_color, uint32_t p_base_mipmap, uint32_t p_mipmaps, uint32_t p_base_layer, uint32_t p_layers);
uint32_t _texture_vrs_method_to_usage_bits() const; uint32_t _texture_vrs_method_to_usage_bits() const;
struct TextureGetDataRequest { struct TextureGetDataRequest {
@@ -1139,6 +1142,7 @@ private:
Vector<RDG::ResourceUsage> draw_trackers_usage; Vector<RDG::ResourceUsage> draw_trackers_usage;
HashMap<RID, RDG::ResourceUsage> untracked_usage; HashMap<RID, RDG::ResourceUsage> untracked_usage;
LocalVector<SharedTexture> shared_textures_to_update; LocalVector<SharedTexture> shared_textures_to_update;
LocalVector<RID> pending_clear_textures;
InvalidationCallback invalidated_callback = nullptr; InvalidationCallback invalidated_callback = nullptr;
void *invalidated_callback_userdata = nullptr; void *invalidated_callback_userdata = nullptr;
}; };
@@ -1146,6 +1150,7 @@ private:
RID_Owner<UniformSet, true> uniform_set_owner; RID_Owner<UniformSet, true> uniform_set_owner;
void _uniform_set_update_shared(UniformSet *p_uniform_set); void _uniform_set_update_shared(UniformSet *p_uniform_set);
void _uniform_set_update_clears(UniformSet *p_uniform_set);
public: public:
/** Bake a set of uniforms that can be bound at runtime with the given shader. /** Bake a set of uniforms that can be bound at runtime with the given shader.

View File

@@ -53,6 +53,8 @@ uint64_t RenderingDeviceDriver::api_trait_get(ApiTrait p_trait) {
return false; return false;
case API_TRAIT_BUFFERS_REQUIRE_TRANSITIONS: case API_TRAIT_BUFFERS_REQUIRE_TRANSITIONS:
return false; return false;
case API_TRAIT_TEXTURE_OUTPUTS_REQUIRE_CLEARS:
return false;
default: default:
ERR_FAIL_V(0); ERR_FAIL_V(0);
} }

View File

@@ -807,6 +807,7 @@ public:
API_TRAIT_CLEARS_WITH_COPY_ENGINE, API_TRAIT_CLEARS_WITH_COPY_ENGINE,
API_TRAIT_USE_GENERAL_IN_COPY_QUEUES, API_TRAIT_USE_GENERAL_IN_COPY_QUEUES,
API_TRAIT_BUFFERS_REQUIRE_TRANSITIONS, API_TRAIT_BUFFERS_REQUIRE_TRANSITIONS,
API_TRAIT_TEXTURE_OUTPUTS_REQUIRE_CLEARS,
}; };
enum ShaderChangeInvalidation { enum ShaderChangeInvalidation {