mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-02-20 19:54:19 +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
|
||||
&& testMode.h == currMode.h
|
||||
&& testMode.refresh_rate == currMode.refresh_rate;
|
||||
&& testMode.h == currMode.h
|
||||
&& testMode.refresh_rate == currMode.refresh_rate;
|
||||
}
|
||||
|
||||
// Convert the SDL display mode to a DXGI display mode info
|
||||
// structure and filter out any unwanted modes based on the
|
||||
// supplied flags.
|
||||
if (!hasMode) {
|
||||
bool isNativeMode = (currMode.w == desktopMode.w)
|
||||
&& (currMode.h == desktopMode.h);
|
||||
|
||||
if (isNativeMode || (Flags & DXGI_ENUM_MODES_SCALING)) {
|
||||
DXGI_MODE_DESC mode;
|
||||
mode.Width = currMode.w;
|
||||
mode.Height = currMode.h;
|
||||
mode.RefreshRate.Numerator = currMode.refresh_rate;
|
||||
mode.RefreshRate.Denominator = 1;
|
||||
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);
|
||||
}
|
||||
DXGI_MODE_DESC mode;
|
||||
mode.Width = currMode.w;
|
||||
mode.Height = currMode.h;
|
||||
mode.RefreshRate.Numerator = currMode.refresh_rate;
|
||||
mode.RefreshRate.Denominator = 1;
|
||||
mode.Format = EnumFormat;
|
||||
mode.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_PROGRESSIVE;
|
||||
mode.Scaling = DXGI_MODE_SCALING_CENTERED;
|
||||
modes.push_back(mode);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,11 +5,8 @@
|
||||
namespace dxvk {
|
||||
|
||||
DxgiPresenter::DxgiPresenter(
|
||||
const Rc<DxvkDevice>& device,
|
||||
HWND window,
|
||||
uint32_t bufferWidth,
|
||||
uint32_t bufferHeight,
|
||||
DXGI_FORMAT bufferFormat)
|
||||
const Rc<DxvkDevice>& device,
|
||||
HWND window)
|
||||
: m_device (device),
|
||||
m_context (device->createContext()) {
|
||||
|
||||
@ -19,15 +16,11 @@ namespace dxvk {
|
||||
|
||||
m_surface = m_device->adapter()->createSurface(instance, window);
|
||||
|
||||
// Create swap chain for the surface
|
||||
DxvkSwapchainProperties swapchainProperties;
|
||||
swapchainProperties.preferredSurfaceFormat = this->pickFormat(bufferFormat);
|
||||
swapchainProperties.preferredPresentMode = VK_PRESENT_MODE_IMMEDIATE_KHR;
|
||||
swapchainProperties.preferredBufferSize.width = bufferWidth;
|
||||
swapchainProperties.preferredBufferSize.height = bufferHeight;
|
||||
|
||||
m_swapchain = m_device->createSwapchain(
|
||||
m_surface, swapchainProperties);
|
||||
// Reset options for the swap chain itself. We will
|
||||
// create a swap chain object before presentation.
|
||||
m_options.preferredSurfaceFormat = { VK_FORMAT_UNDEFINED, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR };
|
||||
m_options.preferredPresentMode = VK_PRESENT_MODE_FIFO_KHR;
|
||||
m_options.preferredBufferSize = { 0u, 0u };
|
||||
|
||||
// Sampler for presentation
|
||||
DxvkSamplerCreateInfo samplerInfo;
|
||||
@ -46,8 +39,11 @@ namespace dxvk {
|
||||
samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS;
|
||||
samplerInfo.borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK;
|
||||
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
|
||||
// constant state objects will never be modified.
|
||||
@ -153,6 +149,10 @@ namespace dxvk {
|
||||
|
||||
|
||||
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_device->createCommandList());
|
||||
|
||||
@ -191,8 +191,10 @@ namespace dxvk {
|
||||
|
||||
m_context->setViewports(1, &viewport, &scissor);
|
||||
|
||||
m_context->bindResourceSampler(BindingIds::Sampler, m_sampler);
|
||||
m_context->bindResourceImage (BindingIds::Texture, m_backBufferView);
|
||||
m_context->bindResourceSampler(BindingIds::Sampler,
|
||||
fitSize ? m_samplerFitting : m_samplerScaling);
|
||||
|
||||
m_context->bindResourceImage(BindingIds::Texture, m_backBufferView);
|
||||
m_context->draw(4, 1, 0, 0);
|
||||
|
||||
m_device->submitCommandList(
|
||||
@ -256,21 +258,34 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
void DxgiPresenter::recreateSwapchain(
|
||||
uint32_t bufferWidth,
|
||||
uint32_t bufferHeight,
|
||||
DXGI_FORMAT bufferFormat) {
|
||||
DxvkSwapchainProperties swapchainProperties;
|
||||
swapchainProperties.preferredSurfaceFormat = this->pickFormat(bufferFormat);
|
||||
swapchainProperties.preferredPresentMode = VK_PRESENT_MODE_IMMEDIATE_KHR;
|
||||
swapchainProperties.preferredBufferSize.width = bufferWidth;
|
||||
swapchainProperties.preferredBufferSize.height = bufferHeight;
|
||||
void DxgiPresenter::recreateSwapchain(const DxvkSwapchainProperties& options) {
|
||||
const bool doRecreate =
|
||||
options.preferredSurfaceFormat.format != m_options.preferredSurfaceFormat.format
|
||||
|| options.preferredSurfaceFormat.colorSpace != m_options.preferredSurfaceFormat.colorSpace
|
||||
|| options.preferredPresentMode != m_options.preferredPresentMode
|
||||
|| options.preferredBufferSize.width != m_options.preferredBufferSize.width
|
||||
|| options.preferredBufferSize.height != m_options.preferredBufferSize.height;
|
||||
|
||||
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;
|
||||
|
||||
switch (fmt) {
|
||||
@ -295,6 +310,11 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
VkPresentModeKHR DxgiPresenter::pickPresentMode(VkPresentModeKHR preferred) const {
|
||||
return m_surface->pickPresentMode(1, &preferred);
|
||||
}
|
||||
|
||||
|
||||
Rc<DxvkShader> DxgiPresenter::createVertexShader() {
|
||||
SpirvModule module;
|
||||
|
||||
|
@ -22,11 +22,8 @@ namespace dxvk {
|
||||
public:
|
||||
|
||||
DxgiPresenter(
|
||||
const Rc<DxvkDevice>& device,
|
||||
HWND window,
|
||||
uint32_t bufferWidth,
|
||||
uint32_t bufferHeight,
|
||||
DXGI_FORMAT bufferFormat);
|
||||
const Rc<DxvkDevice>& device,
|
||||
HWND window);
|
||||
|
||||
~DxgiPresenter();
|
||||
|
||||
@ -50,16 +47,36 @@ namespace dxvk {
|
||||
* \param [in] image Back buffer image
|
||||
*/
|
||||
void updateBackBuffer(
|
||||
const Rc<DxvkImage>& image);
|
||||
const Rc<DxvkImage>& image);
|
||||
|
||||
/**
|
||||
* \brief Renders image to the screen
|
||||
* \param [in] view Source image view
|
||||
* \brief Recreats Vulkan swap chain
|
||||
*
|
||||
* 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(
|
||||
uint32_t bufferWidth,
|
||||
uint32_t bufferHeight,
|
||||
DXGI_FORMAT bufferFormat);
|
||||
const DxvkSwapchainProperties& options);
|
||||
|
||||
/**
|
||||
* \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:
|
||||
|
||||
@ -74,13 +91,14 @@ namespace dxvk {
|
||||
Rc<DxvkSurface> m_surface;
|
||||
Rc<DxvkSwapchain> m_swapchain;
|
||||
|
||||
Rc<DxvkSampler> m_sampler;
|
||||
Rc<DxvkSampler> m_samplerFitting;
|
||||
Rc<DxvkSampler> m_samplerScaling;
|
||||
|
||||
Rc<DxvkImage> m_backBuffer;
|
||||
Rc<DxvkImage> m_backBufferResolve;
|
||||
Rc<DxvkImageView> m_backBufferView;
|
||||
|
||||
VkSurfaceFormatKHR pickFormat(DXGI_FORMAT fmt) const;
|
||||
DxvkSwapchainProperties m_options;
|
||||
|
||||
Rc<DxvkShader> createVertexShader();
|
||||
Rc<DxvkShader> createFragmentShader();
|
||||
|
@ -36,36 +36,24 @@ namespace dxvk {
|
||||
m_stats.SyncQPCTime.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
|
||||
// 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.Height == 0) m_desc.BufferDesc.Height = windowSize.height;
|
||||
|
||||
// Set initial window mode and fullscreen state
|
||||
if (FAILED(this->SetFullscreenState(!pDesc->Windowed, nullptr)))
|
||||
throw DxvkError("DxgiSwapChain::DxgiSwapChain: Failed to set initial fullscreen state");
|
||||
// if (FAILED(this->SetFullscreenState(!pDesc->Windowed, nullptr)))
|
||||
// throw DxvkError("DxgiSwapChain: Failed to set initial fullscreen state");
|
||||
|
||||
this->createPresenter();
|
||||
this->createBackBuffer();
|
||||
TRACE(this);
|
||||
if (FAILED(CreatePresenter()) || FAILED(CreateBackBuffer()))
|
||||
throw DxvkError("DxgiSwapChain: Failed to create presenter or back buffer");
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
return DXGI_ERROR_INVALID_CALL;
|
||||
|
||||
// We can use the display index returned by SDL to query the
|
||||
// containing output, since DxgiAdapter::EnumOutputs uses the
|
||||
// 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);
|
||||
Logger::err("DxgiSwapChain::GetContainingOutput: Not implemented");
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
|
||||
@ -175,10 +153,23 @@ namespace dxvk {
|
||||
// Submit pending rendering commands
|
||||
// before recording the present code.
|
||||
m_presentDevice->FlushRenderingCommands();
|
||||
|
||||
// TODO implement sync interval
|
||||
// TODO implement flags
|
||||
m_presenter->presentImage();
|
||||
|
||||
// Update swap chain properties. This will not only set
|
||||
// up vertical synchronization properly, but also apply
|
||||
// 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;
|
||||
} catch (const DxvkError& err) {
|
||||
Logger::err(err.message());
|
||||
@ -195,9 +186,9 @@ namespace dxvk {
|
||||
UINT SwapChainFlags) {
|
||||
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.Flags = SwapChainFlags;
|
||||
@ -208,17 +199,7 @@ namespace dxvk {
|
||||
if (NewFormat != DXGI_FORMAT_UNKNOWN)
|
||||
m_desc.BufferDesc.Format = NewFormat;
|
||||
|
||||
try {
|
||||
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;
|
||||
}
|
||||
return CreateBackBuffer();
|
||||
}
|
||||
|
||||
|
||||
@ -228,39 +209,21 @@ namespace dxvk {
|
||||
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
// Applies to windowed mode
|
||||
SDL_SetWindowSize(m_window,
|
||||
pNewTargetParameters->Width,
|
||||
pNewTargetParameters->Height);
|
||||
// TODO support fullscreen mode
|
||||
RECT newRect = { 0, 0, 0, 0 };
|
||||
RECT oldRect = { 0, 0, 0, 0 };
|
||||
|
||||
// Applies to fullscreen mode
|
||||
SDL_DisplayMode displayMode;
|
||||
displayMode.format = SDL_PIXELFORMAT_RGBA32;
|
||||
displayMode.w = pNewTargetParameters->Width;
|
||||
displayMode.h = pNewTargetParameters->Height;
|
||||
displayMode.refresh_rate = pNewTargetParameters->RefreshRate.Numerator
|
||||
/ pNewTargetParameters->RefreshRate.Denominator;
|
||||
displayMode.driverdata = nullptr;
|
||||
::GetWindowRect(m_desc.OutputWindow, &oldRect);
|
||||
::SetRect(&newRect, 0, 0, pNewTargetParameters->Width, pNewTargetParameters->Height);
|
||||
::AdjustWindowRectEx(&newRect,
|
||||
::GetWindowLongW(m_desc.OutputWindow, GWL_STYLE), FALSE,
|
||||
::GetWindowLongW(m_desc.OutputWindow, GWL_EXSTYLE));
|
||||
::SetRect(&newRect, 0, 0, newRect.right - newRect.left, newRect.bottom - newRect.top);
|
||||
::OffsetRect(&newRect, oldRect.left, oldRect.top);
|
||||
::MoveWindow(m_desc.OutputWindow, newRect.left, newRect.top,
|
||||
newRect.right - newRect.left, newRect.bottom - newRect.top, TRUE);
|
||||
|
||||
// TODO test mode change flag
|
||||
|
||||
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;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
@ -269,81 +232,54 @@ namespace dxvk {
|
||||
IDXGIOutput* pTarget) {
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
// Unconditionally reset the swap chain to windowed mode first.
|
||||
// This required if the application wants to move the window to
|
||||
// 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;
|
||||
Logger::err("DxgiSwapChain::SetFullscreenState: Not implemented");
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
|
||||
void DxgiSwapChain::createPresenter() {
|
||||
m_presenter = new DxgiPresenter(
|
||||
m_device->GetDXVKDevice(),
|
||||
m_desc.OutputWindow,
|
||||
m_desc.BufferDesc.Width,
|
||||
m_desc.BufferDesc.Height,
|
||||
m_desc.BufferDesc.Format);
|
||||
HRESULT DxgiSwapChain::CreatePresenter() {
|
||||
try {
|
||||
m_presenter = new DxgiPresenter(
|
||||
m_device->GetDXVKDevice(),
|
||||
m_desc.OutputWindow);
|
||||
return S_OK;
|
||||
} catch (const DxvkError& e) {
|
||||
Logger::err(e.message());
|
||||
return E_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DxgiSwapChain::createBackBuffer() {
|
||||
HRESULT DxgiSwapChain::CreateBackBuffer() {
|
||||
VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT;
|
||||
|
||||
if (FAILED(GetSampleCount(m_desc.SampleDesc.Count, &sampleCount)))
|
||||
throw DxvkError("DxgiSwapChain: Invalid sample count");
|
||||
if (FAILED(GetSampleCount(m_desc.SampleDesc.Count, &sampleCount))) {
|
||||
Logger::err("DxgiSwapChain: Invalid sample count");
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
if (FAILED(m_presentDevice->CreateSwapChainBackBuffer(&m_desc, &m_backBuffer)))
|
||||
throw DxvkError("DxgiSwapChain: Failed to create back buffer");
|
||||
if (FAILED(m_presentDevice->CreateSwapChainBackBuffer(&m_desc, &m_backBuffer))) {
|
||||
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 {
|
||||
int winWidth = 0;
|
||||
int winHeight = 0;
|
||||
|
||||
SDL_GetWindowSize(m_window, &winWidth, &winHeight);
|
||||
VkExtent2D DxgiSwapChain::GetWindowSize() const {
|
||||
RECT windowRect;
|
||||
::GetClientRect(m_desc.OutputWindow, &windowRect);
|
||||
|
||||
VkExtent2D result;
|
||||
result.width = winWidth;
|
||||
result.height = winHeight;
|
||||
result.width = windowRect.right;
|
||||
result.height = windowRect.bottom;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -88,20 +88,16 @@ namespace dxvk {
|
||||
Com<IDXGIDevicePrivate> m_device;
|
||||
Com<IDXGIPresentDevicePrivate> m_presentDevice;
|
||||
|
||||
DXGI_SWAP_CHAIN_DESC m_desc;
|
||||
DXGI_FRAME_STATISTICS m_stats;
|
||||
DXGI_SWAP_CHAIN_DESC m_desc;
|
||||
DXGI_FRAME_STATISTICS m_stats;
|
||||
|
||||
SDL_Window* m_window = nullptr;
|
||||
Rc<DxgiPresenter> m_presenter;
|
||||
Com<IDXGIPresentBackBuffer> m_backBuffer;
|
||||
|
||||
Rc<DxgiPresenter> m_presenter;
|
||||
Com<IDXGIPresentBackBuffer> m_backBuffer;
|
||||
HRESULT CreatePresenter();
|
||||
HRESULT CreateBackBuffer();
|
||||
|
||||
void createPresenter();
|
||||
void createBackBuffer();
|
||||
|
||||
void createContext();
|
||||
|
||||
VkExtent2D getWindowSize() const;
|
||||
VkExtent2D GetWindowSize() const;
|
||||
|
||||
HRESULT GetSampleCount(
|
||||
UINT Count,
|
||||
|
Loading…
x
Reference in New Issue
Block a user