mirror of
https://github.com/EduApps-CDG/OpenDX
synced 2024-12-30 09:45:37 +01:00
[dxgi] Reimplemented parts of DxgiSwapchain with win32 APIs
This solves issues in applications that create more than one swap chain for a given window, and helps applications that don't like SDL interference in general. Fullscreen support is currently missing entirely.
This commit is contained in:
parent
588ceba1d1
commit
4412f2f5ff
@ -137,30 +137,23 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
hasMode = testMode.w == currMode.w
|
hasMode = testMode.w == currMode.w
|
||||||
&& testMode.h == currMode.h
|
&& testMode.h == currMode.h
|
||||||
&& testMode.refresh_rate == currMode.refresh_rate;
|
&& testMode.refresh_rate == currMode.refresh_rate;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert the SDL display mode to a DXGI display mode info
|
// Convert the SDL display mode to a DXGI display mode info
|
||||||
// structure and filter out any unwanted modes based on the
|
// structure and filter out any unwanted modes based on the
|
||||||
// supplied flags.
|
// supplied flags.
|
||||||
if (!hasMode) {
|
if (!hasMode) {
|
||||||
bool isNativeMode = (currMode.w == desktopMode.w)
|
DXGI_MODE_DESC mode;
|
||||||
&& (currMode.h == desktopMode.h);
|
mode.Width = currMode.w;
|
||||||
|
mode.Height = currMode.h;
|
||||||
if (isNativeMode || (Flags & DXGI_ENUM_MODES_SCALING)) {
|
mode.RefreshRate.Numerator = currMode.refresh_rate;
|
||||||
DXGI_MODE_DESC mode;
|
mode.RefreshRate.Denominator = 1;
|
||||||
mode.Width = currMode.w;
|
mode.Format = EnumFormat;
|
||||||
mode.Height = currMode.h;
|
mode.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_PROGRESSIVE;
|
||||||
mode.RefreshRate.Numerator = currMode.refresh_rate;
|
mode.Scaling = DXGI_MODE_SCALING_CENTERED;
|
||||||
mode.RefreshRate.Denominator = 1;
|
modes.push_back(mode);
|
||||||
mode.Format = EnumFormat;
|
|
||||||
mode.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_PROGRESSIVE;
|
|
||||||
mode.Scaling = isNativeMode
|
|
||||||
? DXGI_MODE_SCALING_CENTERED
|
|
||||||
: DXGI_MODE_SCALING_STRETCHED;
|
|
||||||
modes.push_back(mode);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,11 +5,8 @@
|
|||||||
namespace dxvk {
|
namespace dxvk {
|
||||||
|
|
||||||
DxgiPresenter::DxgiPresenter(
|
DxgiPresenter::DxgiPresenter(
|
||||||
const Rc<DxvkDevice>& device,
|
const Rc<DxvkDevice>& device,
|
||||||
HWND window,
|
HWND window)
|
||||||
uint32_t bufferWidth,
|
|
||||||
uint32_t bufferHeight,
|
|
||||||
DXGI_FORMAT bufferFormat)
|
|
||||||
: m_device (device),
|
: m_device (device),
|
||||||
m_context (device->createContext()) {
|
m_context (device->createContext()) {
|
||||||
|
|
||||||
@ -19,15 +16,11 @@ namespace dxvk {
|
|||||||
|
|
||||||
m_surface = m_device->adapter()->createSurface(instance, window);
|
m_surface = m_device->adapter()->createSurface(instance, window);
|
||||||
|
|
||||||
// Create swap chain for the surface
|
// Reset options for the swap chain itself. We will
|
||||||
DxvkSwapchainProperties swapchainProperties;
|
// create a swap chain object before presentation.
|
||||||
swapchainProperties.preferredSurfaceFormat = this->pickFormat(bufferFormat);
|
m_options.preferredSurfaceFormat = { VK_FORMAT_UNDEFINED, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR };
|
||||||
swapchainProperties.preferredPresentMode = VK_PRESENT_MODE_IMMEDIATE_KHR;
|
m_options.preferredPresentMode = VK_PRESENT_MODE_FIFO_KHR;
|
||||||
swapchainProperties.preferredBufferSize.width = bufferWidth;
|
m_options.preferredBufferSize = { 0u, 0u };
|
||||||
swapchainProperties.preferredBufferSize.height = bufferHeight;
|
|
||||||
|
|
||||||
m_swapchain = m_device->createSwapchain(
|
|
||||||
m_surface, swapchainProperties);
|
|
||||||
|
|
||||||
// Sampler for presentation
|
// Sampler for presentation
|
||||||
DxvkSamplerCreateInfo samplerInfo;
|
DxvkSamplerCreateInfo samplerInfo;
|
||||||
@ -46,8 +39,11 @@ namespace dxvk {
|
|||||||
samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS;
|
samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS;
|
||||||
samplerInfo.borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK;
|
samplerInfo.borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK;
|
||||||
samplerInfo.usePixelCoord = VK_FALSE;
|
samplerInfo.usePixelCoord = VK_FALSE;
|
||||||
|
m_samplerFitting = m_device->createSampler(samplerInfo);
|
||||||
|
|
||||||
m_sampler = m_device->createSampler(samplerInfo);
|
samplerInfo.magFilter = VK_FILTER_LINEAR;
|
||||||
|
samplerInfo.minFilter = VK_FILTER_LINEAR;
|
||||||
|
m_samplerScaling = m_device->createSampler(samplerInfo);
|
||||||
|
|
||||||
// Set up context state. The shader bindings and the
|
// Set up context state. The shader bindings and the
|
||||||
// constant state objects will never be modified.
|
// constant state objects will never be modified.
|
||||||
@ -153,6 +149,10 @@ namespace dxvk {
|
|||||||
|
|
||||||
|
|
||||||
void DxgiPresenter::presentImage() {
|
void DxgiPresenter::presentImage() {
|
||||||
|
const bool fitSize =
|
||||||
|
m_backBuffer->info().extent.width == m_options.preferredBufferSize.width
|
||||||
|
&& m_backBuffer->info().extent.height == m_options.preferredBufferSize.height;
|
||||||
|
|
||||||
m_context->beginRecording(
|
m_context->beginRecording(
|
||||||
m_device->createCommandList());
|
m_device->createCommandList());
|
||||||
|
|
||||||
@ -191,8 +191,10 @@ namespace dxvk {
|
|||||||
|
|
||||||
m_context->setViewports(1, &viewport, &scissor);
|
m_context->setViewports(1, &viewport, &scissor);
|
||||||
|
|
||||||
m_context->bindResourceSampler(BindingIds::Sampler, m_sampler);
|
m_context->bindResourceSampler(BindingIds::Sampler,
|
||||||
m_context->bindResourceImage (BindingIds::Texture, m_backBufferView);
|
fitSize ? m_samplerFitting : m_samplerScaling);
|
||||||
|
|
||||||
|
m_context->bindResourceImage(BindingIds::Texture, m_backBufferView);
|
||||||
m_context->draw(4, 1, 0, 0);
|
m_context->draw(4, 1, 0, 0);
|
||||||
|
|
||||||
m_device->submitCommandList(
|
m_device->submitCommandList(
|
||||||
@ -256,21 +258,34 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void DxgiPresenter::recreateSwapchain(
|
void DxgiPresenter::recreateSwapchain(const DxvkSwapchainProperties& options) {
|
||||||
uint32_t bufferWidth,
|
const bool doRecreate =
|
||||||
uint32_t bufferHeight,
|
options.preferredSurfaceFormat.format != m_options.preferredSurfaceFormat.format
|
||||||
DXGI_FORMAT bufferFormat) {
|
|| options.preferredSurfaceFormat.colorSpace != m_options.preferredSurfaceFormat.colorSpace
|
||||||
DxvkSwapchainProperties swapchainProperties;
|
|| options.preferredPresentMode != m_options.preferredPresentMode
|
||||||
swapchainProperties.preferredSurfaceFormat = this->pickFormat(bufferFormat);
|
|| options.preferredBufferSize.width != m_options.preferredBufferSize.width
|
||||||
swapchainProperties.preferredPresentMode = VK_PRESENT_MODE_IMMEDIATE_KHR;
|
|| options.preferredBufferSize.height != m_options.preferredBufferSize.height;
|
||||||
swapchainProperties.preferredBufferSize.width = bufferWidth;
|
|
||||||
swapchainProperties.preferredBufferSize.height = bufferHeight;
|
|
||||||
|
|
||||||
m_swapchain->changeProperties(swapchainProperties);
|
if (doRecreate) {
|
||||||
|
Logger::info(str::format(
|
||||||
|
"DxgiPresenter: Recreating swap chain: ",
|
||||||
|
"\n Format: ", options.preferredSurfaceFormat.format,
|
||||||
|
"\n Present mode: ", options.preferredPresentMode,
|
||||||
|
"\n Buffer size: ", options.preferredBufferSize.width, "x", options.preferredBufferSize.height));
|
||||||
|
|
||||||
|
m_options = options;
|
||||||
|
|
||||||
|
if (m_swapchain == nullptr) {
|
||||||
|
m_swapchain = m_device->createSwapchain(
|
||||||
|
m_surface, options);
|
||||||
|
} else {
|
||||||
|
m_swapchain->changeProperties(options);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
VkSurfaceFormatKHR DxgiPresenter::pickFormat(DXGI_FORMAT fmt) const {
|
VkSurfaceFormatKHR DxgiPresenter::pickSurfaceFormat(DXGI_FORMAT fmt) const {
|
||||||
std::vector<VkSurfaceFormatKHR> formats;
|
std::vector<VkSurfaceFormatKHR> formats;
|
||||||
|
|
||||||
switch (fmt) {
|
switch (fmt) {
|
||||||
@ -295,6 +310,11 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VkPresentModeKHR DxgiPresenter::pickPresentMode(VkPresentModeKHR preferred) const {
|
||||||
|
return m_surface->pickPresentMode(1, &preferred);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Rc<DxvkShader> DxgiPresenter::createVertexShader() {
|
Rc<DxvkShader> DxgiPresenter::createVertexShader() {
|
||||||
SpirvModule module;
|
SpirvModule module;
|
||||||
|
|
||||||
|
@ -22,11 +22,8 @@ namespace dxvk {
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
DxgiPresenter(
|
DxgiPresenter(
|
||||||
const Rc<DxvkDevice>& device,
|
const Rc<DxvkDevice>& device,
|
||||||
HWND window,
|
HWND window);
|
||||||
uint32_t bufferWidth,
|
|
||||||
uint32_t bufferHeight,
|
|
||||||
DXGI_FORMAT bufferFormat);
|
|
||||||
|
|
||||||
~DxgiPresenter();
|
~DxgiPresenter();
|
||||||
|
|
||||||
@ -50,16 +47,36 @@ namespace dxvk {
|
|||||||
* \param [in] image Back buffer image
|
* \param [in] image Back buffer image
|
||||||
*/
|
*/
|
||||||
void updateBackBuffer(
|
void updateBackBuffer(
|
||||||
const Rc<DxvkImage>& image);
|
const Rc<DxvkImage>& image);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Renders image to the screen
|
* \brief Recreats Vulkan swap chain
|
||||||
* \param [in] view Source image view
|
*
|
||||||
|
* Only actually recreates the swap chain object
|
||||||
|
* if any of the properties have changed. If no
|
||||||
|
* properties have changed, this is a no-op.
|
||||||
|
* \param [in] options New swap chain options
|
||||||
*/
|
*/
|
||||||
void recreateSwapchain(
|
void recreateSwapchain(
|
||||||
uint32_t bufferWidth,
|
const DxvkSwapchainProperties& options);
|
||||||
uint32_t bufferHeight,
|
|
||||||
DXGI_FORMAT bufferFormat);
|
/**
|
||||||
|
* \brief Picks a surface format based on a DXGI format
|
||||||
|
*
|
||||||
|
* This will return a supported format that, if possible,
|
||||||
|
* has properties similar to those of the DXGI format.
|
||||||
|
* \param [in] fmt The DXGI format
|
||||||
|
* \returns The Vulkan format
|
||||||
|
*/
|
||||||
|
VkSurfaceFormatKHR pickSurfaceFormat(DXGI_FORMAT fmt) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Picks a supported present mode
|
||||||
|
*
|
||||||
|
* \param [in] preferred Preferred present mode
|
||||||
|
* \returns An actually supported present mode
|
||||||
|
*/
|
||||||
|
VkPresentModeKHR pickPresentMode(VkPresentModeKHR preferred) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@ -74,13 +91,14 @@ namespace dxvk {
|
|||||||
Rc<DxvkSurface> m_surface;
|
Rc<DxvkSurface> m_surface;
|
||||||
Rc<DxvkSwapchain> m_swapchain;
|
Rc<DxvkSwapchain> m_swapchain;
|
||||||
|
|
||||||
Rc<DxvkSampler> m_sampler;
|
Rc<DxvkSampler> m_samplerFitting;
|
||||||
|
Rc<DxvkSampler> m_samplerScaling;
|
||||||
|
|
||||||
Rc<DxvkImage> m_backBuffer;
|
Rc<DxvkImage> m_backBuffer;
|
||||||
Rc<DxvkImage> m_backBufferResolve;
|
Rc<DxvkImage> m_backBufferResolve;
|
||||||
Rc<DxvkImageView> m_backBufferView;
|
Rc<DxvkImageView> m_backBufferView;
|
||||||
|
|
||||||
VkSurfaceFormatKHR pickFormat(DXGI_FORMAT fmt) const;
|
DxvkSwapchainProperties m_options;
|
||||||
|
|
||||||
Rc<DxvkShader> createVertexShader();
|
Rc<DxvkShader> createVertexShader();
|
||||||
Rc<DxvkShader> createFragmentShader();
|
Rc<DxvkShader> createFragmentShader();
|
||||||
|
@ -36,36 +36,24 @@ namespace dxvk {
|
|||||||
m_stats.SyncQPCTime.QuadPart = 0;
|
m_stats.SyncQPCTime.QuadPart = 0;
|
||||||
m_stats.SyncGPUTime.QuadPart = 0;
|
m_stats.SyncGPUTime.QuadPart = 0;
|
||||||
|
|
||||||
// Create SDL window handle
|
|
||||||
m_window = SDL_CreateWindowFrom(m_desc.OutputWindow);
|
|
||||||
|
|
||||||
if (m_window == nullptr) {
|
|
||||||
throw DxvkError(str::format(
|
|
||||||
"DxgiSwapChain::DxgiSwapChain: Failed to create window:\n",
|
|
||||||
SDL_GetError()));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Adjust initial back buffer size. If zero, these
|
// Adjust initial back buffer size. If zero, these
|
||||||
// shall be set to the current window size.
|
// shall be set to the current window size.
|
||||||
VkExtent2D windowSize = this->getWindowSize();
|
const VkExtent2D windowSize = GetWindowSize();
|
||||||
|
|
||||||
if (m_desc.BufferDesc.Width == 0) m_desc.BufferDesc.Width = windowSize.width;
|
if (m_desc.BufferDesc.Width == 0) m_desc.BufferDesc.Width = windowSize.width;
|
||||||
if (m_desc.BufferDesc.Height == 0) m_desc.BufferDesc.Height = windowSize.height;
|
if (m_desc.BufferDesc.Height == 0) m_desc.BufferDesc.Height = windowSize.height;
|
||||||
|
|
||||||
// Set initial window mode and fullscreen state
|
// Set initial window mode and fullscreen state
|
||||||
if (FAILED(this->SetFullscreenState(!pDesc->Windowed, nullptr)))
|
// if (FAILED(this->SetFullscreenState(!pDesc->Windowed, nullptr)))
|
||||||
throw DxvkError("DxgiSwapChain::DxgiSwapChain: Failed to set initial fullscreen state");
|
// throw DxvkError("DxgiSwapChain: Failed to set initial fullscreen state");
|
||||||
|
|
||||||
this->createPresenter();
|
if (FAILED(CreatePresenter()) || FAILED(CreateBackBuffer()))
|
||||||
this->createBackBuffer();
|
throw DxvkError("DxgiSwapChain: Failed to create presenter or back buffer");
|
||||||
TRACE(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
DxgiSwapChain::~DxgiSwapChain() {
|
DxgiSwapChain::~DxgiSwapChain() {
|
||||||
TRACE(this);
|
|
||||||
// We do not release the SDL window handle here since
|
|
||||||
// that would destroy the underlying window as well.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -106,18 +94,8 @@ namespace dxvk {
|
|||||||
if (ppOutput != nullptr)
|
if (ppOutput != nullptr)
|
||||||
return DXGI_ERROR_INVALID_CALL;
|
return DXGI_ERROR_INVALID_CALL;
|
||||||
|
|
||||||
// We can use the display index returned by SDL to query the
|
Logger::err("DxgiSwapChain::GetContainingOutput: Not implemented");
|
||||||
// containing output, since DxgiAdapter::EnumOutputs uses the
|
return E_NOTIMPL;
|
||||||
// same output IDs.
|
|
||||||
std::lock_guard<std::mutex> lock(m_mutex);
|
|
||||||
int32_t displayId = SDL_GetWindowDisplayIndex(m_window);
|
|
||||||
|
|
||||||
if (displayId < 0) {
|
|
||||||
Logger::err("DxgiSwapChain::GetContainingOutput: Failed to query window display index");
|
|
||||||
return DXGI_ERROR_DRIVER_INTERNAL_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
return m_adapter->EnumOutputs(displayId, ppOutput);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -175,10 +153,23 @@ namespace dxvk {
|
|||||||
// Submit pending rendering commands
|
// Submit pending rendering commands
|
||||||
// before recording the present code.
|
// before recording the present code.
|
||||||
m_presentDevice->FlushRenderingCommands();
|
m_presentDevice->FlushRenderingCommands();
|
||||||
|
|
||||||
// TODO implement sync interval
|
// Update swap chain properties. This will not only set
|
||||||
// TODO implement flags
|
// up vertical synchronization properly, but also apply
|
||||||
m_presenter->presentImage();
|
// changes that were made to the window size even if the
|
||||||
|
// Vulkan swap chain itself remains valid.
|
||||||
|
DxvkSwapchainProperties swapchainProps;
|
||||||
|
swapchainProps.preferredSurfaceFormat
|
||||||
|
= m_presenter->pickSurfaceFormat(m_desc.BufferDesc.Format);
|
||||||
|
swapchainProps.preferredPresentMode = SyncInterval == 0
|
||||||
|
? m_presenter->pickPresentMode(VK_PRESENT_MODE_IMMEDIATE_KHR)
|
||||||
|
: m_presenter->pickPresentMode(VK_PRESENT_MODE_MAILBOX_KHR);
|
||||||
|
swapchainProps.preferredBufferSize = GetWindowSize();
|
||||||
|
|
||||||
|
m_presenter->recreateSwapchain(swapchainProps);
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < SyncInterval || i < 1; i++)
|
||||||
|
m_presenter->presentImage();
|
||||||
return S_OK;
|
return S_OK;
|
||||||
} catch (const DxvkError& err) {
|
} catch (const DxvkError& err) {
|
||||||
Logger::err(err.message());
|
Logger::err(err.message());
|
||||||
@ -195,9 +186,9 @@ namespace dxvk {
|
|||||||
UINT SwapChainFlags) {
|
UINT SwapChainFlags) {
|
||||||
std::lock_guard<std::mutex> lock(m_mutex);
|
std::lock_guard<std::mutex> lock(m_mutex);
|
||||||
|
|
||||||
VkExtent2D windowSize = this->getWindowSize();
|
const VkExtent2D windowSize = GetWindowSize();
|
||||||
|
|
||||||
m_desc.BufferDesc.Width = Width != 0 ? Width : windowSize.width;
|
m_desc.BufferDesc.Width = Width != 0 ? Width : windowSize.width;
|
||||||
m_desc.BufferDesc.Height = Height != 0 ? Height : windowSize.height;
|
m_desc.BufferDesc.Height = Height != 0 ? Height : windowSize.height;
|
||||||
|
|
||||||
m_desc.Flags = SwapChainFlags;
|
m_desc.Flags = SwapChainFlags;
|
||||||
@ -208,17 +199,7 @@ namespace dxvk {
|
|||||||
if (NewFormat != DXGI_FORMAT_UNKNOWN)
|
if (NewFormat != DXGI_FORMAT_UNKNOWN)
|
||||||
m_desc.BufferDesc.Format = NewFormat;
|
m_desc.BufferDesc.Format = NewFormat;
|
||||||
|
|
||||||
try {
|
return CreateBackBuffer();
|
||||||
m_presenter->recreateSwapchain(
|
|
||||||
m_desc.BufferDesc.Width,
|
|
||||||
m_desc.BufferDesc.Height,
|
|
||||||
m_desc.BufferDesc.Format);
|
|
||||||
this->createBackBuffer();
|
|
||||||
return S_OK;
|
|
||||||
} catch (const DxvkError& err) {
|
|
||||||
Logger::err(err.message());
|
|
||||||
return DXGI_ERROR_DRIVER_INTERNAL_ERROR;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -228,39 +209,21 @@ namespace dxvk {
|
|||||||
|
|
||||||
std::lock_guard<std::mutex> lock(m_mutex);
|
std::lock_guard<std::mutex> lock(m_mutex);
|
||||||
|
|
||||||
// Applies to windowed mode
|
// TODO support fullscreen mode
|
||||||
SDL_SetWindowSize(m_window,
|
RECT newRect = { 0, 0, 0, 0 };
|
||||||
pNewTargetParameters->Width,
|
RECT oldRect = { 0, 0, 0, 0 };
|
||||||
pNewTargetParameters->Height);
|
|
||||||
|
|
||||||
// Applies to fullscreen mode
|
::GetWindowRect(m_desc.OutputWindow, &oldRect);
|
||||||
SDL_DisplayMode displayMode;
|
::SetRect(&newRect, 0, 0, pNewTargetParameters->Width, pNewTargetParameters->Height);
|
||||||
displayMode.format = SDL_PIXELFORMAT_RGBA32;
|
::AdjustWindowRectEx(&newRect,
|
||||||
displayMode.w = pNewTargetParameters->Width;
|
::GetWindowLongW(m_desc.OutputWindow, GWL_STYLE), FALSE,
|
||||||
displayMode.h = pNewTargetParameters->Height;
|
::GetWindowLongW(m_desc.OutputWindow, GWL_EXSTYLE));
|
||||||
displayMode.refresh_rate = pNewTargetParameters->RefreshRate.Numerator
|
::SetRect(&newRect, 0, 0, newRect.right - newRect.left, newRect.bottom - newRect.top);
|
||||||
/ pNewTargetParameters->RefreshRate.Denominator;
|
::OffsetRect(&newRect, oldRect.left, oldRect.top);
|
||||||
displayMode.driverdata = nullptr;
|
::MoveWindow(m_desc.OutputWindow, newRect.left, newRect.top,
|
||||||
|
newRect.right - newRect.left, newRect.bottom - newRect.top, TRUE);
|
||||||
|
|
||||||
// TODO test mode change flag
|
return S_OK;
|
||||||
|
|
||||||
if (SDL_SetWindowDisplayMode(m_window, &displayMode)) {
|
|
||||||
Logger::err(str::format(
|
|
||||||
"DxgiSwapChain::ResizeTarget: Failed to set display mode:\n",
|
|
||||||
SDL_GetError()));
|
|
||||||
return DXGI_ERROR_DRIVER_INTERNAL_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
m_presenter->recreateSwapchain(
|
|
||||||
m_desc.BufferDesc.Width,
|
|
||||||
m_desc.BufferDesc.Height,
|
|
||||||
m_desc.BufferDesc.Format);
|
|
||||||
return S_OK;
|
|
||||||
} catch (const DxvkError& err) {
|
|
||||||
Logger::err(err.message());
|
|
||||||
return DXGI_ERROR_DRIVER_INTERNAL_ERROR;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -269,81 +232,54 @@ namespace dxvk {
|
|||||||
IDXGIOutput* pTarget) {
|
IDXGIOutput* pTarget) {
|
||||||
std::lock_guard<std::mutex> lock(m_mutex);
|
std::lock_guard<std::mutex> lock(m_mutex);
|
||||||
|
|
||||||
// Unconditionally reset the swap chain to windowed mode first.
|
Logger::err("DxgiSwapChain::SetFullscreenState: Not implemented");
|
||||||
// This required if the application wants to move the window to
|
return E_NOTIMPL;
|
||||||
// a different display while remaining in fullscreen mode.
|
|
||||||
if (SDL_SetWindowFullscreen(m_window, 0)) {
|
|
||||||
Logger::err(str::format(
|
|
||||||
"DxgiSwapChain::SetFullscreenState: Failed to set windowed mode:\n",
|
|
||||||
SDL_GetError()));
|
|
||||||
return DXGI_ERROR_NOT_CURRENTLY_AVAILABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_desc.Windowed = !Fullscreen;
|
|
||||||
|
|
||||||
if (Fullscreen) {
|
|
||||||
// If a target output is specified, we need to move the
|
|
||||||
// window to that output first while in windowed mode.
|
|
||||||
if (pTarget != nullptr) {
|
|
||||||
DXGI_OUTPUT_DESC outputDesc;
|
|
||||||
|
|
||||||
if (FAILED(pTarget->GetDesc(&outputDesc))) {
|
|
||||||
Logger::err("DxgiSwapChain::SetFullscreenState: Failed to query output properties");
|
|
||||||
return DXGI_ERROR_NOT_CURRENTLY_AVAILABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
SDL_SetWindowPosition(m_window,
|
|
||||||
outputDesc.DesktopCoordinates.left,
|
|
||||||
outputDesc.DesktopCoordinates.top);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now that the window is located at the target location,
|
|
||||||
// SDL should fullscreen it on the requested display. We
|
|
||||||
// only use borderless fullscreen for now, may be changed.
|
|
||||||
if (SDL_SetWindowFullscreen(m_window, SDL_WINDOW_FULLSCREEN_DESKTOP)) {
|
|
||||||
Logger::err(str::format(
|
|
||||||
"DxgiSwapChain::SetFullscreenState: Failed to set fullscreen mode:\n",
|
|
||||||
SDL_GetError()));
|
|
||||||
return DXGI_ERROR_NOT_CURRENTLY_AVAILABLE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return S_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void DxgiSwapChain::createPresenter() {
|
HRESULT DxgiSwapChain::CreatePresenter() {
|
||||||
m_presenter = new DxgiPresenter(
|
try {
|
||||||
m_device->GetDXVKDevice(),
|
m_presenter = new DxgiPresenter(
|
||||||
m_desc.OutputWindow,
|
m_device->GetDXVKDevice(),
|
||||||
m_desc.BufferDesc.Width,
|
m_desc.OutputWindow);
|
||||||
m_desc.BufferDesc.Height,
|
return S_OK;
|
||||||
m_desc.BufferDesc.Format);
|
} catch (const DxvkError& e) {
|
||||||
|
Logger::err(e.message());
|
||||||
|
return E_FAIL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void DxgiSwapChain::createBackBuffer() {
|
HRESULT DxgiSwapChain::CreateBackBuffer() {
|
||||||
VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT;
|
VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT;
|
||||||
|
|
||||||
if (FAILED(GetSampleCount(m_desc.SampleDesc.Count, &sampleCount)))
|
if (FAILED(GetSampleCount(m_desc.SampleDesc.Count, &sampleCount))) {
|
||||||
throw DxvkError("DxgiSwapChain: Invalid sample count");
|
Logger::err("DxgiSwapChain: Invalid sample count");
|
||||||
|
return E_INVALIDARG;
|
||||||
|
}
|
||||||
|
|
||||||
if (FAILED(m_presentDevice->CreateSwapChainBackBuffer(&m_desc, &m_backBuffer)))
|
if (FAILED(m_presentDevice->CreateSwapChainBackBuffer(&m_desc, &m_backBuffer))) {
|
||||||
throw DxvkError("DxgiSwapChain: Failed to create back buffer");
|
Logger::err("DxgiSwapChain: Failed to create back buffer");
|
||||||
|
return E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
m_presenter->updateBackBuffer(m_backBuffer->GetDXVKImage());
|
try {
|
||||||
|
m_presenter->updateBackBuffer(m_backBuffer->GetDXVKImage());
|
||||||
|
return S_OK;
|
||||||
|
} catch (const DxvkError& e) {
|
||||||
|
Logger::err(e.message());
|
||||||
|
return E_FAIL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
VkExtent2D DxgiSwapChain::getWindowSize() const {
|
VkExtent2D DxgiSwapChain::GetWindowSize() const {
|
||||||
int winWidth = 0;
|
RECT windowRect;
|
||||||
int winHeight = 0;
|
::GetClientRect(m_desc.OutputWindow, &windowRect);
|
||||||
|
|
||||||
SDL_GetWindowSize(m_window, &winWidth, &winHeight);
|
|
||||||
|
|
||||||
VkExtent2D result;
|
VkExtent2D result;
|
||||||
result.width = winWidth;
|
result.width = windowRect.right;
|
||||||
result.height = winHeight;
|
result.height = windowRect.bottom;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,20 +88,16 @@ namespace dxvk {
|
|||||||
Com<IDXGIDevicePrivate> m_device;
|
Com<IDXGIDevicePrivate> m_device;
|
||||||
Com<IDXGIPresentDevicePrivate> m_presentDevice;
|
Com<IDXGIPresentDevicePrivate> m_presentDevice;
|
||||||
|
|
||||||
DXGI_SWAP_CHAIN_DESC m_desc;
|
DXGI_SWAP_CHAIN_DESC m_desc;
|
||||||
DXGI_FRAME_STATISTICS m_stats;
|
DXGI_FRAME_STATISTICS m_stats;
|
||||||
|
|
||||||
SDL_Window* m_window = nullptr;
|
Rc<DxgiPresenter> m_presenter;
|
||||||
|
Com<IDXGIPresentBackBuffer> m_backBuffer;
|
||||||
|
|
||||||
Rc<DxgiPresenter> m_presenter;
|
HRESULT CreatePresenter();
|
||||||
Com<IDXGIPresentBackBuffer> m_backBuffer;
|
HRESULT CreateBackBuffer();
|
||||||
|
|
||||||
void createPresenter();
|
VkExtent2D GetWindowSize() const;
|
||||||
void createBackBuffer();
|
|
||||||
|
|
||||||
void createContext();
|
|
||||||
|
|
||||||
VkExtent2D getWindowSize() const;
|
|
||||||
|
|
||||||
HRESULT GetSampleCount(
|
HRESULT GetSampleCount(
|
||||||
UINT Count,
|
UINT Count,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user