Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Pull swapchain handling code into separate library #1163

Open
wants to merge 17 commits into
base: dev
Choose a base branch
from

Conversation

MarkY-LunarG
Copy link
Contributor

@MarkY-LunarG MarkY-LunarG commented Jun 26, 2023

Pull all of the swapchain handling code into a separate library with the intent of having it be stand-alone for use by other GFXReconstruct utilities.

NOTES:

  1. This library is called compatibility because I intend to move some other universal functionality into it eventually alongside of the swapchain functionality currently in there.
  2. This is currently still using a C++ interface. Going forward, it might make sense to convert this to a C interface if this library is going to be released in a compiled version for other usage scenarios.

First step in preparing to remove swapchain behavior from being
hard-coded inside the decode framework so it can be used to
build a compatibility library for use in additional scenarios.
Modify the swapchain items located in the compatibility library
to be in the compatibility namespace.
Rely on only the items inside the decode::DeviceInfo struct so
that we can start breaking tight coupling.
Remove more decode "_info" structs used in the swapchain interface
in the steps towards making a truly separate library.
Remove unnecessary swapchain functions (which did nothing but
really passthrough to the final func).  This actually increased
debug build performance on Linux for my Talos trace from 19+ seconds
of runtime to 17+ seconds, but I'm not sure how universal that will
be.
Also replace a few more "decode" structures with the Vulkan handle
usage instead for breaking some of the tight bindings.
The AcquireNextImage swapchain logic was mostly a passthrough
with only debug logging.  Removing it to remove an additional
dependency in the library that is unneeded.
Remove decode::ImageInfo usage.  Move virtual swapchain only items
into the class.
Move the swapchain miage tracker header into the compability library,
and then expose it via the swapchain class.
Also remove the need for the object tracker in a few methods.
Remove more usage of the Decode::swapchain_info in the compatibility
library.  This again is intended to break the tight coupling so
that the compatibility library can eventually be a stand-alone library.
- Remove namespace define usage
- Replace using the GFXRECON_LOG_MESSAGE functions with the use
  of passed in function pointers to break coupling.
- Also, use a new create structure to pass in more info without having
  to use the stack.
Remove the use of the function pointer tables pulled in from the
decode namespace and use one specific to the compatibility library.
An external struct was only ever used with the swapchain class and
could just as easily reference the swapchain version so that we
don't have to copy data into/out of the struct when it was referenced
internally by the swapchain class.
@ci-tester-lunarg
Copy link

CI gfxreconstruct build queued with queue ID 1069.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build # 2888 running.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build # 2888 failed.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build queued with queue ID 1091.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build # 2889 running.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build # 2889 failed.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build queued with queue ID 1148.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build # 2890 running.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build # 2890 failed.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build queued with queue ID 1280.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build # 2893 running.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build # 2893 passed.

@andrew-lunarg
Copy link
Contributor

2. Going forward, it might make sense to convert this to a C interface if this library is going to be released in a compiled version for other usage scenarios.

A C-API would make sense if third-party tools were really going to use it without building from source (we are open source: why do they need a binary?) or if we were going to release it entirely outside of GFXR on a different cadence from our own releases, but just to reuse a library internally that is built at the same time using the same compilers as the tools that use it, or for external users who build from source, it seems like a lot of faff for us and some overhead to thunk through a C interrop layer.

I'm guessing you are thinking of something like the hourglass API idiom.
https://www.youtube.com/watch?v=PVYdHDm0q6Y
https://github.com/CppCon/CppCon2014/blob/master/Presentations/Hourglass%20Interfaces%20for%20C%2B%2B%20APIs/Hourglass%20Interfaces%20for%20C%2B%2B%20APIs%20-%20Stefanus%20Du%20Toit%20-%20CppCon%202014.pdf

@MarkY-LunarG
Copy link
Contributor Author

@andrew-lunarg, my current plan is to leave it as a C++ interface because of the overhead of converting all the C++ items (vectors, etc) into C could be a pain. Yes, it would allow us to have a more ABI-resistant interface than C++, but I figure that we can just require anyone dumping out C++ code to eventually need the GFXReconstruct code base to build their samples. I'm not completely against eventually going the C route, but I figured at the very least, this was a good lower impact first step.

@andrew-lunarg andrew-lunarg removed their request for review October 23, 2023 13:35
@bradgrantham-lunarg bradgrantham-lunarg added the P2 A high-priority code maintenance issue or a functional problem that is recoverable or not a crash. label Oct 30, 2023
@@ -14,10 +14,12 @@ target_sources(gfxrecon_application

target_include_directories(gfxrecon_application
PUBLIC
${GFXRECON_SOURCE_DIR}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can compatibility be in framework with other libraries like graphics and util?

${CMAKE_SOURCE_DIR}/compatibility/vulkan_captured_swapchain.h
${CMAKE_SOURCE_DIR}/compatibility/vulkan_captured_swapchain.cpp
${CMAKE_SOURCE_DIR}/compatibility/vulkan_virtual_swapchain.h
${CMAKE_SOURCE_DIR}/compatibility/vulkan_virtual_swapchain.cpp
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think rather than compiling these into decode here, decode should link against libgfxrecon_compatibility. Or maybe the tools have to link against it, not sure. Can you take a look?

@bradgrantham-lunarg bradgrantham-lunarg added P1 Prevents an important capture from being replayed and removed P2 A high-priority code maintenance issue or a functional problem that is recoverable or not a crash. labels Jan 16, 2024
@bradgrantham-lunarg
Copy link
Contributor

Raised to P1 because tocpp work can and should take advantage of this to prevent the code diverging.


#include "vulkan/vulkan.h"

#include <unordered_map>

GFXRECON_BEGIN_NAMESPACE(gfxrecon)
GFXRECON_BEGIN_NAMESPACE(decode)
namespace gfxrecon
Copy link
Contributor

@locke-lunarg locke-lunarg Jan 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we use GFXRECON_BEGIN_NAMESPACE to unified code style?

GFXRECON_BEGIN_NAMESPACE is in util\defines.h. I feel gfxrecon_util.lib is the lowest level library. compatibility should be fine to link gfxrecon_util.lib.

@@ -172,11 +173,13 @@ VulkanReplayConsumerBase::VulkanReplayConsumerBase(std::shared_ptr<application::
// Process option to select swapchain handler. The options is '--use-captured-swapchain-indices'.
if (options.enable_use_captured_swapchain_indices)
{
swapchain_ = std::make_unique<VulkanCapturedSwapchain>();
swapchain_ = std::make_unique<compatibility::VulkanCapturedSwapchain>();
validate_swapchain_image_indices_ = true;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we just use options.enable_use_captured_swapchain_indices, instead of validate_swapchain_image_indices_?

If options.enable_use_captured_swapchain_indices is not enough straightforward, I might add a function, like IsValidateSwapchainImageIndices(). The function returns !options.enable_use_captured_swapchain_indices.

@@ -5525,8 +5753,15 @@ VulkanReplayConsumerBase::OverrideQueuePresentKHR(PFN_vkQueuePresentKHR
// Only attempt to find imported or shadow semaphores if we know at least one around.
if ((!have_imported_semaphores_) && (shadow_semaphores_.empty()) && (modified_present_info.swapchainCount != 0))
{
result = swapchain_->QueuePresentKHR(
func, capture_image_indices_, swapchain_infos_, queue_info, &modified_present_info);
if (queue_info == nullptr || queue_info->handle == VK_NULL_HANDLE)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the begin of OverrideQueuePresentKHR, it has checked queue_info != nullptr. We could also check queue_info->handle != VK_NULL_HANDLE there, so we don't need to check them here again.

VkSwapchainKHR swapchain = VK_NULL_HANDLE;
VkSemaphore semaphore = VK_NULL_HANDLE;
VkFence fence = VK_NULL_HANDLE;
if (swapchain_info != nullptr)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the begin of OverrideAcquireNextImageKHR, it has checked swapchain_info != nullptr. We don't need to check again.

Comment on lines +4901 to +4923
void LogErrorMessage(const char* message, ...)
{
va_list args;
va_start(args, message);
GFXRECON_LOG_ERROR(message, args);
va_end(args);
}

void LogWarningMessage(const char* message, ...)
{
va_list args;
va_start(args, message);
GFXRECON_LOG_WARNING(message, args);
va_end(args);
}

void LogInfoMessage(const char* message, ...)
{
va_list args;
va_start(args, message);
GFXRECON_LOG_INFO(message, args);
va_end(args);
}
Copy link
Contributor

@locke-lunarg locke-lunarg Jan 18, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GFXRECON_LOG is in utils\loggings.h. I feel gfxrecon_util.lib is the lowest level library. compatibility should be fine to link gfxrecon_util.lib.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@locke-lunarg : This is going to be compiled into non-GFXR code (i.e. the generated "toCpp" output). My original design did not intend for that source to have to link back into GFXR source since they may not have it on the generating system. Is this important to maintain? If so, it will likely require more changes.

Comment on lines +4975 to +4979
CreateImageResource,
DestroyImageResource,
AllocateDeviceMemoryResource,
FreeDeviceMemoryResource,
BindImageResourceToDeviceMemoryResource },
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Decode is upper level library. Compatibility is lower level library. I don't know if it's common that lower level library use the function of upper level library?

VkImage* image,
uintptr_t* resource_id)
{
gfxrecon::decode::VulkanResourceAllocator* resource_allocator =
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should move gfxrecon::decode::VulkanResourceAllocator to gfxrecon_graphics.lib. Compatibility could link gfxrecon_graphics.lib, so it doesn't need to send function pointer from decode to compatibility. But I'm not sure if it's a good idea.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is going to require more work because the VulkanResourceAllocator uses objects out of the decode path. (The various Info structures and the HandleId as examples). The plan is to eventually port it over, but this change is already massive as it is.

@locke-lunarg
Copy link
Contributor

locke-lunarg commented Jan 18, 2024

My opinion about library levels is decode -> compatibility -> graphics -> util. Upper level could link lower level, but lower level couldn't not link upper level. util is that every library could use, but it doesn't have vk/d3d code. graphics is similar with util, but for vk/d3d. I know now util has many vk/d3d code. I feel those code should move to graphics, but that's not this PR's topic.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
P1 Prevents an important capture from being replayed
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants