Skip to content

Commit

Permalink
Merge branch 'nsubtil/rel-0.4-rc5' into 'release/v0.4'
Browse files Browse the repository at this point in the history
remix-0.4.0-rc5

See merge request lightspeedrtx/dxvk-remix-nv!641
  • Loading branch information
nsubtil committed Jan 9, 2024
2 parents a01635a + f9258a2 commit ef405b3
Show file tree
Hide file tree
Showing 67 changed files with 786 additions and 562 deletions.
1 change: 1 addition & 0 deletions dxvk.conf
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# override this to control which GPU to use
d3d9.adapterOverride = 0
dxvk.hud = 1

/*
* Copyright (c) 2021-2023, NVIDIA CORPORATION. All rights reserved.
Expand Down
2 changes: 1 addition & 1 deletion meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

project(
'dxvk', ['c', 'cpp'],
version : 'remix-0.4.0-rc3',
version : 'remix-0.4.0-rc5',
meson_version : '>= 0.58',
default_options : ['werror=true', 'b_vscrt=from_buildtype']
)
Expand Down
7 changes: 7 additions & 0 deletions public/include/remix/remix.h
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,8 @@ namespace remix {
Result< detail::dxvk_VkImage > dxvk_GetVkImage(IDirect3DSurface9* source);
Result< void > dxvk_CopyRenderingOutput(IDirect3DSurface9* destination,
remixapi_dxvk_CopyRenderingOutputType type);
Result< void > dxvk_SetDefaultOutput(remixapi_dxvk_CopyRenderingOutputType type,
const remixapi_Float4D& color);
};

namespace lib {
Expand Down Expand Up @@ -731,4 +733,9 @@ namespace remix {
IDirect3DSurface9* destination, remixapi_dxvk_CopyRenderingOutputType type) {
return m_CInterface.dxvk_CopyRenderingOutput(destination, type);
}

inline Result< void > Interface::dxvk_SetDefaultOutput(
remixapi_dxvk_CopyRenderingOutputType type, const remixapi_Float4D& color) {
return m_CInterface.dxvk_SetDefaultOutput(type, color);
}
}
4 changes: 4 additions & 0 deletions public/include/remix/remix_c.h
Original file line number Diff line number Diff line change
Expand Up @@ -496,6 +496,9 @@ extern "C" {
IDirect3DSurface9* destination,
remixapi_dxvk_CopyRenderingOutputType type);

typedef remixapi_ErrorCode(REMIXAPI_PTR* PFN_remixapi_dxvk_SetDefaultOutput)(
remixapi_dxvk_CopyRenderingOutputType type,
const remixapi_Float4D& color);


typedef struct remixapi_InitializeLibraryInfo {
Expand All @@ -522,6 +525,7 @@ extern "C" {
PFN_remixapi_dxvk_GetExternalSwapchain dxvk_GetExternalSwapchain;
PFN_remixapi_dxvk_GetVkImage dxvk_GetVkImage;
PFN_remixapi_dxvk_CopyRenderingOutput dxvk_CopyRenderingOutput;
PFN_remixapi_dxvk_SetDefaultOutput dxvk_SetDefaultOutput;
} remixapi_Interface;

REMIXAPI remixapi_ErrorCode REMIXAPI_CALL remixapi_InitializeLibrary(
Expand Down
18 changes: 15 additions & 3 deletions src/d3d9/d3d9_rtx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ namespace dxvk {
const uint32_t kRenderTargetIndex = 0;

#define CATEGORIES_REQUIRE_DRAW_CALL InstanceCategories::Sky, InstanceCategories::Terrain
#define CATEGORIES_REQUIRE_GEOMETRY_COPY InstanceCategories::DecalStatic, InstanceCategories::DecalDynamic, InstanceCategories::DecalNoOffset, InstanceCategories::Terrain, InstanceCategories::WorldUI
#define CATEGORIES_REQUIRE_GEOMETRY_COPY InstanceCategories::Terrain, InstanceCategories::WorldUI

D3D9Rtx::D3D9Rtx(D3D9DeviceEx* d3d9Device)
: m_rtStagingData(d3d9Device->GetDXVKDevice(), (VkMemoryPropertyFlagBits) (VK_MEMORY_PROPERTY_HOST_CACHED_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT))
Expand Down Expand Up @@ -588,9 +588,12 @@ namespace dxvk {
return { processIgnoredDraws, false };
}

// Max offseted index value within a buffer slice that geoData contains
const uint32_t maxOffsetedIndex = maxIndex - minIndex;

// Copy all the vertices into a staging buffer. Assign fields of the geoData structure.
processVertices(vertexContext, vertexIndexOffset, geoData);
geoData.futureGeometryHashes = computeHash(geoData, (maxIndex - minIndex));
geoData.futureGeometryHashes = computeHash(geoData, maxOffsetedIndex);
geoData.futureBoundingBox = computeAxisAlignedBoundingBox(geoData);

// Process skinning data
Expand Down Expand Up @@ -655,7 +658,7 @@ namespace dxvk {
params.vertexCount = drawInfo.vertexCount;
}

m_drawCallStateQueue.push(std::move(m_activeDrawCallState));
submitActiveDrawCallState();

m_parent->EmitCs([params, this](DxvkContext* ctx) {
assert(dynamic_cast<RtxContext*>(ctx));
Expand All @@ -666,6 +669,15 @@ namespace dxvk {
});
}

void D3D9Rtx::submitActiveDrawCallState() {
// We must be prepared for `push` failing here, this can happen, since we're pushing to a circular buffer, which
// may not have room for new entries. In such cases, we trust that the consumer thread will make space for us, and
// so we may just need to wait a little bit.
while (!m_drawCallStateQueue.push(std::move(m_activeDrawCallState))) {
Sleep(0);
}
}

Future<SkinningData> D3D9Rtx::processSkinning(const RasterGeometry& geoData) {
ScopedCpuProfileZone();

Expand Down
4 changes: 3 additions & 1 deletion src/d3d9/d3d9_rtx.h
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ namespace dxvk {
kAllThreads = (kHashingThreads | kSkinningThread)
};

inline static const uint32_t kMaxConcurrentDraws = 4 * 1024;
inline static const uint32_t kMaxConcurrentDraws = 6 * 1024; // some games issuing >3000 draw calls per frame... account for some consumer thread lag with x2
WorkerThreadPool<kMaxConcurrentDraws> m_gpeWorkers;
AtomicQueue<DrawCallState, kMaxConcurrentDraws> m_drawCallStateQueue;

Expand Down Expand Up @@ -260,5 +260,7 @@ namespace dxvk {
Future<AxisAlignedBoundingBox> computeAxisAlignedBoundingBox(const RasterGeometry& geoData);

Future<GeometryHashes> computeHash(const RasterGeometry& geoData, const uint32_t maxIndexValue);

void submitActiveDrawCallState();
};
}
36 changes: 19 additions & 17 deletions src/d3d9/d3d9_rtx_geometry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,16 @@ namespace dxvk {
// Geometry indices should never be signed. Using this to handle the non-indexed case for templates.
typedef int NoIndices;

enum VertexRegions : uint32_t {
Position = 0,
Texcoord,
Count
};
namespace VertexRegions {
enum Type : uint32_t {
Position = 0,
Texcoord,
Count
};
}

// NOTE: Intentionally leaving the legacy hashes out of here, because they are special (REMIX-656)
const std::map<HashComponents, VertexRegions> componentToRegionMap = {
const std::map<HashComponents, VertexRegions::Type> componentToRegionMap = {
{ HashComponents::VertexPosition, VertexRegions::Position },
{ HashComponents::VertexTexcoord, VertexRegions::Texcoord },
};
Expand Down Expand Up @@ -69,7 +71,7 @@ namespace dxvk {

template<typename T>
void hashGeometryData(const size_t indexCount, const uint32_t maxIndexValue, const void* pIndexData,
DxvkBuffer* indexBufferRef, const HashQuery vertexRegions[Count], GeometryHashes& hashesOut) {
DxvkBuffer* indexBufferRef, const HashQuery vertexRegions[VertexRegions::Count], GeometryHashes& hashesOut) {
ScopedCpuProfileZone();

const HashRule& globalHashRule = RtxOptions::Get()->GeometryHashGenerationRule;
Expand Down Expand Up @@ -99,18 +101,18 @@ namespace dxvk {
const HashComponents& component = (HashComponents) i;

if (globalHashRule.test(component) && componentToRegionMap.count(component) > 0) {
const VertexRegions region = componentToRegionMap.at(component);
const VertexRegions::Type region = componentToRegionMap.at(component);
hashesOut[component] = hashVertexRegionIndexed(vertexRegions[(uint32_t)region], uniqueIndices);
}
}

// TODO (REMIX-656): Remove this once we can transition content to new hash
if (globalHashRule.test(HashComponents::LegacyPositions0) || globalHashRule.test(HashComponents::LegacyPositions1)) {
hashRegionLegacy(vertexRegions[Position], hashesOut[HashComponents::LegacyPositions0], hashesOut[HashComponents::LegacyPositions1]);
hashRegionLegacy(vertexRegions[VertexRegions::Position], hashesOut[HashComponents::LegacyPositions0], hashesOut[HashComponents::LegacyPositions1]);
}

// Release this memory back to the staging allocator
for (uint32_t i = 0; i < Count; i++) {
for (uint32_t i = 0; i < VertexRegions::Count; i++) {
const HashQuery& region = vertexRegions[i];
if (region.size == 0)
continue;
Expand All @@ -128,19 +130,19 @@ namespace dxvk {
const uint32_t indexCount = geoData.indexCount;
const uint32_t vertexCount = geoData.vertexCount;

HashQuery vertexRegions[Count];
HashQuery vertexRegions[VertexRegions::Count];
memset(&vertexRegions[0], 0, sizeof(vertexRegions));

if (!getVertexRegion(geoData.positionBuffer, vertexCount, vertexRegions[Position]))
if (!getVertexRegion(geoData.positionBuffer, vertexCount, vertexRegions[VertexRegions::Position]))
return Future<GeometryHashes>(); //invalid

// Acquire prevents the staging allocator from re-using this memory
vertexRegions[Position].ref->acquire(DxvkAccess::Read);
vertexRegions[Position].ref->incRef();
vertexRegions[VertexRegions::Position].ref->acquire(DxvkAccess::Read);
vertexRegions[VertexRegions::Position].ref->incRef();

if (getVertexRegion(geoData.texcoordBuffer, vertexCount, vertexRegions[Texcoord])) {
vertexRegions[Texcoord].ref->acquire(DxvkAccess::Read);
vertexRegions[Texcoord].ref->incRef();
if (getVertexRegion(geoData.texcoordBuffer, vertexCount, vertexRegions[VertexRegions::Texcoord])) {
vertexRegions[VertexRegions::Texcoord].ref->acquire(DxvkAccess::Read);
vertexRegions[VertexRegions::Texcoord].ref->incRef();
}

// Make sure we hold a ref to the index buffer while hashing.
Expand Down
6 changes: 6 additions & 0 deletions src/d3d9/d3d9_swapchain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -998,6 +998,8 @@ namespace dxvk {

if (m_presentParams.hDeviceWindow == hWindow) {
// NV-DXVK start: DLFG integration
m_device->releasePresenter();

if (m_presenter != nullptr) {
assert(m_dlfgPresenter == nullptr);
m_presenter = nullptr;
Expand Down Expand Up @@ -1310,6 +1312,10 @@ namespace dxvk {

m_device->waitForIdle();

// NV-DXVK start: DLFG integration
m_device->releasePresenter();
// NV-DXVK end

m_presenter = nullptr;
m_presentStatus.result = VK_SUCCESS;

Expand Down
20 changes: 20 additions & 0 deletions src/dxvk/dxvk_device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,18 @@ namespace dxvk {
incrementPresentCount();

// NV-DXVK end

// NV-DXVK start: DLFG integration
if (m_lastPresenter.ptr() != presenter.ptr()) {
// if we're switching presenters, synchronize the old one to make sure nothing stays in flight
if (m_lastPresenter != nullptr) {
m_lastPresenter->synchronize();
}

// stash the presenter object so we can synchronize with it if needed
m_lastPresenter = presenter;
}
// NV-DXVK end
}

void DxvkDevice::incrementPresentCount() {
Expand Down Expand Up @@ -420,6 +432,14 @@ namespace dxvk {
void DxvkDevice::waitForIdle() {
ScopedCpuProfileZone();
this->lockSubmission();

// NV-DXVK start: DLFG integration
// idle DLFG so we can call vkDeviceWaitIdle safely
if (m_lastPresenter != nullptr) {
m_lastPresenter->synchronize();
}
// NV-DXVK end

if (m_vkd->vkDeviceWaitIdle(m_vkd->device()) != VK_SUCCESS)
Logger::err("DxvkDevice: waitForIdle: Operation failed");
this->unlockSubmission();
Expand Down
11 changes: 11 additions & 0 deletions src/dxvk/dxvk_device.h
Original file line number Diff line number Diff line change
Expand Up @@ -597,6 +597,16 @@ namespace dxvk {
return &m_objects;
}

// NV-DXVK start: DLFG integration
// release the current presenter stashed in the device
void releasePresenter() {
if (m_lastPresenter != nullptr) {
m_lastPresenter->synchronize();
m_lastPresenter = nullptr;
}
}
// NV-DXVK end

private:

DxvkOptions m_options;
Expand All @@ -605,6 +615,7 @@ namespace dxvk {
Rc<DxvkAdapter> m_adapter;
Rc<vk::DeviceFn> m_vkd;
DxvkDeviceExtensions m_extensions;
Rc<vk::Presenter> m_lastPresenter;

DxvkDeviceFeatures m_features;
DxvkDeviceInfo m_properties;
Expand Down
32 changes: 32 additions & 0 deletions src/dxvk/dxvk_instance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -537,7 +537,39 @@ namespace dxvk {
initConfig<Config::Type_RtxMod>();

RtxOption<bool>::updateRtxOptions();

m_config.logOptions("Effective (combined)");

// Output environment variable info
// Todo: This being here is kinda not great as this results in the Environment variables being parsed 3 times
// which is quite redundant. Unfortunately this logging can't go in Config::getOption as this function is called
// twice (again, redundant) resulting in duplicate messages. Ideally this system should be refactored to get all the
// relevant environment variable values for the desired RtxOptions in a loop like this, and then use those when
// setting the options up to avoid redundantly making a ton of syscalls. Luckily this code only happens in loading
// so it is not a huge performance overhead, and the value of seeing which environment variables are overriding options
// is currently more valuable (since they continue to cause problems when unseen in the log).

bool firstEnvironmentOverride = true;

for (auto&& option : RtxOptionImpl::getGlobalRtxOptionMap()) {
const auto optionName = option.second->getFullName();
const auto envVarName = option.second->environment;

if (envVarName) {
const std::string& envVarValue = env::getEnvVar(envVarName);

if (envVarValue != "") {
// Note: Only print out the section header if there's at least one environment variable override.
if (firstEnvironmentOverride) {
Logger::info("Environment variable option overrides:");

firstEnvironmentOverride = false;
}

Logger::info(str::format(" ", optionName, " overridden by environment variable: ", envVarName, "=", envVarValue));
}
}
}
}

template<Config::Type type>
Expand Down
34 changes: 0 additions & 34 deletions src/dxvk/imgui/dxvk_imgui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,9 +152,6 @@ namespace dxvk {
{"beamtextures", "Beam Texture (optional)", &RtxOptions::Get()->beamTexturesObject()},
{"lightconvertertextures", "Add Light to Textures (optional)", &RtxOptions::Get()->lightConverterObject()},
{"decaltextures", "Decal Texture (optional)", &RtxOptions::Get()->decalTexturesObject()},
{"dynamicdecaltextures", "Dynamic Decal Texture", &RtxOptions::Get()->dynamicDecalTexturesObject()},
{"singleoffsetdecaltextures", "Single Offset Decal Texture", &RtxOptions::Get()->singleOffsetDecalTexturesObject()},
{"nonoffsetdecaltextures", "Non-Offset Decal Texture", &RtxOptions::Get()->nonOffsetDecalTexturesObject()},
{"cutouttextures", "Legacy Cutout Texture (optional)", &RtxOptions::Get()->cutoutTexturesObject()},
{"terraintextures", "Terrain Texture", &RtxOptions::Get()->terrainTexturesObject()},
{"watertextures", "Water Texture (optional)", &RtxOptions::Get()->animatedWaterTexturesObject()},
Expand Down Expand Up @@ -1952,24 +1949,6 @@ namespace dxvk {
ImGui::Indent();
}

if (IMGUI_ADD_TOOLTIP(ImGui::CollapsingHeader("Dynamic Decal Textures", collapsingHeaderClosedFlags), RtxOptions::Get()->dynamicDecalTexturesDescription())) {
ImGui::Unindent();
showTextureSelectionGrid(ctx, "dynamicdecaltextures", numThumbnailsPerRow, thumbnailSize);
ImGui::Indent();
}

if (IMGUI_ADD_TOOLTIP(ImGui::CollapsingHeader("Single Offset Decal Textures", collapsingHeaderClosedFlags), RtxOptions::Get()->singleOffsetDecalTexturesDescription())) {
ImGui::Unindent();
showTextureSelectionGrid(ctx, "singleoffsetdecaltextures", numThumbnailsPerRow, thumbnailSize);
ImGui::Indent();
}

if (IMGUI_ADD_TOOLTIP(ImGui::CollapsingHeader("Non-Offset Decal Textures", collapsingHeaderClosedFlags), RtxOptions::Get()->nonOffsetDecalTexturesDescription())) {
ImGui::Unindent();
showTextureSelectionGrid(ctx, "nonoffsetdecaltextures", numThumbnailsPerRow, thumbnailSize);
ImGui::Indent();
}

if (IMGUI_ADD_TOOLTIP(ImGui::CollapsingHeader("Legacy Cutout Textures (optional)", collapsingHeaderClosedFlags), RtxOptions::Get()->cutoutTexturesDescription())) {
ImGui::Unindent();
showTextureSelectionGrid(ctx, "cutouttextures", numThumbnailsPerRow, thumbnailSize);
Expand Down Expand Up @@ -2791,19 +2770,6 @@ namespace dxvk {
ImGui::DragInt("Min Prims in Static BLAS", &RtxOptions::Get()->minPrimsInStaticBLASObject(), 1.f, 100, 0);
ImGui::Checkbox("Portals: Virtual Instance Matching", &RtxOptions::Get()->useRayPortalVirtualInstanceMatchingObject());
ImGui::Checkbox("Portals: Fade In Effect", &RtxOptions::Get()->enablePortalFadeInEffectObject());

if (ImGui::CollapsingHeader("Decals", collapsingHeaderClosedFlags)) {
ImGui::Indent();

ImGui::TextWrapped("Warning: changes to these parameters will only apply to new geometry. Existing geometry needs to be invalidated by either a game reload or gameplay and/or camera view change if the game uses runtime or view dependent geometry batching per draw call.");

ImGui::DragFloat("Offset Multiplier [m]", &RtxOptions::Decals::offsetMultiplierMetersObject(), 0.0001f, 0.f, 0.f, "%.5f");
ImGui::DragInt("Base Offset Index", &RtxOptions::Decals::baseOffsetIndexObject(), 1.f, 1, 1000);
ImGui::DragInt("Max Offset Index", &RtxOptions::Decals::maxOffsetIndexObject(), 1.f, 1, 10000);
ImGui::DragInt("Offset Increase Between Decal Draw Calls", &RtxOptions::Decals::offsetIndexIncreaseBetweenDrawCallsObject(), 1.f, 1, 1000);
ImGui::Unindent();
}

ImGui::Unindent();
}

Expand Down
Loading

0 comments on commit ef405b3

Please sign in to comment.