Skip to content

Commit

Permalink
[REMIX-1008] Select objects with mouse on screen for texture tagging
Browse files Browse the repository at this point in the history
  • Loading branch information
sultim-t-nv committed Sep 27, 2023
1 parent e1d5cf4 commit a60b141
Show file tree
Hide file tree
Showing 19 changed files with 760 additions and 114 deletions.
336 changes: 258 additions & 78 deletions src/dxvk/imgui/dxvk_imgui.cpp

Large diffs are not rendered by default.

2 changes: 0 additions & 2 deletions src/dxvk/imgui/dxvk_imgui.h
Original file line number Diff line number Diff line change
Expand Up @@ -207,8 +207,6 @@ namespace dxvk {
// helper to display a configurable grid of all textures currently hooked to ImGUI
void showTextureSelectionGrid(const Rc<DxvkContext>& ctx, const char* uniqueId, const uint32_t texturesPerRow, const float thumbnailSize);

void toggleTextureSelection(XXH64_hash_t textureHash, const char* uniqueId, fast_unordered_set& textureSet);

void createFontsTexture(const Rc<DxvkContext>& ctx);

void setupStyle(ImGuiStyle* dst = NULL); // custom style
Expand Down
52 changes: 49 additions & 3 deletions src/dxvk/rtx_render/rtx_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -532,6 +532,7 @@ namespace dxvk {

// Debug view overrides
dispatchDebugView(srcImage, rtOutput, captureScreenImage);
dispatchHighlighting(rtOutput);

dispatchDLFG();
{
Expand Down Expand Up @@ -886,8 +887,19 @@ namespace dxvk {

constants.gpuPrintThreadIndex = u16vec2 { kInvalidThreadIndex, kInvalidThreadIndex };
constants.gpuPrintElementIndex = frameIdx % kMaxFramesInFlight;

if (debugView.gpuPrint.enable() && ImGui::IsKeyDown(ImGuiKey_ModCtrl)) {
constants.enableTexturePicking = false;

if (auto pixToCheck = debugView.isFindSurfaceRequestActive(frameIdx)) {
auto toDownscaledExtentScale = Vector2 {
downscaledExtent.width / static_cast<float>(targetExtent.width),
downscaledExtent.height / static_cast<float>(targetExtent.height)
};
constants.gpuPrintThreadIndex = u16vec2 {
static_cast<uint16_t>(pixToCheck->x * toDownscaledExtentScale.x),
static_cast<uint16_t>(pixToCheck->y * toDownscaledExtentScale.y)
};
constants.enableTexturePicking = true;
} else if (debugView.gpuPrint.enable() && ImGui::IsKeyDown(ImGuiKey_ModCtrl)) {
if (debugView.gpuPrint.useMousePosition()) {
Vector2 toDownscaledExtentScale = {
downscaledExtent.width / static_cast<float>(targetExtent.width),
Expand Down Expand Up @@ -1392,7 +1404,10 @@ namespace dxvk {
const RaytraceArgs& constants = rtOutput.m_raytraceArgs;
const uint32_t frameIdx = m_device->getCurrentFrameId();

if (debugView.gpuPrint.enable()) {
const bool findSurfaceRequestActive = bool { debugView.isFindSurfaceRequestActive(frameIdx) };

// FindSurfaceRequest uses gpuPrint buffer
if (debugView.gpuPrint.enable() && !findSurfaceRequestActive) {
// Read from the oldest element as it is guaranteed to be written on the GPU by now
VkDeviceSize offset = ((frameIdx + 1) % kMaxFramesInFlight) * sizeof(GpuPrintBufferElement);
GpuPrintBufferElement* gpuPrintElement = reinterpret_cast<GpuPrintBufferElement*>(rtOutput.m_gpuPrintBuffer->mapPtr(offset));
Expand All @@ -1415,6 +1430,24 @@ namespace dxvk {
}
}

if (findSurfaceRequestActive) {
// Read from the oldest element as it is guaranteed to be written on the GPU by now
VkDeviceSize offset = ((frameIdx + 1) % kMaxFramesInFlight) * sizeof(GpuPrintBufferElement);
auto gpuPrintElement = static_cast<GpuPrintBufferElement*>(rtOutput.m_gpuPrintBuffer->mapPtr(offset));

if (gpuPrintElement && gpuPrintElement->isValid()) {
const auto surfaceMaterialIndex = static_cast<uint32_t>(floatBitsToInt(gpuPrintElement->writtenData.x));
debugView.placeFindSurfaceResult(FindSurfaceResult {
/* .surfaceMaterialIndex = */ surfaceMaterialIndex,
/* .legacyTextureHash = */ getSceneManager().findLegacyTextureHashBySurfaceMaterialIndex(surfaceMaterialIndex),
});
} else {
debugView.placeFindSurfaceResult({});
}
} else {
debugView.placeFindSurfaceResult({});
}

if (!debugView.shouldDispatch())
return;

Expand All @@ -1427,6 +1460,19 @@ namespace dxvk {
takeScreenshot("rtxImageDebugView", debugView.getDebugOutput()->image());
}

void RtxContext::dispatchHighlighting(Resources::RaytracingOutput& rtOutput) {
ScopedCpuProfileZone();

if (auto surfMaterialIndexAndColor = m_common->getSceneManager().accessSurfaceMaterialIndexToHighlight(m_device->getCurrentFrameId())) {
m_common->metaPostFx().dispatchHighlighting(
this,
getSceneManager().getCamera().getShaderConstants().resolution,
rtOutput,
surfMaterialIndexAndColor->first,
surfMaterialIndexAndColor->second);
}
}

void RtxContext::dispatchDLFG() {
if (!isDLFGEnabled()) {
return;
Expand Down
1 change: 1 addition & 0 deletions src/dxvk/rtx_render/rtx_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ namespace dxvk {
void dispatchBloom(const Resources::RaytracingOutput& rtOutput);
void dispatchPostFx(Resources::RaytracingOutput& rtOutput);
void dispatchDebugView(Rc<DxvkImage>& srcImage, const Resources::RaytracingOutput& rtOutput, bool captureScreenImage);
void dispatchHighlighting(Resources::RaytracingOutput& rtOutput);
void dispatchDLFG();
void updateMetrics(const float frameTimeSecs, const float gpuIdleTimeSecs) const;

Expand Down
6 changes: 3 additions & 3 deletions src/dxvk/rtx_render/rtx_debug_view.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@ namespace dxvk {
static const auto colormap75 = turboColormap(0.75f);
static const auto colormap100 = turboColormap(1.0f);

ImGui::ComboWithKey<uint32_t> debugViewCombo = ImGui::ComboWithKey<uint32_t>(
static auto debugViewCombo = ImGui::ComboWithKey<uint32_t> {
"Debug View",
ImGui::ComboWithKey<uint32_t>::ComboEntries{ {
{
{DEBUG_VIEW_PRIMITIVE_INDEX, "Primitive Index"},
{DEBUG_VIEW_GEOMETRY_HASH, "Geometry Hash"},
{DEBUG_VIEW_CUSTOM_INDEX, "Custom Index"},
Expand Down Expand Up @@ -208,7 +208,7 @@ namespace dxvk {
{DEBUG_VIEW_NAN, "Inf/NaN Check"},
{DEBUG_SURFACE_LOBE_CONSISTENCY, "Surface/Lobe Consistency Check"},
{DEBUG_VIEW_SCROLLING_LINE, "Scrolling Line"},
} });
} };

ImGui::ComboWithKey<DebugViewDisplayType> displayTypeCombo = ImGui::ComboWithKey<DebugViewDisplayType>(
"Display Type",
Expand Down
44 changes: 44 additions & 0 deletions src/dxvk/rtx_render/rtx_debug_view.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,12 @@ namespace dxvk {
class DxvkContext;
class DxvkObjects;

struct FindSurfaceResult {
uint32_t surfaceMaterialIndex { 0 };
// corresponding legacy texture hash for SurfaceMaterialIndex
std::future<XXH64_hash_t> legacyTextureHash{};
};

class DebugView : public RtxPass {

public:
Expand Down Expand Up @@ -138,5 +144,43 @@ namespace dxvk {
Resources::Resource m_hdrWaveformGreen;
Resources::Resource m_hdrWaveformBlue;
Resources::Resource m_instrumentation;

public:
void requestFindSurfaceUnder(Vector2i pixel, uint32_t frameIdOfTheRequest) {
std::lock_guard lock{ m_texturePickMutex };
m_texturePickRequest = TexturePickingRequest { pixel, frameIdOfTheRequest };
}

std::optional<FindSurfaceResult>&& consumeLastAvailableFindSurfaceResult() {
std::lock_guard lock{ m_texturePickMutex };
return std::move(m_texturePickResult_prev);
}

std::optional<Vector2i> isFindSurfaceRequestActive(uint32_t currentFrameId) const {
std::lock_guard lock{ m_texturePickMutex };
constexpr auto numFramesToConsiderRequest = kMaxFramesInFlight * 2;
if (std::abs(int64_t { m_texturePickRequest.frameId } - int64_t{ currentFrameId }) < numFramesToConsiderRequest) {
return m_texturePickRequest.pixel;
}
return {};
}

private:
friend class RtxContext;
void placeFindSurfaceResult(std::optional<FindSurfaceResult>&& result) {
std::lock_guard lock{ m_texturePickMutex };
m_texturePickResult_prev = std::move(m_texturePickResult);
m_texturePickResult = std::move(result);
}

private:
mutable dxvk::mutex m_texturePickMutex{};
struct TexturePickingRequest {
Vector2i pixel { 0,0 };
uint32_t frameId { kInvalidFrameIndex };
};
TexturePickingRequest m_texturePickRequest{};
std::optional<FindSurfaceResult> m_texturePickResult{};
std::optional<FindSurfaceResult> m_texturePickResult_prev{};
};
} // namespace dxvk
13 changes: 11 additions & 2 deletions src/dxvk/rtx_render/rtx_imgui.h
Original file line number Diff line number Diff line change
Expand Up @@ -231,16 +231,25 @@ namespace ImGui {
template<typename T>
class ComboWithKey {
public:
typedef std::vector<std::pair<T /*key*/, const char* /*entry name*/>> ComboEntries;
using ComboEntries = std::vector<std::pair<T /*key*/, const char* /*entry name*/>>;

ComboWithKey(const char* widgetName, ComboEntries& comboEntries) : m_widgetName(widgetName), m_comboEntries(comboEntries) {
ComboWithKey(const char* widgetName, ComboEntries&& comboEntries)
: m_comboEntries { std::move(comboEntries) }
, m_widgetName { widgetName } {
for (int i = 0; i < m_comboEntries.size(); i++) {
T key = m_comboEntries[i].first;
assert(m_keyToComboIdx.find(key) == m_keyToComboIdx.end() && "Duplicate key found");
m_keyToComboIdx[key] = i;
}
}

~ComboWithKey() = default;

ComboWithKey(const ComboWithKey&) = delete;
ComboWithKey(ComboWithKey&&) noexcept = delete;
ComboWithKey& operator=(const ComboWithKey&) = delete;
ComboWithKey& operator=(ComboWithKey&&) noexcept = delete;

template <typename T, std::enable_if_t<std::is_integral_v<T> || std::is_enum_v<T>, bool> = true>
bool getKey(T* key) {
auto it = m_keyToComboIdx.find(*key);
Expand Down
8 changes: 1 addition & 7 deletions src/dxvk/rtx_render/rtx_instance_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -309,18 +309,12 @@ namespace dxvk {
RtInstance*& pInstance = m_instances[i];
assert(pInstance != nullptr);

const XXH64_hash_t topologicalHash = pInstance->getBlas()->input.getGeometryData().getHashForRule<rules::TopologicalHash>();
const LegacyMaterialData& materialData = pInstance->getBlas()->input.getMaterialData();
const bool isHighlightedInstance = (RtxOptions::Get()->highlightedTexture() != kEmptyHash) &&
((RtxOptions::Get()->highlightedTexture() == materialData.getColorTexture().getImageHash()) ||
(RtxOptions::Get()->highlightedTexture() == materialData.getColorTexture2().getImageHash()));
const bool enableGarbageCollection =
!RtxOptions::AntiCulling::Object::enable() || // It's always True if anti-culling is disabled
(pInstance->m_isInsideFrustum) ||
(pInstance->getBlas()->input.getSkinningState().numBones > 0) ||
(pInstance->m_isAnimated) ||
(pInstance->m_isPlayerModel) ||
isHighlightedInstance;
(pInstance->m_isPlayerModel);

if (((forceGarbageCollection || enableGarbageCollection) &&
pInstance->m_frameLastUpdated + numFramesToKeepInstances <= currentFrame) ||
Expand Down
5 changes: 5 additions & 0 deletions src/dxvk/rtx_render/rtx_materials.h
Original file line number Diff line number Diff line change
Expand Up @@ -2014,4 +2014,9 @@ struct MaterialData {
};
};

enum class HighlightColor {
World,
UI,
};

} // namespace dxvk
2 changes: 0 additions & 2 deletions src/dxvk/rtx_render/rtx_options.h
Original file line number Diff line number Diff line change
Expand Up @@ -864,8 +864,6 @@ namespace dxvk {

RTX_OPTION("rtx", FusedWorldViewMode, fusedWorldViewMode, FusedWorldViewMode::None, "Set if game uses a fused World-View transform matrix.");

RTX_OPTION_FLAG("rtx", XXH64_hash_t, highlightedTexture, kEmptyHash, RtxOptionFlags::NoSave, "Hash of a texture that should be highlighted.");

RTX_OPTION("rtx", bool, useBuffersDirectly, true, "When enabled Remix will use the incoming vertex buffers directly where possible instead of copying data. Note: setting the d3d9.allowDiscard to False will disable this option.");
RTX_OPTION("rtx", bool, alwaysCopyDecalGeometries, true, "When set to True tells the geometry processor to always copy decals geometry. This is an optimization flag to experiment with when rtx.useBuffersDirectly is True.");

Expand Down
70 changes: 70 additions & 0 deletions src/dxvk/rtx_render/rtx_postFx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "rtx/pass/post_fx/post_fx.h"

#include <rtx_shaders/post_fx.h>
#include <rtx_shaders/post_fx_highlight.h>
#include <rtx_shaders/post_fx_motion_blur.h>
#include <rtx_shaders/post_fx_motion_blur_prefilter.h>
#include <pxr/base/arch/math.h>
Expand Down Expand Up @@ -82,6 +83,21 @@ namespace dxvk {
};

PREWARM_SHADER_PIPELINE(PostFxMotionBlurPrefilterShader);

class PostFxHighlightShader : public ManagedShader {
SHADER_SOURCE(PostFxHighlightShader, VK_SHADER_STAGE_COMPUTE_BIT, post_fx_highlight)

PUSH_CONSTANTS(PostFxHighlightingArgs)

BEGIN_PARAMETER()
TEXTURE2D(POST_FX_HIGHLIGHT_INPUT)
TEXTURE2D(POST_FX_HIGHLIGHT_SHARED_SURFACE_INDEX_INPUT)
TEXTURE2D(POST_FX_HIGHLIGHT_PRIMARY_CONE_RADIUS_INPUT)
RW_TEXTURE2D(POST_FX_HIGHLIGHT_OUTPUT)
END_PARAMETER()
};

PREWARM_SHADER_PIPELINE(PostFxHighlightShader);
}

DxvkPostFx::DxvkPostFx(DxvkDevice* device)
Expand Down Expand Up @@ -312,4 +328,58 @@ namespace dxvk {
inputSize);
}
}

void DxvkPostFx::dispatchHighlighting(
Rc<RtxContext> ctx,
const uvec2& mainCameraResolution,
const Resources::RaytracingOutput& rtOutput,
uint32_t surfaceMaterialIndexToHighlight,
HighlightColor color) {
ScopedGpuProfileZone(ctx, "PostFx Highlight");

const Resources::Resource& inOutColorTexture = rtOutput.m_finalOutput;
const VkExtent3D& inputSize = inOutColorTexture.image->info().extent;

const auto workgroups = util::computeBlockCount(inputSize, VkExtent3D { POST_FX_TILE_SIZE , POST_FX_TILE_SIZE, 1 });

auto args = PostFxHighlightingArgs {};
{
args.imageSize = { inputSize.width, inputSize.height };
args.inputOverOutputViewSize = {
static_cast<float>(mainCameraResolution.x) / static_cast<float>(inputSize.width),
static_cast<float>(mainCameraResolution.y) / static_cast<float>(inputSize.height),
};
args.desaturateNonHighlighted = true;
args.timeSinceStartMS = static_cast<float>(ctx->getSceneManager().getGameTimeSinceStartMS());
args.surfaceMaterialIndexToHighlight = surfaceMaterialIndexToHighlight;
args.highlightColorId =
color == HighlightColor::World ? 1 :
color == HighlightColor::UI ? 2 :
0;
}

ctx->pushConstants(0, sizeof(args), &args);

const Resources::Resource* lastOutput = &rtOutput.m_postFxIntermediateTexture;

ctx->bindResourceView(POST_FX_HIGHLIGHT_INPUT, inOutColorTexture.view, nullptr);
ctx->bindResourceView(POST_FX_HIGHLIGHT_SHARED_SURFACE_INDEX_INPUT, rtOutput.m_sharedSurfaceIndex.view, nullptr);
ctx->bindResourceView(POST_FX_HIGHLIGHT_PRIMARY_CONE_RADIUS_INPUT, rtOutput.m_primaryConeRadius.view, nullptr);
ctx->bindResourceView(POST_FX_HIGHLIGHT_OUTPUT, lastOutput->view, nullptr);

ctx->bindShader(VK_SHADER_STAGE_COMPUTE_BIT, PostFxHighlightShader::getShader());
ctx->dispatch(workgroups.width, workgroups.height, workgroups.depth);

// Copy to the output texture if the final output is not the input texture
if (lastOutput->image != inOutColorTexture.image) {
ctx->copyImage(
inOutColorTexture.image,
{ VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 },
{ 0, 0, 0 },
rtOutput.m_postFxIntermediateTexture.image,
{ VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 },
{ 0, 0, 0 },
inputSize);
}
}
}
7 changes: 7 additions & 0 deletions src/dxvk/rtx_render/rtx_postFx.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,13 @@ namespace dxvk {
const Resources::RaytracingOutput& rtOutput,
const bool cameraCutDetected);

void dispatchHighlighting(
Rc<RtxContext> ctx,
const uvec2& mainCameraResolution,
const Resources::RaytracingOutput& rtOutput,
uint32_t surfaceMaterialIndexToHighlight,
HighlightColor color);

void showImguiSettings();

inline bool isPostFxEnabled() const { return enable(); }
Expand Down
Loading

0 comments on commit a60b141

Please sign in to comment.