Skip to content

Commit

Permalink
v1.109:
Browse files Browse the repository at this point in the history
- SwapChain: removed exclusive fullscreen (was partially implemented, should be done in another way)
- D3D12: fixed bug in "ResizeBuffers" (introduced by recent PR)
- D3D11: fixed "locking" (implicit referencing) of resources by CommandBuffer
- D3D11/D3D12: fixed wrong (0 alpha) background color in SwapChain
- VK: fixed mismatched image layouts in some "vkCmdCopy*" calls (introduced by recent PR)
- VK: swap chain improvements
- VK: refactoring
  • Loading branch information
dzhdanNV committed Dec 26, 2023
1 parent a675e32 commit ba92e98
Show file tree
Hide file tree
Showing 31 changed files with 178 additions and 556 deletions.
14 changes: 5 additions & 9 deletions Include/Extensions/NRISwapChain.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ license agreement from NVIDIA CORPORATION is strictly prohibited.
NRI_NAMESPACE_BEGIN

NRI_FORWARD_STRUCT(SwapChain);
NRI_FORWARD_STRUCT(Display);

NRI_ENUM
(
Expand Down Expand Up @@ -84,10 +83,9 @@ NRI_STRUCT(SwapChainDesc)
const NRI_NAME(CommandQueue)* commandQueue;
NRI_NAME(Dim_t) width;
NRI_NAME(Dim_t) height;
uint16_t textureNum;
uint8_t textureNum;
NRI_NAME(SwapChainFormat) format;
uint32_t verticalSyncInterval;
NRI_NAME(Display)* display;
uint8_t verticalSyncInterval;
};

NRI_STRUCT(HdrMetadata)
Expand All @@ -108,12 +106,10 @@ NRI_STRUCT(SwapChainInterface)
void (NRI_CALL *DestroySwapChain)(NRI_NAME_REF(SwapChain) swapChain);
void (NRI_CALL *SetSwapChainDebugName)(NRI_NAME_REF(SwapChain) swapChain, const char* name);
NRI_NAME(Texture)* const* (NRI_CALL *GetSwapChainTextures)(const NRI_NAME_REF(SwapChain) swapChain, uint32_t NRI_REF textureNum);
uint32_t (NRI_CALL *AcquireNextSwapChainTexture)(NRI_NAME_REF(SwapChain) swapChain); // TODO: currently returns "-1" on errors and "out of date"
uint32_t (NRI_CALL *AcquireNextSwapChainTexture)(NRI_NAME_REF(SwapChain) swapChain); // IMPORTANT: return OUT_OF_DATE index to indicate "out of date" swap chain status (VK only)
NRI_NAME(Result) (NRI_CALL *SwapChainPresent)(NRI_NAME_REF(SwapChain) swapChain);
NRI_NAME(Result) (NRI_CALL *ResizeBuffers)(NRI_NAME_REF(SwapChain) swapChain, NRI_NAME(Dim_t) width, NRI_NAME(Dim_t) height);
NRI_NAME(Result) (NRI_CALL *ResizeBuffers)(NRI_NAME_REF(SwapChain) swapChain, NRI_NAME(Dim_t) width, NRI_NAME(Dim_t) height); // IMPORTANT: invalidates swapchain textures, requires GPU idle state, can be deprecated in the future
NRI_NAME(Result) (NRI_CALL *SetSwapChainHdrMetadata)(NRI_NAME_REF(SwapChain) swapChain, const NRI_NAME_REF(HdrMetadata) hdrMetadata);
NRI_NAME(Result) (NRI_CALL *GetDisplays)(NRI_NAME_REF(Device) device, NRI_NAME(Display)** displays, uint32_t NRI_REF displayNum);
NRI_NAME(Result) (NRI_CALL *GetDisplaySize)(NRI_NAME_REF(Device) device, NRI_NAME_REF(Display) display, NRI_NAME_REF(Dim_t) width, NRI_NAME_REF(Dim_t) height);
};
};

NRI_NAMESPACE_END
6 changes: 3 additions & 3 deletions Include/NRI.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ license agreement from NVIDIA CORPORATION is strictly prohibited.
#include <stddef.h>

#define NRI_VERSION_MAJOR 1
#define NRI_VERSION_MINOR 108
#define NRI_VERSION_DATE "18 December 2023"
#define NRI_VERSION_MINOR 109
#define NRI_VERSION_DATE "21 December 2023"

#ifdef _WIN32
#define NRI_CALL __fastcall
Expand All @@ -26,7 +26,7 @@ license agreement from NVIDIA CORPORATION is strictly prohibited.
#ifndef NRI_API
#if NRI_STATIC_LIBRARY
#define NRI_API
#elif( defined(__cplusplus) )
#elif defined(__cplusplus)
#define NRI_API extern "C"
#else
#define NRI_API extern
Expand Down
7 changes: 4 additions & 3 deletions Include/NRIDescs.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ static const uint32_t NRI_CONST_NAME(ALL_SAMPLES) = (uint32_t)(-1);
static const uint32_t NRI_CONST_NAME(ALL_NODES) = 0;
static const bool NRI_CONST_NAME(VARIABLE_DESCRIPTOR_NUM) = true;
static const bool NRI_CONST_NAME(DESCRIPTOR_ARRAY) = true;
static const uint32_t NRI_CONST_NAME(OUT_OF_DATE) = (uint32_t)(-1); // VK only: swap chain is out of date

NRI_ENUM
(
Expand All @@ -52,7 +53,7 @@ NRI_ENUM
OUT_OF_MEMORY,
UNSUPPORTED,
DEVICE_LOST,
SWAPCHAIN_RESIZE,
OUT_OF_DATE, // VK only: swap chain is out of date

MAX_NUM
);
Expand Down Expand Up @@ -201,10 +202,10 @@ NRI_ENUM
DEPTH_STENCIL,
DEPTH_STENCIL_READONLY,
DEPTH_READONLY,
COPY_SOURCE,
COPY_DESTINATION,
STENCIL_READONLY,
SHADER_RESOURCE,
COPY_SOURCE,
COPY_DESTINATION,
PRESENT,
UNKNOWN,

Expand Down
2 changes: 1 addition & 1 deletion Resources/Version.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ Versioning rules:
*/

#define VERSION_MAJOR 1
#define VERSION_MINOR 108
#define VERSION_MINOR 109
#define VERSION_BUILD 0
#define VERSION_REVISION 0

Expand Down
1 change: 1 addition & 0 deletions Source/D3D11/CommandBufferD3D11.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ Result CommandBufferD3D11::Create(ID3D11DeviceContext* precreatedContext)
void CommandBufferD3D11::Submit()
{
m_Device.GetImmediateContext()->ExecuteCommandList(m_CommandList, FALSE);
m_CommandList = nullptr;
}

ID3D11DeviceContext* CommandBufferD3D11::GetNativeObject() const
Expand Down
71 changes: 0 additions & 71 deletions Source/D3D11/DeviceD3D11.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,17 +82,6 @@ DeviceD3D11::~DeviceD3D11()
DeleteCriticalSection(&m_CriticalSection);
}

bool DeviceD3D11::GetOutput(Display* display, ComPtr<IDXGIOutput>& output) const
{
if (!display)
return false;

const uint32_t index = (*(uint32_t*)&display) - 1;
const HRESULT result = m_Adapter->EnumOutputs(index, &output);

return SUCCEEDED(result);
}

Result DeviceD3D11::Create(const DeviceCreationDesc& deviceCreationDesc, ID3D11Device* device, AGSContext* agsContext)
{
m_SkipLiveObjectsReporting = deviceCreationDesc.skipLiveObjectsReporting;
Expand Down Expand Up @@ -497,66 +486,6 @@ inline void DeviceD3D11::DestroySwapChain(SwapChain& swapChain)
Deallocate(GetStdAllocator(), (SwapChainD3D11*)&swapChain);
}

inline Result DeviceD3D11::GetDisplays(Display** displays, uint32_t& displayNum)
{
HRESULT result = S_OK;
if (displays == nullptr || displayNum == 0)
{
UINT i = 0;
for(; result != DXGI_ERROR_NOT_FOUND; i++)
{
ComPtr<IDXGIOutput> output;
result = m_Adapter->EnumOutputs(i, &output);
}

displayNum = i;
return Result::SUCCESS;
}

UINT i = 0;
for(; result != DXGI_ERROR_NOT_FOUND && i < displayNum; i++)
{
ComPtr<IDXGIOutput> output;
result = m_Adapter->EnumOutputs(i, &output);
if (result != DXGI_ERROR_NOT_FOUND)
displays[i] = (Display*)(size_t)(i + 1);
}

for(; i < displayNum; i++)
displays[i] = nullptr;

return Result::SUCCESS;
}

inline Result DeviceD3D11::GetDisplaySize(Display& display, Dim_t& width, Dim_t& height)
{
Display* address = &display;
if (!address)
return Result::UNSUPPORTED;

const uint32_t index = (*(uint32_t*)&address) - 1;

ComPtr<IDXGIOutput> output;
HRESULT result = m_Adapter->EnumOutputs(index, &output);
RETURN_ON_BAD_HRESULT(this, result, "IDXGIAdapter::EnumOutputs()");

DXGI_OUTPUT_DESC outputDesc = {};
result = output->GetDesc(&outputDesc);
RETURN_ON_BAD_HRESULT(this, result, "IDXGIOutput::GetDesc()");

MONITORINFO monitorInfo = {};
monitorInfo.cbSize = sizeof(monitorInfo);

if (!GetMonitorInfoA(outputDesc.Monitor, &monitorInfo))
return Result::UNSUPPORTED;

const RECT& rect = monitorInfo.rcMonitor;
width = uint16_t(rect.right - rect.left);
height = uint16_t(rect.bottom - rect.top);

return Result::SUCCESS;
}

inline Result DeviceD3D11::GetCommandQueue(CommandQueueType commandQueueType, CommandQueue*& commandQueue)
{
commandQueue = (CommandQueue*)&m_CommandQueues[(uint32_t)commandQueueType];
Expand Down
3 changes: 0 additions & 3 deletions Source/D3D11/DeviceD3D11.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ struct DeviceD3D11 final : public DeviceBase
inline const CoreInterface& GetCoreInterface() const
{ return m_CoreInterface; }

bool GetOutput(Display* display, ComPtr<IDXGIOutput>& output) const;
Result Create(const DeviceCreationDesc& deviceCreationDesc, ID3D11Device* precreatedDevice, AGSContext* agsContext);

//================================================================================================================
Expand All @@ -47,8 +46,6 @@ struct DeviceD3D11 final : public DeviceBase

Result CreateSwapChain(const SwapChainDesc& swapChainDesc, SwapChain*& swapChain);
void DestroySwapChain(SwapChain& swapChain);
Result GetDisplays(Display** displays, uint32_t& displayNum);
Result GetDisplaySize(Display& display, Dim_t& width, Dim_t& height);

Result GetCommandQueue(CommandQueueType commandQueueType, CommandQueue*& commandQueue);
Result CreateCommandAllocator(const CommandQueue& commandQueue, CommandAllocator*& commandAllocator);
Expand Down
12 changes: 0 additions & 12 deletions Source/D3D11/DeviceD3D11.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -326,23 +326,11 @@ static void NRI_CALL DestroySwapChain(SwapChain& swapChain)
return device.DestroySwapChain(swapChain);
}

static Result NRI_CALL GetDisplays(Device& device, Display** displays, uint32_t& displayNum)
{
return ((DeviceD3D11&)device).GetDisplays(displays, displayNum);
}

static Result NRI_CALL GetDisplaySize(Device& device, Display& display, Dim_t& width, Dim_t& height)
{
return ((DeviceD3D11&)device).GetDisplaySize(display, width, height);
}

Result DeviceD3D11::FillFunctionTable(SwapChainInterface& swapChainInterface) const
{
swapChainInterface = {};
swapChainInterface.CreateSwapChain = ::CreateSwapChain;
swapChainInterface.DestroySwapChain = ::DestroySwapChain;
swapChainInterface.GetDisplays = ::GetDisplays;
swapChainInterface.GetDisplaySize = ::GetDisplaySize;

SwapChain_PartiallyFillFunctionTableD3D11(swapChainInterface);

Expand Down
75 changes: 18 additions & 57 deletions Source/D3D11/SwapChainD3D11.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,6 @@ static std::array<Format, 5> g_swapChainTextureFormat =

SwapChainD3D11::~SwapChainD3D11()
{
// Swapchain must be destroyed in windowed mode
BOOL fullscreen = FALSE;
HRESULT hr = m_SwapChain->GetFullscreenState(&fullscreen, nullptr);
if (SUCCEEDED(hr) && fullscreen)
m_SwapChain->SetFullscreenState(FALSE, nullptr);

if (m_FrameLatencyWaitableObject)
CloseHandle(m_FrameLatencyWaitableObject);

Expand All @@ -74,14 +68,14 @@ Result SwapChainD3D11::Create(const SwapChainDesc& swapChainDesc)
bool isWin7 = FAILED(hr);

// Is tearing supported?
m_IsTearingAllowed = false;
bool isTearingAllowed = false;
ComPtr<IDXGIFactory5> dxgiFactory5;
hr = dxgiFactory2->QueryInterface(IID_PPV_ARGS(&dxgiFactory5));
if (SUCCEEDED(hr))
{
uint32_t tearingSupport = 0;
hr = dxgiFactory5->CheckFeatureSupport(DXGI_FEATURE_PRESENT_ALLOW_TEARING, &tearingSupport, sizeof(tearingSupport));
m_IsTearingAllowed = (SUCCEEDED(hr) && tearingSupport) ? true : false;
isTearingAllowed = (SUCCEEDED(hr) && tearingSupport) ? true : false;
}

// Create swapchain
Expand All @@ -99,7 +93,7 @@ Result SwapChainD3D11::Create(const SwapChainDesc& swapChainDesc)
desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
desc.AlphaMode = DXGI_ALPHA_MODE_IGNORE;
desc.Flags = isWin7 ? 0 : DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT;
if (m_IsTearingAllowed)
if (isTearingAllowed)
desc.Flags |= DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING;

ComPtr<IDXGISwapChain1> swapChain;
Expand Down Expand Up @@ -158,35 +152,12 @@ Result SwapChainD3D11::Create(const SwapChainDesc& swapChainDesc)
// Background color
if (m_SwapChain.version >= 1)
{
DXGI_RGBA color = {};
DXGI_RGBA color = {0.0f, 0.0f, 0.0f, 1.0f};
hr = m_SwapChain->SetBackgroundColor(&color);
if (FAILED(hr))
REPORT_WARNING(&m_Device, "IDXGISwapChain1::SetBackgroundColor() - FAILED!");
}

// Fullscreen
if (swapChainDesc.display)
{
ComPtr<IDXGIOutput> output;
if (!m_Device.GetOutput(swapChainDesc.display, output))
{
REPORT_ERROR(&m_Device, "Failed to get IDXGIOutput for the specified display");
return Result::UNSUPPORTED;
}

hr = m_SwapChain->SetFullscreenState(TRUE, output);
if (SUCCEEDED(hr))
{
hr = m_SwapChain->ResizeBuffers(desc.BufferCount, desc.Width, desc.Height, desc.Format, desc.Flags);
RETURN_ON_BAD_HRESULT(&m_Device, hr, "IDXGISwapChain::ResizeBuffers()");

m_IsTearingAllowed = false;
m_Fullscreen = TRUE;
}
else
REPORT_WARNING(&m_Device, "IDXGISwapChain::SetFullscreenState() - FAILED!");
}

// Maximum frame latency
if (isWin7)
{
Expand All @@ -212,7 +183,7 @@ Result SwapChainD3D11::Create(const SwapChainDesc& swapChainDesc)
// Finalize
m_Flags = desc.Flags;
m_Format = g_swapChainTextureFormat[(uint32_t)swapChainDesc.format];
m_SwapChainDesc = swapChainDesc;
m_SwapChainDesc = swapChainDesc;
m_SwapChainDesc.textureNum = 1; // In DX11 only 'bufferIndex = 0' can be used to create render targets, so set BufferCount to '1' and ignore 'desc.BufferCount'

m_Textures.reserve(m_SwapChainDesc.textureNum);
Expand Down Expand Up @@ -251,11 +222,12 @@ inline uint32_t SwapChainD3D11::AcquireNextTexture()
{
// https://docs.microsoft.com/en-us/windows/uwp/gaming/reduce-latency-with-dxgi-1-3-swap-chains#step-4-wait-before-rendering-each-frame
if (m_FrameLatencyWaitableObject)
{
{
uint32_t result = WaitForSingleObjectEx(m_FrameLatencyWaitableObject, DEFAULT_TIMEOUT, TRUE);
RETURN_ON_FAILURE(&m_Device, result == WAIT_OBJECT_0, uint32_t(-1), "WaitForSingleObjectEx(): failed, result = 0x%08X!", result);
if (result != WAIT_OBJECT_0)
REPORT_ERROR(&m_Device, "WaitForSingleObjectEx(): failed, result = 0x%08X!", result);
}

uint32_t nextTextureIndex = 0;
if (m_SwapChain.version >= 3)
nextTextureIndex = m_SwapChain->GetCurrentBackBufferIndex();
Expand All @@ -265,40 +237,29 @@ inline uint32_t SwapChainD3D11::AcquireNextTexture()

inline Result SwapChainD3D11::Present()
{
BOOL fullscreen = FALSE;
HRESULT hr = m_SwapChain->GetFullscreenState(&fullscreen, nullptr);
if (SUCCEEDED(hr))
{
bool isResized = fullscreen != m_Fullscreen;
m_Fullscreen = fullscreen;
if (isResized)
return Result::SWAPCHAIN_RESIZE;
}

UINT flags = (!m_SwapChainDesc.verticalSyncInterval && m_IsTearingAllowed) ? DXGI_PRESENT_ALLOW_TEARING : 0;

UINT flags = (!m_SwapChainDesc.verticalSyncInterval && (m_Flags & DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING)) ? DXGI_PRESENT_ALLOW_TEARING : 0; // TODO: and not fullscreen
HRESULT result = m_SwapChain->Present(m_SwapChainDesc.verticalSyncInterval, flags);
RETURN_ON_BAD_HRESULT(&m_Device, result, "IDXGISwapChain::Present()");

return Result::SUCCESS;
}

Result nri::SwapChainD3D11::ResizeBuffers(Dim_t width, Dim_t height)
inline Result nri::SwapChainD3D11::ResizeBuffers(Dim_t width, Dim_t height)
{
for (TextureD3D11* texture : m_Textures)
Deallocate<TextureD3D11>(m_Device.GetStdAllocator(), texture);
m_Textures.clear();

HRESULT result = m_SwapChain->ResizeBuffers(0, width, height, DXGI_FORMAT_UNKNOWN, m_Flags);
RETURN_ON_BAD_HRESULT(&m_Device, result, "IDXGISwapChain::ResizeBuffers()");
HRESULT hr = m_SwapChain->ResizeBuffers(0, width, height, DXGI_FORMAT_UNKNOWN, m_Flags);
RETURN_ON_BAD_HRESULT(&m_Device, hr, "IDXGISwapChain::ResizeBuffers()");

m_Textures.resize(0);
for (uint32_t i = 0; i < m_SwapChainDesc.textureNum; i++) {
ComPtr<ID3D11Resource> textureNative;
result = m_SwapChain->GetBuffer(i, IID_PPV_ARGS(&textureNative));
RETURN_ON_BAD_HRESULT(&m_Device, result, "IDXGISwapChain::GetBuffer()");
ComPtr<ID3D11Resource> resource;
hr = m_SwapChain->GetBuffer(i, IID_PPV_ARGS(&resource));
RETURN_ON_BAD_HRESULT(&m_Device, hr, "IDXGISwapChain::GetBuffer()");

TextureD3D11Desc textureDesc = {};
textureDesc.d3d11Resource = textureNative;
textureDesc.d3d11Resource = resource;

TextureD3D11* texture = Allocate<TextureD3D11>(m_Device.GetStdAllocator(), m_Device);
const nri::Result res = texture->Create(textureDesc);
Expand Down
4 changes: 1 addition & 3 deletions Source/D3D11/SwapChainD3D11.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,7 @@ struct SwapChainD3D11
SwapChainDesc m_SwapChainDesc = {};
HANDLE m_FrameLatencyWaitableObject = nullptr;
Format m_Format = Format::UNKNOWN;
UINT m_Flags = 0;
BOOL m_Fullscreen = FALSE;
bool m_IsTearingAllowed = false;
UINT m_Flags = 0;
};

}
Loading

0 comments on commit ba92e98

Please sign in to comment.