[dxgi] DxgiPresenter now picks format depending on swap chain format

This commit is contained in:
Philip Rebohle 2017-12-04 22:21:02 +01:00
parent 365f992a97
commit f1ee761290
7 changed files with 136 additions and 37 deletions

View File

@ -7,8 +7,9 @@ namespace dxvk {
DxgiPresenter::DxgiPresenter(
const Rc<DxvkDevice>& device,
HWND window,
UINT bufferWidth,
UINT bufferHeight)
uint32_t bufferWidth,
uint32_t bufferHeight,
DXGI_FORMAT bufferFormat)
: m_device (device),
m_context (device->createContext()) {
@ -20,11 +21,10 @@ namespace dxvk {
// Create swap chain for the surface
DxvkSwapchainProperties swapchainProperties;
swapchainProperties.preferredSurfaceFormat.format = VK_FORMAT_B8G8R8A8_SRGB;
swapchainProperties.preferredSurfaceFormat.colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
swapchainProperties.preferredPresentMode = VK_PRESENT_MODE_FIFO_KHR;
swapchainProperties.preferredBufferSize.width = bufferWidth;
swapchainProperties.preferredBufferSize.height = bufferHeight;
swapchainProperties.preferredSurfaceFormat = this->pickFormat(bufferFormat);
swapchainProperties.preferredPresentMode = VK_PRESENT_MODE_FIFO_KHR;
swapchainProperties.preferredBufferSize.width = bufferWidth;
swapchainProperties.preferredBufferSize.height = bufferHeight;
m_swapchain = m_device->createSwapchain(
m_surface, swapchainProperties);
@ -173,6 +173,45 @@ 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_FIFO_KHR;
swapchainProperties.preferredBufferSize.width = bufferWidth;
swapchainProperties.preferredBufferSize.height = bufferHeight;
m_swapchain->changeProperties(swapchainProperties);
}
VkSurfaceFormatKHR DxgiPresenter::pickFormat(DXGI_FORMAT fmt) const {
std::vector<VkSurfaceFormatKHR> formats;
switch (fmt) {
case DXGI_FORMAT_R8G8B8A8_UNORM:
case DXGI_FORMAT_B8G8R8A8_UNORM: {
formats.push_back({ VK_FORMAT_R8G8B8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR });
formats.push_back({ VK_FORMAT_B8G8R8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR });
} break;
case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: {
formats.push_back({ VK_FORMAT_R8G8B8A8_SRGB, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR });
formats.push_back({ VK_FORMAT_B8G8R8A8_SRGB, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR });
} break;
default:
Logger::warn(str::format("DxgiPresenter: Unknown format: ", fmt));
}
return m_surface->pickSurfaceFormat(
formats.size(), formats.data());
}
Rc<DxvkShader> DxgiPresenter::createVertexShader() {
SpirvModule module;

View File

@ -4,6 +4,8 @@
#include <dxvk_surface.h>
#include <dxvk_swapchain.h>
#include "dxgi_include.h"
#include "../spirv/spirv_module.h"
namespace dxvk {
@ -22,8 +24,9 @@ namespace dxvk {
DxgiPresenter(
const Rc<DxvkDevice>& device,
HWND window,
UINT bufferWidth,
UINT bufferHeight);
uint32_t bufferWidth,
uint32_t bufferHeight,
DXGI_FORMAT bufferFormat);
~DxgiPresenter();
@ -41,6 +44,15 @@ namespace dxvk {
void presentImage(
const Rc<DxvkImageView>& view);
/**
* \brief Renders image to the screen
* \param [in] view Source image view
*/
void recreateSwapchain(
uint32_t bufferWidth,
uint32_t bufferHeight,
DXGI_FORMAT bufferFormat);
private:
enum BindingIds : uint32_t {
@ -59,6 +71,8 @@ namespace dxvk {
Rc<DxvkSampler> m_sampler;
VkSurfaceFormatKHR pickFormat(DXGI_FORMAT fmt) const;
Rc<DxvkShader> createVertexShader();
Rc<DxvkShader> createFragmentShader();

View File

@ -46,6 +46,13 @@ namespace dxvk {
SDL_GetError()));
}
// Adjust initial back buffer size. If zero, these
// shall be set to the current window size.
VkExtent2D windowSize = this->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");
@ -187,15 +194,24 @@ namespace dxvk {
UINT SwapChainFlags) {
std::lock_guard<std::mutex> lock(m_mutex);
m_desc.BufferDesc.Width = Width;
m_desc.BufferDesc.Height = Height;
m_desc.BufferDesc.Format = NewFormat;
m_desc.Flags = SwapChainFlags;
VkExtent2D windowSize = this->getWindowSize();
m_desc.BufferDesc.Width = Width != 0 ? Width : windowSize.width;
m_desc.BufferDesc.Height = Height != 0 ? Height : windowSize.height;
m_desc.Flags = SwapChainFlags;
if (BufferCount != 0)
m_desc.BufferCount = BufferCount;
m_desc.BufferCount = BufferCount;
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) {
@ -289,7 +305,8 @@ namespace dxvk {
m_device->GetDXVKDevice(),
m_desc.OutputWindow,
m_desc.BufferDesc.Width,
m_desc.BufferDesc.Height);
m_desc.BufferDesc.Height,
m_desc.BufferDesc.Format);
}
@ -369,4 +386,17 @@ namespace dxvk {
m_presenter->initBackBuffer(m_backBuffer);
}
VkExtent2D DxgiSwapChain::getWindowSize() const {
int winWidth = 0;
int winHeight = 0;
SDL_GetWindowSize(m_window, &winWidth, &winHeight);
VkExtent2D result;
result.width = winWidth;
result.height = winHeight;
return result;
}
}

View File

@ -113,6 +113,8 @@ namespace dxvk {
void createContext();
VkExtent2D getWindowSize() const;
};
}

View File

@ -32,18 +32,24 @@ namespace dxvk {
}
VkSurfaceFormatKHR DxvkSurface::pickSurfaceFormat(VkSurfaceFormatKHR preferred) const {
// If the implementation allows us to freely choose
// the format, we'll just use the preferred format.
if (m_surfaceFormats.size() == 1 && m_surfaceFormats.at(0).format == VK_FORMAT_UNDEFINED)
return preferred;
// If the preferred format is explicitly listed in
// the array of supported surface formats, use it
for (auto fmt : m_surfaceFormats) {
if (fmt.format == preferred.format
&& fmt.colorSpace == preferred.colorSpace)
return fmt;
VkSurfaceFormatKHR DxvkSurface::pickSurfaceFormat(
uint32_t preferredCount,
const VkSurfaceFormatKHR* preferred) const {
if (preferredCount > 0) {
// If the implementation allows us to freely choose
// the format, we'll just use the preferred format.
if (m_surfaceFormats.size() == 1 && m_surfaceFormats.at(0).format == VK_FORMAT_UNDEFINED)
return preferred[0];
// If the preferred format is explicitly listed in
// the array of supported surface formats, use it
for (uint32_t i = 0; i < preferredCount; i++) {
for (auto fmt : m_surfaceFormats) {
if (fmt.format == preferred[i].format
&& fmt.colorSpace == preferred[i].colorSpace)
return fmt;
}
}
}
// Otherwise, fall back to the first format
@ -51,10 +57,14 @@ namespace dxvk {
}
VkPresentModeKHR DxvkSurface::pickPresentMode(VkPresentModeKHR preferred) const {
for (auto mode : m_presentModes) {
if (mode == preferred)
return mode;
VkPresentModeKHR DxvkSurface::pickPresentMode(
uint32_t preferredCount,
const VkPresentModeKHR* preferred) const {
for (uint32_t i = 0; i < preferredCount; i++) {
for (auto mode : m_presentModes) {
if (mode == preferred[i])
return mode;
}
}
// This mode is guaranteed to be available

View File

@ -41,20 +41,24 @@ namespace dxvk {
/**
* \brief Picks a suitable surface format
*
* \param [in] preferred Preferred surface format
* \param [in] preferredCount Number of formats to probe
* \param [in] preferred Preferred surface formats
* \returns The actual surface format
*/
VkSurfaceFormatKHR pickSurfaceFormat(
VkSurfaceFormatKHR preferred) const;
uint32_t preferredCount,
const VkSurfaceFormatKHR* preferred) const;
/**
* \brief Picks a supported present mode
*
* \param [in] preferred The preferred present mode
* \param [in] preferredCount Number of modes to probe
* \param [in] preferred Preferred present modes
* \returns The actual present mode
*/
VkPresentModeKHR pickPresentMode(
VkPresentModeKHR preferred) const;
uint32_t preferredCount,
const VkPresentModeKHR* preferred) const;
/**
* \brief Picks a suitable image count for a swap chain

View File

@ -94,8 +94,8 @@ namespace dxvk {
// Recreate the actual swapchain object
auto caps = m_surface->getSurfaceCapabilities();
auto fmt = m_surface->pickSurfaceFormat(m_properties.preferredSurfaceFormat);
auto mode = m_surface->pickPresentMode (m_properties.preferredPresentMode);
auto fmt = m_surface->pickSurfaceFormat(1, &m_properties.preferredSurfaceFormat);
auto mode = m_surface->pickPresentMode (1, &m_properties.preferredPresentMode);
VkSwapchainCreateInfoKHR swapInfo;
swapInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;