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

Handle VR frame delimiters #1138

Merged
merged 4 commits into from
Jul 19, 2023

Conversation

davidd-lunarg
Copy link
Contributor

When a command buffer containing a VR end of frame debug marker is submitted, treat that as a frame delimiter. During capture, write end of frame markers to the capture file when this special end of frame condition is encountered and handle those frame markers in the file processor.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build queued with queue ID 6966.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build # 2811 running.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build # 2811 passed.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build queued with queue ID 9654.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build # 2818 running.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build # 2818 passed.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build queued with queue ID 9735.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build # 2819 running.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build # 2819 passed.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build queued with queue ID 17215.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build # 2859 running.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build queued with queue ID 17249.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build # 2861 running.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build # 2861 passed.

Copy link
Contributor

@andrew-lunarg andrew-lunarg left a comment

Choose a reason for hiding this comment

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

Looking good!

layer/trace_layer.cpp Outdated Show resolved Hide resolved
Comment on lines 60 to 67
std::unordered_set<std::string> kProvidedDeviceFunctions = { "vkCmdDebugMarkerBeginEXT",
"vkCmdDebugMarkerEndEXT",
"vkCmdDebugMarkerInsertEXT",
"vkDebugMarkerSetObjectNameEXT",
"vkDebugMarkerSetObjectTagEXT" };

Copy link
Contributor

@andrew-lunarg andrew-lunarg Jun 26, 2023

Choose a reason for hiding this comment

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

Why not const? Also, is 5 entries really enough entries for the asymptotic advantage of an unordered set to beat the memory coherence / simple code advantage of a linear scan of an array? I made a little benchmark to compare linear scan versus set.

Results

Listing

#include <unordered_set>

const std::unordered_set<std::string> kProvidedDeviceFunctions = { "vkCmdDebugMarkerBeginEXT",
                                                             "vkCmdDebugMarkerEndEXT",
                                                             "vkCmdDebugMarkerInsertEXT",
                                                             "vkDebugMarkerSetObjectNameEXT",
                                                             "vkDebugMarkerSetObjectTagEXT" };

const std::string kProvidedDeviceFunctionsArray[] = { "vkCmdDebugMarkerBeginEXT",
                                                             "vkCmdDebugMarkerEndEXT",
                                                             "vkCmdDebugMarkerInsertEXT",
                                                             "vkDebugMarkerSetObjectNameEXT",
                                                             "vkDebugMarkerSetObjectTagEXT" };

constexpr int ITERS { 10000 };

std::vector<std::string> inputs;
const auto& init = [] () {
  for(int i = 0; i < ITERS; ++i)
  {
    for(const std::string& in : kProvidedDeviceFunctionsArray){
      inputs.push_back(in);
    }
  }
  std::random_shuffle(inputs.begin(), inputs.end());
  return true;
}();

static void TouchInputs(benchmark::State& state) {
  // Code inside this loop is measured repeatedly
  for (auto _ : state) {
    for(const auto& in : inputs){
      benchmark::DoNotOptimize(in);
   }
  }
}
BENCHMARK(TouchInputs);

static void LinearScanArray(benchmark::State& state) {
  // Code inside this loop is measured repeatedly
  for (auto _ : state) {
    for(const auto& in : inputs){
      bool found = std::find(std::begin(kProvidedDeviceFunctionsArray), std::end(kProvidedDeviceFunctionsArray), in) != std::end(kProvidedDeviceFunctionsArray);
      benchmark::DoNotOptimize(found);
   }
  }
}
BENCHMARK(LinearScanArray);

static void AmortisedConstantTimeSet(benchmark::State& state) {
  // Code inside this loop is measured repeatedly
  for (auto _ : state) {
    for(const auto& in : inputs){
      bool found = (kProvidedDeviceFunctions.find(in) != kProvidedDeviceFunctions.end());
      benchmark::DoNotOptimize(found);
   }
  }
}
BENCHMARK(AmortisedConstantTimeSet);

static void HotInputLinearScanArray(benchmark::State& state) {
  // Code inside this loop is measured repeatedly
  for (auto _ : state) {
    for(int i = 0; i < ITERS; ++i)
    {
      for(const std::string& in : kProvidedDeviceFunctionsArray){
        bool found = std::find(std::begin(kProvidedDeviceFunctionsArray), std::end(kProvidedDeviceFunctionsArray), in) != std::end(kProvidedDeviceFunctionsArray);
        benchmark::DoNotOptimize(found);
      }
    }
  }
}
BENCHMARK(HotInputLinearScanArray);

static void HotInputAmortisedConstantTimeSet(benchmark::State& state) {
  // Code inside this loop is measured repeatedly
  for (auto _ : state) {
    for(int i = 0; i < ITERS; ++i)
    {
      for(const std::string& in : kProvidedDeviceFunctionsArray){
        bool found = (kProvidedDeviceFunctions.find(in) != kProvidedDeviceFunctions.end());
        benchmark::DoNotOptimize(found);
      }
    }
  }
}
BENCHMARK(HotInputAmortisedConstantTimeSet);

Copy link
Contributor

Choose a reason for hiding this comment

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

find(...) != ...end() on a set is idiomatic and seems fine to me. This array could get longer, so we'd have to worry about where the crossover point is, and you'd have to verify clang and MSVC also behave the same way. While I commend your thoroughness including writing a test case in QuickBench (I learned that exists today!), we have a lot of work to do and I don't think this change important enough to microbenchmark something that occurs once at application startup.

I agree it could be const.

My only thought about this new variable would be that in the functions below, kProvidedDeviceFunctions.count(in) > 0 is slightly more readable to me until unordered_set::contains in C++20.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added const.

layer/trace_layer.cpp Outdated Show resolved Hide resolved
layer/trace_layer.cpp Show resolved Hide resolved
@@ -327,6 +327,6 @@ def make_cmd_decl(self, return_type, proto, values, name):
.format(return_type)
)
return_value = '{}{{}}'.format(return_type)
return 'static {}({}) {{ GFXRECON_LOG_WARNING("Unsupported function {} was called, resulting in no-op behavior."); return {}; }}'.format(
return 'static {}({}) {{ GFXRECON_LOG_WARNING_ONCE("Unsupported function {} was called, resulting in no-op behavior."); return {}; }}'.format(
Copy link
Contributor

Choose a reason for hiding this comment

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

These look great but they make a massive change in framework/generated/generated_vulkan_dispatch_table.h that seems unrelated to the rest of the commit this lives in. Not asking for the containing commit to be split just wondering if (and only if) it were easy to change and commits were being reorged before merging, whether this could be made live in its own commit for logical separation and cleaner atomic revert if ever needed.

framework/encode/vulkan_capture_manager.cpp Outdated Show resolved Hide resolved
framework/encode/vulkan_capture_manager.cpp Outdated Show resolved Hide resolved
@@ -3329,6 +3366,44 @@ VkResult VulkanReplayConsumerBase::OverrideQueueSubmit2(PFN_vkQueueSubmit2 func,
GetDeviceTable(queue_info->handle)->QueueWaitIdle(queue_info->handle);
}

// Check whether any of the submitted command buffers are frame boundaries.
if (screenshot_handler_ != nullptr)
{
Copy link
Contributor

Choose a reason for hiding this comment

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

This isn't the other place I saw a search of command buffers. I saw it in another file too.

framework/decode/vulkan_replay_consumer_base.cpp Outdated Show resolved Hide resolved
@andrew-lunarg
Copy link
Contributor

Is there anything in CI that tests this? I think CI is currently just going to test that it doesn't break anything when the markers are not in use?

@ci-tester-lunarg
Copy link

CI gfxreconstruct build queued with queue ID 1766.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build # 2895 running.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build # 2895 passed.

@davidd-lunarg
Copy link
Contributor Author

Is there anything in CI that tests this? I think CI is currently just going to test that it doesn't break anything when the markers are not in use?

That's right, CI doesn't currently have any tests that contain the VR frame markers.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build queued with queue ID 3352.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build # 2910 running.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build # 2910 passed.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build queued with queue ID 4632.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build # 2962 running.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build # 2962 passed.

Also commit change to `generated_vulkan_export_json_consumer.cpp`
that was made when running generate_vulkan.py
Some VR applications use debug markers to identify frame boundaries but
not all VR devices provide support for VK_EXT_debug_marker. With this
change GFXR provides function pointers for the extension's functions
in order to capture the debug marker calls and track VR frames.
@ci-tester-lunarg
Copy link

CI gfxreconstruct build queued with queue ID 9251.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build # 2997 running.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build # 2997 passed.

@davidd-lunarg davidd-lunarg marked this pull request as ready for review July 19, 2023 21:37
@davidd-lunarg davidd-lunarg merged commit 7ad0ef7 into LunarG:dev Jul 19, 2023
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants