[dxvk,d3d9,d3d11] Decouple ID3DUserDefinedAnnotation from internal markers

Some games nope out when we expose debug markers, so add a debug mode
that doesn't while still providing internal markers and debug names.
This commit is contained in:
Philip Rebohle 2025-03-06 02:01:43 +01:00
parent 91b48dd31d
commit 542e0d2ab0
15 changed files with 65 additions and 38 deletions

View file

@ -38,7 +38,7 @@ namespace dxvk {
ContextType* container,
const Rc<DxvkDevice>& dxvkDevice)
: m_container(container),
m_annotationsEnabled(dxvkDevice->isDebugEnabled()) {
m_annotationsEnabled(dxvkDevice->debugFlags().test(DxvkDebugFlag::Markers)) {
if (!IsDeferred && m_annotationsEnabled)
RegisterUserDefinedAnnotation<true>(this);
}

View file

@ -98,7 +98,7 @@ namespace dxvk {
// on queries without ever flushing the context otherwise.
D3D10DeviceLock lock = LockContext();
if (unlikely(m_device->isDebugEnabled()))
if (unlikely(m_device->debugFlags().test(DxvkDebugFlag::Capture)))
m_flushReason = "Query read-back";
ConsiderFlush(GpuFlushType::ImplicitSynchronization);
@ -160,7 +160,7 @@ namespace dxvk {
void STDMETHODCALLTYPE D3D11ImmediateContext::Flush() {
D3D10DeviceLock lock = LockContext();
if (unlikely(m_device->isDebugEnabled()))
if (unlikely(m_device->debugFlags().test(DxvkDebugFlag::Capture)))
m_flushReason = "Explicit Flush";
ExecuteFlush(GpuFlushType::ExplicitFlush, nullptr, true);
@ -172,7 +172,7 @@ namespace dxvk {
HANDLE hEvent) {
D3D10DeviceLock lock = LockContext();
if (unlikely(m_device->isDebugEnabled()))
if (unlikely(m_device->debugFlags().test(DxvkDebugFlag::Capture)))
m_flushReason = "Explicit Flush";
ExecuteFlush(GpuFlushType::ExplicitFlush, hEvent, true);
@ -195,7 +195,7 @@ namespace dxvk {
ctx->signalFence(cFence, cValue);
});
if (unlikely(m_device->isDebugEnabled()))
if (unlikely(m_device->debugFlags().test(DxvkDebugFlag::Capture)))
m_flushReason = "Fence signal";
ExecuteFlush(GpuFlushType::ExplicitFlush, nullptr, true);
@ -212,7 +212,7 @@ namespace dxvk {
if (!fence)
return E_INVALIDARG;
if (unlikely(m_device->isDebugEnabled()))
if (unlikely(m_device->debugFlags().test(DxvkDebugFlag::Capture)))
m_flushReason = "Fence wait";
ExecuteFlush(GpuFlushType::ExplicitFlush, nullptr, true);
@ -926,7 +926,7 @@ namespace dxvk {
return true;
}
if (unlikely(m_device->isDebugEnabled())) {
if (unlikely(m_device->debugFlags().test(DxvkDebugFlag::Capture))) {
m_flushReason = str::format("Map ", Resource.getDebugName(), " (MAP",
MapType != D3D11_MAP_WRITE ? "_READ" : "",
MapType != D3D11_MAP_READ ? "_WRITE" : "", ")");

View file

@ -70,7 +70,7 @@ namespace dxvk {
if (canSWVP)
Logger::info("D3D9DeviceEx: Using extended constant set for software vertex processing.");
if (m_dxvkDevice->isDebugEnabled())
if (m_dxvkDevice->debugFlags().test(DxvkDebugFlag::Markers))
m_annotation = new D3D9UserDefinedAnnotation(this);
m_initializer = new D3D9Initializer(this);

View file

@ -20,7 +20,7 @@ namespace dxvk {
m_allocator->registerResource(this);
// Assign debug name to buffer
if (device->isDebugEnabled()) {
if (device->debugFlags().test(DxvkDebugFlag::Capture)) {
m_debugName = createDebugName(createInfo.debugName);
m_info.debugName = m_debugName.c_str();
} else {

View file

@ -150,7 +150,7 @@ namespace dxvk {
if (vk->vkBeginCommandBuffer(commandBuffer, &info))
throw DxvkError("DxvkCommandPool: Failed to begin command buffer");
if (m_device->isDebugEnabled()) {
if (m_device->debugFlags().test(DxvkDebugFlag::Capture)) {
auto vki = m_device->vki();
VkDebugUtilsLabelEXT label = { };
@ -470,7 +470,7 @@ namespace dxvk {
void DxvkCommandList::endCommandBuffer(VkCommandBuffer cmdBuffer) {
auto vk = m_device->vkd();
if (m_device->isDebugEnabled())
if (m_device->debugFlags().test(DxvkDebugFlag::Capture))
m_vki->vkCmdEndDebugUtilsLabelEXT(cmdBuffer);
if (vk->vkEndCommandBuffer(cmdBuffer))

View file

@ -55,7 +55,7 @@ namespace dxvk {
m_features.set(DxvkContextFeature::DirectMultiDraw);
// Add a fast path to query debug utils support
if (m_device->isDebugEnabled())
if (m_device->debugFlags().test(DxvkDebugFlag::Capture))
m_features.set(DxvkContextFeature::DebugUtils);
}

View file

@ -16,6 +16,7 @@ namespace dxvk {
m_instance (instance),
m_adapter (adapter),
m_vkd (vkd),
m_debugFlags (instance->debugFlags()),
m_queues (queues),
m_features (features),
m_properties (adapter->devicePropertiesExt()),

View file

@ -115,8 +115,8 @@ namespace dxvk {
* \brief Checks whether debug functionality is enabled
* \returns \c true if debug utils are enabled
*/
bool isDebugEnabled() const {
return bool(m_instance->extensions().extDebugUtils);
DxvkDebugFlags debugFlags() const {
return m_debugFlags;
}
/**
@ -602,6 +602,7 @@ namespace dxvk {
Rc<DxvkAdapter> m_adapter;
Rc<vk::DeviceFn> m_vkd;
DxvkDebugFlags m_debugFlags;
DxvkDeviceQueueSet m_queues;
DxvkDeviceFeatures m_features;

View file

@ -19,7 +19,7 @@ namespace dxvk {
copyFormatList(createInfo.viewFormatCount, createInfo.viewFormats);
// Assign debug name to image
if (device->isDebugEnabled()) {
if (device->debugFlags().test(DxvkDebugFlag::Capture)) {
m_debugName = createDebugName(createInfo.debugName);
m_info.debugName = m_debugName.c_str();
} else {

View file

@ -117,8 +117,7 @@ namespace dxvk {
DxvkNameList layerList;
m_extensionSet = DxvkNameSet();
bool enablePerfEvents = false;
bool enableValidation = false;
DxvkDebugFlags debugFlags = 0u;
if (args.instance) {
m_extensionNames = DxvkNameList(args.extensionCount, args.extensionNames);
@ -133,15 +132,17 @@ namespace dxvk {
// This extension adds additional overhead to winevulkan.
std::string debugEnv = env::getEnvVar("DXVK_DEBUG");
enablePerfEvents = debugEnv == "markers";
enableValidation = debugEnv == "validation";
if (debugEnv == "validation")
debugFlags.set(DxvkDebugFlag::Validation);
else if (debugEnv == "markers")
debugFlags.set(DxvkDebugFlag::Capture, DxvkDebugFlag::Markers);
else if (debugEnv == "capture" || m_options.enableDebugUtils)
debugFlags.set(DxvkDebugFlag::Capture);
bool enableDebug = enablePerfEvents || enableValidation || m_options.enableDebugUtils;
if (enableDebug) {
if (!debugFlags.isClear()) {
Logger::warn("Debug Utils are enabled. May affect performance.");
if (enableValidation) {
if (debugFlags.test(DxvkDebugFlag::Validation)) {
const char* layerName = "VK_LAYER_KHRONOS_validation";
DxvkNameSet layers = DxvkNameSet::enumInstanceLayers(m_vkl);
@ -157,7 +158,7 @@ namespace dxvk {
// Get set of extensions to enable based on available
// extensions and extension providers.
auto extensionInfos = getExtensionList(m_extensions, enableDebug);
auto extensionInfos = getExtensionList(m_extensions, !debugFlags.isClear());
DxvkNameSet extensionsAvailable = DxvkNameSet::enumInstanceExtensions(m_vkl);
if (!extensionsAvailable.enableExtensions(extensionInfos.size(), extensionInfos.data(), &m_extensionSet))
@ -202,7 +203,7 @@ namespace dxvk {
// Create the Vulkan instance loader
m_vki = new vk::InstanceFn(m_vkl, !args.instance, instance);
if (enableValidation) {
if (debugFlags.test(DxvkDebugFlag::Validation)) {
VkDebugUtilsMessengerCreateInfoEXT messengerInfo = { VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT };
messengerInfo.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT
| VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT
@ -214,6 +215,9 @@ namespace dxvk {
if (m_vki->vkCreateDebugUtilsMessengerEXT(m_vki->instance(), &messengerInfo, nullptr, &m_messenger))
Logger::err("DxvkInstance::createInstance: Failed to create debug messenger, proceeding without.");
}
// Write back debug flags
m_debugFlags = debugFlags;
}

View file

@ -20,6 +20,18 @@ namespace dxvk {
};
/**
* \brief Debug flags
*/
enum class DxvkDebugFlag : uint32_t {
Validation = 0,
Capture = 1,
Markers = 2,
};
using DxvkDebugFlags = Flags<DxvkDebugFlag>;
/**
* \brief Instance creation flags
*
@ -156,6 +168,14 @@ namespace dxvk {
const DxvkNameList& extensionNameList() const {
return m_extensionNames;
}
/**
* \brief Debug flags
* \returns Debug flags
*/
DxvkDebugFlags debugFlags() const {
return m_debugFlags;
}
private:
@ -167,6 +187,7 @@ namespace dxvk {
DxvkInstanceExtensions m_extensions;
DxvkNameSet m_extensionSet;
DxvkNameList m_extensionNames;
DxvkDebugFlags m_debugFlags = 0u;
VkDebugUtilsMessengerEXT m_messenger = VK_NULL_HANDLE;

View file

@ -774,7 +774,7 @@ namespace dxvk {
} else {
// Do not suballocate buffers if debug mode is enabled in order
// to allow the application to set meaningful debug names.
allowSuballocation = !m_device->isDebugEnabled();
allowSuballocation = !m_device->debugFlags().test(DxvkDebugFlag::Capture);
}
// If there is at least one memory type that supports the required
@ -1219,7 +1219,7 @@ namespace dxvk {
result.cookie = ++m_nextCookie;
if (unlikely(m_device->isDebugEnabled()))
if (unlikely(m_device->debugFlags().test(DxvkDebugFlag::Capture)))
assignMemoryDebugName(result, type);
type.stats.memoryAllocated += size;

View file

@ -267,7 +267,7 @@ namespace dxvk {
VkColorSpaceKHR dstColorSpace = dstView->image()->info().colorSpace;
VkColorSpaceKHR srcColorSpace = srcView->image()->info().colorSpace;
if (unlikely(m_device->isDebugEnabled())) {
if (unlikely(m_device->debugFlags().test(DxvkDebugFlag::Capture))) {
ctx.cmd->cmdBeginDebugUtilsLabel(DxvkCmdBuffer::ExecBuffer,
vk::makeLabel(0xdcc0f0, "Swapchain blit"));
}
@ -388,7 +388,7 @@ namespace dxvk {
ctx.cmd->cmdDraw(3, 1, 0, 0);
if (unlikely(m_device->isDebugEnabled()))
if (unlikely(m_device->debugFlags().test(DxvkDebugFlag::Capture)))
ctx.cmd->cmdEndDebugUtilsLabel(DxvkCmdBuffer::ExecBuffer);
// Make sure to keep used resources alive
@ -420,7 +420,7 @@ namespace dxvk {
if (!m_hudImage || m_hudImage->info().extent != extent)
createHudImage(extent);
if (unlikely(m_device->isDebugEnabled())) {
if (unlikely(m_device->debugFlags().test(DxvkDebugFlag::Capture))) {
ctx.cmd->cmdBeginDebugUtilsLabel(DxvkCmdBuffer::ExecBuffer,
vk::makeLabel(0xdcc0f0, "HUD render"));
}
@ -474,7 +474,7 @@ namespace dxvk {
ctx.cmd->cmdPipelineBarrier(DxvkCmdBuffer::ExecBuffer, &depInfo);
if (unlikely(m_device->isDebugEnabled()))
if (unlikely(m_device->debugFlags().test(DxvkDebugFlag::Capture)))
ctx.cmd->cmdEndDebugUtilsLabel(DxvkCmdBuffer::ExecBuffer);
ctx.cmd->track(m_hudImage, DxvkAccess::Write);
@ -532,7 +532,7 @@ namespace dxvk {
if (!m_cursorRect.extent.width || !m_cursorRect.extent.height)
return;
if (unlikely(m_device->isDebugEnabled())) {
if (unlikely(m_device->debugFlags().test(DxvkDebugFlag::Capture))) {
ctx.cmd->cmdBeginDebugUtilsLabel(DxvkCmdBuffer::ExecBuffer,
vk::makeLabel(0xdcc0f0, "Software cursor"));
}
@ -601,7 +601,7 @@ namespace dxvk {
ctx.cmd->cmdDraw(4, 1, 0, 0);
if (unlikely(m_device->isDebugEnabled()))
if (unlikely(m_device->debugFlags().test(DxvkDebugFlag::Capture)))
ctx.cmd->cmdEndDebugUtilsLabel(DxvkCmdBuffer::ExecBuffer);
ctx.cmd->track(m_cursorImage, DxvkAccess::Write);
@ -1137,4 +1137,4 @@ namespace dxvk {
}
}
}
}

View file

@ -279,7 +279,7 @@ namespace dxvk::hud {
uint32_t dataPoint,
HudPos minPos,
HudPos maxPos) {
if (unlikely(m_device->isDebugEnabled())) {
if (unlikely(m_device->debugFlags().test(DxvkDebugFlag::Capture))) {
ctx.cmd->cmdBeginDebugUtilsLabel(DxvkCmdBuffer::InitBuffer,
vk::makeLabel(0xf0c0dc, "HUD frame time processing"));
}
@ -379,7 +379,7 @@ namespace dxvk::hud {
renderer.drawTextIndirect(ctx, key, drawParamBuffer,
drawInfoBuffer, textBufferView, 2u);
if (unlikely(m_device->isDebugEnabled()))
if (unlikely(m_device->debugFlags().test(DxvkDebugFlag::Capture)))
ctx.cmd->cmdEndDebugUtilsLabel(DxvkCmdBuffer::InitBuffer);
// Make sure GPU resources are being kept alive as necessary

View file

@ -58,7 +58,7 @@ namespace dxvk::hud {
const DxvkContextObjects& ctx,
const Rc<DxvkImageView>& dstView,
const HudOptions& options) {
if (unlikely(m_device->isDebugEnabled())) {
if (unlikely(m_device->debugFlags().test(DxvkDebugFlag::Capture))) {
ctx.cmd->cmdBeginDebugUtilsLabel(DxvkCmdBuffer::ExecBuffer,
vk::makeLabel(0xf0c0dc, "HUD"));
}
@ -93,7 +93,7 @@ namespace dxvk::hud {
void HudRenderer::endFrame(
const DxvkContextObjects& ctx) {
if (unlikely(m_device->isDebugEnabled()))
if (unlikely(m_device->debugFlags().test(DxvkDebugFlag::Capture)))
ctx.cmd->cmdEndDebugUtilsLabel(DxvkCmdBuffer::ExecBuffer);
}