1
0
mirror of https://github.com/EduApps-CDG/OpenDX synced 2024-12-30 09:45:37 +01:00

[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( DxgiPresenter::DxgiPresenter(
const Rc<DxvkDevice>& device, const Rc<DxvkDevice>& device,
HWND window, HWND window,
UINT bufferWidth, uint32_t bufferWidth,
UINT bufferHeight) uint32_t bufferHeight,
DXGI_FORMAT bufferFormat)
: m_device (device), : m_device (device),
m_context (device->createContext()) { m_context (device->createContext()) {
@ -20,11 +21,10 @@ namespace dxvk {
// Create swap chain for the surface // Create swap chain for the surface
DxvkSwapchainProperties swapchainProperties; DxvkSwapchainProperties swapchainProperties;
swapchainProperties.preferredSurfaceFormat.format = VK_FORMAT_B8G8R8A8_SRGB; swapchainProperties.preferredSurfaceFormat = this->pickFormat(bufferFormat);
swapchainProperties.preferredSurfaceFormat.colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR; swapchainProperties.preferredPresentMode = VK_PRESENT_MODE_FIFO_KHR;
swapchainProperties.preferredPresentMode = VK_PRESENT_MODE_FIFO_KHR; swapchainProperties.preferredBufferSize.width = bufferWidth;
swapchainProperties.preferredBufferSize.width = bufferWidth; swapchainProperties.preferredBufferSize.height = bufferHeight;
swapchainProperties.preferredBufferSize.height = bufferHeight;
m_swapchain = m_device->createSwapchain( m_swapchain = m_device->createSwapchain(
m_surface, swapchainProperties); 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() { Rc<DxvkShader> DxgiPresenter::createVertexShader() {
SpirvModule module; SpirvModule module;

View File

@ -4,6 +4,8 @@
#include <dxvk_surface.h> #include <dxvk_surface.h>
#include <dxvk_swapchain.h> #include <dxvk_swapchain.h>
#include "dxgi_include.h"
#include "../spirv/spirv_module.h" #include "../spirv/spirv_module.h"
namespace dxvk { namespace dxvk {
@ -22,8 +24,9 @@ namespace dxvk {
DxgiPresenter( DxgiPresenter(
const Rc<DxvkDevice>& device, const Rc<DxvkDevice>& device,
HWND window, HWND window,
UINT bufferWidth, uint32_t bufferWidth,
UINT bufferHeight); uint32_t bufferHeight,
DXGI_FORMAT bufferFormat);
~DxgiPresenter(); ~DxgiPresenter();
@ -41,6 +44,15 @@ namespace dxvk {
void presentImage( void presentImage(
const Rc<DxvkImageView>& view); 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: private:
enum BindingIds : uint32_t { enum BindingIds : uint32_t {
@ -59,6 +71,8 @@ namespace dxvk {
Rc<DxvkSampler> m_sampler; Rc<DxvkSampler> m_sampler;
VkSurfaceFormatKHR pickFormat(DXGI_FORMAT fmt) const;
Rc<DxvkShader> createVertexShader(); Rc<DxvkShader> createVertexShader();
Rc<DxvkShader> createFragmentShader(); Rc<DxvkShader> createFragmentShader();

View File

@ -46,6 +46,13 @@ namespace dxvk {
SDL_GetError())); 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 // 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::DxgiSwapChain: Failed to set initial fullscreen state");
@ -187,15 +194,24 @@ namespace dxvk {
UINT SwapChainFlags) { UINT SwapChainFlags) {
std::lock_guard<std::mutex> lock(m_mutex); std::lock_guard<std::mutex> lock(m_mutex);
m_desc.BufferDesc.Width = Width; VkExtent2D windowSize = this->getWindowSize();
m_desc.BufferDesc.Height = Height;
m_desc.BufferDesc.Format = NewFormat; m_desc.BufferDesc.Width = Width != 0 ? Width : windowSize.width;
m_desc.Flags = SwapChainFlags; m_desc.BufferDesc.Height = Height != 0 ? Height : windowSize.height;
m_desc.Flags = SwapChainFlags;
if (BufferCount != 0) if (BufferCount != 0)
m_desc.BufferCount = BufferCount; m_desc.BufferCount = BufferCount;
if (NewFormat != DXGI_FORMAT_UNKNOWN)
m_desc.BufferDesc.Format = NewFormat;
try { try {
m_presenter->recreateSwapchain(
m_desc.BufferDesc.Width,
m_desc.BufferDesc.Height,
m_desc.BufferDesc.Format);
this->createBackBuffer(); this->createBackBuffer();
return S_OK; return S_OK;
} catch (const DxvkError& err) { } catch (const DxvkError& err) {
@ -289,7 +305,8 @@ namespace dxvk {
m_device->GetDXVKDevice(), m_device->GetDXVKDevice(),
m_desc.OutputWindow, m_desc.OutputWindow,
m_desc.BufferDesc.Width, 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); 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(); void createContext();
VkExtent2D getWindowSize() const;
}; };
} }

View File

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

View File

@ -41,20 +41,24 @@ namespace dxvk {
/** /**
* \brief Picks a suitable surface format * \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 * \returns The actual surface format
*/ */
VkSurfaceFormatKHR pickSurfaceFormat( VkSurfaceFormatKHR pickSurfaceFormat(
VkSurfaceFormatKHR preferred) const; uint32_t preferredCount,
const VkSurfaceFormatKHR* preferred) const;
/** /**
* \brief Picks a supported present mode * \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 * \returns The actual present mode
*/ */
VkPresentModeKHR pickPresentMode( VkPresentModeKHR pickPresentMode(
VkPresentModeKHR preferred) const; uint32_t preferredCount,
const VkPresentModeKHR* preferred) const;
/** /**
* \brief Picks a suitable image count for a swap chain * \brief Picks a suitable image count for a swap chain

View File

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