Skip to content

Commit

Permalink
Lazily resolve Vulkan commands (actually all indirect commands) (#1990)
Browse files Browse the repository at this point in the history
* Lazily resolve Vulkan commands

This is probably the 'minimum changes' approach. It uses lambda
functions, which will take a copy of the handles used for command resolving.
  • Loading branch information
Qining authored Jun 20, 2018
1 parent e5b2d6b commit dcec0ee
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 7 deletions.
49 changes: 49 additions & 0 deletions gapir/cc/gfx_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,55 @@ class Api {
FunctionTable mFunctions;
};

// LazyResolved is for resolving indirect commands only when the commands are
// going to be called. It takes a resolver callback, which will be used for
// command resolving for the first time the command is to be called. And caches
// the resolved pointer.
template <typename FuncPtr>
class LazyResolved {
public:
LazyResolved() : resolve_(nullptr), ptr_(nullptr) {}
LazyResolved(std::nullptr_t) : LazyResolved() {}
explicit LazyResolved(std::function<void*()> resolver)
: resolve_(resolver), ptr_(nullptr) {}
// Pass forward the arguments to the command, if the function has never been
// resolved before, resolve it first.
template <typename... Args>
typename std::result_of<FuncPtr(Args...)>::type operator()(Args&&... args) {
if (!ptr_) {
ptr_ = reinterpret_cast<FuncPtr>(resolve_());
}
return ptr_(std::forward<Args>(args)...);
}
// Overloaded not-equal nullptr comparison. Returns true if the underlying
// function can be resolved and is not nullptr.
bool operator!=(std::nullptr_t) {
if (!resolve_) {
return true;
}
if (!ptr_) {
ptr_ = reinterpret_cast<FuncPtr>(resolve_());
}
return ptr_ != nullptr;
}
// Overloaded boolean comparison. Returns true if the underlying function can
// be resolved and is not nullptr.
operator bool() {
if (!resolve_) {
return false;
}
if (!ptr_) {
ptr_ = reinterpret_cast<FuncPtr>(resolve_());
}
return ptr_ != nullptr;
}
private:
// The function resolving callback.
std::function<void*()> resolve_;
// The cached function pointer to the underlying function.
FuncPtr ptr_;
};

} // namespace gapir

#endif // GAPIR_GFX_API_H
12 changes: 12 additions & 0 deletions gapis/api/templates/cpp_common.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -1119,6 +1119,18 @@
{{end}}


{{/*
-------------------------------------------------------------------------------
Emits the C++ lazy resolved function variable extern for a given command.
-------------------------------------------------------------------------------
*/}}
{{define "C++.LazyResolvedFunctionDecl"}}
{{AssertType $ "Function"}}

LazyResolved<{{Template "C++.FunctionPtrType" $}}> {{Template "CmdName" $}}
{{end}}


{{/*
-------------------------------------------------------------------------------
Emits the method name for the given command or subroutine.
Expand Down
7 changes: 6 additions & 1 deletion gapis/api/templates/specific_gfx_api.h.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
#include "core/cc/{{Global "API"}}_ptr_types.h"
#include <stdint.h>
#include <functional>
#include <string>
{{/* Forward declare structs used by the graphics API in the global namespace. */}}
Expand Down Expand Up @@ -88,7 +89,11 @@ class {{Title (Global "API")}} : public Api {
struct {{$table}}FunctionStubs {
{{range $f := $p}}
{{if and (not (GetAnnotation $f "synthetic")) (not (GetAnnotation $f "pfn"))}}
{{Template "C++.FunctionPtrDecl" $f}} = nullptr;
{{if not (GetAnnotation $f "indirect")}}
{{Template "C++.FunctionPtrDecl" $f}} = nullptr;
{{else}}
{{Template "C++.LazyResolvedFunctionDecl" $f}} = nullptr;
{{end}}
{{end}}
{{end}}
};
Expand Down
12 changes: 6 additions & 6 deletions gapis/api/templates/vulkan_gfx_api_extras.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@

std::vector<Vulkan::VkPhysicalDevice> getVkPhysicalDevices(§
Vulkan::PFNVKENUMERATEPHYSICALDEVICES vkEnumeratePhysicalDevices, Vulkan::VkInstance instance) {
LazyResolved<Vulkan::PFNVKENUMERATEPHYSICALDEVICES> vkEnumeratePhysicalDevices, Vulkan::VkInstance instance) {
uint32_t count = 0;
vkEnumeratePhysicalDevices(instance, &count, nullptr);
std::vector<Vulkan::VkPhysicalDevice> devices(count);
Expand All @@ -73,7 +73,7 @@
}
std::vector<Vulkan::VkQueue> getVkQueues(§
Vulkan::PFNVKGETDEVICEQUEUE vkGetDeviceQueue, Vulkan::VkDevice device, §
LazyResolved<Vulkan::PFNVKGETDEVICEQUEUE> vkGetDeviceQueue, Vulkan::VkDevice device, §
Vulkan::VkDeviceCreateInfo* createInfo) {
std::vector<Vulkan::VkQueue> queues;
for (uint32_t i = 0; i < createInfo->queueCreateInfoCount; ++i) {
Expand Down Expand Up @@ -204,8 +204,8 @@ bool Vulkan::replayCreateVkDeviceImpl(Stack* stack, size_val physicalDevice,
{{range $c := AllCommands $}}
{{if (Macro "IsIndirected" "Command" $c "IndirectOn" "VkInstance")}}
{{$name := Macro "CmdName" $c}}
stubs.{{$name}} = reinterpret_cast<{{Template "C++.FunctionPtrType" $c}}>(§
core::GetVulkanInstanceProcAddress(instance, "{{$name}}", false));
stubs.{{$name}} = LazyResolved<{{Template "C++.FunctionPtrType" $c}}>(
[instance]() -> void* { return core::GetVulkanInstanceProcAddress(instance, "{{$name}}", false); });
{{end}}
{{end}}
// Get all physical devices for this instance and bind them.
Expand Down Expand Up @@ -255,8 +255,8 @@ bool Vulkan::replayCreateVkDeviceImpl(Stack* stack, size_val physicalDevice,
{{range $c := AllCommands $}}
{{if (Macro "IsIndirected" "Command" $c "IndirectOn" "VkDevice")}}
{{$name := Macro "CmdName" $c}}
stubs.{{$name}} = reinterpret_cast<{{Template "C++.FunctionPtrType" $c}}>(§
core::GetVulkanDeviceProcAddress(instance, device, "{{$name}}", false));
stubs.{{$name}} = LazyResolved<{{Template "C++.FunctionPtrType" $c}}>(
[instance, device]() -> void* { return core::GetVulkanDeviceProcAddress(instance, device, "{{$name}}", false); });
{{end}}
{{end}}
// Get all queues for this device and bind them.
Expand Down

0 comments on commit dcec0ee

Please sign in to comment.