1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-02-18 04:54:15 +01:00

[dxgi] Added initial support for format conversion

This commit is contained in:
Philip Rebohle 2017-12-04 11:33:04 +01:00
parent 1b77d58a2a
commit 9fa6592b7d
8 changed files with 314 additions and 29 deletions

View File

@ -2,9 +2,12 @@
#include <cstring>
#include "dxgi_adapter.h"
#include "dxgi_enums.h"
#include "dxgi_factory.h"
#include "dxgi_output.h"
#include "../dxvk/vulkan/dxvk_vulkan_names.h"
namespace dxvk {
DxgiAdapter::DxgiAdapter(
@ -12,7 +15,7 @@ namespace dxvk {
const Rc<DxvkAdapter>& adapter)
: m_factory (factory),
m_adapter (adapter) {
SetupFormatTable();
}
@ -134,4 +137,127 @@ namespace dxvk {
return m_adapter;
}
DxgiFormatPair DxgiAdapter::LookupFormat(DXGI_FORMAT format) {
auto pair = m_formats.find(format);
return pair != m_formats.end()
? pair->second
: DxgiFormatPair();
}
void DxgiAdapter::AddFormat(
DXGI_FORMAT srcFormat,
VkFormat dstFormat,
const std::initializer_list<VkFormat>& fallbacks,
VkFormatFeatureFlags features) {
DxgiFormatPair formatPair;
formatPair.wanted = dstFormat;
formatPair.actual = VK_FORMAT_UNDEFINED;
if (this->HasFormatSupport(dstFormat, features)) {
formatPair.actual = dstFormat;
} else {
for (VkFormat fmt : fallbacks) {
if (this->HasFormatSupport(fmt, features)) {
formatPair.actual = fmt;
break;
}
}
}
if (formatPair.actual == VK_FORMAT_UNDEFINED)
Logger::err(str::format("DxgiAdapter: ", srcFormat, " not supported"));
else if (formatPair.actual != formatPair.wanted)
Logger::warn(str::format("DxgiAdapter: ", srcFormat, " -> ", formatPair.actual));
m_formats.insert(std::make_pair(srcFormat, formatPair));
}
void DxgiAdapter::SetupFormatTable() {
AddFormat(
DXGI_FORMAT_R8G8B8A8_TYPELESS,
VK_FORMAT_R8G8B8A8_UINT, {}, 0);
AddFormat(
DXGI_FORMAT_R8G8B8A8_UINT,
VK_FORMAT_R8G8B8A8_UINT, {},
VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT |
VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT |
VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT |
VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT |
VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT |
VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT);
AddFormat(
DXGI_FORMAT_R8G8B8A8_UNORM,
VK_FORMAT_R8G8B8A8_UNORM, {},
VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT |
VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT |
VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT |
VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT |
VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT |
VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT |
VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT |
VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT);
AddFormat(
DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
VK_FORMAT_R8G8B8A8_SRGB, {},
VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT |
VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT |
VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT |
VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT |
VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT |
VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT);
AddFormat(
DXGI_FORMAT_R8G8B8A8_SINT,
VK_FORMAT_R8G8B8A8_SINT, {},
VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT |
VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT |
VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT |
VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT |
VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT |
VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT);
AddFormat(
DXGI_FORMAT_R8G8B8A8_SNORM,
VK_FORMAT_R8G8B8A8_SNORM, {},
VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT |
VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT |
VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT |
VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT |
VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT |
VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT |
VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT |
VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT);
AddFormat(
DXGI_FORMAT_D24_UNORM_S8_UINT,
VK_FORMAT_D24_UNORM_S8_UINT, {
VK_FORMAT_D32_SFLOAT_S8_UINT,
},
VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT |
VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT);
AddFormat(
DXGI_FORMAT_D16_UNORM,
VK_FORMAT_D16_UNORM, {},
VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT |
VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT);
// TODO finish me
}
bool DxgiAdapter::HasFormatSupport(
VkFormat format,
VkFormatFeatureFlags features) const {
VkFormatProperties info = m_adapter->formatProperties(format);
return ((info.optimalTilingFeatures | info.bufferFeatures) & features) == features;
}
}

View File

@ -1,6 +1,8 @@
#pragma once
#include <initializer_list>
#include <memory>
#include <unordered_map>
#include <vector>
#include <dxvk_adapter.h>
@ -46,11 +48,28 @@ namespace dxvk {
Rc<DxvkAdapter> GetDXVKAdapter() final;
DxgiFormatPair LookupFormat(
DXGI_FORMAT format) final;
private:
Com<DxgiFactory> m_factory;
Rc<DxvkAdapter> m_adapter;
std::unordered_map<DXGI_FORMAT, DxgiFormatPair> m_formats;
void AddFormat(
DXGI_FORMAT srcFormat,
VkFormat dstFormat,
const std::initializer_list<VkFormat>& fallbacks,
VkFormatFeatureFlags features);
void SetupFormatTable();
bool HasFormatSupport(
VkFormat format,
VkFormatFeatureFlags features) const;
};
}

123
src/dxgi/dxgi_enums.cpp Normal file
View File

@ -0,0 +1,123 @@
#include "dxgi_enums.h"
std::ostream& operator << (std::ostream& os, DXGI_FORMAT e) {
switch (e) {
ENUM_NAME(DXGI_FORMAT_UNKNOWN);
ENUM_NAME(DXGI_FORMAT_R32G32B32A32_TYPELESS);
ENUM_NAME(DXGI_FORMAT_R32G32B32A32_FLOAT);
ENUM_NAME(DXGI_FORMAT_R32G32B32A32_UINT);
ENUM_NAME(DXGI_FORMAT_R32G32B32A32_SINT);
ENUM_NAME(DXGI_FORMAT_R32G32B32_TYPELESS);
ENUM_NAME(DXGI_FORMAT_R32G32B32_FLOAT);
ENUM_NAME(DXGI_FORMAT_R32G32B32_UINT);
ENUM_NAME(DXGI_FORMAT_R32G32B32_SINT);
ENUM_NAME(DXGI_FORMAT_R16G16B16A16_TYPELESS);
ENUM_NAME(DXGI_FORMAT_R16G16B16A16_FLOAT);
ENUM_NAME(DXGI_FORMAT_R16G16B16A16_UNORM);
ENUM_NAME(DXGI_FORMAT_R16G16B16A16_UINT);
ENUM_NAME(DXGI_FORMAT_R16G16B16A16_SNORM);
ENUM_NAME(DXGI_FORMAT_R16G16B16A16_SINT);
ENUM_NAME(DXGI_FORMAT_R32G32_TYPELESS);
ENUM_NAME(DXGI_FORMAT_R32G32_FLOAT);
ENUM_NAME(DXGI_FORMAT_R32G32_UINT);
ENUM_NAME(DXGI_FORMAT_R32G32_SINT);
ENUM_NAME(DXGI_FORMAT_R32G8X24_TYPELESS);
ENUM_NAME(DXGI_FORMAT_D32_FLOAT_S8X24_UINT);
ENUM_NAME(DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS);
ENUM_NAME(DXGI_FORMAT_X32_TYPELESS_G8X24_UINT);
ENUM_NAME(DXGI_FORMAT_R10G10B10A2_TYPELESS);
ENUM_NAME(DXGI_FORMAT_R10G10B10A2_UNORM);
ENUM_NAME(DXGI_FORMAT_R10G10B10A2_UINT);
ENUM_NAME(DXGI_FORMAT_R11G11B10_FLOAT);
ENUM_NAME(DXGI_FORMAT_R8G8B8A8_TYPELESS);
ENUM_NAME(DXGI_FORMAT_R8G8B8A8_UNORM);
ENUM_NAME(DXGI_FORMAT_R8G8B8A8_UNORM_SRGB);
ENUM_NAME(DXGI_FORMAT_R8G8B8A8_UINT);
ENUM_NAME(DXGI_FORMAT_R8G8B8A8_SNORM);
ENUM_NAME(DXGI_FORMAT_R8G8B8A8_SINT);
ENUM_NAME(DXGI_FORMAT_R16G16_TYPELESS);
ENUM_NAME(DXGI_FORMAT_R16G16_FLOAT);
ENUM_NAME(DXGI_FORMAT_R16G16_UNORM);
ENUM_NAME(DXGI_FORMAT_R16G16_UINT);
ENUM_NAME(DXGI_FORMAT_R16G16_SNORM);
ENUM_NAME(DXGI_FORMAT_R16G16_SINT);
ENUM_NAME(DXGI_FORMAT_R32_TYPELESS);
ENUM_NAME(DXGI_FORMAT_D32_FLOAT);
ENUM_NAME(DXGI_FORMAT_R32_FLOAT);
ENUM_NAME(DXGI_FORMAT_R32_UINT);
ENUM_NAME(DXGI_FORMAT_R32_SINT);
ENUM_NAME(DXGI_FORMAT_R24G8_TYPELESS);
ENUM_NAME(DXGI_FORMAT_D24_UNORM_S8_UINT);
ENUM_NAME(DXGI_FORMAT_R24_UNORM_X8_TYPELESS);
ENUM_NAME(DXGI_FORMAT_X24_TYPELESS_G8_UINT);
ENUM_NAME(DXGI_FORMAT_R8G8_TYPELESS);
ENUM_NAME(DXGI_FORMAT_R8G8_UNORM);
ENUM_NAME(DXGI_FORMAT_R8G8_UINT);
ENUM_NAME(DXGI_FORMAT_R8G8_SNORM);
ENUM_NAME(DXGI_FORMAT_R8G8_SINT);
ENUM_NAME(DXGI_FORMAT_R16_TYPELESS);
ENUM_NAME(DXGI_FORMAT_R16_FLOAT);
ENUM_NAME(DXGI_FORMAT_D16_UNORM);
ENUM_NAME(DXGI_FORMAT_R16_UNORM);
ENUM_NAME(DXGI_FORMAT_R16_UINT);
ENUM_NAME(DXGI_FORMAT_R16_SNORM);
ENUM_NAME(DXGI_FORMAT_R16_SINT);
ENUM_NAME(DXGI_FORMAT_R8_TYPELESS);
ENUM_NAME(DXGI_FORMAT_R8_UNORM);
ENUM_NAME(DXGI_FORMAT_R8_UINT);
ENUM_NAME(DXGI_FORMAT_R8_SNORM);
ENUM_NAME(DXGI_FORMAT_R8_SINT);
ENUM_NAME(DXGI_FORMAT_A8_UNORM);
ENUM_NAME(DXGI_FORMAT_R1_UNORM);
ENUM_NAME(DXGI_FORMAT_R9G9B9E5_SHAREDEXP);
ENUM_NAME(DXGI_FORMAT_R8G8_B8G8_UNORM);
ENUM_NAME(DXGI_FORMAT_G8R8_G8B8_UNORM);
ENUM_NAME(DXGI_FORMAT_BC1_TYPELESS);
ENUM_NAME(DXGI_FORMAT_BC1_UNORM);
ENUM_NAME(DXGI_FORMAT_BC1_UNORM_SRGB);
ENUM_NAME(DXGI_FORMAT_BC2_TYPELESS);
ENUM_NAME(DXGI_FORMAT_BC2_UNORM);
ENUM_NAME(DXGI_FORMAT_BC2_UNORM_SRGB);
ENUM_NAME(DXGI_FORMAT_BC3_TYPELESS);
ENUM_NAME(DXGI_FORMAT_BC3_UNORM);
ENUM_NAME(DXGI_FORMAT_BC3_UNORM_SRGB);
ENUM_NAME(DXGI_FORMAT_BC4_TYPELESS);
ENUM_NAME(DXGI_FORMAT_BC4_UNORM);
ENUM_NAME(DXGI_FORMAT_BC4_SNORM);
ENUM_NAME(DXGI_FORMAT_BC5_TYPELESS);
ENUM_NAME(DXGI_FORMAT_BC5_UNORM);
ENUM_NAME(DXGI_FORMAT_BC5_SNORM);
ENUM_NAME(DXGI_FORMAT_B5G6R5_UNORM);
ENUM_NAME(DXGI_FORMAT_B5G5R5A1_UNORM);
ENUM_NAME(DXGI_FORMAT_B8G8R8A8_UNORM);
ENUM_NAME(DXGI_FORMAT_B8G8R8X8_UNORM);
ENUM_NAME(DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM);
ENUM_NAME(DXGI_FORMAT_B8G8R8A8_TYPELESS);
ENUM_NAME(DXGI_FORMAT_B8G8R8A8_UNORM_SRGB);
ENUM_NAME(DXGI_FORMAT_B8G8R8X8_TYPELESS);
ENUM_NAME(DXGI_FORMAT_B8G8R8X8_UNORM_SRGB);
ENUM_NAME(DXGI_FORMAT_BC6H_TYPELESS);
ENUM_NAME(DXGI_FORMAT_BC6H_UF16);
ENUM_NAME(DXGI_FORMAT_BC6H_SF16);
ENUM_NAME(DXGI_FORMAT_BC7_TYPELESS);
ENUM_NAME(DXGI_FORMAT_BC7_UNORM);
ENUM_NAME(DXGI_FORMAT_BC7_UNORM_SRGB);
ENUM_NAME(DXGI_FORMAT_AYUV);
ENUM_NAME(DXGI_FORMAT_Y410);
ENUM_NAME(DXGI_FORMAT_Y416);
ENUM_NAME(DXGI_FORMAT_NV12);
ENUM_NAME(DXGI_FORMAT_P010);
ENUM_NAME(DXGI_FORMAT_P016);
ENUM_NAME(DXGI_FORMAT_420_OPAQUE);
ENUM_NAME(DXGI_FORMAT_YUY2);
ENUM_NAME(DXGI_FORMAT_Y210);
ENUM_NAME(DXGI_FORMAT_Y216);
ENUM_NAME(DXGI_FORMAT_NV11);
ENUM_NAME(DXGI_FORMAT_AI44);
ENUM_NAME(DXGI_FORMAT_IA44);
ENUM_NAME(DXGI_FORMAT_P8);
ENUM_NAME(DXGI_FORMAT_A8P8);
ENUM_NAME(DXGI_FORMAT_B4G4R4A4_UNORM);
ENUM_DEFAULT(e);
}
}

5
src/dxgi/dxgi_enums.h Normal file
View File

@ -0,0 +1,5 @@
#pragma once
#include "dxgi_include.h"
std::ostream& operator << (std::ostream& os, DXGI_FORMAT e);

View File

@ -1,5 +1,7 @@
#pragma once
#include "../dxvk/dxvk_include.h"
#include "dxgi_include.h"
namespace dxvk {
@ -8,6 +10,20 @@ namespace dxvk {
class DxvkBuffer;
class DxvkDevice;
class DxvkImage;
/**
* \brief Format pair
*
* For a DXGI format, this stores two Vulkan formats:
* The format that directly corresponds to the DXGI
* format, and a similar format that the device can
* use. If the device supports the desired format,
* both formats will be equal.
*/
struct DxgiFormatPair {
VkFormat wanted = VK_FORMAT_UNDEFINED;
VkFormat actual = VK_FORMAT_UNDEFINED;
};
}
/**
@ -22,6 +38,9 @@ IDXGIAdapterPrivate : public IDXGIAdapter1 {
static const GUID guid;
virtual dxvk::Rc<dxvk::DxvkAdapter> GetDXVKAdapter() = 0;
virtual dxvk::DxgiFormatPair LookupFormat(
DXGI_FORMAT format) = 0;
};

View File

@ -14,18 +14,20 @@ namespace dxvk {
// Retrieve a device pointer that allows us to
// communicate with the underlying D3D device
if (FAILED(pDevice->QueryInterface(__uuidof(IDXGIPresentDevicePrivate),
reinterpret_cast<void**>(&m_device))))
reinterpret_cast<void**>(&m_presentDevice))))
throw DxvkError("DxgiSwapChain::DxgiSwapChain: Invalid device");
// Retrieve the adapter, which is going
// to be used to enumerate displays.
Com<IDXGIDevice> device;
Com<IDXGIAdapter> adapter;
if (FAILED(pDevice->QueryInterface(__uuidof(IDXGIDevice),
reinterpret_cast<void**>(&device))))
if (FAILED(pDevice->QueryInterface(__uuidof(IDXGIDevicePrivate),
reinterpret_cast<void**>(&m_device))))
throw DxvkError("DxgiSwapChain::DxgiSwapChain: Invalid device");
if (FAILED(device->GetAdapter(&m_adapter)))
if (FAILED(m_device->GetAdapter(&adapter))
|| FAILED(adapter->QueryInterface(__uuidof(IDXGIAdapterPrivate),
reinterpret_cast<void**>(&m_adapter))))
throw DxvkError("DxgiSwapChain::DxgiSwapChain: Failed to retrieve adapter");
// Initialize frame statistics
@ -161,16 +163,10 @@ namespace dxvk {
HRESULT DxgiSwapChain::Present(UINT SyncInterval, UINT Flags) {
std::lock_guard<std::mutex> lock(m_mutex);
// Query DXGI device to retrieve DXVK device
Com<IDXGIDevicePrivate> dxgiDevice;
m_device->GetDevice(__uuidof(IDXGIDevicePrivate),
reinterpret_cast<void**>(&dxgiDevice));
try {
// Submit pending rendering commands
// before recording the present code.
m_device->FlushRenderingCommands();
m_presentDevice->FlushRenderingCommands();
// TODO implement sync interval
// TODO implement flags
@ -289,12 +285,8 @@ namespace dxvk {
void DxgiSwapChain::createPresenter() {
Com<IDXGIDevicePrivate> dxgiDevice;
m_device->GetDevice(__uuidof(IDXGIDevicePrivate),
reinterpret_cast<void**>(&dxgiDevice));
m_presenter = new DxgiPresenter(
dxgiDevice->GetDXVKDevice(),
m_device->GetDXVKDevice(),
m_desc.OutputWindow,
m_desc.BufferDesc.Width,
m_desc.BufferDesc.Height);
@ -302,13 +294,12 @@ namespace dxvk {
void DxgiSwapChain::createBackBuffer() {
// TODO select format based on DXGI format
// TODO support proper multi-sampling
Com<IDXGIDevicePrivate> dxgiDevice;
m_device->GetDevice(__uuidof(IDXGIDevicePrivate),
reinterpret_cast<void**>(&dxgiDevice));
// Pick the back buffer format based on the requested swap chain format
DxgiFormatPair bufferFormat = m_adapter->LookupFormat(m_desc.BufferDesc.Format);
Logger::info(str::format("DxgiSwapChain: Creating back buffer with ", bufferFormat.actual));
const Rc<DxvkDevice> dxvkDevice = dxgiDevice->GetDXVKDevice();
// TODO support proper multi-sampling
const Rc<DxvkDevice> dxvkDevice = m_device->GetDXVKDevice();
// Create an image that can be rendered to
// and that can be used as a sampled texture.
@ -316,7 +307,7 @@ namespace dxvk {
DxvkImageCreateInfo imageInfo;
imageInfo.type = VK_IMAGE_TYPE_2D;
imageInfo.format = VK_FORMAT_R8G8B8A8_SRGB;
imageInfo.format = bufferFormat.actual;
imageInfo.sampleCount = VK_SAMPLE_COUNT_1_BIT;
imageInfo.extent.width = m_desc.BufferDesc.Width;
imageInfo.extent.height = m_desc.BufferDesc.Height;
@ -348,7 +339,7 @@ namespace dxvk {
| VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT;
}
if (FAILED(DXGICreateImageResourcePrivate(dxgiDevice.ptr(), &imageInfo,
if (FAILED(DXGICreateImageResourcePrivate(m_device.ptr(), &imageInfo,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, DXGI_USAGE_BACK_BUFFER | m_desc.BufferUsage,
&resource)))
throw DxvkError("DxgiSwapChain::createBackBuffer: Failed to create back buffer");
@ -370,7 +361,7 @@ namespace dxvk {
// Wrap the back buffer image into an interface
// that the device can use to access the image.
if (FAILED(m_device->WrapSwapChainBackBuffer(resource.ptr(), &m_desc, &m_backBufferIface)))
if (FAILED(m_presentDevice->WrapSwapChainBackBuffer(resource.ptr(), &m_desc, &m_backBufferIface)))
throw DxvkError("DxgiSwapChain::createBackBuffer: Failed to create back buffer interface");
// Initialize the image properly so that

View File

@ -84,8 +84,9 @@ namespace dxvk {
std::mutex m_mutex;
Com<DxgiFactory> m_factory;
Com<IDXGIAdapter> m_adapter;
Com<IDXGIPresentDevicePrivate> m_device;
Com<IDXGIAdapterPrivate> m_adapter;
Com<IDXGIDevicePrivate> m_device;
Com<IDXGIPresentDevicePrivate> m_presentDevice;
DXGI_SWAP_CHAIN_DESC m_desc;
DXGI_FRAME_STATISTICS m_stats;

View File

@ -1,6 +1,7 @@
dxgi_src = [
'dxgi_adapter.cpp',
'dxgi_device.cpp',
'dxgi_enums.cpp',
'dxgi_factory.cpp',
'dxgi_main.cpp',
'dxgi_output.cpp',