Merge pull request #91769 from DarioSamo/d3d12_enhanced_barriers
Add support for enhanced barriers in D3D12.
This commit is contained in:
commit
f2796fa06d
File diff suppressed because it is too large
Load Diff
|
@ -122,6 +122,10 @@ class RenderingDeviceDriverD3D12 : public RenderingDeviceDriver {
|
|||
bool relaxed_casting_supported = false;
|
||||
};
|
||||
|
||||
struct BarrierCapabilities {
|
||||
bool enhanced_barriers_supported = false;
|
||||
};
|
||||
|
||||
RenderingContextDriverD3D12 *context_driver = nullptr;
|
||||
RenderingContextDriver::Device context_device;
|
||||
ComPtr<IDXGIAdapter> adapter;
|
||||
|
@ -136,6 +140,7 @@ class RenderingDeviceDriverD3D12 : public RenderingDeviceDriver {
|
|||
ShaderCapabilities shader_capabilities;
|
||||
StorageBufferCapabilities storage_buffer_capabilities;
|
||||
FormatCapabilities format_capabilities;
|
||||
BarrierCapabilities barrier_capabilities;
|
||||
String pipeline_cache_id;
|
||||
|
||||
class DescriptorsHeap {
|
||||
|
@ -218,11 +223,6 @@ private:
|
|||
// As many subresources as mipmaps * layers; planes (for depth-stencil) are tracked together.
|
||||
TightLocalVector<D3D12_RESOURCE_STATES> subresource_states; // Used only if not a view.
|
||||
uint32_t last_batch_with_uav_barrier = 0;
|
||||
struct CrossFamillyFallback {
|
||||
TightLocalVector<uint64_t> subresources_dirty;
|
||||
ComPtr<ID3D12Resource> interim_buffer;
|
||||
ComPtr<D3D12MA::Allocation> interim_buffer_alloc;
|
||||
} xfamily_fallback; // [[CROSS_FAMILY_FALLBACK]].
|
||||
};
|
||||
|
||||
ID3D12Resource *resource = nullptr; // Non-null even if not owned.
|
||||
|
@ -275,7 +275,6 @@ private:
|
|||
uint64_t size = 0;
|
||||
struct {
|
||||
bool usable_as_uav : 1;
|
||||
bool is_for_upload : 1;
|
||||
} flags = {};
|
||||
};
|
||||
|
||||
|
@ -317,10 +316,14 @@ private:
|
|||
UINT _compute_component_mapping(const TextureView &p_view);
|
||||
UINT _compute_plane_slice(DataFormat p_format, BitField<TextureAspectBits> p_aspect_bits);
|
||||
UINT _compute_plane_slice(DataFormat p_format, TextureAspect p_aspect);
|
||||
UINT _compute_subresource_from_layers(TextureInfo *p_texture, const TextureSubresourceLayers &p_layers, uint32_t p_layer_offset);
|
||||
|
||||
struct CommandBufferInfo;
|
||||
void _discard_texture_subresources(const TextureInfo *p_tex_info, const CommandBufferInfo *p_cmd_buf_info);
|
||||
|
||||
protected:
|
||||
virtual bool _unordered_access_supported_by_format(DataFormat p_format);
|
||||
|
||||
public:
|
||||
virtual TextureID texture_create(const TextureFormat &p_format, const TextureView &p_view) override final;
|
||||
virtual TextureID texture_create_from_extension(uint64_t p_native_texture, TextureType p_type, DataFormat p_format, uint32_t p_array_layers, bool p_depth_stencil) override final;
|
||||
|
@ -332,6 +335,7 @@ public:
|
|||
virtual uint8_t *texture_map(TextureID p_texture, const TextureSubresource &p_subresource) override final;
|
||||
virtual void texture_unmap(TextureID p_texture) override final;
|
||||
virtual BitField<TextureUsageBits> texture_get_usages_supported_by_format(DataFormat p_format, bool p_cpu_readable) override final;
|
||||
virtual bool texture_can_make_shared_with_format(TextureID p_texture, DataFormat p_format, bool &r_raw_reinterpretation) override final;
|
||||
|
||||
private:
|
||||
TextureID _texture_create_shared_from_slice(TextureID p_original_texture, const TextureView &p_view, TextureSliceType p_slice_type, uint32_t p_layer, uint32_t p_layers, uint32_t p_mipmap, uint32_t p_mipmaps);
|
||||
|
@ -367,8 +371,8 @@ public:
|
|||
|
||||
virtual void command_pipeline_barrier(
|
||||
CommandBufferID p_cmd_buffer,
|
||||
BitField<RDD::PipelineStageBits> p_src_stages,
|
||||
BitField<RDD::PipelineStageBits> p_dst_stages,
|
||||
BitField<PipelineStageBits> p_src_stages,
|
||||
BitField<PipelineStageBits> p_dst_stages,
|
||||
VectorView<RDD::MemoryBarrier> p_memory_barriers,
|
||||
VectorView<RDD::BufferBarrier> p_buffer_barriers,
|
||||
VectorView<RDD::TextureBarrier> p_texture_barriers) override final;
|
||||
|
@ -465,16 +469,6 @@ private:
|
|||
|
||||
RenderPassState render_pass_state;
|
||||
bool descriptor_heaps_set = false;
|
||||
|
||||
// [[CROSS_FAMILY_FALLBACK]].
|
||||
struct FamilyFallbackCopy {
|
||||
TextureInfo *texture = nullptr;
|
||||
uint32_t subresource = 0;
|
||||
uint32_t mipmap = 0;
|
||||
D3D12_RESOURCE_STATES dst_wanted_state = {};
|
||||
};
|
||||
LocalVector<FamilyFallbackCopy> family_fallback_copies;
|
||||
uint32_t family_fallback_copy_count = 0;
|
||||
};
|
||||
|
||||
public:
|
||||
|
@ -961,7 +955,6 @@ private:
|
|||
bool rtv = false;
|
||||
} desc_heaps_exhausted_reported;
|
||||
CD3DX12_CPU_DESCRIPTOR_HANDLE null_rtv_handle = {}; // For [[MANUAL_SUBPASSES]].
|
||||
ComPtr<D3D12MA::Allocation> aux_resource;
|
||||
uint32_t segment_serial = 0;
|
||||
|
||||
#ifdef DEV_ENABLED
|
||||
|
|
|
@ -264,6 +264,63 @@ static const VkFormat RD_TO_VK_FORMAT[RDD::DATA_FORMAT_MAX] = {
|
|||
VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM,
|
||||
};
|
||||
|
||||
static VkImageLayout RD_TO_VK_LAYOUT[RDD::TEXTURE_LAYOUT_MAX] = {
|
||||
VK_IMAGE_LAYOUT_UNDEFINED, // TEXTURE_LAYOUT_UNDEFINED
|
||||
VK_IMAGE_LAYOUT_GENERAL, // TEXTURE_LAYOUT_STORAGE_OPTIMAL
|
||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // TEXTURE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
|
||||
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // TEXTURE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL
|
||||
VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, // TEXTURE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL
|
||||
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, // TEXTURE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
|
||||
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // TEXTURE_LAYOUT_COPY_SRC_OPTIMAL
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // TEXTURE_LAYOUT_COPY_DST_OPTIMAL
|
||||
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // TEXTURE_LAYOUT_RESOLVE_SRC_OPTIMAL
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // TEXTURE_LAYOUT_RESOLVE_DST_OPTIMAL
|
||||
VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR, // TEXTURE_LAYOUT_VRS_ATTACHMENT_OPTIMAL
|
||||
};
|
||||
|
||||
static VkPipelineStageFlags _rd_to_vk_pipeline_stages(BitField<RDD::PipelineStageBits> p_stages) {
|
||||
VkPipelineStageFlags vk_flags = 0;
|
||||
if (p_stages.has_flag(RDD::PIPELINE_STAGE_COPY_BIT) || p_stages.has_flag(RDD::PIPELINE_STAGE_RESOLVE_BIT)) {
|
||||
// Transfer has been split into copy and resolve bits. Clear them and merge them into one bit.
|
||||
vk_flags |= VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||
p_stages.clear_flag(RDD::PIPELINE_STAGE_COPY_BIT);
|
||||
p_stages.clear_flag(RDD::PIPELINE_STAGE_RESOLVE_BIT);
|
||||
}
|
||||
|
||||
if (p_stages.has_flag(RDD::PIPELINE_STAGE_CLEAR_STORAGE_BIT)) {
|
||||
// Vulkan should never use this as API_TRAIT_CLEAR_RESOURCES_WITH_VIEWS is not specified.
|
||||
// Therefore, storage is never cleared with an explicit command.
|
||||
p_stages.clear_flag(RDD::PIPELINE_STAGE_CLEAR_STORAGE_BIT);
|
||||
}
|
||||
|
||||
// The rest of the flags have compatible numeric values with Vulkan.
|
||||
return VkPipelineStageFlags(p_stages) | vk_flags;
|
||||
}
|
||||
|
||||
static VkAccessFlags _rd_to_vk_access_flags(BitField<RDD::BarrierAccessBits> p_access) {
|
||||
VkAccessFlags vk_flags = 0;
|
||||
if (p_access.has_flag(RDD::BARRIER_ACCESS_COPY_READ_BIT) || p_access.has_flag(RDD::BARRIER_ACCESS_RESOLVE_READ_BIT)) {
|
||||
vk_flags |= VK_ACCESS_TRANSFER_READ_BIT;
|
||||
p_access.clear_flag(RDD::BARRIER_ACCESS_COPY_READ_BIT);
|
||||
p_access.clear_flag(RDD::BARRIER_ACCESS_RESOLVE_READ_BIT);
|
||||
}
|
||||
|
||||
if (p_access.has_flag(RDD::BARRIER_ACCESS_COPY_WRITE_BIT) || p_access.has_flag(RDD::BARRIER_ACCESS_RESOLVE_WRITE_BIT)) {
|
||||
vk_flags |= VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||
p_access.clear_flag(RDD::BARRIER_ACCESS_COPY_WRITE_BIT);
|
||||
p_access.clear_flag(RDD::BARRIER_ACCESS_RESOLVE_WRITE_BIT);
|
||||
}
|
||||
|
||||
if (p_access.has_flag(RDD::BARRIER_ACCESS_STORAGE_CLEAR_BIT)) {
|
||||
// Vulkan should never use this as API_TRAIT_CLEAR_RESOURCES_WITH_VIEWS is not specified.
|
||||
// Therefore, storage is never cleared with an explicit command.
|
||||
p_access.clear_flag(RDD::BARRIER_ACCESS_STORAGE_CLEAR_BIT);
|
||||
}
|
||||
|
||||
// The rest of the flags have compatible numeric values with Vulkan.
|
||||
return VkAccessFlags(p_access) | vk_flags;
|
||||
}
|
||||
|
||||
// RDD::CompareOperator == VkCompareOp.
|
||||
static_assert(ENUM_MEMBERS_EQUAL(RDD::COMPARE_OP_NEVER, VK_COMPARE_OP_NEVER));
|
||||
static_assert(ENUM_MEMBERS_EQUAL(RDD::COMPARE_OP_LESS, VK_COMPARE_OP_LESS));
|
||||
|
@ -1334,18 +1391,6 @@ static_assert(ENUM_MEMBERS_EQUAL(RDD::TEXTURE_SWIZZLE_G, VK_COMPONENT_SWIZZLE_G)
|
|||
static_assert(ENUM_MEMBERS_EQUAL(RDD::TEXTURE_SWIZZLE_B, VK_COMPONENT_SWIZZLE_B));
|
||||
static_assert(ENUM_MEMBERS_EQUAL(RDD::TEXTURE_SWIZZLE_A, VK_COMPONENT_SWIZZLE_A));
|
||||
|
||||
// RDD::TextureLayout == VkImageLayout.
|
||||
static_assert(ENUM_MEMBERS_EQUAL(RDD::TEXTURE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_UNDEFINED));
|
||||
static_assert(ENUM_MEMBERS_EQUAL(RDD::TEXTURE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL));
|
||||
static_assert(ENUM_MEMBERS_EQUAL(RDD::TEXTURE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL));
|
||||
static_assert(ENUM_MEMBERS_EQUAL(RDD::TEXTURE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL));
|
||||
static_assert(ENUM_MEMBERS_EQUAL(RDD::TEXTURE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL));
|
||||
static_assert(ENUM_MEMBERS_EQUAL(RDD::TEXTURE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL));
|
||||
static_assert(ENUM_MEMBERS_EQUAL(RDD::TEXTURE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL));
|
||||
static_assert(ENUM_MEMBERS_EQUAL(RDD::TEXTURE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL));
|
||||
static_assert(ENUM_MEMBERS_EQUAL(RDD::TEXTURE_LAYOUT_PREINITIALIZED, VK_IMAGE_LAYOUT_PREINITIALIZED));
|
||||
static_assert(ENUM_MEMBERS_EQUAL(RDD::TEXTURE_LAYOUT_VRS_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR));
|
||||
|
||||
// RDD::TextureAspectBits == VkImageAspectFlagBits.
|
||||
static_assert(ENUM_MEMBERS_EQUAL(RDD::TEXTURE_ASPECT_COLOR_BIT, VK_IMAGE_ASPECT_COLOR_BIT));
|
||||
static_assert(ENUM_MEMBERS_EQUAL(RDD::TEXTURE_ASPECT_DEPTH_BIT, VK_IMAGE_ASPECT_DEPTH_BIT));
|
||||
|
@ -1774,6 +1819,11 @@ BitField<RDD::TextureUsageBits> RenderingDeviceDriverVulkan::texture_get_usages_
|
|||
return supported;
|
||||
}
|
||||
|
||||
bool RenderingDeviceDriverVulkan::texture_can_make_shared_with_format(TextureID p_texture, DataFormat p_format, bool &r_raw_reinterpretation) {
|
||||
r_raw_reinterpretation = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*****************/
|
||||
/**** SAMPLER ****/
|
||||
/*****************/
|
||||
|
@ -1893,7 +1943,6 @@ static_assert(ENUM_MEMBERS_EQUAL(RDD::PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, V
|
|||
static_assert(ENUM_MEMBERS_EQUAL(RDD::PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT));
|
||||
static_assert(ENUM_MEMBERS_EQUAL(RDD::PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT));
|
||||
static_assert(ENUM_MEMBERS_EQUAL(RDD::PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT));
|
||||
static_assert(ENUM_MEMBERS_EQUAL(RDD::PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT));
|
||||
static_assert(ENUM_MEMBERS_EQUAL(RDD::PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT));
|
||||
static_assert(ENUM_MEMBERS_EQUAL(RDD::PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT));
|
||||
static_assert(ENUM_MEMBERS_EQUAL(RDD::PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT));
|
||||
|
@ -1910,8 +1959,6 @@ static_assert(ENUM_MEMBERS_EQUAL(RDD::BARRIER_ACCESS_COLOR_ATTACHMENT_READ_BIT,
|
|||
static_assert(ENUM_MEMBERS_EQUAL(RDD::BARRIER_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT));
|
||||
static_assert(ENUM_MEMBERS_EQUAL(RDD::BARRIER_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT));
|
||||
static_assert(ENUM_MEMBERS_EQUAL(RDD::BARRIER_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT));
|
||||
static_assert(ENUM_MEMBERS_EQUAL(RDD::BARRIER_ACCESS_TRANSFER_READ_BIT, VK_ACCESS_TRANSFER_READ_BIT));
|
||||
static_assert(ENUM_MEMBERS_EQUAL(RDD::BARRIER_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_TRANSFER_WRITE_BIT));
|
||||
static_assert(ENUM_MEMBERS_EQUAL(RDD::BARRIER_ACCESS_HOST_READ_BIT, VK_ACCESS_HOST_READ_BIT));
|
||||
static_assert(ENUM_MEMBERS_EQUAL(RDD::BARRIER_ACCESS_HOST_WRITE_BIT, VK_ACCESS_HOST_WRITE_BIT));
|
||||
static_assert(ENUM_MEMBERS_EQUAL(RDD::BARRIER_ACCESS_MEMORY_READ_BIT, VK_ACCESS_MEMORY_READ_BIT));
|
||||
|
@ -1929,8 +1976,8 @@ void RenderingDeviceDriverVulkan::command_pipeline_barrier(
|
|||
for (uint32_t i = 0; i < p_memory_barriers.size(); i++) {
|
||||
vk_memory_barriers[i] = {};
|
||||
vk_memory_barriers[i].sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
|
||||
vk_memory_barriers[i].srcAccessMask = (VkPipelineStageFlags)p_memory_barriers[i].src_access;
|
||||
vk_memory_barriers[i].dstAccessMask = (VkAccessFlags)p_memory_barriers[i].dst_access;
|
||||
vk_memory_barriers[i].srcAccessMask = _rd_to_vk_access_flags(p_memory_barriers[i].src_access);
|
||||
vk_memory_barriers[i].dstAccessMask = _rd_to_vk_access_flags(p_memory_barriers[i].dst_access);
|
||||
}
|
||||
|
||||
VkBufferMemoryBarrier *vk_buffer_barriers = ALLOCA_ARRAY(VkBufferMemoryBarrier, p_buffer_barriers.size());
|
||||
|
@ -1939,8 +1986,8 @@ void RenderingDeviceDriverVulkan::command_pipeline_barrier(
|
|||
vk_buffer_barriers[i].sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
|
||||
vk_buffer_barriers[i].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
vk_buffer_barriers[i].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
vk_buffer_barriers[i].srcAccessMask = (VkAccessFlags)p_buffer_barriers[i].src_access;
|
||||
vk_buffer_barriers[i].dstAccessMask = (VkAccessFlags)p_buffer_barriers[i].dst_access;
|
||||
vk_buffer_barriers[i].srcAccessMask = _rd_to_vk_access_flags(p_buffer_barriers[i].src_access);
|
||||
vk_buffer_barriers[i].dstAccessMask = _rd_to_vk_access_flags(p_buffer_barriers[i].dst_access);
|
||||
vk_buffer_barriers[i].buffer = ((const BufferInfo *)p_buffer_barriers[i].buffer.id)->vk_buffer;
|
||||
vk_buffer_barriers[i].offset = p_buffer_barriers[i].offset;
|
||||
vk_buffer_barriers[i].size = p_buffer_barriers[i].size;
|
||||
|
@ -1951,10 +1998,10 @@ void RenderingDeviceDriverVulkan::command_pipeline_barrier(
|
|||
const TextureInfo *tex_info = (const TextureInfo *)p_texture_barriers[i].texture.id;
|
||||
vk_image_barriers[i] = {};
|
||||
vk_image_barriers[i].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
||||
vk_image_barriers[i].srcAccessMask = (VkAccessFlags)p_texture_barriers[i].src_access;
|
||||
vk_image_barriers[i].dstAccessMask = (VkAccessFlags)p_texture_barriers[i].dst_access;
|
||||
vk_image_barriers[i].oldLayout = (VkImageLayout)p_texture_barriers[i].prev_layout;
|
||||
vk_image_barriers[i].newLayout = (VkImageLayout)p_texture_barriers[i].next_layout;
|
||||
vk_image_barriers[i].srcAccessMask = _rd_to_vk_access_flags(p_texture_barriers[i].src_access);
|
||||
vk_image_barriers[i].dstAccessMask = _rd_to_vk_access_flags(p_texture_barriers[i].dst_access);
|
||||
vk_image_barriers[i].oldLayout = RD_TO_VK_LAYOUT[p_texture_barriers[i].prev_layout];
|
||||
vk_image_barriers[i].newLayout = RD_TO_VK_LAYOUT[p_texture_barriers[i].next_layout];
|
||||
vk_image_barriers[i].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
vk_image_barriers[i].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
vk_image_barriers[i].image = tex_info->vk_view_create_info.image;
|
||||
|
@ -1984,8 +2031,8 @@ void RenderingDeviceDriverVulkan::command_pipeline_barrier(
|
|||
|
||||
vkCmdPipelineBarrier(
|
||||
(VkCommandBuffer)p_cmd_buffer.id,
|
||||
(VkPipelineStageFlags)p_src_stages,
|
||||
(VkPipelineStageFlags)p_dst_stages,
|
||||
_rd_to_vk_pipeline_stages(p_src_stages),
|
||||
_rd_to_vk_pipeline_stages(p_dst_stages),
|
||||
0,
|
||||
p_memory_barriers.size(), vk_memory_barriers,
|
||||
p_buffer_barriers.size(), vk_buffer_barriers,
|
||||
|
@ -3727,7 +3774,7 @@ void RenderingDeviceDriverVulkan::command_copy_texture(CommandBufferID p_cmd_buf
|
|||
|
||||
const TextureInfo *src_tex_info = (const TextureInfo *)p_src_texture.id;
|
||||
const TextureInfo *dst_tex_info = (const TextureInfo *)p_dst_texture.id;
|
||||
vkCmdCopyImage((VkCommandBuffer)p_cmd_buffer.id, src_tex_info->vk_view_create_info.image, (VkImageLayout)p_src_texture_layout, dst_tex_info->vk_view_create_info.image, (VkImageLayout)p_dst_texture_layout, p_regions.size(), vk_copy_regions);
|
||||
vkCmdCopyImage((VkCommandBuffer)p_cmd_buffer.id, src_tex_info->vk_view_create_info.image, RD_TO_VK_LAYOUT[p_src_texture_layout], dst_tex_info->vk_view_create_info.image, RD_TO_VK_LAYOUT[p_dst_texture_layout], p_regions.size(), vk_copy_regions);
|
||||
}
|
||||
|
||||
void RenderingDeviceDriverVulkan::command_resolve_texture(CommandBufferID p_cmd_buffer, TextureID p_src_texture, TextureLayout p_src_texture_layout, uint32_t p_src_layer, uint32_t p_src_mipmap, TextureID p_dst_texture, TextureLayout p_dst_texture_layout, uint32_t p_dst_layer, uint32_t p_dst_mipmap) {
|
||||
|
@ -3747,7 +3794,7 @@ void RenderingDeviceDriverVulkan::command_resolve_texture(CommandBufferID p_cmd_
|
|||
vk_resolve.extent.height = MAX(1u, src_tex_info->vk_create_info.extent.height >> p_src_mipmap);
|
||||
vk_resolve.extent.depth = MAX(1u, src_tex_info->vk_create_info.extent.depth >> p_src_mipmap);
|
||||
|
||||
vkCmdResolveImage((VkCommandBuffer)p_cmd_buffer.id, src_tex_info->vk_view_create_info.image, (VkImageLayout)p_src_texture_layout, dst_tex_info->vk_view_create_info.image, (VkImageLayout)p_dst_texture_layout, 1, &vk_resolve);
|
||||
vkCmdResolveImage((VkCommandBuffer)p_cmd_buffer.id, src_tex_info->vk_view_create_info.image, RD_TO_VK_LAYOUT[p_src_texture_layout], dst_tex_info->vk_view_create_info.image, RD_TO_VK_LAYOUT[p_dst_texture_layout], 1, &vk_resolve);
|
||||
}
|
||||
|
||||
void RenderingDeviceDriverVulkan::command_clear_color_texture(CommandBufferID p_cmd_buffer, TextureID p_texture, TextureLayout p_texture_layout, const Color &p_color, const TextureSubresourceRange &p_subresources) {
|
||||
|
@ -3758,7 +3805,7 @@ void RenderingDeviceDriverVulkan::command_clear_color_texture(CommandBufferID p_
|
|||
_texture_subresource_range_to_vk(p_subresources, &vk_subresources);
|
||||
|
||||
const TextureInfo *tex_info = (const TextureInfo *)p_texture.id;
|
||||
vkCmdClearColorImage((VkCommandBuffer)p_cmd_buffer.id, tex_info->vk_view_create_info.image, (VkImageLayout)p_texture_layout, &vk_color, 1, &vk_subresources);
|
||||
vkCmdClearColorImage((VkCommandBuffer)p_cmd_buffer.id, tex_info->vk_view_create_info.image, RD_TO_VK_LAYOUT[p_texture_layout], &vk_color, 1, &vk_subresources);
|
||||
}
|
||||
|
||||
void RenderingDeviceDriverVulkan::command_copy_buffer_to_texture(CommandBufferID p_cmd_buffer, BufferID p_src_buffer, TextureID p_dst_texture, TextureLayout p_dst_texture_layout, VectorView<BufferTextureCopyRegion> p_regions) {
|
||||
|
@ -3769,7 +3816,7 @@ void RenderingDeviceDriverVulkan::command_copy_buffer_to_texture(CommandBufferID
|
|||
|
||||
const BufferInfo *buf_info = (const BufferInfo *)p_src_buffer.id;
|
||||
const TextureInfo *tex_info = (const TextureInfo *)p_dst_texture.id;
|
||||
vkCmdCopyBufferToImage((VkCommandBuffer)p_cmd_buffer.id, buf_info->vk_buffer, tex_info->vk_view_create_info.image, (VkImageLayout)p_dst_texture_layout, p_regions.size(), vk_copy_regions);
|
||||
vkCmdCopyBufferToImage((VkCommandBuffer)p_cmd_buffer.id, buf_info->vk_buffer, tex_info->vk_view_create_info.image, RD_TO_VK_LAYOUT[p_dst_texture_layout], p_regions.size(), vk_copy_regions);
|
||||
}
|
||||
|
||||
void RenderingDeviceDriverVulkan::command_copy_texture_to_buffer(CommandBufferID p_cmd_buffer, TextureID p_src_texture, TextureLayout p_src_texture_layout, BufferID p_dst_buffer, VectorView<BufferTextureCopyRegion> p_regions) {
|
||||
|
@ -3780,7 +3827,7 @@ void RenderingDeviceDriverVulkan::command_copy_texture_to_buffer(CommandBufferID
|
|||
|
||||
const TextureInfo *tex_info = (const TextureInfo *)p_src_texture.id;
|
||||
const BufferInfo *buf_info = (const BufferInfo *)p_dst_buffer.id;
|
||||
vkCmdCopyImageToBuffer((VkCommandBuffer)p_cmd_buffer.id, tex_info->vk_view_create_info.image, (VkImageLayout)p_src_texture_layout, buf_info->vk_buffer, p_regions.size(), vk_copy_regions);
|
||||
vkCmdCopyImageToBuffer((VkCommandBuffer)p_cmd_buffer.id, tex_info->vk_view_create_info.image, RD_TO_VK_LAYOUT[p_src_texture_layout], buf_info->vk_buffer, p_regions.size(), vk_copy_regions);
|
||||
}
|
||||
|
||||
/******************/
|
||||
|
@ -3926,7 +3973,7 @@ static void _attachment_reference_to_vk(const RDD::AttachmentReference &p_attach
|
|||
*r_vk_attachment_reference = {};
|
||||
r_vk_attachment_reference->sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2_KHR;
|
||||
r_vk_attachment_reference->attachment = p_attachment_reference.attachment;
|
||||
r_vk_attachment_reference->layout = (VkImageLayout)p_attachment_reference.layout;
|
||||
r_vk_attachment_reference->layout = RD_TO_VK_LAYOUT[p_attachment_reference.layout];
|
||||
r_vk_attachment_reference->aspectMask = (VkImageAspectFlags)p_attachment_reference.aspect;
|
||||
}
|
||||
|
||||
|
@ -3945,8 +3992,8 @@ RDD::RenderPassID RenderingDeviceDriverVulkan::render_pass_create(VectorView<Att
|
|||
vk_attachments[i].storeOp = (VkAttachmentStoreOp)p_attachments[i].store_op;
|
||||
vk_attachments[i].stencilLoadOp = (VkAttachmentLoadOp)p_attachments[i].stencil_load_op;
|
||||
vk_attachments[i].stencilStoreOp = (VkAttachmentStoreOp)p_attachments[i].stencil_store_op;
|
||||
vk_attachments[i].initialLayout = (VkImageLayout)p_attachments[i].initial_layout;
|
||||
vk_attachments[i].finalLayout = (VkImageLayout)p_attachments[i].final_layout;
|
||||
vk_attachments[i].initialLayout = RD_TO_VK_LAYOUT[p_attachments[i].initial_layout];
|
||||
vk_attachments[i].finalLayout = RD_TO_VK_LAYOUT[p_attachments[i].final_layout];
|
||||
}
|
||||
|
||||
VkSubpassDescription2KHR *vk_subpasses = ALLOCA_ARRAY(VkSubpassDescription2KHR, p_subpasses.size());
|
||||
|
@ -4010,10 +4057,10 @@ RDD::RenderPassID RenderingDeviceDriverVulkan::render_pass_create(VectorView<Att
|
|||
vk_subpass_dependencies[i].sType = VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2;
|
||||
vk_subpass_dependencies[i].srcSubpass = p_subpass_dependencies[i].src_subpass;
|
||||
vk_subpass_dependencies[i].dstSubpass = p_subpass_dependencies[i].dst_subpass;
|
||||
vk_subpass_dependencies[i].srcStageMask = (VkPipelineStageFlags)p_subpass_dependencies[i].src_stages;
|
||||
vk_subpass_dependencies[i].dstStageMask = (VkPipelineStageFlags)p_subpass_dependencies[i].dst_stages;
|
||||
vk_subpass_dependencies[i].srcAccessMask = (VkAccessFlags)p_subpass_dependencies[i].src_access;
|
||||
vk_subpass_dependencies[i].dstAccessMask = (VkAccessFlags)p_subpass_dependencies[i].dst_access;
|
||||
vk_subpass_dependencies[i].srcStageMask = _rd_to_vk_pipeline_stages(p_subpass_dependencies[i].src_stages);
|
||||
vk_subpass_dependencies[i].dstStageMask = _rd_to_vk_pipeline_stages(p_subpass_dependencies[i].dst_stages);
|
||||
vk_subpass_dependencies[i].srcAccessMask = _rd_to_vk_access_flags(p_subpass_dependencies[i].src_access);
|
||||
vk_subpass_dependencies[i].dstAccessMask = _rd_to_vk_access_flags(p_subpass_dependencies[i].dst_access);
|
||||
}
|
||||
|
||||
VkRenderPassCreateInfo2KHR create_info = {};
|
||||
|
|
|
@ -210,6 +210,7 @@ public:
|
|||
virtual uint8_t *texture_map(TextureID p_texture, const TextureSubresource &p_subresource) override final;
|
||||
virtual void texture_unmap(TextureID p_texture) override final;
|
||||
virtual BitField<TextureUsageBits> texture_get_usages_supported_by_format(DataFormat p_format, bool p_cpu_readable) override final;
|
||||
virtual bool texture_can_make_shared_with_format(TextureID p_texture, DataFormat p_format, bool &r_raw_reinterpretation) override final;
|
||||
|
||||
/*****************/
|
||||
/**** SAMPLER ****/
|
||||
|
|
|
@ -824,8 +824,8 @@ RID RenderingDevice::texture_create(const TextureFormat &p_format, const Texture
|
|||
}
|
||||
|
||||
if (texture.draw_tracker != nullptr) {
|
||||
// Draw tracker can assume the texture will be in transfer destination.
|
||||
texture.draw_tracker->usage = RDG::RESOURCE_USAGE_TRANSFER_TO;
|
||||
// Draw tracker can assume the texture will be in copy destination.
|
||||
texture.draw_tracker->usage = RDG::RESOURCE_USAGE_COPY_TO;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -847,8 +847,11 @@ RID RenderingDevice::texture_create_shared(const TextureView &p_view, RID p_with
|
|||
// Create view.
|
||||
|
||||
Texture texture = *src_texture;
|
||||
texture.shared_fallback = nullptr;
|
||||
|
||||
RDD::TextureView tv;
|
||||
bool create_shared = true;
|
||||
bool raw_reintepretation = false;
|
||||
if (p_view.format_override == DATA_FORMAT_MAX || p_view.format_override == texture.format) {
|
||||
tv.format = texture.format;
|
||||
} else {
|
||||
|
@ -857,13 +860,47 @@ RID RenderingDevice::texture_create_shared(const TextureView &p_view, RID p_with
|
|||
ERR_FAIL_COND_V_MSG(!texture.allowed_shared_formats.has(p_view.format_override), RID(),
|
||||
"Format override is not in the list of allowed shareable formats for original texture.");
|
||||
tv.format = p_view.format_override;
|
||||
create_shared = driver->texture_can_make_shared_with_format(texture.driver_id, p_view.format_override, raw_reintepretation);
|
||||
}
|
||||
tv.swizzle_r = p_view.swizzle_r;
|
||||
tv.swizzle_g = p_view.swizzle_g;
|
||||
tv.swizzle_b = p_view.swizzle_b;
|
||||
tv.swizzle_a = p_view.swizzle_a;
|
||||
|
||||
texture.driver_id = driver->texture_create_shared(texture.driver_id, tv);
|
||||
if (create_shared) {
|
||||
texture.driver_id = driver->texture_create_shared(texture.driver_id, tv);
|
||||
} else {
|
||||
// The regular view will use the same format as the main texture.
|
||||
RDD::TextureView regular_view = tv;
|
||||
regular_view.format = src_texture->format;
|
||||
texture.driver_id = driver->texture_create_shared(texture.driver_id, regular_view);
|
||||
|
||||
// Create the independent texture for the alias.
|
||||
RDD::TextureFormat alias_format = texture.texture_format();
|
||||
alias_format.format = tv.format;
|
||||
alias_format.usage_bits = TEXTURE_USAGE_SAMPLING_BIT | TEXTURE_USAGE_CAN_COPY_TO_BIT;
|
||||
|
||||
_texture_check_shared_fallback(src_texture);
|
||||
_texture_check_shared_fallback(&texture);
|
||||
|
||||
texture.shared_fallback->texture = driver->texture_create(alias_format, tv);
|
||||
texture.shared_fallback->raw_reinterpretation = raw_reintepretation;
|
||||
texture_memory += driver->texture_get_allocation_size(texture.shared_fallback->texture);
|
||||
|
||||
RDG::ResourceTracker *tracker = RDG::resource_tracker_create();
|
||||
tracker->texture_driver_id = texture.shared_fallback->texture;
|
||||
tracker->texture_subresources = texture.barrier_range();
|
||||
tracker->texture_usage = alias_format.usage_bits;
|
||||
tracker->reference_count = 1;
|
||||
texture.shared_fallback->texture_tracker = tracker;
|
||||
texture.shared_fallback->revision = 0;
|
||||
|
||||
if (raw_reintepretation && src_texture->shared_fallback->buffer.id == 0) {
|
||||
// For shared textures of the same size, we create the buffer on the main texture if it doesn't have it already.
|
||||
_texture_create_reinterpret_buffer(src_texture);
|
||||
}
|
||||
}
|
||||
|
||||
ERR_FAIL_COND_V(!texture.driver_id, RID());
|
||||
|
||||
texture.slice_trackers.clear();
|
||||
|
@ -965,6 +1002,7 @@ RID RenderingDevice::texture_create_shared_from_slice(const TextureView &p_view,
|
|||
}
|
||||
|
||||
Texture texture = *src_texture;
|
||||
texture.shared_fallback = nullptr;
|
||||
|
||||
get_image_format_required_size(texture.format, texture.width, texture.height, texture.depth, p_mipmap + 1, &texture.width, &texture.height);
|
||||
texture.mipmaps = p_mipmaps;
|
||||
|
@ -979,6 +1017,8 @@ RID RenderingDevice::texture_create_shared_from_slice(const TextureView &p_view,
|
|||
}
|
||||
|
||||
RDD::TextureView tv;
|
||||
bool create_shared = true;
|
||||
bool raw_reintepretation = false;
|
||||
if (p_view.format_override == DATA_FORMAT_MAX || p_view.format_override == texture.format) {
|
||||
tv.format = texture.format;
|
||||
} else {
|
||||
|
@ -987,7 +1027,9 @@ RID RenderingDevice::texture_create_shared_from_slice(const TextureView &p_view,
|
|||
ERR_FAIL_COND_V_MSG(!texture.allowed_shared_formats.has(p_view.format_override), RID(),
|
||||
"Format override is not in the list of allowed shareable formats for original texture.");
|
||||
tv.format = p_view.format_override;
|
||||
create_shared = driver->texture_can_make_shared_with_format(texture.driver_id, p_view.format_override, raw_reintepretation);
|
||||
}
|
||||
|
||||
tv.swizzle_r = p_view.swizzle_r;
|
||||
tv.swizzle_g = p_view.swizzle_g;
|
||||
tv.swizzle_b = p_view.swizzle_b;
|
||||
|
@ -1000,7 +1042,47 @@ RID RenderingDevice::texture_create_shared_from_slice(const TextureView &p_view,
|
|||
"Specified layer must be a multiple of 6.");
|
||||
}
|
||||
|
||||
texture.driver_id = driver->texture_create_shared_from_slice(src_texture->driver_id, tv, p_slice_type, p_layer, slice_layers, p_mipmap, p_mipmaps);
|
||||
if (create_shared) {
|
||||
texture.driver_id = driver->texture_create_shared_from_slice(src_texture->driver_id, tv, p_slice_type, p_layer, slice_layers, p_mipmap, p_mipmaps);
|
||||
} else {
|
||||
// The regular view will use the same format as the main texture.
|
||||
RDD::TextureView regular_view = tv;
|
||||
regular_view.format = src_texture->format;
|
||||
texture.driver_id = driver->texture_create_shared_from_slice(src_texture->driver_id, regular_view, p_slice_type, p_layer, slice_layers, p_mipmap, p_mipmaps);
|
||||
|
||||
// Create the independent texture for the slice.
|
||||
RDD::TextureSubresourceRange slice_range = texture.barrier_range();
|
||||
slice_range.base_mipmap = 0;
|
||||
slice_range.base_layer = 0;
|
||||
|
||||
RDD::TextureFormat slice_format = texture.texture_format();
|
||||
slice_format.width = MAX(texture.width >> p_mipmap, 1U);
|
||||
slice_format.height = MAX(texture.height >> p_mipmap, 1U);
|
||||
slice_format.depth = MAX(texture.depth >> p_mipmap, 1U);
|
||||
slice_format.format = tv.format;
|
||||
slice_format.usage_bits = TEXTURE_USAGE_SAMPLING_BIT | TEXTURE_USAGE_CAN_COPY_TO_BIT;
|
||||
|
||||
_texture_check_shared_fallback(src_texture);
|
||||
_texture_check_shared_fallback(&texture);
|
||||
|
||||
texture.shared_fallback->texture = driver->texture_create(slice_format, tv);
|
||||
texture.shared_fallback->raw_reinterpretation = raw_reintepretation;
|
||||
texture_memory += driver->texture_get_allocation_size(texture.shared_fallback->texture);
|
||||
|
||||
RDG::ResourceTracker *tracker = RDG::resource_tracker_create();
|
||||
tracker->texture_driver_id = texture.shared_fallback->texture;
|
||||
tracker->texture_subresources = slice_range;
|
||||
tracker->texture_usage = slice_format.usage_bits;
|
||||
tracker->reference_count = 1;
|
||||
texture.shared_fallback->texture_tracker = tracker;
|
||||
texture.shared_fallback->revision = 0;
|
||||
|
||||
if (raw_reintepretation && src_texture->shared_fallback->buffer.id == 0) {
|
||||
// For shared texture slices, we create the buffer on the slice if the source texture has no reinterpretation buffer.
|
||||
_texture_create_reinterpret_buffer(&texture);
|
||||
}
|
||||
}
|
||||
|
||||
ERR_FAIL_COND_V(!texture.driver_id, RID());
|
||||
|
||||
const Rect2i slice_rect(p_mipmap, p_layer, p_mipmaps, slice_layers);
|
||||
|
@ -1093,15 +1175,18 @@ Error RenderingDevice::_texture_update(RID p_texture, uint32_t p_layer, const Ve
|
|||
// When using the setup queue directly, we transition the texture to the optimal layout.
|
||||
RDD::TextureBarrier tb;
|
||||
tb.texture = texture->driver_id;
|
||||
tb.dst_access = RDD::BARRIER_ACCESS_TRANSFER_WRITE_BIT;
|
||||
tb.dst_access = RDD::BARRIER_ACCESS_COPY_WRITE_BIT;
|
||||
tb.prev_layout = RDD::TEXTURE_LAYOUT_UNDEFINED;
|
||||
tb.next_layout = RDD::TEXTURE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
||||
tb.next_layout = RDD::TEXTURE_LAYOUT_COPY_DST_OPTIMAL;
|
||||
tb.subresources.aspect = texture->barrier_aspect_flags;
|
||||
tb.subresources.mipmap_count = texture->mipmaps;
|
||||
tb.subresources.base_layer = p_layer;
|
||||
tb.subresources.layer_count = 1;
|
||||
|
||||
driver->command_pipeline_barrier(frames[frame].setup_command_buffer, RDD::PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, RDD::PIPELINE_STAGE_TRANSFER_BIT, {}, {}, tb);
|
||||
driver->command_pipeline_barrier(frames[frame].setup_command_buffer, RDD::PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, RDD::PIPELINE_STAGE_COPY_BIT, {}, {}, tb);
|
||||
} else if (!p_use_setup_queue) {
|
||||
// Indicate the texture will get modified for the shared texture fallback.
|
||||
_texture_update_shared_fallback(p_texture, texture, true);
|
||||
}
|
||||
|
||||
uint32_t mipmap_offset = 0;
|
||||
|
@ -1199,7 +1284,7 @@ Error RenderingDevice::_texture_update(RID p_texture, uint32_t p_layer, const Ve
|
|||
copy_region.texture_region_size = Vector3i(region_logic_w, region_logic_h, 1);
|
||||
|
||||
if (p_use_setup_queue) {
|
||||
driver->command_copy_buffer_to_texture(frames[frame].setup_command_buffer, staging_buffer_blocks[staging_buffer_current].driver_id, texture->driver_id, RDD::TEXTURE_LAYOUT_TRANSFER_DST_OPTIMAL, copy_region);
|
||||
driver->command_copy_buffer_to_texture(frames[frame].setup_command_buffer, staging_buffer_blocks[staging_buffer_current].driver_id, texture->driver_id, RDD::TEXTURE_LAYOUT_COPY_DST_OPTIMAL, copy_region);
|
||||
} else {
|
||||
RDG::RecordedBufferToTextureCopy buffer_to_texture_copy;
|
||||
buffer_to_texture_copy.from_buffer = staging_buffer_blocks[staging_buffer_current].driver_id;
|
||||
|
@ -1221,14 +1306,14 @@ Error RenderingDevice::_texture_update(RID p_texture, uint32_t p_layer, const Ve
|
|||
// If the texture does not have a tracker, it means it must be transitioned to the sampling state.
|
||||
RDD::TextureBarrier tb;
|
||||
tb.texture = texture->driver_id;
|
||||
tb.src_access = RDD::BARRIER_ACCESS_TRANSFER_WRITE_BIT;
|
||||
tb.prev_layout = RDD::TEXTURE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
||||
tb.src_access = RDD::BARRIER_ACCESS_COPY_WRITE_BIT;
|
||||
tb.prev_layout = RDD::TEXTURE_LAYOUT_COPY_DST_OPTIMAL;
|
||||
tb.next_layout = RDD::TEXTURE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
tb.subresources.aspect = texture->barrier_aspect_flags;
|
||||
tb.subresources.mipmap_count = texture->mipmaps;
|
||||
tb.subresources.base_layer = p_layer;
|
||||
tb.subresources.layer_count = 1;
|
||||
driver->command_pipeline_barrier(frames[frame].setup_command_buffer, RDD::PIPELINE_STAGE_TRANSFER_BIT, RDD::PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, {}, {}, tb);
|
||||
driver->command_pipeline_barrier(frames[frame].setup_command_buffer, RDD::PIPELINE_STAGE_COPY_BIT, RDD::PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, {}, {}, tb);
|
||||
} else if (!p_use_setup_queue && !command_buffer_to_texture_copies_vector.is_empty()) {
|
||||
if (_texture_make_mutable(texture, p_texture)) {
|
||||
// The texture must be mutable to be used as a copy destination.
|
||||
|
@ -1241,6 +1326,186 @@ Error RenderingDevice::_texture_update(RID p_texture, uint32_t p_layer, const Ve
|
|||
return OK;
|
||||
}
|
||||
|
||||
void RenderingDevice::_texture_check_shared_fallback(Texture *p_texture) {
|
||||
if (p_texture->shared_fallback == nullptr) {
|
||||
p_texture->shared_fallback = memnew(Texture::SharedFallback);
|
||||
}
|
||||
}
|
||||
|
||||
void RenderingDevice::_texture_update_shared_fallback(RID p_texture_rid, Texture *p_texture, bool p_for_writing) {
|
||||
if (p_texture->shared_fallback == nullptr) {
|
||||
// This texture does not use any of the shared texture fallbacks.
|
||||
return;
|
||||
}
|
||||
|
||||
if (p_texture->owner.is_valid()) {
|
||||
Texture *owner_texture = texture_owner.get_or_null(p_texture->owner);
|
||||
ERR_FAIL_NULL(owner_texture);
|
||||
if (p_for_writing) {
|
||||
// Only the main texture is used for writing when using the shared fallback.
|
||||
owner_texture->shared_fallback->revision++;
|
||||
} else if (p_texture->shared_fallback->revision != owner_texture->shared_fallback->revision) {
|
||||
// Copy the contents of the main texture into the shared texture fallback slice. Update the revision.
|
||||
_texture_copy_shared(p_texture->owner, owner_texture, p_texture_rid, p_texture);
|
||||
p_texture->shared_fallback->revision = owner_texture->shared_fallback->revision;
|
||||
}
|
||||
} else if (p_for_writing) {
|
||||
// Increment the revision of the texture so shared texture fallback slices must be updated.
|
||||
p_texture->shared_fallback->revision++;
|
||||
}
|
||||
}
|
||||
|
||||
void RenderingDevice::_texture_free_shared_fallback(Texture *p_texture) {
|
||||
if (p_texture->shared_fallback != nullptr) {
|
||||
if (p_texture->shared_fallback->texture_tracker != nullptr) {
|
||||
RDG::resource_tracker_free(p_texture->shared_fallback->texture_tracker);
|
||||
}
|
||||
|
||||
if (p_texture->shared_fallback->buffer_tracker != nullptr) {
|
||||
RDG::resource_tracker_free(p_texture->shared_fallback->buffer_tracker);
|
||||
}
|
||||
|
||||
if (p_texture->shared_fallback->texture.id != 0) {
|
||||
texture_memory -= driver->texture_get_allocation_size(p_texture->shared_fallback->texture);
|
||||
driver->texture_free(p_texture->shared_fallback->texture);
|
||||
}
|
||||
|
||||
if (p_texture->shared_fallback->buffer.id != 0) {
|
||||
buffer_memory -= driver->buffer_get_allocation_size(p_texture->shared_fallback->buffer);
|
||||
driver->buffer_free(p_texture->shared_fallback->buffer);
|
||||
}
|
||||
|
||||
memdelete(p_texture->shared_fallback);
|
||||
p_texture->shared_fallback = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void RenderingDevice::_texture_copy_shared(RID p_src_texture_rid, Texture *p_src_texture, RID p_dst_texture_rid, Texture *p_dst_texture) {
|
||||
// The only type of copying allowed is from the main texture to the slice texture, as slice textures are not allowed to be used for writing when using this fallback.
|
||||
DEV_ASSERT(p_src_texture != nullptr);
|
||||
DEV_ASSERT(p_dst_texture != nullptr);
|
||||
DEV_ASSERT(p_src_texture->owner.is_null());
|
||||
DEV_ASSERT(p_dst_texture->owner == p_src_texture_rid);
|
||||
|
||||
bool src_made_mutable = _texture_make_mutable(p_src_texture, p_src_texture_rid);
|
||||
bool dst_made_mutable = _texture_make_mutable(p_dst_texture, p_dst_texture_rid);
|
||||
if (src_made_mutable || dst_made_mutable) {
|
||||
draw_graph.add_synchronization();
|
||||
}
|
||||
|
||||
if (p_dst_texture->shared_fallback->raw_reinterpretation) {
|
||||
// If one of the textures is a main texture and they have a reinterpret buffer, we prefer using that as it's guaranteed to be big enough to hold
|
||||
// anything and it's how the shared textures that don't use slices are created.
|
||||
bool src_has_buffer = p_src_texture->shared_fallback->buffer.id != 0;
|
||||
bool dst_has_buffer = p_dst_texture->shared_fallback->buffer.id != 0;
|
||||
bool from_src = p_src_texture->owner.is_null() && src_has_buffer;
|
||||
bool from_dst = p_dst_texture->owner.is_null() && dst_has_buffer;
|
||||
if (!from_src && !from_dst) {
|
||||
// If neither texture passed the condition, we just pick whichever texture has a reinterpretation buffer.
|
||||
from_src = src_has_buffer;
|
||||
from_dst = dst_has_buffer;
|
||||
}
|
||||
|
||||
// Pick the buffer and tracker to use from the right texture.
|
||||
RDD::BufferID shared_buffer;
|
||||
RDG::ResourceTracker *shared_buffer_tracker = nullptr;
|
||||
if (from_src) {
|
||||
shared_buffer = p_src_texture->shared_fallback->buffer;
|
||||
shared_buffer_tracker = p_src_texture->shared_fallback->buffer_tracker;
|
||||
} else if (from_dst) {
|
||||
shared_buffer = p_dst_texture->shared_fallback->buffer;
|
||||
shared_buffer_tracker = p_dst_texture->shared_fallback->buffer_tracker;
|
||||
} else {
|
||||
DEV_ASSERT(false && "This path should not be reachable.");
|
||||
}
|
||||
|
||||
// FIXME: When using reinterpretation buffers, the only texture aspect supported is color. Depth or stencil contents won't get copied.
|
||||
RDD::BufferTextureCopyRegion get_data_region;
|
||||
RDG::RecordedBufferToTextureCopy update_copy;
|
||||
RDD::TextureCopyableLayout first_copyable_layout;
|
||||
RDD::TextureCopyableLayout copyable_layout;
|
||||
RDD::TextureSubresource texture_subresource;
|
||||
texture_subresource.aspect = RDD::TEXTURE_ASPECT_COLOR;
|
||||
texture_subresource.layer = 0;
|
||||
texture_subresource.mipmap = 0;
|
||||
driver->texture_get_copyable_layout(p_dst_texture->shared_fallback->texture, texture_subresource, &first_copyable_layout);
|
||||
|
||||
// Copying each mipmap from main texture to a buffer and then to the slice texture.
|
||||
thread_local LocalVector<RDD::BufferTextureCopyRegion> get_data_vector;
|
||||
thread_local LocalVector<RDG::RecordedBufferToTextureCopy> update_vector;
|
||||
get_data_vector.clear();
|
||||
update_vector.clear();
|
||||
for (uint32_t i = 0; i < p_dst_texture->mipmaps; i++) {
|
||||
driver->texture_get_copyable_layout(p_dst_texture->shared_fallback->texture, texture_subresource, ©able_layout);
|
||||
|
||||
uint32_t mipmap = p_dst_texture->base_mipmap + i;
|
||||
get_data_region.buffer_offset = copyable_layout.offset - first_copyable_layout.offset;
|
||||
get_data_region.texture_subresources.aspect = RDD::TEXTURE_ASPECT_COLOR_BIT;
|
||||
get_data_region.texture_subresources.base_layer = p_dst_texture->base_layer;
|
||||
get_data_region.texture_subresources.mipmap = mipmap;
|
||||
get_data_region.texture_subresources.layer_count = p_dst_texture->layers;
|
||||
get_data_region.texture_region_size.x = MAX(1U, p_src_texture->width >> mipmap);
|
||||
get_data_region.texture_region_size.y = MAX(1U, p_src_texture->height >> mipmap);
|
||||
get_data_region.texture_region_size.z = MAX(1U, p_src_texture->depth >> mipmap);
|
||||
get_data_vector.push_back(get_data_region);
|
||||
|
||||
update_copy.from_buffer = shared_buffer;
|
||||
update_copy.region.buffer_offset = get_data_region.buffer_offset;
|
||||
update_copy.region.texture_subresources.aspect = RDD::TEXTURE_ASPECT_COLOR_BIT;
|
||||
update_copy.region.texture_subresources.base_layer = texture_subresource.layer;
|
||||
update_copy.region.texture_subresources.mipmap = texture_subresource.mipmap;
|
||||
update_copy.region.texture_subresources.layer_count = get_data_region.texture_subresources.layer_count;
|
||||
update_copy.region.texture_region_size.x = get_data_region.texture_region_size.x;
|
||||
update_copy.region.texture_region_size.y = get_data_region.texture_region_size.y;
|
||||
update_copy.region.texture_region_size.z = get_data_region.texture_region_size.z;
|
||||
update_vector.push_back(update_copy);
|
||||
|
||||
texture_subresource.mipmap++;
|
||||
}
|
||||
|
||||
draw_graph.add_texture_get_data(p_src_texture->driver_id, p_src_texture->draw_tracker, shared_buffer, get_data_vector, shared_buffer_tracker);
|
||||
draw_graph.add_texture_update(p_dst_texture->shared_fallback->texture, p_dst_texture->shared_fallback->texture_tracker, update_vector, shared_buffer_tracker);
|
||||
} else {
|
||||
// Raw reinterpretation is not required. Use a regular texture copy.
|
||||
RDD::TextureCopyRegion copy_region;
|
||||
copy_region.src_subresources.aspect = p_src_texture->read_aspect_flags;
|
||||
copy_region.src_subresources.base_layer = p_dst_texture->base_layer;
|
||||
copy_region.src_subresources.layer_count = p_dst_texture->layers;
|
||||
copy_region.dst_subresources.aspect = p_dst_texture->read_aspect_flags;
|
||||
copy_region.dst_subresources.base_layer = 0;
|
||||
copy_region.dst_subresources.layer_count = copy_region.src_subresources.layer_count;
|
||||
|
||||
// Copying each mipmap from main texture to to the slice texture.
|
||||
thread_local LocalVector<RDD::TextureCopyRegion> region_vector;
|
||||
region_vector.clear();
|
||||
for (uint32_t i = 0; i < p_dst_texture->mipmaps; i++) {
|
||||
uint32_t mipmap = p_dst_texture->base_mipmap + i;
|
||||
copy_region.src_subresources.mipmap = mipmap;
|
||||
copy_region.dst_subresources.mipmap = i;
|
||||
copy_region.size.x = MAX(1U, p_src_texture->width >> mipmap);
|
||||
copy_region.size.y = MAX(1U, p_src_texture->height >> mipmap);
|
||||
copy_region.size.z = MAX(1U, p_src_texture->depth >> mipmap);
|
||||
region_vector.push_back(copy_region);
|
||||
}
|
||||
|
||||
draw_graph.add_texture_copy(p_src_texture->driver_id, p_src_texture->draw_tracker, p_dst_texture->shared_fallback->texture, p_dst_texture->shared_fallback->texture_tracker, region_vector);
|
||||
}
|
||||
}
|
||||
|
||||
void RenderingDevice::_texture_create_reinterpret_buffer(Texture *p_texture) {
|
||||
uint64_t row_pitch_step = driver->api_trait_get(RDD::API_TRAIT_TEXTURE_DATA_ROW_PITCH_STEP);
|
||||
uint64_t transfer_alignment = driver->api_trait_get(RDD::API_TRAIT_TEXTURE_TRANSFER_ALIGNMENT);
|
||||
uint32_t pixel_bytes = get_image_format_pixel_size(p_texture->format);
|
||||
uint32_t row_pitch = STEPIFY(p_texture->width * pixel_bytes, row_pitch_step);
|
||||
uint64_t buffer_size = STEPIFY(pixel_bytes * row_pitch * p_texture->height * p_texture->depth, transfer_alignment);
|
||||
p_texture->shared_fallback->buffer = driver->buffer_create(buffer_size, RDD::BUFFER_USAGE_TRANSFER_FROM_BIT | RDD::BUFFER_USAGE_TRANSFER_TO_BIT, RDD::MEMORY_ALLOCATION_TYPE_GPU);
|
||||
buffer_memory += driver->buffer_get_allocation_size(p_texture->shared_fallback->buffer);
|
||||
|
||||
RDG::ResourceTracker *tracker = RDG::resource_tracker_create();
|
||||
tracker->buffer_driver_id = p_texture->shared_fallback->buffer;
|
||||
p_texture->shared_fallback->buffer_tracker = tracker;
|
||||
}
|
||||
|
||||
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);
|
||||
|
@ -1535,6 +1800,9 @@ Error RenderingDevice::texture_copy(RID p_from_texture, RID p_to_texture, const
|
|||
|
||||
copy_region.size = p_size;
|
||||
|
||||
// Indicate the texture will get modified for the shared texture fallback.
|
||||
_texture_update_shared_fallback(p_to_texture, dst_tex, true);
|
||||
|
||||
// The textures must be mutable to be used in the copy operation.
|
||||
bool src_made_mutable = _texture_make_mutable(src_tex, p_from_texture);
|
||||
bool dst_made_mutable = _texture_make_mutable(dst_tex, p_to_texture);
|
||||
|
@ -1578,6 +1846,9 @@ Error RenderingDevice::texture_resolve_multisample(RID p_from_texture, RID p_to_
|
|||
ERR_FAIL_COND_V_MSG(src_tex->read_aspect_flags != dst_tex->read_aspect_flags, ERR_INVALID_PARAMETER,
|
||||
"Source and destination texture must be of the same type (color or depth).");
|
||||
|
||||
// Indicate the texture will get modified for the shared texture fallback.
|
||||
_texture_update_shared_fallback(p_to_texture, dst_tex, true);
|
||||
|
||||
// The textures must be mutable to be used in the resolve operation.
|
||||
bool src_made_mutable = _texture_make_mutable(src_tex, p_from_texture);
|
||||
bool dst_made_mutable = _texture_make_mutable(dst_tex, p_to_texture);
|
||||
|
@ -1620,6 +1891,9 @@ Error RenderingDevice::texture_clear(RID p_texture, const Color &p_color, uint32
|
|||
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();
|
||||
|
@ -2526,6 +2800,14 @@ RID RenderingDevice::uniform_buffer_create(uint32_t p_size_bytes, const Vector<u
|
|||
return id;
|
||||
}
|
||||
|
||||
void RenderingDevice::_uniform_set_update_shared(UniformSet *p_uniform_set) {
|
||||
for (UniformSet::SharedTexture shared : p_uniform_set->shared_textures_to_update) {
|
||||
Texture *texture = texture_owner.get_or_null(shared.texture);
|
||||
ERR_CONTINUE(texture == nullptr);
|
||||
_texture_update_shared_fallback(shared.texture, texture, shared.writing);
|
||||
}
|
||||
}
|
||||
|
||||
RID RenderingDevice::uniform_set_create(const Vector<Uniform> &p_uniforms, RID p_shader, uint32_t p_shader_set) {
|
||||
_THREAD_SAFE_METHOD_
|
||||
|
||||
|
@ -2554,6 +2836,7 @@ RID RenderingDevice::uniform_set_create(const Vector<Uniform> &p_uniforms, RID p
|
|||
Vector<RDG::ResourceTracker *> draw_trackers;
|
||||
Vector<RDG::ResourceUsage> draw_trackers_usage;
|
||||
HashMap<RID, RDG::ResourceUsage> untracked_usage;
|
||||
Vector<UniformSet::SharedTexture> shared_textures_to_update;
|
||||
|
||||
for (uint32_t i = 0; i < set_uniform_count; i++) {
|
||||
const ShaderUniform &set_uniform = set_uniforms[i];
|
||||
|
@ -2619,8 +2902,16 @@ RID RenderingDevice::uniform_set_create(const Vector<Uniform> &p_uniforms, RID p
|
|||
attachable_textures.push_back(attachable_texture);
|
||||
}
|
||||
|
||||
if (texture->draw_tracker != nullptr) {
|
||||
draw_trackers.push_back(texture->draw_tracker);
|
||||
RDD::TextureID driver_id = texture->driver_id;
|
||||
RDG::ResourceTracker *tracker = texture->draw_tracker;
|
||||
if (texture->shared_fallback != nullptr && texture->shared_fallback->texture.id != 0) {
|
||||
driver_id = texture->shared_fallback->texture;
|
||||
tracker = texture->shared_fallback->texture_tracker;
|
||||
shared_textures_to_update.push_back({ false, texture_id });
|
||||
}
|
||||
|
||||
if (tracker != nullptr) {
|
||||
draw_trackers.push_back(tracker);
|
||||
draw_trackers_usage.push_back(RDG::RESOURCE_USAGE_TEXTURE_SAMPLE);
|
||||
} else {
|
||||
untracked_usage[texture_id] = RDG::RESOURCE_USAGE_TEXTURE_SAMPLE;
|
||||
|
@ -2629,7 +2920,7 @@ RID RenderingDevice::uniform_set_create(const Vector<Uniform> &p_uniforms, RID p
|
|||
DEV_ASSERT(!texture->owner.is_valid() || texture_owner.get_or_null(texture->owner));
|
||||
|
||||
driver_uniform.ids.push_back(*sampler_driver_id);
|
||||
driver_uniform.ids.push_back(texture->driver_id);
|
||||
driver_uniform.ids.push_back(driver_id);
|
||||
}
|
||||
} break;
|
||||
case UNIFORM_TYPE_TEXTURE: {
|
||||
|
@ -2656,8 +2947,16 @@ RID RenderingDevice::uniform_set_create(const Vector<Uniform> &p_uniforms, RID p
|
|||
attachable_textures.push_back(attachable_texture);
|
||||
}
|
||||
|
||||
if (texture->draw_tracker != nullptr) {
|
||||
draw_trackers.push_back(texture->draw_tracker);
|
||||
RDD::TextureID driver_id = texture->driver_id;
|
||||
RDG::ResourceTracker *tracker = texture->draw_tracker;
|
||||
if (texture->shared_fallback != nullptr && texture->shared_fallback->texture.id != 0) {
|
||||
driver_id = texture->shared_fallback->texture;
|
||||
tracker = texture->shared_fallback->texture_tracker;
|
||||
shared_textures_to_update.push_back({ false, texture_id });
|
||||
}
|
||||
|
||||
if (tracker != nullptr) {
|
||||
draw_trackers.push_back(tracker);
|
||||
draw_trackers_usage.push_back(RDG::RESOURCE_USAGE_TEXTURE_SAMPLE);
|
||||
} else {
|
||||
untracked_usage[texture_id] = RDG::RESOURCE_USAGE_TEXTURE_SAMPLE;
|
||||
|
@ -2665,7 +2964,7 @@ RID RenderingDevice::uniform_set_create(const Vector<Uniform> &p_uniforms, RID p
|
|||
|
||||
DEV_ASSERT(!texture->owner.is_valid() || texture_owner.get_or_null(texture->owner));
|
||||
|
||||
driver_uniform.ids.push_back(texture->driver_id);
|
||||
driver_uniform.ids.push_back(driver_id);
|
||||
}
|
||||
} break;
|
||||
case UNIFORM_TYPE_IMAGE: {
|
||||
|
@ -2687,6 +2986,10 @@ RID RenderingDevice::uniform_set_create(const Vector<Uniform> &p_uniforms, RID p
|
|||
ERR_FAIL_COND_V_MSG(!(texture->usage_flags & TEXTURE_USAGE_STORAGE_BIT), RID(),
|
||||
"Image (binding: " + itos(uniform.binding) + ", index " + itos(j) + ") needs the TEXTURE_USAGE_STORAGE_BIT usage flag set in order to be used as uniform.");
|
||||
|
||||
if (texture->owner.is_null() && texture->shared_fallback != nullptr) {
|
||||
shared_textures_to_update.push_back({ true, texture_id });
|
||||
}
|
||||
|
||||
if (_texture_make_mutable(texture, texture_id)) {
|
||||
// The texture must be mutable as a layout transition will be required.
|
||||
draw_graph.add_synchronization();
|
||||
|
@ -2872,6 +3175,7 @@ RID RenderingDevice::uniform_set_create(const Vector<Uniform> &p_uniforms, RID p
|
|||
uniform_set.draw_trackers = draw_trackers;
|
||||
uniform_set.draw_trackers_usage = draw_trackers_usage;
|
||||
uniform_set.untracked_usage = untracked_usage;
|
||||
uniform_set.shared_textures_to_update = shared_textures_to_update;
|
||||
uniform_set.shader_set = p_shader_set;
|
||||
uniform_set.shader_id = p_shader;
|
||||
|
||||
|
@ -3347,12 +3651,16 @@ Error RenderingDevice::_draw_list_render_pass_begin(Framebuffer *p_framebuffer,
|
|||
for (int i = 0; i < p_framebuffer->texture_ids.size(); i++) {
|
||||
RDD::RenderPassClearValue clear_value;
|
||||
|
||||
Texture *texture = texture_owner.get_or_null(p_framebuffer->texture_ids[i]);
|
||||
RID texture_rid = p_framebuffer->texture_ids[i];
|
||||
Texture *texture = texture_owner.get_or_null(texture_rid);
|
||||
if (!texture) {
|
||||
color_index++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Indicate the texture will get modified for the shared texture fallback.
|
||||
_texture_update_shared_fallback(texture_rid, texture, true);
|
||||
|
||||
if (texture->usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) {
|
||||
if (color_index < p_clear_colors.size()) {
|
||||
ERR_FAIL_INDEX_V(color_index, p_clear_colors.size(), ERR_BUG); // A bug.
|
||||
|
@ -3816,6 +4124,8 @@ void RenderingDevice::draw_list_draw(DrawListID p_list, bool p_use_indices, uint
|
|||
draw_graph.add_draw_list_bind_uniform_set(dl->state.pipeline_shader_driver_id, dl->state.sets[i].uniform_set_driver_id, i);
|
||||
|
||||
UniformSet *uniform_set = uniform_set_owner.get_or_null(dl->state.sets[i].uniform_set);
|
||||
_uniform_set_update_shared(uniform_set);
|
||||
|
||||
draw_graph.add_draw_list_usages(uniform_set->draw_trackers, uniform_set->draw_trackers_usage);
|
||||
|
||||
dl->state.sets[i].bound = true;
|
||||
|
@ -4222,6 +4532,8 @@ void RenderingDevice::compute_list_dispatch(ComputeListID p_list, uint32_t p_x_g
|
|||
draw_graph.add_compute_list_bind_uniform_set(cl->state.pipeline_shader_driver_id, cl->state.sets[i].uniform_set_driver_id, i);
|
||||
|
||||
UniformSet *uniform_set = uniform_set_owner.get_or_null(cl->state.sets[i].uniform_set);
|
||||
_uniform_set_update_shared(uniform_set);
|
||||
|
||||
draw_graph.add_compute_list_usages(uniform_set->draw_trackers, uniform_set->draw_trackers_usage);
|
||||
|
||||
cl->state.sets[i].bound = true;
|
||||
|
@ -4329,6 +4641,8 @@ void RenderingDevice::compute_list_dispatch_indirect(ComputeListID p_list, RID p
|
|||
draw_graph.add_compute_list_bind_uniform_set(cl->state.pipeline_shader_driver_id, cl->state.sets[i].uniform_set_driver_id, i);
|
||||
|
||||
UniformSet *uniform_set = uniform_set_owner.get_or_null(cl->state.sets[i].uniform_set);
|
||||
_uniform_set_update_shared(uniform_set);
|
||||
|
||||
draw_graph.add_compute_list_usages(uniform_set->draw_trackers, uniform_set->draw_trackers_usage);
|
||||
|
||||
cl->state.sets[i].bound = true;
|
||||
|
@ -4420,6 +4734,7 @@ bool RenderingDevice::_texture_make_mutable(Texture *p_texture, RID p_texture_id
|
|||
draw_tracker->parent = owner_texture->draw_tracker;
|
||||
draw_tracker->texture_driver_id = p_texture->driver_id;
|
||||
draw_tracker->texture_subresources = p_texture->barrier_range();
|
||||
draw_tracker->texture_usage = p_texture->usage_flags;
|
||||
draw_tracker->texture_slice_or_dirty_rect = p_texture->slice_rect;
|
||||
owner_texture->slice_trackers[p_texture->slice_rect] = draw_tracker;
|
||||
}
|
||||
|
@ -4441,6 +4756,7 @@ bool RenderingDevice::_texture_make_mutable(Texture *p_texture, RID p_texture_id
|
|||
p_texture->draw_tracker = RDG::resource_tracker_create();
|
||||
p_texture->draw_tracker->texture_driver_id = p_texture->driver_id;
|
||||
p_texture->draw_tracker->texture_subresources = p_texture->barrier_range();
|
||||
p_texture->draw_tracker->texture_usage = p_texture->usage_flags;
|
||||
p_texture->draw_tracker->reference_count = 1;
|
||||
|
||||
if (p_texture_id.is_valid()) {
|
||||
|
@ -4837,6 +5153,8 @@ void RenderingDevice::_free_pending_resources(int p_frame) {
|
|||
WARN_PRINT("Deleted a texture while it was bound.");
|
||||
}
|
||||
|
||||
_texture_free_shared_fallback(texture);
|
||||
|
||||
texture_memory -= driver->texture_get_allocation_size(texture->driver_id);
|
||||
driver->texture_free(texture->driver_id);
|
||||
|
||||
|
|
|
@ -207,6 +207,15 @@ public:
|
|||
// for a framebuffer to render into it.
|
||||
|
||||
struct Texture {
|
||||
struct SharedFallback {
|
||||
uint32_t revision = 1;
|
||||
RDD::TextureID texture;
|
||||
RDG::ResourceTracker *texture_tracker = nullptr;
|
||||
RDD::BufferID buffer;
|
||||
RDG::ResourceTracker *buffer_tracker = nullptr;
|
||||
bool raw_reinterpretation = false;
|
||||
};
|
||||
|
||||
RDD::TextureID driver_id;
|
||||
|
||||
TextureType type = TEXTURE_TYPE_MAX;
|
||||
|
@ -235,6 +244,7 @@ public:
|
|||
|
||||
RDG::ResourceTracker *draw_tracker = nullptr;
|
||||
HashMap<Rect2i, RDG::ResourceTracker *> slice_trackers;
|
||||
SharedFallback *shared_fallback = nullptr;
|
||||
|
||||
RDD::TextureSubresourceRange barrier_range() const {
|
||||
RDD::TextureSubresourceRange r;
|
||||
|
@ -245,6 +255,22 @@ public:
|
|||
r.layer_count = layers;
|
||||
return r;
|
||||
}
|
||||
|
||||
TextureFormat texture_format() const {
|
||||
TextureFormat tf;
|
||||
tf.format = format;
|
||||
tf.width = width;
|
||||
tf.height = height;
|
||||
tf.depth = depth;
|
||||
tf.array_layers = layers;
|
||||
tf.mipmaps = mipmaps;
|
||||
tf.texture_type = type;
|
||||
tf.samples = samples;
|
||||
tf.usage_bits = usage_flags;
|
||||
tf.shareable_formats = allowed_shared_formats;
|
||||
tf.is_resolve_buffer = is_resolve_buffer;
|
||||
return tf;
|
||||
}
|
||||
};
|
||||
|
||||
RID_Owner<Texture> texture_owner;
|
||||
|
@ -252,6 +278,11 @@ public:
|
|||
|
||||
Vector<uint8_t> _texture_get_data(Texture *tex, uint32_t p_layer, bool p_2d = false);
|
||||
Error _texture_update(RID p_texture, uint32_t p_layer, const Vector<uint8_t> &p_data, bool p_use_setup_queue, bool p_validate_can_update);
|
||||
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);
|
||||
|
||||
public:
|
||||
struct TextureView {
|
||||
|
@ -916,16 +947,24 @@ private:
|
|||
RID texture;
|
||||
};
|
||||
|
||||
struct SharedTexture {
|
||||
uint32_t writing = 0;
|
||||
RID texture;
|
||||
};
|
||||
|
||||
LocalVector<AttachableTexture> attachable_textures; // Used for validation.
|
||||
Vector<RDG::ResourceTracker *> draw_trackers;
|
||||
Vector<RDG::ResourceUsage> draw_trackers_usage;
|
||||
HashMap<RID, RDG::ResourceUsage> untracked_usage;
|
||||
LocalVector<SharedTexture> shared_textures_to_update;
|
||||
InvalidationCallback invalidated_callback = nullptr;
|
||||
void *invalidated_callback_userdata = nullptr;
|
||||
};
|
||||
|
||||
RID_Owner<UniformSet> uniform_set_owner;
|
||||
|
||||
void _uniform_set_update_shared(UniformSet *p_uniform_set);
|
||||
|
||||
public:
|
||||
RID uniform_set_create(const Vector<Uniform> &p_uniforms, RID p_shader, uint32_t p_shader_set);
|
||||
bool uniform_set_is_valid(RID p_uniform_set);
|
||||
|
|
|
@ -372,6 +372,8 @@ uint64_t RenderingDeviceDriver::api_trait_get(ApiTrait p_trait) {
|
|||
return 1;
|
||||
case API_TRAIT_SECONDARY_VIEWPORT_SCISSOR:
|
||||
return 1;
|
||||
case API_TRAIT_CLEARS_WITH_COPY_ENGINE:
|
||||
return true;
|
||||
default:
|
||||
ERR_FAIL_V(0);
|
||||
}
|
||||
|
|
|
@ -220,15 +220,17 @@ public:
|
|||
|
||||
enum TextureLayout {
|
||||
TEXTURE_LAYOUT_UNDEFINED,
|
||||
TEXTURE_LAYOUT_GENERAL,
|
||||
TEXTURE_LAYOUT_STORAGE_OPTIMAL,
|
||||
TEXTURE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||
TEXTURE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
|
||||
TEXTURE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL,
|
||||
TEXTURE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||
TEXTURE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||
TEXTURE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
TEXTURE_LAYOUT_PREINITIALIZED,
|
||||
TEXTURE_LAYOUT_VRS_ATTACHMENT_OPTIMAL = 1000164003,
|
||||
TEXTURE_LAYOUT_COPY_SRC_OPTIMAL,
|
||||
TEXTURE_LAYOUT_COPY_DST_OPTIMAL,
|
||||
TEXTURE_LAYOUT_RESOLVE_SRC_OPTIMAL,
|
||||
TEXTURE_LAYOUT_RESOLVE_DST_OPTIMAL,
|
||||
TEXTURE_LAYOUT_VRS_ATTACHMENT_OPTIMAL,
|
||||
TEXTURE_LAYOUT_MAX
|
||||
};
|
||||
|
||||
enum TextureAspect {
|
||||
|
@ -284,6 +286,7 @@ public:
|
|||
virtual uint8_t *texture_map(TextureID p_texture, const TextureSubresource &p_subresource) = 0;
|
||||
virtual void texture_unmap(TextureID p_texture) = 0;
|
||||
virtual BitField<TextureUsageBits> texture_get_usages_supported_by_format(DataFormat p_format, bool p_cpu_readable) = 0;
|
||||
virtual bool texture_can_make_shared_with_format(TextureID p_texture, DataFormat p_format, bool &r_raw_reinterpretation) = 0;
|
||||
|
||||
/*****************/
|
||||
/**** SAMPLER ****/
|
||||
|
@ -317,10 +320,12 @@ public:
|
|||
PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT = (1 << 9),
|
||||
PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT = (1 << 10),
|
||||
PIPELINE_STAGE_COMPUTE_SHADER_BIT = (1 << 11),
|
||||
PIPELINE_STAGE_TRANSFER_BIT = (1 << 12),
|
||||
PIPELINE_STAGE_COPY_BIT = (1 << 12),
|
||||
PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT = (1 << 13),
|
||||
PIPELINE_STAGE_RESOLVE_BIT = (1 << 14),
|
||||
PIPELINE_STAGE_ALL_GRAPHICS_BIT = (1 << 15),
|
||||
PIPELINE_STAGE_ALL_COMMANDS_BIT = (1 << 16),
|
||||
PIPELINE_STAGE_CLEAR_STORAGE_BIT = (1 << 17),
|
||||
};
|
||||
|
||||
enum BarrierAccessBits {
|
||||
|
@ -335,13 +340,16 @@ public:
|
|||
BARRIER_ACCESS_COLOR_ATTACHMENT_WRITE_BIT = (1 << 8),
|
||||
BARRIER_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT = (1 << 9),
|
||||
BARRIER_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT = (1 << 10),
|
||||
BARRIER_ACCESS_TRANSFER_READ_BIT = (1 << 11),
|
||||
BARRIER_ACCESS_TRANSFER_WRITE_BIT = (1 << 12),
|
||||
BARRIER_ACCESS_COPY_READ_BIT = (1 << 11),
|
||||
BARRIER_ACCESS_COPY_WRITE_BIT = (1 << 12),
|
||||
BARRIER_ACCESS_HOST_READ_BIT = (1 << 13),
|
||||
BARRIER_ACCESS_HOST_WRITE_BIT = (1 << 14),
|
||||
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_STORAGE_CLEAR_BIT = (1 << 27),
|
||||
};
|
||||
|
||||
struct MemoryBarrier {
|
||||
|
@ -735,7 +743,9 @@ public:
|
|||
API_TRAIT_TEXTURE_TRANSFER_ALIGNMENT,
|
||||
API_TRAIT_TEXTURE_DATA_ROW_PITCH_STEP,
|
||||
API_TRAIT_SECONDARY_VIEWPORT_SCISSOR,
|
||||
API_TRAIT_CLEARS_WITH_COPY_ENGINE,
|
||||
};
|
||||
|
||||
enum ShaderChangeInvalidation {
|
||||
SHADER_CHANGE_INVALIDATION_ALL_BOUND_UNIFORM_SETS,
|
||||
// What Vulkan does.
|
||||
|
|
|
@ -36,7 +36,8 @@
|
|||
#define PRINT_COMMAND_RECORDING 0
|
||||
|
||||
RenderingDeviceGraph::RenderingDeviceGraph() {
|
||||
// Default initialization.
|
||||
driver_honors_barriers = false;
|
||||
driver_clears_with_copy_engine = false;
|
||||
}
|
||||
|
||||
RenderingDeviceGraph::~RenderingDeviceGraph() {
|
||||
|
@ -44,7 +45,8 @@ RenderingDeviceGraph::~RenderingDeviceGraph() {
|
|||
|
||||
bool RenderingDeviceGraph::_is_write_usage(ResourceUsage p_usage) {
|
||||
switch (p_usage) {
|
||||
case RESOURCE_USAGE_TRANSFER_FROM:
|
||||
case RESOURCE_USAGE_COPY_FROM:
|
||||
case RESOURCE_USAGE_RESOLVE_FROM:
|
||||
case RESOURCE_USAGE_UNIFORM_BUFFER_READ:
|
||||
case RESOURCE_USAGE_INDIRECT_BUFFER_READ:
|
||||
case RESOURCE_USAGE_TEXTURE_BUFFER_READ:
|
||||
|
@ -54,7 +56,8 @@ bool RenderingDeviceGraph::_is_write_usage(ResourceUsage p_usage) {
|
|||
case RESOURCE_USAGE_TEXTURE_SAMPLE:
|
||||
case RESOURCE_USAGE_STORAGE_IMAGE_READ:
|
||||
return false;
|
||||
case RESOURCE_USAGE_TRANSFER_TO:
|
||||
case RESOURCE_USAGE_COPY_TO:
|
||||
case RESOURCE_USAGE_RESOLVE_TO:
|
||||
case RESOURCE_USAGE_TEXTURE_BUFFER_READ_WRITE:
|
||||
case RESOURCE_USAGE_STORAGE_BUFFER_READ_WRITE:
|
||||
case RESOURCE_USAGE_STORAGE_IMAGE_READ_WRITE:
|
||||
|
@ -69,15 +72,19 @@ bool RenderingDeviceGraph::_is_write_usage(ResourceUsage p_usage) {
|
|||
|
||||
RDD::TextureLayout RenderingDeviceGraph::_usage_to_image_layout(ResourceUsage p_usage) {
|
||||
switch (p_usage) {
|
||||
case RESOURCE_USAGE_TRANSFER_FROM:
|
||||
return RDD::TEXTURE_LAYOUT_TRANSFER_SRC_OPTIMAL;
|
||||
case RESOURCE_USAGE_TRANSFER_TO:
|
||||
return RDD::TEXTURE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
||||
case RESOURCE_USAGE_COPY_FROM:
|
||||
return RDD::TEXTURE_LAYOUT_COPY_SRC_OPTIMAL;
|
||||
case RESOURCE_USAGE_COPY_TO:
|
||||
return RDD::TEXTURE_LAYOUT_COPY_DST_OPTIMAL;
|
||||
case RESOURCE_USAGE_RESOLVE_FROM:
|
||||
return RDD::TEXTURE_LAYOUT_RESOLVE_SRC_OPTIMAL;
|
||||
case RESOURCE_USAGE_RESOLVE_TO:
|
||||
return RDD::TEXTURE_LAYOUT_RESOLVE_DST_OPTIMAL;
|
||||
case RESOURCE_USAGE_TEXTURE_SAMPLE:
|
||||
return RDD::TEXTURE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
case RESOURCE_USAGE_STORAGE_IMAGE_READ:
|
||||
case RESOURCE_USAGE_STORAGE_IMAGE_READ_WRITE:
|
||||
return RDD::TEXTURE_LAYOUT_GENERAL;
|
||||
return RDD::TEXTURE_LAYOUT_STORAGE_OPTIMAL;
|
||||
case RESOURCE_USAGE_ATTACHMENT_COLOR_READ_WRITE:
|
||||
return RDD::TEXTURE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
case RESOURCE_USAGE_ATTACHMENT_DEPTH_STENCIL_READ_WRITE:
|
||||
|
@ -97,10 +104,14 @@ RDD::BarrierAccessBits RenderingDeviceGraph::_usage_to_access_bits(ResourceUsage
|
|||
switch (p_usage) {
|
||||
case RESOURCE_USAGE_NONE:
|
||||
return RDD::BarrierAccessBits(0);
|
||||
case RESOURCE_USAGE_TRANSFER_FROM:
|
||||
return RDD::BARRIER_ACCESS_TRANSFER_READ_BIT;
|
||||
case RESOURCE_USAGE_TRANSFER_TO:
|
||||
return RDD::BARRIER_ACCESS_TRANSFER_WRITE_BIT;
|
||||
case RESOURCE_USAGE_COPY_FROM:
|
||||
return RDD::BARRIER_ACCESS_COPY_READ_BIT;
|
||||
case RESOURCE_USAGE_COPY_TO:
|
||||
return RDD::BARRIER_ACCESS_COPY_WRITE_BIT;
|
||||
case RESOURCE_USAGE_RESOLVE_FROM:
|
||||
return RDD::BARRIER_ACCESS_RESOLVE_READ_BIT;
|
||||
case RESOURCE_USAGE_RESOLVE_TO:
|
||||
return RDD::BARRIER_ACCESS_RESOLVE_WRITE_BIT;
|
||||
case RESOURCE_USAGE_UNIFORM_BUFFER_READ:
|
||||
return RDD::BARRIER_ACCESS_UNIFORM_READ_BIT;
|
||||
case RESOURCE_USAGE_INDIRECT_BUFFER_READ:
|
||||
|
@ -818,26 +829,27 @@ void RenderingDeviceGraph::_run_render_commands(int32_t p_level, const RecordedC
|
|||
} break;
|
||||
case RecordedCommand::TYPE_TEXTURE_CLEAR: {
|
||||
const RecordedTextureClearCommand *texture_clear_command = reinterpret_cast<const RecordedTextureClearCommand *>(command);
|
||||
driver->command_clear_color_texture(r_command_buffer, texture_clear_command->texture, RDD::TEXTURE_LAYOUT_TRANSFER_DST_OPTIMAL, texture_clear_command->color, texture_clear_command->range);
|
||||
driver->command_clear_color_texture(r_command_buffer, texture_clear_command->texture, RDD::TEXTURE_LAYOUT_COPY_DST_OPTIMAL, texture_clear_command->color, texture_clear_command->range);
|
||||
} break;
|
||||
case RecordedCommand::TYPE_TEXTURE_COPY: {
|
||||
const RecordedTextureCopyCommand *texture_copy_command = reinterpret_cast<const RecordedTextureCopyCommand *>(command);
|
||||
driver->command_copy_texture(r_command_buffer, texture_copy_command->from_texture, RDD::TEXTURE_LAYOUT_TRANSFER_SRC_OPTIMAL, texture_copy_command->to_texture, RDD::TEXTURE_LAYOUT_TRANSFER_DST_OPTIMAL, texture_copy_command->region);
|
||||
const VectorView<RDD::TextureCopyRegion> command_texture_copy_regions_view(texture_copy_command->texture_copy_regions(), texture_copy_command->texture_copy_regions_count);
|
||||
driver->command_copy_texture(r_command_buffer, texture_copy_command->from_texture, RDD::TEXTURE_LAYOUT_COPY_SRC_OPTIMAL, texture_copy_command->to_texture, RDD::TEXTURE_LAYOUT_COPY_DST_OPTIMAL, command_texture_copy_regions_view);
|
||||
} break;
|
||||
case RecordedCommand::TYPE_TEXTURE_GET_DATA: {
|
||||
const RecordedTextureGetDataCommand *texture_get_data_command = reinterpret_cast<const RecordedTextureGetDataCommand *>(command);
|
||||
const VectorView<RDD::BufferTextureCopyRegion> command_buffer_texture_copy_regions_view(texture_get_data_command->buffer_texture_copy_regions(), texture_get_data_command->buffer_texture_copy_regions_count);
|
||||
driver->command_copy_texture_to_buffer(r_command_buffer, texture_get_data_command->from_texture, RDD::TEXTURE_LAYOUT_TRANSFER_SRC_OPTIMAL, texture_get_data_command->to_buffer, command_buffer_texture_copy_regions_view);
|
||||
driver->command_copy_texture_to_buffer(r_command_buffer, texture_get_data_command->from_texture, RDD::TEXTURE_LAYOUT_COPY_SRC_OPTIMAL, texture_get_data_command->to_buffer, command_buffer_texture_copy_regions_view);
|
||||
} break;
|
||||
case RecordedCommand::TYPE_TEXTURE_RESOLVE: {
|
||||
const RecordedTextureResolveCommand *texture_resolve_command = reinterpret_cast<const RecordedTextureResolveCommand *>(command);
|
||||
driver->command_resolve_texture(r_command_buffer, texture_resolve_command->from_texture, RDD::TEXTURE_LAYOUT_TRANSFER_SRC_OPTIMAL, texture_resolve_command->src_layer, texture_resolve_command->src_mipmap, texture_resolve_command->to_texture, RDD::TEXTURE_LAYOUT_TRANSFER_DST_OPTIMAL, texture_resolve_command->dst_layer, texture_resolve_command->dst_mipmap);
|
||||
driver->command_resolve_texture(r_command_buffer, texture_resolve_command->from_texture, RDD::TEXTURE_LAYOUT_RESOLVE_SRC_OPTIMAL, texture_resolve_command->src_layer, texture_resolve_command->src_mipmap, texture_resolve_command->to_texture, RDD::TEXTURE_LAYOUT_RESOLVE_DST_OPTIMAL, texture_resolve_command->dst_layer, texture_resolve_command->dst_mipmap);
|
||||
} break;
|
||||
case RecordedCommand::TYPE_TEXTURE_UPDATE: {
|
||||
const RecordedTextureUpdateCommand *texture_update_command = reinterpret_cast<const RecordedTextureUpdateCommand *>(command);
|
||||
const RecordedBufferToTextureCopy *command_buffer_to_texture_copies = texture_update_command->buffer_to_texture_copies();
|
||||
for (uint32_t j = 0; j < texture_update_command->buffer_to_texture_copies_count; j++) {
|
||||
driver->command_copy_buffer_to_texture(r_command_buffer, command_buffer_to_texture_copies[j].from_buffer, texture_update_command->to_texture, RDD::TEXTURE_LAYOUT_TRANSFER_DST_OPTIMAL, command_buffer_to_texture_copies[j].region);
|
||||
driver->command_copy_buffer_to_texture(r_command_buffer, command_buffer_to_texture_copies[j].from_buffer, texture_update_command->to_texture, RDD::TEXTURE_LAYOUT_COPY_DST_OPTIMAL, command_buffer_to_texture_copies[j].region);
|
||||
}
|
||||
} break;
|
||||
case RecordedCommand::TYPE_CAPTURE_TIMESTAMP: {
|
||||
|
@ -1271,6 +1283,7 @@ void RenderingDeviceGraph::initialize(RDD *p_driver, RenderingContextDriver::Dev
|
|||
}
|
||||
|
||||
driver_honors_barriers = driver->api_trait_get(RDD::API_TRAIT_HONORS_PIPELINE_BARRIERS);
|
||||
driver_clears_with_copy_engine = driver->api_trait_get(RDD::API_TRAIT_CLEARS_WITH_COPY_ENGINE);
|
||||
}
|
||||
|
||||
void RenderingDeviceGraph::finalize() {
|
||||
|
@ -1321,12 +1334,12 @@ void RenderingDeviceGraph::add_buffer_clear(RDD::BufferID p_dst, ResourceTracker
|
|||
int32_t command_index;
|
||||
RecordedBufferClearCommand *command = static_cast<RecordedBufferClearCommand *>(_allocate_command(sizeof(RecordedBufferClearCommand), command_index));
|
||||
command->type = RecordedCommand::TYPE_BUFFER_CLEAR;
|
||||
command->self_stages = RDD::PIPELINE_STAGE_TRANSFER_BIT;
|
||||
command->self_stages = RDD::PIPELINE_STAGE_COPY_BIT;
|
||||
command->buffer = p_dst;
|
||||
command->offset = p_offset;
|
||||
command->size = p_size;
|
||||
|
||||
ResourceUsage usage = RESOURCE_USAGE_TRANSFER_TO;
|
||||
ResourceUsage usage = RESOURCE_USAGE_COPY_TO;
|
||||
_add_command_to_graph(&p_dst_tracker, &usage, 1, command_index, command);
|
||||
}
|
||||
|
||||
|
@ -1337,13 +1350,13 @@ void RenderingDeviceGraph::add_buffer_copy(RDD::BufferID p_src, ResourceTracker
|
|||
int32_t command_index;
|
||||
RecordedBufferCopyCommand *command = static_cast<RecordedBufferCopyCommand *>(_allocate_command(sizeof(RecordedBufferCopyCommand), command_index));
|
||||
command->type = RecordedCommand::TYPE_BUFFER_COPY;
|
||||
command->self_stages = RDD::PIPELINE_STAGE_TRANSFER_BIT;
|
||||
command->self_stages = RDD::PIPELINE_STAGE_COPY_BIT;
|
||||
command->source = p_src;
|
||||
command->destination = p_dst;
|
||||
command->region = p_region;
|
||||
|
||||
ResourceTracker *trackers[2] = { p_dst_tracker, p_src_tracker };
|
||||
ResourceUsage usages[2] = { RESOURCE_USAGE_TRANSFER_TO, RESOURCE_USAGE_TRANSFER_FROM };
|
||||
ResourceUsage usages[2] = { RESOURCE_USAGE_COPY_TO, RESOURCE_USAGE_COPY_FROM };
|
||||
_add_command_to_graph(trackers, usages, p_src_tracker != nullptr ? 2 : 1, command_index, command);
|
||||
}
|
||||
|
||||
|
@ -1352,13 +1365,13 @@ void RenderingDeviceGraph::add_buffer_get_data(RDD::BufferID p_src, ResourceTrac
|
|||
int32_t command_index;
|
||||
RecordedBufferGetDataCommand *command = static_cast<RecordedBufferGetDataCommand *>(_allocate_command(sizeof(RecordedBufferGetDataCommand), command_index));
|
||||
command->type = RecordedCommand::TYPE_BUFFER_GET_DATA;
|
||||
command->self_stages = RDD::PIPELINE_STAGE_TRANSFER_BIT;
|
||||
command->self_stages = RDD::PIPELINE_STAGE_COPY_BIT;
|
||||
command->source = p_src;
|
||||
command->destination = p_dst;
|
||||
command->region = p_region;
|
||||
|
||||
if (p_src_tracker != nullptr) {
|
||||
ResourceUsage usage = RESOURCE_USAGE_TRANSFER_FROM;
|
||||
ResourceUsage usage = RESOURCE_USAGE_COPY_FROM;
|
||||
_add_command_to_graph(&p_src_tracker, &usage, 1, command_index, command);
|
||||
} else {
|
||||
_add_command_to_graph(nullptr, nullptr, 0, command_index, command);
|
||||
|
@ -1373,7 +1386,7 @@ void RenderingDeviceGraph::add_buffer_update(RDD::BufferID p_dst, ResourceTracke
|
|||
int32_t command_index;
|
||||
RecordedBufferUpdateCommand *command = static_cast<RecordedBufferUpdateCommand *>(_allocate_command(command_size, command_index));
|
||||
command->type = RecordedCommand::TYPE_BUFFER_UPDATE;
|
||||
command->self_stages = RDD::PIPELINE_STAGE_TRANSFER_BIT;
|
||||
command->self_stages = RDD::PIPELINE_STAGE_COPY_BIT;
|
||||
command->destination = p_dst;
|
||||
command->buffer_copies_count = p_buffer_copies.size();
|
||||
|
||||
|
@ -1382,7 +1395,7 @@ void RenderingDeviceGraph::add_buffer_update(RDD::BufferID p_dst, ResourceTracke
|
|||
buffer_copies[i] = p_buffer_copies[i];
|
||||
}
|
||||
|
||||
ResourceUsage buffer_usage = RESOURCE_USAGE_TRANSFER_TO;
|
||||
ResourceUsage buffer_usage = RESOURCE_USAGE_COPY_TO;
|
||||
_add_command_to_graph(&p_dst_tracker, &buffer_usage, 1, command_index, command);
|
||||
}
|
||||
|
||||
|
@ -1710,40 +1723,60 @@ void RenderingDeviceGraph::add_texture_clear(RDD::TextureID p_dst, ResourceTrack
|
|||
int32_t command_index;
|
||||
RecordedTextureClearCommand *command = static_cast<RecordedTextureClearCommand *>(_allocate_command(sizeof(RecordedTextureClearCommand), command_index));
|
||||
command->type = RecordedCommand::TYPE_TEXTURE_CLEAR;
|
||||
command->self_stages = RDD::PIPELINE_STAGE_TRANSFER_BIT;
|
||||
command->texture = p_dst;
|
||||
command->color = p_color;
|
||||
command->range = p_range;
|
||||
|
||||
ResourceUsage usage = RESOURCE_USAGE_TRANSFER_TO;
|
||||
ResourceUsage usage;
|
||||
if (driver_clears_with_copy_engine) {
|
||||
command->self_stages = RDD::PIPELINE_STAGE_COPY_BIT;
|
||||
usage = RESOURCE_USAGE_COPY_TO;
|
||||
} else {
|
||||
// If the driver is uncapable of using the copy engine for clearing the image (e.g. D3D12), we must either transition the
|
||||
// resource to a render target or a storage image as that's the only two ways it can perform the operation.
|
||||
if (p_dst_tracker->texture_usage & RDD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) {
|
||||
command->self_stages = RDD::PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||
usage = RESOURCE_USAGE_ATTACHMENT_COLOR_READ_WRITE;
|
||||
} else {
|
||||
command->self_stages = RDD::PIPELINE_STAGE_CLEAR_STORAGE_BIT;
|
||||
usage = RESOURCE_USAGE_STORAGE_IMAGE_READ_WRITE;
|
||||
}
|
||||
}
|
||||
|
||||
_add_command_to_graph(&p_dst_tracker, &usage, 1, command_index, command);
|
||||
}
|
||||
|
||||
void RenderingDeviceGraph::add_texture_copy(RDD::TextureID p_src, ResourceTracker *p_src_tracker, RDD::TextureID p_dst, ResourceTracker *p_dst_tracker, RDD::TextureCopyRegion p_region) {
|
||||
void RenderingDeviceGraph::add_texture_copy(RDD::TextureID p_src, ResourceTracker *p_src_tracker, RDD::TextureID p_dst, ResourceTracker *p_dst_tracker, VectorView<RDD::TextureCopyRegion> p_texture_copy_regions) {
|
||||
DEV_ASSERT(p_src_tracker != nullptr);
|
||||
DEV_ASSERT(p_dst_tracker != nullptr);
|
||||
|
||||
int32_t command_index;
|
||||
RecordedTextureCopyCommand *command = static_cast<RecordedTextureCopyCommand *>(_allocate_command(sizeof(RecordedTextureCopyCommand), command_index));
|
||||
uint64_t command_size = sizeof(RecordedTextureCopyCommand) + p_texture_copy_regions.size() * sizeof(RDD::TextureCopyRegion);
|
||||
RecordedTextureCopyCommand *command = static_cast<RecordedTextureCopyCommand *>(_allocate_command(command_size, command_index));
|
||||
command->type = RecordedCommand::TYPE_TEXTURE_COPY;
|
||||
command->self_stages = RDD::PIPELINE_STAGE_TRANSFER_BIT;
|
||||
command->self_stages = RDD::PIPELINE_STAGE_COPY_BIT;
|
||||
command->from_texture = p_src;
|
||||
command->to_texture = p_dst;
|
||||
command->region = p_region;
|
||||
command->texture_copy_regions_count = p_texture_copy_regions.size();
|
||||
|
||||
RDD::TextureCopyRegion *texture_copy_regions = command->texture_copy_regions();
|
||||
for (uint32_t i = 0; i < command->texture_copy_regions_count; i++) {
|
||||
texture_copy_regions[i] = p_texture_copy_regions[i];
|
||||
}
|
||||
|
||||
ResourceTracker *trackers[2] = { p_dst_tracker, p_src_tracker };
|
||||
ResourceUsage usages[2] = { RESOURCE_USAGE_TRANSFER_TO, RESOURCE_USAGE_TRANSFER_FROM };
|
||||
ResourceUsage usages[2] = { RESOURCE_USAGE_COPY_TO, RESOURCE_USAGE_COPY_FROM };
|
||||
_add_command_to_graph(trackers, usages, 2, command_index, command);
|
||||
}
|
||||
|
||||
void RenderingDeviceGraph::add_texture_get_data(RDD::TextureID p_src, ResourceTracker *p_src_tracker, RDD::BufferID p_dst, VectorView<RDD::BufferTextureCopyRegion> p_buffer_texture_copy_regions) {
|
||||
void RenderingDeviceGraph::add_texture_get_data(RDD::TextureID p_src, ResourceTracker *p_src_tracker, RDD::BufferID p_dst, VectorView<RDD::BufferTextureCopyRegion> p_buffer_texture_copy_regions, ResourceTracker *p_dst_tracker) {
|
||||
DEV_ASSERT(p_src_tracker != nullptr);
|
||||
|
||||
int32_t command_index;
|
||||
uint64_t command_size = sizeof(RecordedTextureGetDataCommand) + p_buffer_texture_copy_regions.size() * sizeof(RDD::BufferTextureCopyRegion);
|
||||
RecordedTextureGetDataCommand *command = static_cast<RecordedTextureGetDataCommand *>(_allocate_command(command_size, command_index));
|
||||
command->type = RecordedCommand::TYPE_TEXTURE_GET_DATA;
|
||||
command->self_stages = RDD::PIPELINE_STAGE_TRANSFER_BIT;
|
||||
command->self_stages = RDD::PIPELINE_STAGE_COPY_BIT;
|
||||
command->from_texture = p_src;
|
||||
command->to_buffer = p_dst;
|
||||
command->buffer_texture_copy_regions_count = p_buffer_texture_copy_regions.size();
|
||||
|
@ -1753,8 +1786,15 @@ void RenderingDeviceGraph::add_texture_get_data(RDD::TextureID p_src, ResourceTr
|
|||
buffer_texture_copy_regions[i] = p_buffer_texture_copy_regions[i];
|
||||
}
|
||||
|
||||
ResourceUsage usage = RESOURCE_USAGE_TRANSFER_FROM;
|
||||
_add_command_to_graph(&p_src_tracker, &usage, 1, command_index, command);
|
||||
if (p_dst_tracker != nullptr) {
|
||||
// Add the optional destination tracker if it was provided.
|
||||
ResourceTracker *trackers[2] = { p_dst_tracker, p_src_tracker };
|
||||
ResourceUsage usages[2] = { RESOURCE_USAGE_COPY_TO, RESOURCE_USAGE_COPY_FROM };
|
||||
_add_command_to_graph(trackers, usages, 2, command_index, command);
|
||||
} else {
|
||||
ResourceUsage usage = RESOURCE_USAGE_COPY_FROM;
|
||||
_add_command_to_graph(&p_src_tracker, &usage, 1, command_index, command);
|
||||
}
|
||||
}
|
||||
|
||||
void RenderingDeviceGraph::add_texture_resolve(RDD::TextureID p_src, ResourceTracker *p_src_tracker, RDD::TextureID p_dst, ResourceTracker *p_dst_tracker, uint32_t p_src_layer, uint32_t p_src_mipmap, uint32_t p_dst_layer, uint32_t p_dst_mipmap) {
|
||||
|
@ -1764,7 +1804,7 @@ void RenderingDeviceGraph::add_texture_resolve(RDD::TextureID p_src, ResourceTra
|
|||
int32_t command_index;
|
||||
RecordedTextureResolveCommand *command = static_cast<RecordedTextureResolveCommand *>(_allocate_command(sizeof(RecordedTextureResolveCommand), command_index));
|
||||
command->type = RecordedCommand::TYPE_TEXTURE_RESOLVE;
|
||||
command->self_stages = RDD::PIPELINE_STAGE_TRANSFER_BIT;
|
||||
command->self_stages = RDD::PIPELINE_STAGE_RESOLVE_BIT;
|
||||
command->from_texture = p_src;
|
||||
command->to_texture = p_dst;
|
||||
command->src_layer = p_src_layer;
|
||||
|
@ -1773,18 +1813,18 @@ void RenderingDeviceGraph::add_texture_resolve(RDD::TextureID p_src, ResourceTra
|
|||
command->dst_mipmap = p_dst_mipmap;
|
||||
|
||||
ResourceTracker *trackers[2] = { p_dst_tracker, p_src_tracker };
|
||||
ResourceUsage usages[2] = { RESOURCE_USAGE_TRANSFER_TO, RESOURCE_USAGE_TRANSFER_FROM };
|
||||
ResourceUsage usages[2] = { RESOURCE_USAGE_RESOLVE_TO, RESOURCE_USAGE_RESOLVE_FROM };
|
||||
_add_command_to_graph(trackers, usages, 2, command_index, command);
|
||||
}
|
||||
|
||||
void RenderingDeviceGraph::add_texture_update(RDD::TextureID p_dst, ResourceTracker *p_dst_tracker, VectorView<RecordedBufferToTextureCopy> p_buffer_copies) {
|
||||
void RenderingDeviceGraph::add_texture_update(RDD::TextureID p_dst, ResourceTracker *p_dst_tracker, VectorView<RecordedBufferToTextureCopy> p_buffer_copies, VectorView<ResourceTracker *> p_buffer_trackers) {
|
||||
DEV_ASSERT(p_dst_tracker != nullptr);
|
||||
|
||||
int32_t command_index;
|
||||
uint64_t command_size = sizeof(RecordedTextureUpdateCommand) + p_buffer_copies.size() * sizeof(RecordedBufferToTextureCopy);
|
||||
RecordedTextureUpdateCommand *command = static_cast<RecordedTextureUpdateCommand *>(_allocate_command(command_size, command_index));
|
||||
command->type = RecordedCommand::TYPE_TEXTURE_UPDATE;
|
||||
command->self_stages = RDD::PIPELINE_STAGE_TRANSFER_BIT;
|
||||
command->self_stages = RDD::PIPELINE_STAGE_COPY_BIT;
|
||||
command->to_texture = p_dst;
|
||||
command->buffer_to_texture_copies_count = p_buffer_copies.size();
|
||||
|
||||
|
@ -1793,8 +1833,25 @@ void RenderingDeviceGraph::add_texture_update(RDD::TextureID p_dst, ResourceTrac
|
|||
buffer_to_texture_copies[i] = p_buffer_copies[i];
|
||||
}
|
||||
|
||||
ResourceUsage usage = RESOURCE_USAGE_TRANSFER_TO;
|
||||
_add_command_to_graph(&p_dst_tracker, &usage, 1, command_index, command);
|
||||
if (p_buffer_trackers.size() > 0) {
|
||||
// Add the optional buffer trackers if they were provided.
|
||||
thread_local LocalVector<ResourceTracker *> trackers;
|
||||
thread_local LocalVector<ResourceUsage> usages;
|
||||
trackers.clear();
|
||||
usages.clear();
|
||||
for (uint32_t i = 0; i < p_buffer_trackers.size(); i++) {
|
||||
trackers.push_back(p_buffer_trackers[i]);
|
||||
usages.push_back(RESOURCE_USAGE_COPY_FROM);
|
||||
}
|
||||
|
||||
trackers.push_back(p_dst_tracker);
|
||||
usages.push_back(RESOURCE_USAGE_COPY_TO);
|
||||
|
||||
_add_command_to_graph(trackers.ptr(), usages.ptr(), trackers.size(), command_index, command);
|
||||
} else {
|
||||
ResourceUsage usage = RESOURCE_USAGE_COPY_TO;
|
||||
_add_command_to_graph(&p_dst_tracker, &usage, 1, command_index, command);
|
||||
}
|
||||
}
|
||||
|
||||
void RenderingDeviceGraph::add_capture_timestamp(RDD::QueryPoolID p_query_pool, uint32_t p_index) {
|
||||
|
|
|
@ -129,8 +129,10 @@ public:
|
|||
|
||||
enum ResourceUsage {
|
||||
RESOURCE_USAGE_NONE,
|
||||
RESOURCE_USAGE_TRANSFER_FROM,
|
||||
RESOURCE_USAGE_TRANSFER_TO,
|
||||
RESOURCE_USAGE_COPY_FROM,
|
||||
RESOURCE_USAGE_COPY_TO,
|
||||
RESOURCE_USAGE_RESOLVE_FROM,
|
||||
RESOURCE_USAGE_RESOLVE_TO,
|
||||
RESOURCE_USAGE_UNIFORM_BUFFER_READ,
|
||||
RESOURCE_USAGE_INDIRECT_BUFFER_READ,
|
||||
RESOURCE_USAGE_TEXTURE_BUFFER_READ,
|
||||
|
@ -161,6 +163,7 @@ public:
|
|||
RDD::BufferID buffer_driver_id;
|
||||
RDD::TextureID texture_driver_id;
|
||||
RDD::TextureSubresourceRange texture_subresources;
|
||||
uint32_t texture_usage = 0;
|
||||
int32_t texture_slice_command_index = -1;
|
||||
ResourceTracker *parent = nullptr;
|
||||
ResourceTracker *dirty_shared_list = nullptr;
|
||||
|
@ -337,7 +340,15 @@ private:
|
|||
struct RecordedTextureCopyCommand : RecordedCommand {
|
||||
RDD::TextureID from_texture;
|
||||
RDD::TextureID to_texture;
|
||||
RDD::TextureCopyRegion region;
|
||||
uint32_t texture_copy_regions_count = 0;
|
||||
|
||||
_FORCE_INLINE_ RDD::TextureCopyRegion *texture_copy_regions() {
|
||||
return reinterpret_cast<RDD::TextureCopyRegion *>(&this[1]);
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ const RDD::TextureCopyRegion *texture_copy_regions() const {
|
||||
return reinterpret_cast<const RDD::TextureCopyRegion *>(&this[1]);
|
||||
}
|
||||
};
|
||||
|
||||
struct RecordedTextureGetDataCommand : RecordedCommand {
|
||||
|
@ -596,7 +607,8 @@ private:
|
|||
int32_t command_synchronization_index = -1;
|
||||
bool command_synchronization_pending = false;
|
||||
BarrierGroup barrier_group;
|
||||
bool driver_honors_barriers = false;
|
||||
bool driver_honors_barriers : 1;
|
||||
bool driver_clears_with_copy_engine : 1;
|
||||
WorkaroundsState workarounds_state;
|
||||
TightLocalVector<Frame> frames;
|
||||
uint32_t frame = 0;
|
||||
|
@ -672,10 +684,10 @@ public:
|
|||
void add_draw_list_usages(VectorView<ResourceTracker *> p_trackers, VectorView<ResourceUsage> p_usages);
|
||||
void add_draw_list_end();
|
||||
void add_texture_clear(RDD::TextureID p_dst, ResourceTracker *p_dst_tracker, const Color &p_color, const RDD::TextureSubresourceRange &p_range);
|
||||
void add_texture_copy(RDD::TextureID p_src, ResourceTracker *p_src_tracker, RDD::TextureID p_dst, ResourceTracker *p_dst_tracker, RDD::TextureCopyRegion p_region);
|
||||
void add_texture_get_data(RDD::TextureID p_src, ResourceTracker *p_src_tracker, RDD::BufferID p_dst, VectorView<RDD::BufferTextureCopyRegion> p_buffer_texture_copy_regions);
|
||||
void add_texture_copy(RDD::TextureID p_src, ResourceTracker *p_src_tracker, RDD::TextureID p_dst, ResourceTracker *p_dst_tracker, VectorView<RDD::TextureCopyRegion> p_texture_copy_regions);
|
||||
void add_texture_get_data(RDD::TextureID p_src, ResourceTracker *p_src_tracker, RDD::BufferID p_dst, VectorView<RDD::BufferTextureCopyRegion> p_buffer_texture_copy_regions, ResourceTracker *p_dst_tracker = nullptr);
|
||||
void add_texture_resolve(RDD::TextureID p_src, ResourceTracker *p_src_tracker, RDD::TextureID p_dst, ResourceTracker *p_dst_tracker, uint32_t p_src_layer, uint32_t p_src_mipmap, uint32_t p_dst_layer, uint32_t p_dst_mipmap);
|
||||
void add_texture_update(RDD::TextureID p_dst, ResourceTracker *p_dst_tracker, VectorView<RecordedBufferToTextureCopy> p_buffer_copies);
|
||||
void add_texture_update(RDD::TextureID p_dst, ResourceTracker *p_dst_tracker, VectorView<RecordedBufferToTextureCopy> p_buffer_copies, VectorView<ResourceTracker *> p_buffer_trackers = VectorView<ResourceTracker *>());
|
||||
void add_capture_timestamp(RDD::QueryPoolID p_query_pool, uint32_t p_index);
|
||||
void add_synchronization();
|
||||
void begin_label(const String &p_label_name, const Color &p_color);
|
||||
|
|
Loading…
Reference in New Issue