Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions include/reshade_api_format.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -549,6 +549,40 @@ namespace reshade { namespace api
return 0;
}

/// <summary>
/// Returns whether <paramref name="value"/> is a block compressed (BC) format.
/// </summary>
inline bool format_is_block_compressed(format value)
{
switch (value)
{
case format::bc1_typeless:
case format::bc1_unorm:
case format::bc1_unorm_srgb:
case format::bc2_typeless:
case format::bc2_unorm:
case format::bc2_unorm_srgb:
case format::bc3_typeless:
case format::bc3_unorm:
case format::bc3_unorm_srgb:
case format::bc4_typeless:
case format::bc4_unorm:
case format::bc4_snorm:
case format::bc5_typeless:
case format::bc5_unorm:
case format::bc5_snorm:
case format::bc6h_typeless:
case format::bc6h_ufloat:
case format::bc6h_sfloat:
case format::bc7_typeless:
case format::bc7_unorm:
case format::bc7_unorm_srgb:
return true;
default:
return false;
}
}

/// <summary>
/// Gets the number of bytes a texture slice of the specified format <paramref name="value"/> occupies.
/// </summary>
Expand Down
43 changes: 35 additions & 8 deletions source/vulkan/vulkan_hooks_command_list.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -666,25 +666,34 @@ void VKAPI_CALL vkCmdCopyImage(VkCommandBuffer commandBuffer, VkImage srcImage,
{
reshade::vulkan::command_list_impl *const cmd_impl = device_impl->get_private_data_for_object<VK_OBJECT_TYPE_COMMAND_BUFFER>(commandBuffer);

const auto src_data = device_impl->get_private_data_for_object<VK_OBJECT_TYPE_IMAGE>(srcImage);
const auto dst_data = device_impl->get_private_data_for_object<VK_OBJECT_TYPE_IMAGE>(dstImage);

const bool src_is_3d = src_data != nullptr && src_data->create_info.imageType == VK_IMAGE_TYPE_3D;
const bool dst_is_3d = dst_data != nullptr && dst_data->create_info.imageType == VK_IMAGE_TYPE_3D;


for (uint32_t i = 0; i < regionCount; ++i)
{
const VkImageCopy &region = pRegions[i];
const uint32_t src_depth = src_is_3d ? region.extent.depth : region.srcSubresource.layerCount;
const uint32_t dst_depth = dst_is_3d ? region.extent.depth : region.dstSubresource.layerCount;

const reshade::api::subresource_box src_box = {
static_cast<uint32_t>(region.srcOffset.x),
static_cast<uint32_t>(region.srcOffset.y),
static_cast<uint32_t>(region.srcOffset.z),
static_cast<uint32_t>(region.srcOffset.x + region.extent.width),
static_cast<uint32_t>(region.srcOffset.y + region.extent.height),
static_cast<uint32_t>(region.srcOffset.z + region.extent.depth) + region.srcSubresource.layerCount
static_cast<uint32_t>(region.srcOffset.z) + src_depth
};
const reshade::api::subresource_box dst_box = {
static_cast<uint32_t>(region.dstOffset.x),
static_cast<uint32_t>(region.dstOffset.y),
static_cast<uint32_t>(region.dstOffset.z),
static_cast<uint32_t>(region.dstOffset.x + region.extent.width),
static_cast<uint32_t>(region.dstOffset.y + region.extent.height),
static_cast<uint32_t>(region.dstOffset.z + region.extent.depth) + region.dstSubresource.layerCount
static_cast<uint32_t>(region.dstOffset.z) + dst_depth
};

if (reshade::invoke_addon_event<reshade::addon_event::copy_texture_region>(
Expand All @@ -711,26 +720,32 @@ void VKAPI_CALL vkCmdBlitImage(VkCommandBuffer commandBuffer, VkImage srcImage,
if (reshade::has_addon_event<reshade::addon_event::copy_texture_region>())
{
reshade::vulkan::command_list_impl *const cmd_impl = device_impl->get_private_data_for_object<VK_OBJECT_TYPE_COMMAND_BUFFER>(commandBuffer);
const auto src_data = device_impl->get_private_data_for_object<VK_OBJECT_TYPE_IMAGE>(srcImage);
const auto dst_data = device_impl->get_private_data_for_object<VK_OBJECT_TYPE_IMAGE>(dstImage);
const bool src_is_3d = src_data != nullptr && src_data->create_info.imageType == VK_IMAGE_TYPE_3D;
const bool dst_is_3d = dst_data != nullptr && dst_data->create_info.imageType == VK_IMAGE_TYPE_3D;

for (uint32_t i = 0; i < regionCount; ++i)
{
const VkImageBlit &region = pRegions[i];
const uint32_t src_depth = src_is_3d ? static_cast<uint32_t>(region.srcOffsets[1].z - region.srcOffsets[0].z) : region.srcSubresource.layerCount;
const uint32_t dst_depth = dst_is_3d ? static_cast<uint32_t>(region.dstOffsets[1].z - region.dstOffsets[0].z) : region.dstSubresource.layerCount;

const reshade::api::subresource_box src_box = {
static_cast<uint32_t>(region.srcOffsets[0].x),
static_cast<uint32_t>(region.srcOffsets[0].y),
static_cast<uint32_t>(region.srcOffsets[0].z),
static_cast<uint32_t>(region.srcOffsets[1].x),
static_cast<uint32_t>(region.srcOffsets[1].y),
static_cast<uint32_t>(region.srcOffsets[1].z) + region.srcSubresource.layerCount,
static_cast<uint32_t>(region.srcOffsets[0].z) + src_depth,
};
const reshade::api::subresource_box dst_box = {
static_cast<uint32_t>(region.dstOffsets[0].x),
static_cast<uint32_t>(region.dstOffsets[0].y),
static_cast<uint32_t>(region.dstOffsets[0].z),
static_cast<uint32_t>(region.dstOffsets[1].x),
static_cast<uint32_t>(region.dstOffsets[1].y),
static_cast<uint32_t>(region.dstOffsets[1].z) + region.dstSubresource.layerCount,
static_cast<uint32_t>(region.dstOffsets[0].z) + dst_depth,
};

if (reshade::invoke_addon_event<reshade::addon_event::copy_texture_region>(
Expand Down Expand Up @@ -1495,26 +1510,32 @@ void VKAPI_CALL vkCmdCopyImage2(VkCommandBuffer commandBuffer, const VkCopyImage
if (reshade::has_addon_event<reshade::addon_event::copy_texture_region>())
{
reshade::vulkan::command_list_impl *const cmd_impl = device_impl->get_private_data_for_object<VK_OBJECT_TYPE_COMMAND_BUFFER>(commandBuffer);
const auto src_data = device_impl->get_private_data_for_object<VK_OBJECT_TYPE_IMAGE>(pCopyImageInfo->srcImage);
const auto dst_data = device_impl->get_private_data_for_object<VK_OBJECT_TYPE_IMAGE>(pCopyImageInfo->dstImage);
const bool src_is_3d = src_data != nullptr && src_data->create_info.imageType == VK_IMAGE_TYPE_3D;
const bool dst_is_3d = dst_data != nullptr && dst_data->create_info.imageType == VK_IMAGE_TYPE_3D;

for (uint32_t i = 0; i < pCopyImageInfo->regionCount; ++i)
{
const VkImageCopy2 &region = pCopyImageInfo->pRegions[i];
const uint32_t src_depth = src_is_3d ? region.extent.depth : region.srcSubresource.layerCount;
const uint32_t dst_depth = dst_is_3d ? region.extent.depth : region.dstSubresource.layerCount;

const reshade::api::subresource_box src_box = {
static_cast<uint32_t>(region.srcOffset.x),
static_cast<uint32_t>(region.srcOffset.y),
static_cast<uint32_t>(region.srcOffset.z),
static_cast<uint32_t>(region.srcOffset.x + region.extent.width),
static_cast<uint32_t>(region.srcOffset.y + region.extent.height),
static_cast<uint32_t>(region.srcOffset.z + region.extent.depth) + region.srcSubresource.layerCount
static_cast<uint32_t>(region.srcOffset.z) + src_depth
};
const reshade::api::subresource_box dst_box = {
static_cast<uint32_t>(region.dstOffset.x),
static_cast<uint32_t>(region.dstOffset.y),
static_cast<uint32_t>(region.dstOffset.z),
static_cast<uint32_t>(region.dstOffset.x + region.extent.width),
static_cast<uint32_t>(region.dstOffset.y + region.extent.height),
static_cast<uint32_t>(region.dstOffset.z + region.extent.depth) + region.dstSubresource.layerCount
static_cast<uint32_t>(region.dstOffset.z) + dst_depth
};

if (reshade::invoke_addon_event<reshade::addon_event::copy_texture_region>(
Expand Down Expand Up @@ -1625,26 +1646,32 @@ void VKAPI_CALL vkCmdBlitImage2(VkCommandBuffer commandBuffer, const VkBlitImage
if (reshade::has_addon_event<reshade::addon_event::copy_texture_region>())
{
reshade::vulkan::command_list_impl *const cmd_impl = device_impl->get_private_data_for_object<VK_OBJECT_TYPE_COMMAND_BUFFER>(commandBuffer);
const auto src_data = device_impl->get_private_data_for_object<VK_OBJECT_TYPE_IMAGE>(pBlitImageInfo->srcImage);
const auto dst_data = device_impl->get_private_data_for_object<VK_OBJECT_TYPE_IMAGE>(pBlitImageInfo->dstImage);
const bool src_is_3d = src_data != nullptr && src_data->create_info.imageType == VK_IMAGE_TYPE_3D;
const bool dst_is_3d = dst_data != nullptr && dst_data->create_info.imageType == VK_IMAGE_TYPE_3D;

for (uint32_t i = 0; i < pBlitImageInfo->regionCount; ++i)
{
const VkImageBlit2 &region = pBlitImageInfo->pRegions[i];
const uint32_t src_depth = src_is_3d ? static_cast<uint32_t>(region.srcOffsets[1].z - region.srcOffsets[0].z) : region.srcSubresource.layerCount;
const uint32_t dst_depth = dst_is_3d ? static_cast<uint32_t>(region.dstOffsets[1].z - region.dstOffsets[0].z) : region.dstSubresource.layerCount;

const reshade::api::subresource_box src_box = {
static_cast<uint32_t>(region.srcOffsets[0].x),
static_cast<uint32_t>(region.srcOffsets[0].y),
static_cast<uint32_t>(region.srcOffsets[0].z),
static_cast<uint32_t>(region.srcOffsets[1].x),
static_cast<uint32_t>(region.srcOffsets[1].y),
static_cast<uint32_t>(region.srcOffsets[1].z) + region.srcSubresource.layerCount
static_cast<uint32_t>(region.srcOffsets[0].z) + src_depth
};
const reshade::api::subresource_box dst_box = {
static_cast<uint32_t>(region.dstOffsets[0].x),
static_cast<uint32_t>(region.dstOffsets[0].y),
static_cast<uint32_t>(region.dstOffsets[0].z),
static_cast<uint32_t>(region.dstOffsets[1].x),
static_cast<uint32_t>(region.dstOffsets[1].y),
static_cast<uint32_t>(region.dstOffsets[1].z) + region.dstSubresource.layerCount
static_cast<uint32_t>(region.dstOffsets[0].z) + dst_depth
};

if (reshade::invoke_addon_event<reshade::addon_event::copy_texture_region>(
Expand Down
16 changes: 14 additions & 2 deletions source/vulkan/vulkan_impl_command_list.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -843,8 +843,20 @@ void reshade::vulkan::command_list_impl::copy_texture_region(api::resource src,
const auto src_data = _device_impl->get_private_data_for_object<VK_OBJECT_TYPE_IMAGE>((VkImage)src.handle);
const auto dst_data = _device_impl->get_private_data_for_object<VK_OBJECT_TYPE_IMAGE>((VkImage)dst.handle);

if ((src_box == nullptr && dst_box == nullptr && std::memcmp(&src_data->create_info.extent, &dst_data->create_info.extent, sizeof(VkExtent3D)) == 0) ||
(src_box != nullptr && dst_box != nullptr && src_box->width() == dst_box->width() && src_box->height() == dst_box->height() && src_box->depth() == dst_box->depth()))
const auto src_format = convert_format(src_data->create_info.format);
const auto dst_format = convert_format(dst_data->create_info.format);
const bool size_compatible =
(src_format != api::format::unknown && dst_format != api::format::unknown) &&
(api::format_is_block_compressed(src_format) != api::format_is_block_compressed(dst_format)) &&
(api::format_row_pitch(api::format_is_block_compressed(src_format) ? dst_format : src_format, 1) ==
api::format_row_pitch(api::format_is_block_compressed(src_format) ? src_format : dst_format, 1));
const bool format_compatible =
(src_data->create_info.format == dst_data->create_info.format) || size_compatible;
const bool copy_region_compatible =
(src_box == nullptr && dst_box == nullptr && std::memcmp(&src_data->create_info.extent, &dst_data->create_info.extent, sizeof(VkExtent3D)) == 0) ||
(src_box != nullptr && dst_box != nullptr && src_box->width() == dst_box->width() && src_box->height() == dst_box->height() && src_box->depth() == dst_box->depth());

if (format_compatible && copy_region_compatible)
{
VkImageCopy region;

Expand Down
14 changes: 13 additions & 1 deletion source/vulkan/vulkan_impl_device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2007,7 +2007,7 @@ bool reshade::vulkan::device_impl::create_pipeline_layout(uint32_t param_count,
if (range->count == 0)
continue;

const uint32_t max_binding = range->binding + (range->count - range->array_size);
const uint32_t max_binding = (range->count == UINT32_MAX) ? range->binding : range->binding + (range->count - range->array_size);
if (max_binding >= data.binding_to_offset.size())
data.binding_to_offset.resize(max_binding + 1);
data.binding_to_offset[range->binding] = offset;
Expand Down Expand Up @@ -2212,10 +2212,22 @@ void reshade::vulkan::device_impl::get_descriptor_heap_offset(api::descriptor_ta
assert(heap != nullptr && offset != nullptr);

const auto set_data = get_private_data_for_object<VK_OBJECT_TYPE_DESCRIPTOR_SET>((VkDescriptorSet)table.handle);
if (set_data == nullptr)
goto invalid;
const auto set_layout_data = get_private_data_for_object<VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT>(set_data->layout);
if (set_layout_data == nullptr || binding >= set_layout_data->binding_to_offset.size())
goto invalid;

*heap = { (uint64_t)set_data->pool };
*offset = set_data->offset + set_layout_data->binding_to_offset[binding] + array_offset;
return;

invalid:
reshade::log::message(reshade::log::level::warning,
"get_descriptor_heap_offset: invalid table=%p binding=%u array_offset=%u",
reinterpret_cast<void *>(table.handle), binding, array_offset);
*heap = { 0 };
*offset = 0;
}

void reshade::vulkan::device_impl::copy_descriptor_tables(uint32_t count, const api::descriptor_table_copy *copies)
Expand Down