vulkan: refactor debug defines (#7170)

Add more fine grain debug defines and add some systrace markers.
This commit is contained in:
Powei Feng
2023-09-14 15:30:42 -07:00
committed by GitHub
parent c80fbfdf17
commit 976b8c6ae4
15 changed files with 241 additions and 132 deletions
@@ -28,8 +28,6 @@
#include "generated/vkshaders/vkshaders.h"
#define FILAMENT_VULKAN_CHECK_BLIT_FORMAT 0
using namespace bluevk;
using namespace utils;
@@ -69,7 +67,7 @@ inline void blitFast(const VkCommandBuffer cmdbuffer, VkImageAspectFlags aspect,
.layerCount = 1,
};
if constexpr (FILAMENT_VULKAN_VERBOSE) {
if constexpr (FVK_ENABLED(FVK_DEBUG_BLITTER)) {
utils::slog.d << "Fast blit from=" << src.texture->getVkImage() << ",level=" << (int) src.level
<< "layout=" << src.getLayout()
<< " to=" << dst.texture->getVkImage() << ",level=" << (int) dst.level
@@ -132,7 +130,7 @@ void VulkanBlitter::blitColor(BlitArgs args) {
const VulkanAttachment dst = args.dstTarget->getColor(0);
const VkImageAspectFlags aspect = VK_IMAGE_ASPECT_COLOR_BIT;
#if FILAMENT_VULKAN_CHECK_BLIT_FORMAT
#if FVK_ENABLED(FVK_DEBUG_BLIT_FORMAT)
VkPhysicalDevice const gpu = mPhysicalDevice;
VkFormatProperties info;
vkGetPhysicalDeviceFormatProperties(gpu, src.getFormat(), &info);
@@ -160,7 +158,7 @@ void VulkanBlitter::blitDepth(BlitArgs args) {
const VulkanAttachment dst = args.dstTarget->getDepth();
const VkImageAspectFlags aspect = VK_IMAGE_ASPECT_DEPTH_BIT;
#if FILAMENT_VULKAN_CHECK_BLIT_FORMAT
#if FVK_ENABLED(FVK_DEBUG_BLIT_FORMAT)
VkPhysicalDevice const gpu = mPhysicalDevice;
VkFormatProperties info;
vkGetPhysicalDeviceFormatProperties(gpu, src.getFormat(), &info);
@@ -241,7 +239,7 @@ void VulkanBlitter::lazyInit() noexcept {
mDepthResolveProgram->samplerGroupInfo[0].samplers.reserve(1);
mDepthResolveProgram->samplerGroupInfo[0].samplers.resize(1);
if constexpr (FILAMENT_VULKAN_VERBOSE) {
if constexpr (FVK_ENABLED(FVK_DEBUG_BLITTER)) {
utils::slog.d << "Created Shader Module for VulkanBlitter "
<< "shaders = (" << vertexShader << ", " << fragmentShader << ")"
<< utils::io::endl;
+38 -20
View File
@@ -33,7 +33,9 @@ using namespace utils;
namespace filament::backend {
#if FVK_ENABLED(FVK_DEBUG_GROUP_MARKERS)
using Timestamp = VulkanGroupMarkers::Timestamp;
#endif
VulkanCmdFence::VulkanCmdFence(VkFence ifence)
: fence(ifence) {
@@ -63,20 +65,21 @@ CommandBufferObserver::~CommandBufferObserver() {}
static VkCommandPool createPool(VkDevice device, uint32_t queueFamilyIndex) {
VkCommandPoolCreateInfo createInfo = {
.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
.flags =
VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT | VK_COMMAND_POOL_CREATE_TRANSIENT_BIT,
.queueFamilyIndex = queueFamilyIndex,
.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT
| VK_COMMAND_POOL_CREATE_TRANSIENT_BIT,
.queueFamilyIndex = queueFamilyIndex,
};
VkCommandPool pool;
vkCreateCommandPool(device, &createInfo, VKALLOC, &pool);
return pool;
}
#if FVK_ENABLED(FVK_DEBUG_GROUP_MARKERS)
void VulkanGroupMarkers::push(std::string const& marker, Timestamp start) noexcept {
mMarkers.push_back(marker);
#if FILAMENT_VULKAN_VERBOSE
#if FVK_ENABLED(FVK_DEBUG_PRINT_GROUP_MARKERS)
mTimestamps.push_back(start.time_since_epoch().count() > 0.0
? start
: std::chrono::high_resolution_clock::now());
@@ -87,7 +90,7 @@ std::pair<std::string, Timestamp> VulkanGroupMarkers::pop() noexcept {
auto const marker = mMarkers.back();
mMarkers.pop_back();
#if FILAMENT_VULKAN_VERBOSE
#if FVK_ENABLED(FVK_DEBUG_PRINT_GROUP_MARKERS)
auto const timestamp = mTimestamps.back();
mTimestamps.pop_back();
return std::make_pair(marker, timestamp);
@@ -100,7 +103,7 @@ std::pair<std::string, Timestamp> VulkanGroupMarkers::pop_bottom() noexcept {
auto const marker = mMarkers.front();
mMarkers.pop_front();
#if FILAMENT_VULKAN_VERBOSE
#if FVK_ENABLED(FVK_DEBUG_PRINT_GROUP_MARKERS)
auto const timestamp = mTimestamps.front();
mTimestamps.pop_front();
return std::make_pair(marker, timestamp);
@@ -112,7 +115,7 @@ std::pair<std::string, Timestamp> VulkanGroupMarkers::pop_bottom() noexcept {
std::pair<std::string, Timestamp> VulkanGroupMarkers::top() const {
assert_invariant(!empty());
auto const marker = mMarkers.back();
#if FILAMENT_VULKAN_VERBOSE
#if FVK_ENABLED(FVK_DEBUG_PRINT_GROUP_MARKERS)
auto const topTimestamp = mTimestamps.front();
return std::make_pair(marker, topTimestamp);
#else
@@ -124,6 +127,8 @@ bool VulkanGroupMarkers::empty() const noexcept {
return mMarkers.empty();
}
#endif // FVK_DEBUG_GROUP_MARKERS
VulkanCommands::VulkanCommands(VkDevice device, VkQueue queue, uint32_t queueFamilyIndex,
VulkanContext* context, VulkanResourceAllocator* allocator)
: mDevice(device),
@@ -144,6 +149,10 @@ VulkanCommands::VulkanCommands(VkDevice device, VkQueue queue, uint32_t queueFam
for (size_t i = 0; i < CAPACITY; ++i) {
mStorage[i] = std::make_unique<VulkanCommandBuffer>(allocator, mDevice, mPool);
}
#if !FVK_ENABLED(FVK_DEBUG_GROUP_MARKERS)
(void) mContext;
#endif
}
VulkanCommands::~VulkanCommands() {
@@ -167,7 +176,7 @@ VulkanCommandBuffer& VulkanCommands::get() {
// It occurs only when Filament invokes commit() or endFrame() a large number of times without
// presenting the swap chain or waiting on a fence.
while (mAvailableBufferCount == 0) {
#if VK_REPORT_STALLS
#if FVK_ENABLED(FVK_DEBUG_COMMAND_BUFFER)
slog.i << "VulkanCommands has stalled. "
<< "If this occurs frequently, consider increasing VK_MAX_COMMAND_BUFFERS."
<< io::endl;
@@ -207,12 +216,14 @@ VulkanCommandBuffer& VulkanCommands::get() {
mObserver->onCommandBuffer(*currentbuf);
}
#if FVK_ENABLED(FVK_DEBUG_GROUP_MARKERS)
// We push the current markers onto a temporary stack. This must be placed after currentbuf is
// set to the new command buffer since pushGroupMarker also calls get().
while (mCarriedOverMarkers && !mCarriedOverMarkers->empty()) {
auto [marker, time] = mCarriedOverMarkers->pop();
pushGroupMarker(marker.c_str(), time);
}
#endif
return *currentbuf;
}
@@ -224,6 +235,7 @@ bool VulkanCommands::flush() {
// Before actually submitting, we need to pop any leftover group markers.
// Note that this needs to occur before vkEndCommandBuffer.
#if FVK_ENABLED(FVK_DEBUG_GROUP_MARKERS)
while (mGroupMarkers && !mGroupMarkers->empty()) {
if (!mCarriedOverMarkers) {
mCarriedOverMarkers = std::make_unique<VulkanGroupMarkers>();
@@ -233,7 +245,7 @@ bool VulkanCommands::flush() {
// We still need to call through to vkCmdEndDebugUtilsLabelEXT.
popGroupMarker();
}
#endif
int8_t const index = mCurrentCommandBufferIndex;
VulkanCommandBuffer const* currentbuf = mStorage[index].get();
@@ -283,7 +295,7 @@ bool VulkanCommands::flush() {
submitInfo.pWaitSemaphores = VK_NULL_HANDLE;
}
#if FILAMENT_VULKAN_VERBOSE
#if FVK_ENABLED(FVK_DEBUG_COMMAND_BUFFER)
slog.i << "Submitting cmdbuffer=" << cmdbuffer
<< " wait=(" << signals[0] << ", " << signals[1] << ") "
<< " signal=" << renderingFinished
@@ -297,7 +309,7 @@ bool VulkanCommands::flush() {
cmdfence->condition.notify_all();
lock.unlock();
#if FILAMENT_VULKAN_VERBOSE
#if FVK_ENABLED(FVK_DEBUG_COMMAND_BUFFER)
if (result != VK_SUCCESS) {
utils::slog.d << "Failed command buffer submission result: " << result << utils::io::endl;
}
@@ -313,8 +325,8 @@ bool VulkanCommands::flush() {
VkSemaphore VulkanCommands::acquireFinishedSignal() {
VkSemaphore semaphore = mSubmissionSignal;
mSubmissionSignal = VK_NULL_HANDLE;
#if FILAMENT_VULKAN_VERBOSE
slog.i << "Acquiring " << semaphore << " (e.g. for vkQueuePresentKHR)" << io::endl;
#if FVK_ENABLED(FVK_DEBUG_COMMAND_BUFFER)
slog.i << "Acquiring " << semaphore << " (e.g. for vkQueuePresentKHR)" << io::endl;
#endif
return semaphore;
}
@@ -322,7 +334,7 @@ VkSemaphore VulkanCommands::acquireFinishedSignal() {
void VulkanCommands::injectDependency(VkSemaphore next) {
assert_invariant(mInjectedSignal == VK_NULL_HANDLE);
mInjectedSignal = next;
#if FILAMENT_VULKAN_VERBOSE
#if FVK_ENABLED(FVK_DEBUG_COMMAND_BUFFER)
slog.i << "Injecting " << next << " (e.g. due to vkAcquireNextImageKHR)" << io::endl;
#endif
}
@@ -344,6 +356,9 @@ void VulkanCommands::wait() {
}
void VulkanCommands::gc() {
FVK_SYSTRACE_CONTEXT();
FVK_SYSTRACE_START("commands::gc");
VkFence fences[CAPACITY];
size_t count = 0;
@@ -365,6 +380,7 @@ void VulkanCommands::gc() {
if (count > 0) {
vkResetFences(mDevice, count, fences);
}
FVK_SYSTRACE_END();
}
void VulkanCommands::updateFences() {
@@ -381,8 +397,10 @@ void VulkanCommands::updateFences() {
}
}
#if FVK_ENABLED(FVK_DEBUG_GROUP_MARKERS)
void VulkanCommands::pushGroupMarker(char const* str, VulkanGroupMarkers::Timestamp timestamp) {
#if FILAMENT_VULKAN_VERBOSE
#if FVK_ENABLED(FVK_DEBUG_PRINT_GROUP_MARKERS)
// If the timestamp is not 0, then we are carrying over a marker across buffer submits.
// If it is 0, then this is a normal marker push and we should just print debug line as usual.
if (timestamp.time_since_epoch().count() == 0.0) {
@@ -420,7 +438,7 @@ void VulkanCommands::popGroupMarker() {
if (!mGroupMarkers->empty()) {
VkCommandBuffer const cmdbuffer = get().buffer();
#if FILAMENT_VULKAN_VERBOSE
#if FVK_ENABLED(FVK_DEBUG_PRINT_GROUP_MARKERS)
auto const [marker, startTime] = mGroupMarkers->pop();
auto const endTime = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> diff = endTime - startTime;
@@ -429,7 +447,6 @@ void VulkanCommands::popGroupMarker() {
#else
mGroupMarkers->pop();
#endif
if (mContext->isDebugUtilsSupported()) {
vkCmdEndDebugUtilsLabelEXT(cmdbuffer);
} else if (mContext->isDebugMarkersSupported()) {
@@ -468,8 +485,9 @@ std::string VulkanCommands::getTopGroupMarker() const {
}
return std::get<0>(mGroupMarkers->top());
}
#endif // FVK_DEBUG_GROUP_MARKERS
}// namespace filament::backend
} // namespace filament::backend
#if defined(_MSC_VER)
#pragma warning( pop )
+9 -2
View File
@@ -39,6 +39,7 @@ namespace filament::backend {
struct VulkanContext;
#if FVK_ENABLED(FVK_DEBUG_GROUP_MARKERS)
class VulkanGroupMarkers {
public:
using Timestamp = std::chrono::time_point<std::chrono::high_resolution_clock>;
@@ -51,11 +52,13 @@ public:
private:
std::list<std::string> mMarkers;
#if FILAMENT_VULKAN_VERBOSE
#if FVK_ENABLED(FVK_DEBUG_PRINT_GROUP_MARKERS)
std::list<Timestamp> mTimestamps;
#endif
};
#endif // FVK_DEBUG_GROUP_MARKERS
// Wrapper to enable use of shared_ptr for implementing shared ownership of low-level Vulkan fences.
struct VulkanCmdFence {
VulkanCmdFence(VkFence ifence);
@@ -170,6 +173,7 @@ class VulkanCommands {
// The observer's event handler can only be called during get().
void setObserver(CommandBufferObserver* observer) { mObserver = observer; }
#if FVK_ENABLED(FVK_DEBUG_GROUP_MARKERS)
void pushGroupMarker(char const* str, VulkanGroupMarkers::Timestamp timestamp = {});
void popGroupMarker();
@@ -177,9 +181,10 @@ class VulkanCommands {
void insertEventMarker(char const* string, uint32_t len);
std::string getTopGroupMarker() const;
#endif
private:
static constexpr int CAPACITY = VK_MAX_COMMAND_BUFFERS;
static constexpr int CAPACITY = FVK_MAX_COMMAND_BUFFERS;
VkDevice const mDevice;
VkQueue const mQueue;
VkCommandPool const mPool;
@@ -196,8 +201,10 @@ class VulkanCommands {
uint8_t mAvailableBufferCount = CAPACITY;
CommandBufferObserver* mObserver = nullptr;
#if FVK_ENABLED(FVK_DEBUG_GROUP_MARKERS)
std::unique_ptr<VulkanGroupMarkers> mGroupMarkers;
std::unique_ptr<VulkanGroupMarkers> mCarriedOverMarkers;
#endif
};
} // namespace filament::backend
+70 -18
View File
@@ -19,13 +19,6 @@
#include <stdint.h>
#define FILAMENT_VULKAN_VERBOSE 0
#define FILAMENT_VULKAN_DUMP_API 0
#ifndef FILAMENT_VULKAN_HANDLE_ARENA_SIZE_IN_MB
#define FILAMENT_VULKAN_HANDLE_ARENA_SIZE_IN_MB 8
#endif
// In debug builds, we enable validation layers and set up a debug callback.
//
// To enable validation layers in Android, also be sure to set the jniLibs property in the gradle
@@ -43,21 +36,80 @@
// ndkVersion "23.1.7779620"
//
// Also consider changing the root `gradle.properties` to point to a debug build, although this is
// not required for validation if you change the definition of VK_ENABLE_VALIDATION below.
#if defined(NDEBUG)
#define VK_ENABLE_VALIDATION 0
// not required for validation.
// FVK is short for Filament Vulkan
#define FVK_DEBUG_SYSTRACE 0x00000001
#define FVK_DEBUG_GROUP_MARKERS 0x00000002
#define FVK_DEBUG_TEXTURE 0x00000004
#define FVK_DEBUG_LAYOUT_TRANSITION 0x00000008
#define FVK_DEBUG_COMMAND_BUFFER 0x00000010
#define FVK_DEBUG_DUMP_API 0x00000020
#define FVK_DEBUG_VALIDATION 0x00000040
#define FVK_DEBUG_PRINT_GROUP_MARKERS 0x00000080
#define FVK_DEBUG_BLIT_FORMAT 0x00000100
#define FVK_DEBUG_BLITTER 0x00000200
#define FVK_DEBUG_FBO_CACHE 0x00000400
#define FVK_DEBUG_SHADER_MODULE 0x00000800
#define FVK_DEBUG_READ_PIXELS 0x00001000
#define FVK_DEBUG_PIPELINE_CACHE 0x00002000
#define FVK_DEBUG_ALLOCATION 0x00004000
// Usefaul default combinations
#define FVK_DEBUG_EVERYTHING 0xFFFFFFFF
#define FVK_DEBUG_PERFORMANCE \
FVK_DEBUG_SYSTRACE | \
FVK_DEBUG_GROUP_MARKERS
#define FVK_DEBUG_CORRECTNESS \
FVK_DEBUG_VALIDATION | \
FVK_DEBUG_SHADER_MODULE | \
FVK_DEBUG_TEXTURE | \
FVK_DEBUG_LAYOUT_TRANSITION
#define FVK_DEBUG_RENDER_PASSES \
FVK_DEBUG_GROUP_MARKERS | \
FVK_DEBUG_PRINT_GROUP_MARKERS
#ifndef NDEBUG
#define FVK_DEBUG_FLAGS FVK_DEBUG_PERFORMANCE
#else
#define VK_ENABLE_VALIDATION 1
#define FVK_DEBUG_FLAGS 0
#endif
#define VK_REPORT_STALLS 0
#define FVK_ENABLED(flags) ((FVK_DEBUG_FLAGS) & (flags))
#define FVK_ENABLED_BOOL(flags) ((bool) FVK_ENABLED(flags))
// Ensure dependencies are met between debug options
#if FVK_ENABLED(FVK_DEBUG_PRINT_GROUP_MARKERS)
static_assert(FVK_ENABLED(FVK_DEBUG_GROUP_MARKERS));
#endif
// end dependcy checks
#if FVK_ENABLED(FVK_DEBUG_SYSTRACE)
#include <utils/Systrace.h>
#define FVK_SYSTRACE_CONTEXT() SYSTRACE_CONTEXT()
#define FVK_SYSTRACE_START(marker) SYSTRACE_NAME_BEGIN(marker)
#define FVK_SYSTRACE_END() SYSTRACE_NAME_END()
#else
#define FVK_SYSTRACE_CONTEXT()
#define FVK_SYSTRACE_START(marker)
#define FVK_SYSTRACE_END()
#endif
#ifndef FVK_HANDLE_ARENA_SIZE_IN_MB
#define FVK_HANDLE_ARENA_SIZE_IN_MB 8
#endif
// All vkCreate* functions take an optional allocator. For now we select the default allocator by
// passing in a null pointer, and we highlight the argument by using the VKALLOC constant.
constexpr struct VkAllocationCallbacks* VKALLOC = nullptr;
constexpr static const int VK_REQUIRED_VERSION_MAJOR = 1;
constexpr static const int VK_REQUIRED_VERSION_MINOR = 1;
constexpr static const int FVK_REQUIRED_VERSION_MAJOR = 1;
constexpr static const int FVK_REQUIRED_VERSION_MINOR = 1;
// Maximum number of VkCommandBuffer handles managed simultaneously by VulkanCommands.
//
@@ -65,18 +117,18 @@ constexpr static const int VK_REQUIRED_VERSION_MINOR = 1;
// buffers that have been submitted but have not yet finished rendering. Note that Filament can
// issue multiple commit calls in a single frame, and that we use a triple buffered swap chain on
// some platforms.
constexpr static const int VK_MAX_COMMAND_BUFFERS = 10;
constexpr static const int FVK_MAX_COMMAND_BUFFERS = 10;
// Number of command buffer submissions that should occur before an unused pipeline is removed
// from the cache.
//
// If this number is low, VkPipeline construction will occur frequently, which can
// be extremely slow. If this number is high, the memory footprint will be large.
constexpr static const int VK_MAX_PIPELINE_AGE = 10;
constexpr static const int FVK_MAX_PIPELINE_AGE = 10;
// VulkanPipelineCache does not track which command buffers contain references to which pipelines,
// instead it simply waits for at least VK_MAX_COMMAND_BUFFERS submissions to occur before
// instead it simply waits for at least FVK_MAX_COMMAND_BUFFERS submissions to occur before
// destroying any unused pipeline object.
static_assert(VK_MAX_PIPELINE_AGE >= VK_MAX_COMMAND_BUFFERS);
static_assert(FVK_MAX_PIPELINE_AGE >= FVK_MAX_COMMAND_BUFFERS);
#endif
+56 -29
View File
@@ -30,10 +30,9 @@
#include <utils/CString.h>
#include <utils/FixedCapacityVector.h>
#include <utils/Panic.h>
#include <utils/Systrace.h>
#ifndef NDEBUG
#include <set>
#include <set> // For VulkanDriver::debugCommandBegin
#endif
using namespace bluevk;
@@ -101,7 +100,7 @@ VulkanTexture* createEmptyTexture(VkDevice device, VkPhysicalDevice physicalDevi
return emptyTexture;
}
#if VK_ENABLE_VALIDATION
#if FVK_ENABLED(FVK_DEBUG_VALIDATION)
VKAPI_ATTR VkBool32 VKAPI_CALL debugReportCallback(VkDebugReportFlagsEXT flags,
VkDebugReportObjectTypeEXT objectType, uint64_t object, size_t location,
int32_t messageCode, const char* pLayerPrefix, const char* pMessage, void* pUserData) {
@@ -136,7 +135,7 @@ VKAPI_ATTR VkBool32 VKAPI_CALL debugUtilsCallback(VkDebugUtilsMessageSeverityFla
utils::slog.e << utils::io::endl;
return VK_FALSE;
}
#endif// VK_ENABLE_VALIDATION
#endif // FVK_EANBLED(FVK_DEBUG_VALIDATION)
} // anonymous namespace
@@ -159,7 +158,7 @@ VulkanDriver::VulkanDriver(VulkanPlatform* platform, VulkanContext const& contex
mBlitter(mStagePool, mPipelineCache, mFramebufferCache, mSamplerCache),
mReadPixels(mPlatform->getDevice()) {
#if VK_ENABLE_VALIDATION
#if FVK_ENABLED(FVK_DEBUG_VALIDATION)
UTILS_UNUSED const PFN_vkCreateDebugReportCallbackEXT createDebugReportCallback
= vkCreateDebugReportCallbackEXT;
VkResult result;
@@ -214,7 +213,7 @@ UTILS_NOINLINE
Driver* VulkanDriver::create(VulkanPlatform* platform, VulkanContext const& context,
Platform::DriverConfig const& driverConfig) noexcept {
assert_invariant(platform);
size_t defaultSize = FILAMENT_VULKAN_HANDLE_ARENA_SIZE_IN_MB * 1024U * 1024U;
size_t defaultSize = FVK_HANDLE_ARENA_SIZE_IN_MB * 1024U * 1024U;
Platform::DriverConfig validConfig{
.handleArenaSize = std::max(driverConfig.handleArenaSize, defaultSize)};
return new VulkanDriver(platform, context, validConfig);
@@ -266,24 +265,15 @@ void VulkanDriver::tick(int) {
// rather than the wall clock, because we must wait 3 frames after a DriverAPI-level resource has
// been destroyed for safe destruction, due to outstanding command buffers and triple buffering.
void VulkanDriver::collectGarbage() {
FVK_SYSTRACE_CONTEXT();
FVK_SYSTRACE_START("gc");
// Command buffers need to be submitted and completed before other resources can be gc'd. And
// its gc() function carrys out the *wait*.
SYSTRACE_CONTEXT();
SYSTRACE_NAME_BEGIN("gc");
mCommands->gc();
SYSTRACE_NAME_BEGIN("stagepool-gc");
mStagePool.gc();
SYSTRACE_NAME_END();
SYSTRACE_NAME_BEGIN("framebuffercache-gc");
mFramebufferCache.gc();
SYSTRACE_NAME_END();
SYSTRACE_NAME_END(); // "gc"
FVK_SYSTRACE_END();
}
void VulkanDriver::beginFrame(int64_t monotonic_clock_ns, uint32_t frameId) {
// Do nothing.
}
@@ -306,14 +296,21 @@ void VulkanDriver::endFrame(uint32_t frameId) {
}
void VulkanDriver::flush(int) {
FVK_SYSTRACE_CONTEXT();
FVK_SYSTRACE_START("flush");
mCommands->flush();
FVK_SYSTRACE_END();
}
void VulkanDriver::finish(int dummy) {
FVK_SYSTRACE_CONTEXT();
FVK_SYSTRACE_START("finish");
mCommands->flush();
mCommands->wait();
mReadPixels.runUntilComplete();
FVK_SYSTRACE_END();
}
void VulkanDriver::createSamplerGroupR(Handle<HwSamplerGroup> sbh, uint32_t count) {
@@ -990,6 +987,9 @@ void VulkanDriver::compilePrograms(CompilerPriorityQueue priority,
}
void VulkanDriver::beginRenderPass(Handle<HwRenderTarget> rth, const RenderPassParams& params) {
FVK_SYSTRACE_CONTEXT();
FVK_SYSTRACE_START("beginRenderPass");
VulkanRenderTarget* const rt = mResourceAllocator.handle_cast<VulkanRenderTarget*>(rth);
const VkExtent2D extent = rt->getExtent();
assert_invariant(extent.width > 0 && extent.height > 0);
@@ -1008,7 +1008,8 @@ void VulkanDriver::beginRenderPass(Handle<HwRenderTarget> rth, const RenderPassP
}
VulkanAttachment depth = rt->getSamples() == 1 ? rt->getDepth() : rt->getMsaaDepth();
#if FILAMENT_VULKAN_VERBOSE
#if FVK_ENABLED(FVK_DEBUG_TEXTURE)
if (depth.texture) {
depth.texture->print();
}
@@ -1153,6 +1154,7 @@ void VulkanDriver::beginRenderPass(Handle<HwRenderTarget> rth, const RenderPassP
VkFramebuffer vkfb = mFramebufferCache.getFramebuffer(fbkey);
// Assign a label to the framebuffer for debugging purposes.
#if FVK_ENABLED(FVK_DEBUG_GROUP_MARKERS)
if (UTILS_UNLIKELY(mContext.isDebugUtilsSupported())) {
auto const topMarker = mCommands->getTopGroupMarker();
if (!topMarker.empty()) {
@@ -1166,6 +1168,7 @@ void VulkanDriver::beginRenderPass(Handle<HwRenderTarget> rth, const RenderPassP
vkSetDebugUtilsObjectNameEXT(mPlatform->getDevice(), &info);
}
}
#endif
// The current command buffer now owns a reference to the render target and its attachments.
// Note that we must acquire parent textures, not sidecars.
@@ -1242,9 +1245,13 @@ void VulkanDriver::beginRenderPass(Handle<HwRenderTarget> rth, const RenderPassP
.params = params,
.currentSubpass = 0,
};
FVK_SYSTRACE_END();
}
void VulkanDriver::endRenderPass(int) {
FVK_SYSTRACE_CONTEXT();
FVK_SYSTRACE_START("endRenderPass");
VulkanCommandBuffer& commands = mCommands->get();
VkCommandBuffer cmdbuffer = commands.buffer();
vkCmdEndRenderPass(cmdbuffer);
@@ -1288,6 +1295,7 @@ void VulkanDriver::endRenderPass(int) {
}
mCurrentRenderPass.renderTarget = nullptr;
mCurrentRenderPass.renderPass = VK_NULL_HANDLE;
FVK_SYSTRACE_END();
}
void VulkanDriver::nextSubpass(int) {
@@ -1334,6 +1342,9 @@ void VulkanDriver::setRenderPrimitiveRange(Handle<HwRenderPrimitive> rph,
}
void VulkanDriver::makeCurrent(Handle<HwSwapChain> drawSch, Handle<HwSwapChain> readSch) {
FVK_SYSTRACE_CONTEXT();
FVK_SYSTRACE_START("makeCurrent");
ASSERT_PRECONDITION_NON_FATAL(drawSch == readSch,
"Vulkan driver does not support distinct draw/read swap chains.");
VulkanSwapChain* swapChain = mCurrentSwapChain
@@ -1349,9 +1360,14 @@ void VulkanDriver::makeCurrent(Handle<HwSwapChain> drawSch, Handle<HwSwapChain>
if (UTILS_LIKELY(mDefaultRenderTarget)) {
mDefaultRenderTarget->bindToSwapChain(*swapChain);
}
FVK_SYSTRACE_END();
}
void VulkanDriver::commit(Handle<HwSwapChain> sch) {
FVK_SYSTRACE_CONTEXT();
FVK_SYSTRACE_START("commit");
VulkanSwapChain* swapChain = mResourceAllocator.handle_cast<VulkanSwapChain*>(sch);
if (mCommands->flush()) {
@@ -1360,6 +1376,7 @@ void VulkanDriver::commit(Handle<HwSwapChain> sch) {
// Present the backbuffer after the most recent command buffer submission has finished.
swapChain->present();
FVK_SYSTRACE_END();
}
void VulkanDriver::bindUniformBuffer(uint32_t index, Handle<HwBufferObject> boh) {
@@ -1391,24 +1408,26 @@ void VulkanDriver::bindSamplers(uint32_t index, Handle<HwSamplerGroup> sbh) {
}
void VulkanDriver::insertEventMarker(char const* string, uint32_t len) {
#if FVK_ENABLED(FVK_DEBUG_GROUP_MARKERS)
mCommands->insertEventMarker(string, len);
#endif
}
void VulkanDriver::pushGroupMarker(char const* string, uint32_t) {
// Turns out all the markers are 0-terminated, so we can just pass it without len.
#if FVK_ENABLED(FVK_DEBUG_GROUP_MARKERS)
mCommands->pushGroupMarker(string);
{
SYSTRACE_CONTEXT();
SYSTRACE_NAME_BEGIN(string);
}
#endif
FVK_SYSTRACE_CONTEXT();
FVK_SYSTRACE_START(string);
}
void VulkanDriver::popGroupMarker(int) {
#if FVK_ENABLED(FVK_DEBUG_GROUP_MARKERS)
mCommands->popGroupMarker();
{
SYSTRACE_CONTEXT();
SYSTRACE_NAME_END();
}
#endif
FVK_SYSTRACE_CONTEXT();
FVK_SYSTRACE_END();
}
void VulkanDriver::startCapture(int) {}
@@ -1439,6 +1458,9 @@ void VulkanDriver::readBufferSubData(backend::BufferObjectHandle boh,
void VulkanDriver::blit(TargetBufferFlags buffers, Handle<HwRenderTarget> dst, Viewport dstRect,
Handle<HwRenderTarget> src, Viewport srcRect, SamplerMagFilter filter) {
FVK_SYSTRACE_CONTEXT();
FVK_SYSTRACE_START("blit");
assert_invariant(mCurrentRenderPass.renderPass == VK_NULL_HANDLE);
// blit operation only support COLOR0 color buffer
@@ -1478,10 +1500,14 @@ void VulkanDriver::blit(TargetBufferFlags buffers, Handle<HwRenderTarget> dst, V
if (any(buffers & TargetBufferFlags::COLOR0)) {
mBlitter.blitColor({ dstTarget, dstOffsets, srcTarget, srcOffsets, vkfilter, int(0) });
}
FVK_SYSTRACE_END();
}
void VulkanDriver::draw(PipelineState pipelineState, Handle<HwRenderPrimitive> rph,
const uint32_t instanceCount) {
FVK_SYSTRACE_CONTEXT();
FVK_SYSTRACE_START("draw");
VulkanCommandBuffer* commands = &mCommands->get();
VkCommandBuffer cmdbuffer = commands->buffer();
const VulkanRenderPrimitive& prim = *mResourceAllocator.handle_cast<VulkanRenderPrimitive*>(rph);
@@ -1497,7 +1523,7 @@ void VulkanDriver::draw(PipelineState pipelineState, Handle<HwRenderPrimitive> r
commands->acquire(prim.vertexBuffer);
// If this is a debug build, validate the current shader.
#if !defined(NDEBUG)
#if FVK_ENABLED(FVK_DEBUG_SHADER_MODULE)
if (program->bundle.vertex == VK_NULL_HANDLE || program->bundle.fragment == VK_NULL_HANDLE) {
utils::slog.e << "Binding missing shader: " << program->name.c_str() << utils::io::endl;
}
@@ -1613,7 +1639,7 @@ void VulkanDriver::draw(PipelineState pipelineState, Handle<HwRenderPrimitive> r
// This fallback path is very flaky because the dummy texture might not have
// matching characteristics. (e.g. if the missing texture is a 3D texture)
if (UTILS_UNLIKELY(texture->getPrimaryImageLayout() == VulkanLayout::UNDEFINED)) {
#ifndef NDEBUG
#if FVK_ENABLED(FVK_DEBUG_TEXTURE)
utils::slog.w << "Uninitialized texture bound to '" << sampler.name.c_str() << "'";
utils::slog.w << " in material '" << program->name.c_str() << "'";
utils::slog.w << " at binding point " << +sampler.binding << utils::io::endl;
@@ -1687,6 +1713,7 @@ void VulkanDriver::draw(PipelineState pipelineState, Handle<HwRenderPrimitive> r
const uint32_t firstInstId = 0;
vkCmdDrawIndexed(cmdbuffer, indexCount, instanceCount, firstIndex, vertexOffset, firstInstId);
FVK_SYSTRACE_END();
}
void VulkanDriver::dispatchCompute(Handle<HwProgram> program, math::uint3 workGroupCount) {
@@ -23,7 +23,7 @@
// If any VkRenderPass or VkFramebuffer is unused for more than TIME_BEFORE_EVICTION frames, it
// is evicted from the cache.
static constexpr uint32_t TIME_BEFORE_EVICTION = VK_MAX_COMMAND_BUFFERS;
static constexpr uint32_t TIME_BEFORE_EVICTION = FVK_MAX_COMMAND_BUFFERS;
using namespace bluevk;
@@ -97,7 +97,7 @@ VkFramebuffer VulkanFboCache::getFramebuffer(FboKey config) noexcept {
attachments[attachmentCount++] = config.depth;
}
#if FILAMENT_VULKAN_VERBOSE
#if FVK_ENABLED(FVK_DEBUG_FBO_CACHE)
utils::slog.d << "Creating framebuffer " << config.width << "x" << config.height << " "
<< "for render pass " << config.renderPass << ", "
<< "samples = " << int(config.samples) << ", "
@@ -312,7 +312,7 @@ VkRenderPass VulkanFboCache::getRenderPass(RenderPassKey config) noexcept {
ASSERT_POSTCONDITION(!error, "Unable to create render pass.");
mRenderPassCache[config] = {renderPass, mCurrentTime};
#if FILAMENT_VULKAN_VERBOSE
#if FVK_ENABLED(FVK_DEBUG_FBO_CACHE)
utils::slog.d << "Created render pass " << renderPass << " with "
<< "samples = " << int(config.samples) << ", "
<< "depth = " << (hasDepth ? 1 : 0) << ", "
@@ -338,6 +338,9 @@ void VulkanFboCache::reset() noexcept {
// Frees up old framebuffers and render passes, then nulls out their key. Doesn't bother removing
// the actual map entry since it is fairly small.
void VulkanFboCache::gc() noexcept {
FVK_SYSTRACE_CONTEXT();
FVK_SYSTRACE_START("fbocache::gc");
// If this is one of the first few frames, return early to avoid wrapping unsigned integers.
if (++mCurrentTime <= TIME_BEFORE_EVICTION) {
return;
@@ -359,6 +362,7 @@ void VulkanFboCache::gc() noexcept {
iter.value().handle = VK_NULL_HANDLE;
}
}
FVK_SYSTRACE_END();
}
} // namespace filament::backend
@@ -114,10 +114,10 @@ VulkanProgram::VulkanProgram(VkDevice device, const Program& builder) noexcept
// Make a copy of the binding map
samplerGroupInfo = builder.getSamplerGroupInfo();
if constexpr (FILAMENT_VULKAN_VERBOSE) {
#if FVK_ENABLED(FVK_DEBUG_SHADER_MODULE)
utils::slog.d << "Created VulkanProgram " << builder << ", shaders = (" << bundle.vertex
<< ", " << bundle.fragment << ")" << utils::io::endl;
}
#endif
}
VulkanProgram::VulkanProgram(VkDevice device, VkShaderModule vs, VkShaderModule fs) noexcept
@@ -218,7 +218,7 @@ bool operator<(const VkImageSubresourceRange& a, const VkImageSubresourceRange&
return false;
}
#if FILAMENT_VULKAN_VERBOSE
#if FVK_ENABLED(FVK_DEBUG_LAYOUT_TRANSITION | FVK_DEBUG_TEXTURE)
#define CASE(VALUE) \
case filament::backend::VulkanLayout::VALUE: { \
out << #VALUE; \
@@ -481,10 +481,10 @@ VulkanPipelineCache::PipelineCacheEntry* VulkanPipelineCache::createPipeline() n
PipelineCacheEntry cacheEntry = {};
if constexpr (FILAMENT_VULKAN_VERBOSE) {
#if FVK_ENABLED(FVK_DEBUG_SHADER_MODULE)
utils::slog.d << "vkCreateGraphicsPipelines with shaders = ("
<< shaderStages[0].module << ", " << shaderStages[1].module << ")" << utils::io::endl;
}
#endif
VkResult error = vkCreateGraphicsPipelines(mDevice, VK_NULL_HANDLE, 1, &pipelineCreateInfo,
VKALLOC, &cacheEntry.handle);
assert_invariant(error == VK_SUCCESS);
@@ -681,7 +681,7 @@ void VulkanPipelineCache::terminate() noexcept {
void VulkanPipelineCache::onCommandBuffer(const VulkanCommandBuffer& commands) {
// The timestamp associated with a given cache entry represents "time" as a count of flush
// events since the cache was constructed. If any cache entry was most recently used over
// VK_MAX_PIPELINE_AGE flush events in the past, then we can be sure that it is no longer
// FVK_MAX_PIPELINE_AGE flush events in the past, then we can be sure that it is no longer
// being used by the GPU, and is therefore safe to destroy or reclaim.
++mCurrentTime;
@@ -698,7 +698,7 @@ void VulkanPipelineCache::onCommandBuffer(const VulkanCommandBuffer& commands) {
using ConstDescIterator = decltype(mDescriptorSets)::const_iterator;
for (ConstDescIterator iter = mDescriptorSets.begin(); iter != mDescriptorSets.end();) {
const DescriptorCacheEntry& cacheEntry = iter.value();
if (cacheEntry.lastUsed + VK_MAX_PIPELINE_AGE < mCurrentTime) {
if (cacheEntry.lastUsed + FVK_MAX_PIPELINE_AGE < mCurrentTime) {
auto& arenas = mPipelineLayouts[cacheEntry.pipelineLayout].descriptorSetArenas;
for (uint32_t i = 0; i < DESCRIPTOR_TYPE_COUNT; ++i) {
arenas[i].push_back(cacheEntry.handles[i]);
@@ -712,11 +712,11 @@ void VulkanPipelineCache::onCommandBuffer(const VulkanCommandBuffer& commands) {
}
// Evict any pipelines that have not been used in a while.
// Any pipeline older than VK_MAX_COMMAND_BUFFERS can be safely destroyed.
// Any pipeline older than FVK_MAX_COMMAND_BUFFERS can be safely destroyed.
using ConstPipeIterator = decltype(mPipelines)::const_iterator;
for (ConstPipeIterator iter = mPipelines.begin(); iter != mPipelines.end();) {
const PipelineCacheEntry& cacheEntry = iter.value();
if (cacheEntry.lastUsed + VK_MAX_PIPELINE_AGE < mCurrentTime) {
if (cacheEntry.lastUsed + FVK_MAX_PIPELINE_AGE < mCurrentTime) {
vkDestroyPipeline(mDevice, iter->second.handle, VKALLOC);
iter = mPipelines.erase(iter);
} else {
@@ -728,15 +728,15 @@ void VulkanPipelineCache::onCommandBuffer(const VulkanCommandBuffer& commands) {
using ConstLayoutIterator = decltype(mPipelineLayouts)::const_iterator;
for (ConstLayoutIterator iter = mPipelineLayouts.begin(); iter != mPipelineLayouts.end();) {
const PipelineLayoutCacheEntry& cacheEntry = iter.value();
if (cacheEntry.lastUsed + VK_MAX_PIPELINE_AGE < mCurrentTime) {
if (cacheEntry.lastUsed + FVK_MAX_PIPELINE_AGE < mCurrentTime) {
vkDestroyPipelineLayout(mDevice, iter->second.handle, VKALLOC);
for (auto setLayout : iter->second.descriptorSetLayouts) {
#ifndef NDEBUG
#if FVK_ENABLED(FVK_DEBUG_PIPELINE_CACHE)
PipelineLayoutKey key = iter.key();
for (auto& pair : mDescriptorSets) {
assert_invariant(pair.second.pipelineLayout != key);
}
#endif
#endif
vkDestroyDescriptorSetLayout(mDevice, setLayout, VKALLOC);
}
auto& arenas = iter->second.descriptorSetArenas;
@@ -755,7 +755,7 @@ void VulkanPipelineCache::onCommandBuffer(const VulkanCommandBuffer& commands) {
// destroy the extinct pools, which implicitly frees their associated descriptor sets.
bool canPurgeExtinctPools = true;
for (auto& bundle : mExtinctDescriptorBundles) {
if (bundle.lastUsed + VK_MAX_PIPELINE_AGE >= mCurrentTime) {
if (bundle.lastUsed + FVK_MAX_PIPELINE_AGE >= mCurrentTime) {
canPurgeExtinctPools = false;
break;
}
@@ -799,7 +799,7 @@ VkDescriptorPool VulkanPipelineCache::createDescriptorPool(uint32_t size) const
void VulkanPipelineCache::destroyLayoutsAndDescriptors() noexcept {
// Our current descriptor set strategy can cause the # of descriptor sets to explode in certain
// situations, so it's interesting to report the number that get stuffed into the cache.
#ifndef NDEBUG
#if FVK_ENABLED(FVK_DEBUG_PIPELINE_CACHE)
utils::slog.d << "Destroying " << mDescriptorSets.size() << " bundles of descriptor sets."
<< utils::io::endl;
#endif
@@ -808,7 +808,7 @@ void VulkanPipelineCache::destroyLayoutsAndDescriptors() noexcept {
// Our current layout bundle strategy can cause the # of layout bundles to explode in certain
// situations, so it's interesting to report the number that get stuffed into the cache.
#ifndef NDEBUG
#if FVK_ENABLED(FVK_DEBUG_PIPELINE_CACHE)
utils::slog.d << "Destroying " << mPipelineLayouts.size() << " pipeline layouts."
<< utils::io::endl;
#endif
@@ -340,7 +340,7 @@ private:
// The timestamp associated with a given cache entry represents time as a count of flush
// events since the cache was constructed. If any cache entry was most recently used over
// VK_MAX_PIPELINE_AGE flushes in the past, then we can be sure that it is no longer
// FVK_MAX_PIPELINE_AGE flushes in the past, then we can be sure that it is no longer
// being used by the GPU, and is therefore safe to destroy or reclaim.
using Timestamp = uint64_t;
Timestamp mCurrentTime = 0;
@@ -167,7 +167,7 @@ void VulkanReadPixels::run(VulkanRenderTarget const* srcTarget, uint32_t const x
VkImage stagingImage;
vkCreateImage(device, &imageInfo, VKALLOC, &stagingImage);
#if FILAMENT_VULKAN_VERBOSE
#if FVK_ENABLED(FVK_DEBUG_READ_PIXELS)
utils::slog.d << "readPixels created image=" << stagingImage
<< " to copy from image=" << srcTexture->getVkImage()
<< " src-layout=" << srcTexture->getLayout(0, 0) << utils::io::endl;
@@ -22,7 +22,7 @@
#include <utils/Panic.h>
static constexpr uint32_t TIME_BEFORE_EVICTION = VK_MAX_COMMAND_BUFFERS;
static constexpr uint32_t TIME_BEFORE_EVICTION = FVK_MAX_COMMAND_BUFFERS;
namespace filament::backend {
@@ -59,7 +59,7 @@ VulkanStage const* VulkanStagePool::acquireStage(uint32_t numBytes) {
UTILS_UNUSED_IN_RELEASE VkResult result = vmaCreateBuffer(mAllocator, &bufferInfo,
&allocInfo, &stage->buffer, &stage->memory, nullptr);
#ifndef NDEBUG
#if FVK_ENABLED(FVK_DEBUG_ALLOCATION)
if (result != VK_SUCCESS) {
utils::slog.e << "Allocation error: " << result << utils::io::endl;
}
@@ -129,6 +129,9 @@ VulkanStageImage const* VulkanStagePool::acquireImage(PixelDataFormat format, Pi
}
void VulkanStagePool::gc() noexcept {
FVK_SYSTRACE_CONTEXT();
FVK_SYSTRACE_START("stagepool::gc");
// If this is one of the first few frames, return early to avoid wrapping unsigned integers.
if (++mCurrentFrame <= TIME_BEFORE_EVICTION) {
return;
@@ -182,6 +185,7 @@ void VulkanStagePool::gc() noexcept {
mUsedImages.insert(image);
}
}
FVK_SYSTRACE_END();
}
void VulkanStagePool::terminate() noexcept {
@@ -106,7 +106,7 @@ VulkanTexture::VulkanTexture(VkDevice device, VkPhysicalDevice physicalDevice,
if (any(usage & TextureUsage::SAMPLEABLE)) {
#if VK_ENABLE_VALIDATION
#if FVK_ENABLED(FVK_DEBUG_TEXTURE)
// Validate that the format is actually sampleable.
VkFormatProperties props;
vkGetPhysicalDeviceFormatProperties(physicalDevice, mVkFormat, &props);
@@ -160,7 +160,7 @@ VulkanTexture::VulkanTexture(VkDevice device, VkPhysicalDevice physicalDevice,
imageInfo.samples = (VkSampleCountFlagBits) samples;
VkResult error = vkCreateImage(mDevice, &imageInfo, VKALLOC, &mTextureImage);
if (error || FILAMENT_VULKAN_VERBOSE) {
if (error || FVK_ENABLED_BOOL(FVK_DEBUG_TEXTURE)) {
utils::slog.d << "vkCreateImage: "
<< "image = " << mTextureImage << ", "
<< "result = " << error << ", "
@@ -417,7 +417,7 @@ void VulkanTexture::transitionLayout(VkCommandBuffer cmdbuf, const VkImageSubres
VulkanLayout newLayout) {
VulkanLayout oldLayout = getLayout(range.baseArrayLayer, range.baseMipLevel);
#if FILAMENT_VULKAN_VERBOSE
#if FVK_ENABLED(FVK_DEBUG_LAYOUT_TRANSITION)
utils::slog.i << "transition layout of " << mTextureImage << ",layer=" << range.baseArrayLayer
<< ",level=" << range.baseMipLevel << " from=" << oldLayout << " to=" << newLayout
<< " format=" << mVkFormat
@@ -463,7 +463,7 @@ VulkanLayout VulkanTexture::getLayout(uint32_t layer, uint32_t level) const {
return mSubresourceLayouts.get(key);
}
#if FILAMENT_VULKAN_VERBOSE
#if FVK_ENABLED(FVK_DEBUG_TEXTURE)
void VulkanTexture::print() const {
const uint32_t firstLayer = 0;
const uint32_t lastLayer = firstLayer + mPrimaryViewRange.layerCount;
+1 -1
View File
@@ -84,7 +84,7 @@ struct VulkanTexture : public HwTexture, VulkanResource {
// For now this always returns either DEPTH or COLOR.
VkImageAspectFlags getImageAspect() const;
#if FILAMENT_VULKAN_VERBOSE
#if FVK_ENABLED(FVK_DEBUG_TEXTURE)
void print() const;
#endif
@@ -45,11 +45,11 @@ constexpr uint32_t const INVALID_VK_INDEX = 0xFFFFFFFF;
typedef std::unordered_set<std::string_view> ExtensionSet;
#if VK_ENABLE_VALIDATION
#if FVK_ENABLED(FVK_DEBUG_VALIDATION)
// These strings need to be allocated outside a function stack
const std::string_view DESIRED_LAYERS[] = {
"VK_LAYER_KHRONOS_validation",
#if FILAMENT_VULKAN_DUMP_API
#if FVK_ENABLED(FVK_DEBUG_DUMP_API)
"VK_LAYER_LUNARG_api_dump",
#endif
#if defined(ENABLE_RENDERDOC)
@@ -75,7 +75,7 @@ FixedCapacityVector<const char*> getEnabledLayers() {
}
return enabledLayers;
}
#endif
#endif // FVK_EANBLED(FVK_DEBUG_VALIDATION)
void printDeviceInfo(VkInstance instance, VkPhysicalDevice device) {
// Print some driver or MoltenVK information if it is available.
@@ -129,27 +129,27 @@ void printDeviceInfo(VkInstance instance, VkPhysicalDevice device) {
<< minor << ")" << utils::io::endl;
}
#if FVK_ENABLED(FVK_DEBUG_VALIDATION)
void printDepthFormats(VkPhysicalDevice device) {
// For diagnostic purposes, print useful information about available depth formats.
// Note that Vulkan is more constrained than OpenGL ES 3.1 in this area.
if constexpr (VK_ENABLE_VALIDATION && FILAMENT_VULKAN_VERBOSE) {
const VkFormatFeatureFlags required = VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT
const VkFormatFeatureFlags required = VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT
| VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT;
utils::slog.i << "Sampleable depth formats: ";
for (VkFormat format = (VkFormat) 1;;) {
VkFormatProperties props;
vkGetPhysicalDeviceFormatProperties(device, format, &props);
if ((props.optimalTilingFeatures & required) == required) {
utils::slog.i << format << " ";
}
if (format == VK_FORMAT_ASTC_12x12_SRGB_BLOCK) {
utils::slog.i << utils::io::endl;
break;
}
format = (VkFormat) (1 + (int) format);
utils::slog.i << "Sampleable depth formats: ";
for (VkFormat format = (VkFormat) 1;;) {
VkFormatProperties props;
vkGetPhysicalDeviceFormatProperties(device, format, &props);
if ((props.optimalTilingFeatures & required) == required) {
utils::slog.i << format << " ";
}
if (format == VK_FORMAT_ASTC_12x12_SRGB_BLOCK) {
utils::slog.i << utils::io::endl;
break;
}
format = (VkFormat) (1 + (int) format);
}
}
#endif
ExtensionSet getInstanceExtensions() {
std::string_view const TARGET_EXTS[] = {
@@ -161,7 +161,7 @@ ExtensionSet getInstanceExtensions() {
VK_EXT_DEBUG_UTILS_EXTENSION_NAME,
VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME,
#if VK_ENABLE_VALIDATION
#if FVK_ENABLED(FVK_DEBUG_VALIDATION)
VK_EXT_DEBUG_REPORT_EXTENSION_NAME,
#endif
};
@@ -207,7 +207,7 @@ VkInstance createInstance(ExtensionSet const& requiredExts) {
VkInstanceCreateInfo instanceCreateInfo = {};
bool validationFeaturesSupported = false;
#if VK_ENABLE_VALIDATION
#if FVK_ENABLED(FVK_DEBUG_VALIDATION)
auto const enabledLayers = getEnabledLayers();
if (!enabledLayers.empty()) {
// If layers are supported, Check if VK_EXT_validation_features is supported.
@@ -229,9 +229,10 @@ VkInstance createInstance(ExtensionSet const& requiredExts) {
#else
utils::slog.d << "Validation layer not available; did you install the Vulkan SDK?\n"
<< "Please ensure that VK_LAYER_PATH is set correctly." << utils::io::endl;
#endif
#endif // __ANDROID__
}
#endif// VK_ENABLE_VALIDATION
#endif // FVK_ENABLED(FVK_DEBUG_VALIDATION)
// The Platform class can require 1 or 2 instance extensions, plus we'll request at most 5
// instance extensions here in the common code. So that's a max of 7.
@@ -252,7 +253,7 @@ VkInstance createInstance(ExtensionSet const& requiredExts) {
VkApplicationInfo appInfo = {};
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
appInfo.apiVersion
= VK_MAKE_API_VERSION(0, VK_REQUIRED_VERSION_MAJOR, VK_REQUIRED_VERSION_MINOR, 0);
= VK_MAKE_API_VERSION(0, FVK_REQUIRED_VERSION_MAJOR, FVK_REQUIRED_VERSION_MINOR, 0);
instanceCreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
instanceCreateInfo.pApplicationInfo = &appInfo;
instanceCreateInfo.enabledExtensionCount = enabledExtensionCount;
@@ -274,12 +275,8 @@ VkInstance createInstance(ExtensionSet const& requiredExts) {
}
VkResult result = vkCreateInstance(&instanceCreateInfo, VKALLOC, &instance);
#ifndef NDEBUG
if (result != VK_SUCCESS) {
utils::slog.e << "Unable to create instance: " << result << utils::io::endl;
}
#endif
ASSERT_POSTCONDITION(result == VK_SUCCESS, "Unable to create Vulkan instance.");
ASSERT_POSTCONDITION(result == VK_SUCCESS, "Unable to create Vulkan instance. Result=%d",
result);
return instance;
}
@@ -443,10 +440,10 @@ VkPhysicalDevice selectPhysicalDevice(VkInstance instance,
int const minor = VK_VERSION_MINOR(targetDeviceProperties.apiVersion);
// Does the device support the required Vulkan level?
if (major < VK_REQUIRED_VERSION_MAJOR) {
if (major < FVK_REQUIRED_VERSION_MAJOR) {
continue;
}
if (major == VK_REQUIRED_VERSION_MAJOR && minor < VK_REQUIRED_VERSION_MINOR) {
if (major == FVK_REQUIRED_VERSION_MAJOR && minor < FVK_REQUIRED_VERSION_MINOR) {
continue;
}
@@ -667,7 +664,9 @@ Driver* VulkanPlatform::createDriver(void* sharedContext,
// just yet, since that would require a corollary change to the "aspect" flags for the VkImage.
context.mDepthFormat = findSupportedFormat(mImpl->mPhysicalDevice);
#if FVK_ENABLED(FVK_DEBUG_VALIDATION)
printDepthFormats(mImpl->mPhysicalDevice);
#endif
// Keep a copy of context for swapchains.
mImpl->mContext = context;