[d3d11] Refactored texture creation

This commit is contained in:
Philip Rebohle 2017-12-19 16:01:50 +01:00
parent f2587ab1b6
commit 2c5b1c151f
17 changed files with 268 additions and 490 deletions

View File

@ -107,97 +107,12 @@ namespace dxvk {
const D3D11_TEXTURE2D_DESC* pDesc,
const D3D11_SUBRESOURCE_DATA* pInitialData,
ID3D11Texture2D** ppTexture2D) {
DxgiFormatMode formatMode = DxgiFormatMode::Any;
if (pDesc->BindFlags & D3D11_BIND_RENDER_TARGET)
formatMode = DxgiFormatMode::Color;
if (pDesc->BindFlags & D3D11_BIND_DEPTH_STENCIL)
formatMode = DxgiFormatMode::Depth;
DxvkImageCreateInfo info;
info.type = VK_IMAGE_TYPE_2D;
info.format = m_dxgiAdapter->LookupFormat(pDesc->Format, formatMode).actual;
info.flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
info.sampleCount = VK_SAMPLE_COUNT_1_BIT;
info.extent.width = pDesc->Width;
info.extent.height = pDesc->Height;
info.extent.depth = 1;
info.numLayers = pDesc->ArraySize;
info.mipLevels = pDesc->MipLevels;
info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT
| VK_IMAGE_USAGE_TRANSFER_DST_BIT;
info.stages = VK_PIPELINE_STAGE_TRANSFER_BIT;
info.access = VK_ACCESS_TRANSFER_READ_BIT
| VK_ACCESS_TRANSFER_WRITE_BIT;
info.tiling = VK_IMAGE_TILING_OPTIMAL;
info.layout = VK_IMAGE_LAYOUT_GENERAL;
if (FAILED(GetSampleCount(pDesc->SampleDesc.Count, &info.sampleCount))) {
Logger::err(str::format("D3D11: Invalid sample count: ", pDesc->SampleDesc.Count));
return E_INVALIDARG;
}
if (pDesc->BindFlags & D3D11_BIND_SHADER_RESOURCE) {
info.usage |= VK_IMAGE_USAGE_SAMPLED_BIT;
info.stages |= GetEnabledShaderStages();
info.access |= VK_ACCESS_SHADER_READ_BIT;
}
if (pDesc->BindFlags & D3D11_BIND_RENDER_TARGET) {
info.usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
info.stages |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
info.access |= VK_ACCESS_COLOR_ATTACHMENT_READ_BIT
| VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
}
if (pDesc->BindFlags & D3D11_BIND_DEPTH_STENCIL) {
info.usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
info.stages |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT
| VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
info.access |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT
| VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
}
if (pDesc->BindFlags & D3D11_BIND_UNORDERED_ACCESS) {
info.usage |= VK_IMAGE_USAGE_STORAGE_BIT;
info.stages |= GetEnabledShaderStages();
info.access |= VK_ACCESS_SHADER_READ_BIT
| VK_ACCESS_SHADER_WRITE_BIT;
}
if (pDesc->CPUAccessFlags != 0) {
info.tiling = VK_IMAGE_TILING_LINEAR;
info.stages |= VK_PIPELINE_STAGE_HOST_BIT;
if (pDesc->CPUAccessFlags & D3D11_CPU_ACCESS_WRITE)
info.access |= VK_ACCESS_HOST_WRITE_BIT;
if (pDesc->CPUAccessFlags & D3D11_CPU_ACCESS_READ)
info.access |= VK_ACCESS_HOST_READ_BIT;
}
if (pDesc->MiscFlags & D3D11_RESOURCE_MISC_TEXTURECUBE)
info.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
if (pDesc->MipLevels == 0)
info.mipLevels = util::computeMipLevelCount(info.extent);
if (ppTexture2D != nullptr) {
Com<IDXGIImageResourcePrivate> image;
const Com<D3D11Texture2D> texture
= new D3D11Texture2D(this, pDesc);
HRESULT hr = DXGICreateImageResourcePrivate(
m_dxgiDevice.ptr(), &info,
GetMemoryFlagsForUsage(pDesc->Usage), 0,
&image);
if (FAILED(hr))
return hr;
*ppTexture2D = ref(new D3D11Texture2D(
this, image.ptr(), formatMode, *pDesc));
InitTexture(image.ptr(), pInitialData);
this->InitTexture(texture.ptr(), pInitialData);
*ppTexture2D = texture.ref();
}
return S_OK;
@ -235,28 +150,20 @@ namespace dxvk {
Logger::err("D3D11: Shader resource views for buffers not yet supported");
return E_INVALIDARG;
} else {
// Retrieve the image that we are going to create a view for
Com<IDXGIImageResourcePrivate> imageResource;
// Retrieve info about the image
D3D11TextureInfo textureInfo;
if (FAILED(pResource->QueryInterface(
__uuidof(IDXGIImageResourcePrivate),
reinterpret_cast<void**>(&imageResource))))
if (FAILED(GetCommonTextureInfo(pResource, &textureInfo))) {
Logger::err("D3D11Device: Cannot create shader resource view: Invalid texture");
return E_INVALIDARG;
// TODO fix this properly
DxgiFormatMode formatMode = DxgiFormatMode::Any;
Com<D3D11Texture2D> texture2D;
if (SUCCEEDED(pResource->QueryInterface(
__uuidof(ID3D11Texture2D),
reinterpret_cast<void**>(&texture2D))))
formatMode = texture2D->GetFormatMode();
}
// Fill in the view info. The view type depends solely
// on the view dimension field in the view description,
// not on the resource type.
DxvkImageViewCreateInfo viewInfo;
viewInfo.format = m_dxgiAdapter->LookupFormat(desc.Format, formatMode).actual;
viewInfo.format = m_dxgiAdapter->LookupFormat(
desc.Format, textureInfo.formatMode).actual;
viewInfo.aspect = imageFormatInfo(viewInfo.format)->aspectMask;
switch (desc.ViewDimension) {
@ -346,8 +253,7 @@ namespace dxvk {
*ppSRView = ref(new D3D11ShaderResourceView(
this, pResource, desc, nullptr,
m_dxvkDevice->createImageView(
imageResource->GetDXVKImage(),
viewInfo)));
textureInfo.image, viewInfo)));
return S_OK;
} catch (const DxvkError& e) {
Logger::err(e.message());
@ -391,12 +297,12 @@ namespace dxvk {
}
// Retrieve the image that we are going to create the view for
Com<IDXGIImageResourcePrivate> imageResource;
D3D11TextureInfo textureInfo;
if (FAILED(pResource->QueryInterface(
__uuidof(IDXGIImageResourcePrivate),
reinterpret_cast<void**>(&imageResource))))
if (FAILED(GetCommonTextureInfo(pResource, &textureInfo))) {
Logger::err("D3D11Device: Cannot create shader resource view: Invalid texture");
return E_INVALIDARG;
}
// Fill in Vulkan image view info
DxvkImageViewCreateInfo viewInfo;
@ -451,8 +357,7 @@ namespace dxvk {
*ppRTView = ref(new D3D11RenderTargetView(
this, pResource, desc, nullptr,
m_dxvkDevice->createImageView(
imageResource->GetDXVKImage(),
viewInfo)));
textureInfo.image, viewInfo)));
return S_OK;
} catch (const DxvkError& e) {
Logger::err(e.message());
@ -486,12 +391,12 @@ namespace dxvk {
}
// Retrieve the image that we are going to create the view for
Com<IDXGIImageResourcePrivate> imageResource;
D3D11TextureInfo textureInfo;
if (FAILED(pResource->QueryInterface(
__uuidof(IDXGIImageResourcePrivate),
reinterpret_cast<void**>(&imageResource))))
if (FAILED(GetCommonTextureInfo(pResource, &textureInfo))) {
Logger::err("D3D11Device: Cannot create shader resource view: Invalid texture");
return E_INVALIDARG;
}
// Fill in Vulkan image view info
DxvkImageViewCreateInfo viewInfo;
@ -546,8 +451,7 @@ namespace dxvk {
*ppDepthStencilView = ref(new D3D11DepthStencilView(
this, pResource, desc, nullptr,
m_dxvkDevice->createImageView(
imageResource->GetDXVKImage(),
viewInfo)));
textureInfo.image, viewInfo)));
return S_OK;
} catch (const DxvkError& e) {
Logger::err(e.message());
@ -1120,6 +1024,13 @@ namespace dxvk {
}
DxgiFormatPair STDMETHODCALLTYPE D3D11Device::LookupFormat(
DXGI_FORMAT format,
DxgiFormatMode mode) const {
return m_dxgiAdapter->LookupFormat(format, mode);
}
VkPipelineStageFlags D3D11Device::GetEnabledShaderStages() const {
VkPipelineStageFlags enabledShaderPipelineStages
= VK_PIPELINE_STAGE_VERTEX_SHADER_BIT
@ -1251,7 +1162,7 @@ namespace dxvk {
void D3D11Device::InitTexture(
IDXGIImageResourcePrivate* pImage,
D3D11Texture2D* pImage,
const D3D11_SUBRESOURCE_DATA* pInitialData) {
std::lock_guard<std::mutex> lock(m_resourceInitMutex);;
m_resourceInitContext->beginRecording(
@ -1445,19 +1356,6 @@ namespace dxvk {
}
HRESULT D3D11Device::GetSampleCount(UINT Count, VkSampleCountFlagBits* pCount) const {
switch (Count) {
case 1: *pCount = VK_SAMPLE_COUNT_1_BIT; return S_OK;
case 2: *pCount = VK_SAMPLE_COUNT_2_BIT; return S_OK;
case 4: *pCount = VK_SAMPLE_COUNT_4_BIT; return S_OK;
case 8: *pCount = VK_SAMPLE_COUNT_8_BIT; return S_OK;
case 16: *pCount = VK_SAMPLE_COUNT_16_BIT; return S_OK;
}
return E_INVALIDARG;
}
VkSamplerAddressMode D3D11Device::DecodeAddressMode(
D3D11_TEXTURE_ADDRESS_MODE mode) const {
switch (mode) {

View File

@ -1,7 +1,6 @@
#pragma once
#include "../dxgi/dxgi_object.h"
#include "../dxgi/dxgi_resource.h"
#include "d3d11_interfaces.h"
#include "d3d11_state.h"
@ -16,6 +15,9 @@ namespace dxvk {
class D3D11DeviceContext;
class D3D11PresentDevice;
class D3D11ShaderModule;
class D3D11Texture1D;
class D3D11Texture2D;
class D3D11Texture3D;
class D3D11Device : public ComObject<ID3D11Device> {
@ -226,6 +228,10 @@ namespace dxvk {
VkPipelineStageFlags GetEnabledShaderStages() const;
DxgiFormatPair STDMETHODCALLTYPE LookupFormat(
DXGI_FORMAT format,
DxgiFormatMode mode) const;
static bool CheckFeatureLevelSupport(
const Rc<DxvkAdapter>& adapter,
D3D_FEATURE_LEVEL featureLevel);
@ -266,7 +272,7 @@ namespace dxvk {
const D3D11_SUBRESOURCE_DATA* pInitialData);
void InitTexture(
IDXGIImageResourcePrivate* pImage,
D3D11Texture2D* pImage,
const D3D11_SUBRESOURCE_DATA* pInitialData);
HRESULT GetShaderResourceViewDescFromResource(
@ -285,10 +291,6 @@ namespace dxvk {
ID3D11Resource* pResource,
D3D11_DEPTH_STENCIL_VIEW_DESC* pDesc);
HRESULT GetSampleCount(
UINT Count,
VkSampleCountFlagBits* pCount) const;
VkSamplerAddressMode DecodeAddressMode(
D3D11_TEXTURE_ADDRESS_MODE mode) const;

View File

@ -1,9 +1,18 @@
#include "d3d11_device.h"
#include "d3d11_present.h"
#include "d3d11_texture.h"
namespace dxvk {
HRESULT STDMETHODCALLTYPE D3D11PresentBackBuffer::QueryInterface(REFIID riid, void** ppvObject) {
return m_texture->QueryInterface(riid, ppvObject);
}
Rc<DxvkImage> D3D11PresentBackBuffer::GetDXVKImage() {
return m_texture->GetDXVKImage();
}
D3D11PresentDevice:: D3D11PresentDevice() { }
D3D11PresentDevice::~D3D11PresentDevice() { }
@ -17,10 +26,9 @@ namespace dxvk {
}
HRESULT STDMETHODCALLTYPE D3D11PresentDevice::WrapSwapChainBackBuffer(
IDXGIImageResourcePrivate* pResource,
HRESULT STDMETHODCALLTYPE D3D11PresentDevice::CreateSwapChainBackBuffer(
const DXGI_SWAP_CHAIN_DESC* pSwapChainDesc,
IUnknown** ppInterface) {
IDXGIPresentBackBuffer** ppInterface) {
D3D11_TEXTURE2D_DESC desc;
desc.Width = pSwapChainDesc->BufferDesc.Width;
desc.Height = pSwapChainDesc->BufferDesc.Height;
@ -34,9 +42,14 @@ namespace dxvk {
desc.CPUAccessFlags = 0;
desc.MiscFlags = 0;
*ppInterface = ref(new D3D11Texture2D(
m_device, pResource, DxgiFormatMode::Color, desc));
return S_OK;
try {
*ppInterface = ref(new D3D11PresentBackBuffer(
new D3D11Texture2D(m_device, &desc)));
return S_OK;
} catch (const DxvkError& e) {
Logger::err(e.message());
return E_FAIL;
}
}

View File

@ -2,14 +2,34 @@
#include "../dxgi/dxgi_device.h"
#include "../dxgi/dxgi_interfaces.h"
#include "../dxgi/dxgi_resource.h"
#include "d3d11_include.h"
#include "d3d11_texture.h"
namespace dxvk {
class D3D11Device;
class D3D11PresentBackBuffer : public ComObject<IDXGIPresentBackBuffer> {
public:
D3D11PresentBackBuffer(D3D11Texture2D* pTexture)
: m_texture(pTexture) { }
HRESULT STDMETHODCALLTYPE QueryInterface(
REFIID riid,
void** ppvObject) final;
Rc<DxvkImage> GetDXVKImage() final;
public:
Com<D3D11Texture2D> m_texture;
};
class D3D11PresentDevice : public ComObject<IDXGIPresentDevicePrivate> {
public:
@ -21,10 +41,9 @@ namespace dxvk {
REFIID riid,
void** ppvObject) final;
HRESULT STDMETHODCALLTYPE WrapSwapChainBackBuffer(
IDXGIImageResourcePrivate* pResource,
HRESULT STDMETHODCALLTYPE CreateSwapChainBackBuffer(
const DXGI_SWAP_CHAIN_DESC* pSwapChainDesc,
IUnknown** ppInterface) final;
IDXGIPresentBackBuffer** ppInterface) final;
HRESULT STDMETHODCALLTYPE FlushRenderingCommands() final;

View File

@ -3,16 +3,93 @@
namespace dxvk {
D3D11Texture2D::D3D11Texture2D(
D3D11Device* device,
IDXGIImageResourcePrivate* resource,
DxgiFormatMode formatMode,
const D3D11_TEXTURE2D_DESC& desc)
: m_device (device),
m_resource (resource),
m_formatMode(formatMode),
m_desc (desc) {
static DxgiFormatMode GetFormatModeFromBindFlags(UINT BindFlags) {
if (BindFlags & D3D11_BIND_RENDER_TARGET)
return DxgiFormatMode::Color;
if (BindFlags & D3D11_BIND_DEPTH_STENCIL)
return DxgiFormatMode::Depth;
return DxgiFormatMode::Any;
}
D3D11Texture2D::D3D11Texture2D(
D3D11Device* pDevice,
const D3D11_TEXTURE2D_DESC* pDesc)
: m_device (pDevice),
m_formatMode(GetFormatModeFromBindFlags(pDesc->BindFlags)),
m_desc (*pDesc) {
DxvkImageCreateInfo info;
info.type = VK_IMAGE_TYPE_2D;
info.format = pDevice->LookupFormat(
pDesc->Format, m_formatMode).actual;
info.flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
info.sampleCount = VK_SAMPLE_COUNT_1_BIT;
info.extent.width = pDesc->Width;
info.extent.height = pDesc->Height;
info.extent.depth = 1;
info.numLayers = pDesc->ArraySize;
info.mipLevels = pDesc->MipLevels;
info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT
| VK_IMAGE_USAGE_TRANSFER_DST_BIT;
info.stages = VK_PIPELINE_STAGE_TRANSFER_BIT;
info.access = VK_ACCESS_TRANSFER_READ_BIT
| VK_ACCESS_TRANSFER_WRITE_BIT;
info.tiling = VK_IMAGE_TILING_OPTIMAL;
info.layout = VK_IMAGE_LAYOUT_GENERAL;
if (FAILED(GetSampleCount(pDesc->SampleDesc.Count, &info.sampleCount)))
throw DxvkError(str::format("D3D11: Invalid sample count: ", pDesc->SampleDesc.Count));
if (pDesc->BindFlags & D3D11_BIND_SHADER_RESOURCE) {
info.usage |= VK_IMAGE_USAGE_SAMPLED_BIT;
info.stages |= pDevice->GetEnabledShaderStages();
info.access |= VK_ACCESS_SHADER_READ_BIT;
}
if (pDesc->BindFlags & D3D11_BIND_RENDER_TARGET) {
info.usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
info.stages |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
info.access |= VK_ACCESS_COLOR_ATTACHMENT_READ_BIT
| VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
}
if (pDesc->BindFlags & D3D11_BIND_DEPTH_STENCIL) {
info.usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
info.stages |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT
| VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
info.access |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT
| VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
}
if (pDesc->BindFlags & D3D11_BIND_UNORDERED_ACCESS) {
info.usage |= VK_IMAGE_USAGE_STORAGE_BIT;
info.stages |= pDevice->GetEnabledShaderStages();
info.access |= VK_ACCESS_SHADER_READ_BIT
| VK_ACCESS_SHADER_WRITE_BIT;
}
if (pDesc->CPUAccessFlags != 0) {
info.tiling = VK_IMAGE_TILING_LINEAR;
info.stages |= VK_PIPELINE_STAGE_HOST_BIT;
if (pDesc->CPUAccessFlags & D3D11_CPU_ACCESS_WRITE)
info.access |= VK_ACCESS_HOST_WRITE_BIT;
if (pDesc->CPUAccessFlags & D3D11_CPU_ACCESS_READ)
info.access |= VK_ACCESS_HOST_READ_BIT;
}
if (pDesc->MiscFlags & D3D11_RESOURCE_MISC_TEXTURECUBE)
info.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
if (pDesc->MipLevels == 0)
info.mipLevels = util::computeMipLevelCount(info.extent);
m_image = pDevice->GetDXVKDevice()->createImage(
info, GetMemoryFlagsForUsage(pDesc->Usage));
}
@ -27,10 +104,6 @@ namespace dxvk {
COM_QUERY_IFACE(riid, ppvObject, ID3D11Resource);
COM_QUERY_IFACE(riid, ppvObject, ID3D11Texture2D);
if (riid == __uuidof(IDXGIResource)
|| riid == __uuidof(IDXGIImageResourcePrivate))
return m_resource->QueryInterface(riid, ppvObject);
Logger::warn("D3D11Texture2D::QueryInterface: Unknown interface query");
return E_NOINTERFACE;
}
@ -47,14 +120,13 @@ namespace dxvk {
UINT STDMETHODCALLTYPE D3D11Texture2D::GetEvictionPriority() {
UINT EvictionPriority = DXGI_RESOURCE_PRIORITY_NORMAL;
m_resource->GetEvictionPriority(&EvictionPriority);
return EvictionPriority;
Logger::warn("D3D11Texture2D::GetEvictionPriority: Stub");
return DXGI_RESOURCE_PRIORITY_NORMAL;
}
void STDMETHODCALLTYPE D3D11Texture2D::SetEvictionPriority(UINT EvictionPriority) {
m_resource->SetEvictionPriority(EvictionPriority);
Logger::warn("D3D11Texture2D::SetEvictionPriority: Stub");
}
@ -62,4 +134,24 @@ namespace dxvk {
*pDesc = m_desc;
}
HRESULT GetCommonTextureInfo(
ID3D11Resource* pResource,
D3D11TextureInfo* pTextureInfo) {
D3D11_RESOURCE_DIMENSION dimension = D3D11_RESOURCE_DIMENSION_UNKNOWN;
pResource->GetType(&dimension);
switch (dimension) {
case D3D11_RESOURCE_DIMENSION_TEXTURE2D: {
auto tex = static_cast<D3D11Texture2D*>(pResource);
pTextureInfo->formatMode = tex->GetFormatMode();
pTextureInfo->image = tex->GetDXVKImage();
} return S_OK;
default:
return E_INVALIDARG;
}
}
}

View File

@ -9,16 +9,14 @@ namespace dxvk {
class D3D11Device;
class D3D11Texture2D : public D3D11DeviceChild<ID3D11Texture2D> {
public:
D3D11Texture2D(
D3D11Device* device,
IDXGIImageResourcePrivate* resource,
DxgiFormatMode formatMode,
const D3D11_TEXTURE2D_DESC& desc);
D3D11Device* pDevice,
const D3D11_TEXTURE2D_DESC* pDesc);
~D3D11Texture2D();
HRESULT STDMETHODCALLTYPE QueryInterface(
@ -43,16 +41,40 @@ namespace dxvk {
}
Rc<DxvkImage> GetDXVKImage() const {
return m_resource->GetDXVKImage();
return m_image;
}
private:
Com<D3D11Device> m_device;
Com<IDXGIImageResourcePrivate> m_resource;
DxgiFormatMode m_formatMode;
D3D11_TEXTURE2D_DESC m_desc;
Rc<DxvkImage> m_image;
};
/**
* \brief Common texture info
*
* Stores the image and the image format
* mode for a texture of any type.
*/
struct D3D11TextureInfo {
DxgiFormatMode formatMode;
Rc<DxvkImage> image;
};
/**
* \brief Retrieves common info about a texture
*
* \param [in] pResource The resource. Must be a texture.
* \param [out] pTextureInfo Pointer to the texture info struct.
* \returns E_INVALIDARG if the resource is not a texture
*/
HRESULT GetCommonTextureInfo(
ID3D11Resource* pResource,
D3D11TextureInfo* pTextureInfo);
}

View File

@ -2,6 +2,19 @@
namespace dxvk {
HRESULT GetSampleCount(UINT Count, VkSampleCountFlagBits* pCount) {
switch (Count) {
case 1: *pCount = VK_SAMPLE_COUNT_1_BIT; return S_OK;
case 2: *pCount = VK_SAMPLE_COUNT_2_BIT; return S_OK;
case 4: *pCount = VK_SAMPLE_COUNT_4_BIT; return S_OK;
case 8: *pCount = VK_SAMPLE_COUNT_8_BIT; return S_OK;
case 16: *pCount = VK_SAMPLE_COUNT_16_BIT; return S_OK;
}
return E_INVALIDARG;
}
VkCompareOp DecodeCompareOp(
D3D11_COMPARISON_FUNC mode) {
switch (mode) {

View File

@ -8,10 +8,14 @@
namespace dxvk {
HRESULT GetSampleCount(
UINT Count,
VkSampleCountFlagBits* pCount);
VkCompareOp DecodeCompareOp(
D3D11_COMPARISON_FUNC mode);
D3D11_COMPARISON_FUNC mode);
VkMemoryPropertyFlags GetMemoryFlagsForUsage(
D3D11_USAGE usage);
D3D11_USAGE usage);
}

View File

@ -89,32 +89,17 @@ IDXGIDevicePrivate : public IDXGIDevice1 {
/**
* \brief Private buffer resource interface
* Provides access to a raw DXVK buffer.
* \brief Swap chain back buffer interface
*
* Allows the swap chain and presenter to query
* the underlying image while it is embedded in
* a texture object specified by the client API.
*/
MIDL_INTERFACE("5679becd-8547-4d93-96a1-e61a1ce7ef37")
IDXGIBufferResourcePrivate : public IDXGIResource {
IDXGIPresentBackBuffer : public IUnknown {
static const GUID guid;
virtual dxvk::Rc<dxvk::DxvkBuffer> STDMETHODCALLTYPE GetDXVKBuffer() = 0;
virtual void STDMETHODCALLTYPE SetResourceLayer(
IUnknown* pLayer) = 0;
};
/**
* \brief Private image resource interface
* Provides access to a raw DXVK image.
*/
MIDL_INTERFACE("1cfe6592-7de0-4a07-8dcb-4543cbbc6a7d")
IDXGIImageResourcePrivate : public IDXGIResource {
static const GUID guid;
virtual dxvk::Rc<dxvk::DxvkImage> STDMETHODCALLTYPE GetDXVKImage() = 0;
virtual void STDMETHODCALLTYPE SetResourceLayer(
IUnknown* pLayer) = 0;
virtual dxvk::Rc<dxvk::DxvkImage> GetDXVKImage() = 0;
};
@ -130,20 +115,13 @@ IDXGIPresentDevicePrivate : public IUnknown {
static const GUID guid;
/**
* \brief Wraps swap chain image into a texture interface
* \brief Creates a swap chain back buffer
*
* Creates an interface to the back buffer image of a
* swap chain. This interface will be returned by the
* swap chain's \c GetBuffer method.
* \param [in] image Image to wrap
* \param [in] pSwapChainDesc Swap chain properties
* \param [in] ppInterface Target interface
* \returns \c S_OK on success
*/
virtual HRESULT STDMETHODCALLTYPE WrapSwapChainBackBuffer(
IDXGIImageResourcePrivate* pResource,
virtual HRESULT STDMETHODCALLTYPE CreateSwapChainBackBuffer(
const DXGI_SWAP_CHAIN_DESC* pSwapChainDesc,
IUnknown** ppInterface) = 0;
IDXGIPresentBackBuffer** ppBackBuffer) = 0;
/**
* \brief Flushes the immediate context
@ -170,6 +148,5 @@ IDXGIPresentDevicePrivate : public IUnknown {
DXVK_DEFINE_GUID(IDXGIAdapterPrivate);
DXVK_DEFINE_GUID(IDXGIDevicePrivate);
DXVK_DEFINE_GUID(IDXGIPresentBackBuffer);
DXVK_DEFINE_GUID(IDXGIPresentDevicePrivate);
DXVK_DEFINE_GUID(IDXGIBufferResourcePrivate);
DXVK_DEFINE_GUID(IDXGIImageResourcePrivate);

View File

@ -207,70 +207,22 @@ namespace dxvk {
}
Rc<DxvkImage> DxgiPresenter::createBackBuffer(
uint32_t bufferWidth,
uint32_t bufferHeight,
VkFormat bufferFormat,
VkSampleCountFlagBits sampleCount) {
Logger::info(str::format("DxgiPresenter: Creating back buffer with ", bufferFormat));
void DxgiPresenter::updateBackBuffer(const Rc<DxvkImage>& image) {
// Explicitly destroy the old stuff
m_backBuffer = nullptr;
m_backBuffer = image;
m_backBufferResolve = nullptr;
m_backBufferView = nullptr;
// Create an image that can be rendered to
// and that can be used as a sampled texture.
DxvkImageCreateInfo imageInfo;
imageInfo.type = VK_IMAGE_TYPE_2D;
imageInfo.format = bufferFormat;
imageInfo.flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
imageInfo.sampleCount = sampleCount;
imageInfo.extent.width = bufferWidth;
imageInfo.extent.height = bufferHeight;
imageInfo.extent.depth = 1;
imageInfo.numLayers = 1;
imageInfo.mipLevels = 1;
imageInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT
| VK_IMAGE_USAGE_SAMPLED_BIT
| VK_IMAGE_USAGE_TRANSFER_DST_BIT
| VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
imageInfo.stages = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT
| VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT
| VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT
| VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT
| VK_PIPELINE_STAGE_TRANSFER_BIT;
imageInfo.access = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT
| VK_ACCESS_COLOR_ATTACHMENT_READ_BIT
| VK_ACCESS_TRANSFER_WRITE_BIT
| VK_ACCESS_TRANSFER_READ_BIT
| VK_ACCESS_SHADER_READ_BIT;
imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
imageInfo.layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
if (m_device->features().geometryShader)
imageInfo.stages |= VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT;
if (m_device->features().tessellationShader) {
imageInfo.stages |= VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT
| VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT;
}
m_backBuffer = m_device->createImage(imageInfo,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
// If a multisampled back buffer was requested, we also need to
// create a resolve image with otherwise identical properties.
// Multisample images cannot be sampled from.
if (sampleCount != VK_SAMPLE_COUNT_1_BIT) {
if (image->info().sampleCount != VK_SAMPLE_COUNT_1_BIT) {
DxvkImageCreateInfo resolveInfo;
resolveInfo.type = VK_IMAGE_TYPE_2D;
resolveInfo.format = bufferFormat;
resolveInfo.format = image->info().format;
resolveInfo.flags = 0;
resolveInfo.sampleCount = VK_SAMPLE_COUNT_1_BIT;
resolveInfo.extent.width = bufferWidth;
resolveInfo.extent.height = bufferHeight;
resolveInfo.extent.depth = 1;
resolveInfo.extent = image->info().extent;
resolveInfo.numLayers = 1;
resolveInfo.mipLevels = 1;
resolveInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT
@ -290,7 +242,7 @@ namespace dxvk {
// image to be bound as a shader resource.
DxvkImageViewCreateInfo viewInfo;
viewInfo.type = VK_IMAGE_VIEW_TYPE_2D;
viewInfo.format = imageInfo.format;
viewInfo.format = image->info().format;
viewInfo.aspect = VK_IMAGE_ASPECT_COLOR_BIT;
viewInfo.minLevel = 0;
viewInfo.numLevels = 1;
@ -305,7 +257,6 @@ namespace dxvk {
// TODO move this elsewhere
this->initBackBuffer(m_backBuffer);
return m_backBuffer;
}

View File

@ -43,18 +43,14 @@ namespace dxvk {
void presentImage();
/**
* \brief Recreates back buffer
* \brief Sets new back buffer
*
* \param [in] bufferWidth Buffer width
* \param [in] bufferHeight Buffer height
* \param [in] bufferFormat Buffer format
* \returns Back buffer image
* Recreates internal structures when
* the back buffer image was replaced.
* \param [in] image Back buffer image
*/
Rc<DxvkImage> createBackBuffer(
uint32_t bufferWidth,
uint32_t bufferHeight,
VkFormat bufferFormat,
VkSampleCountFlagBits sampleCount);
void updateBackBuffer(
const Rc<DxvkImage>& image);
/**
* \brief Renders image to the screen

View File

@ -1,81 +0,0 @@
#include "dxgi_resource.h"
namespace dxvk {
DxgiImageResource::DxgiImageResource(
IDXGIDevicePrivate* pDevice,
const Rc<DxvkImage>& image,
UINT usageFlags)
: Base(pDevice, usageFlags), m_image(image) {
}
DxgiImageResource::DxgiImageResource(
IDXGIDevicePrivate* pDevice,
const dxvk::DxvkImageCreateInfo* pCreateInfo,
VkMemoryPropertyFlags memoryFlags,
UINT usageFlags)
: Base(pDevice, usageFlags) {
m_image = pDevice->GetDXVKDevice()->createImage(
*pCreateInfo, memoryFlags);
}
DxgiImageResource::~DxgiImageResource() {
}
HRESULT STDMETHODCALLTYPE DxgiImageResource::QueryInterface(REFIID riid, void** ppvObject) {
COM_QUERY_IFACE(riid, ppvObject, IUnknown);
COM_QUERY_IFACE(riid, ppvObject, IDXGIObject);
COM_QUERY_IFACE(riid, ppvObject, IDXGIDeviceSubObject);
COM_QUERY_IFACE(riid, ppvObject, IDXGIResource);
COM_QUERY_IFACE(riid, ppvObject, IDXGIImageResourcePrivate);
if (m_layer != nullptr)
return m_layer->QueryInterface(riid, ppvObject);
Logger::err("DxgiImageResource::QueryInterface: Unknown interface query");
return E_NOINTERFACE;
}
HRESULT STDMETHODCALLTYPE DxgiImageResource::GetParent(REFIID riid, void** ppParent) {
Logger::err("DxgiImageResource::GetParent: Unknown interface query");
return E_NOINTERFACE;
}
Rc<DxvkImage> STDMETHODCALLTYPE DxgiImageResource::GetDXVKImage() {
return m_image;
}
void STDMETHODCALLTYPE DxgiImageResource::SetResourceLayer(IUnknown* pLayer) {
m_layer = pLayer;
}
}
extern "C" {
DLLEXPORT HRESULT __stdcall DXGICreateImageResourcePrivate(
IDXGIDevicePrivate* pDevice,
const dxvk::DxvkImageCreateInfo* pCreateInfo,
VkMemoryPropertyFlags memoryFlags,
UINT usageFlags,
IDXGIImageResourcePrivate** ppResource) {
try {
*ppResource = dxvk::ref(new dxvk::DxgiImageResource(
pDevice, pCreateInfo, memoryFlags, usageFlags));
return S_OK;
} catch (const dxvk::DxvkError& e) {
dxvk::Logger::err(e.message());
return DXGI_ERROR_UNSUPPORTED;
}
}
}

View File

@ -1,116 +0,0 @@
#pragma once
#include <dxvk_device.h>
#include "dxgi_object.h"
#include "dxgi_interfaces.h"
namespace dxvk {
template<typename... Base>
class DxgiResource : public DxgiObject<Base...> {
public:
DxgiResource(
IDXGIDevicePrivate* pDevice,
UINT usage)
: m_device (pDevice),
m_usageFlags(usage) { }
HRESULT STDMETHODCALLTYPE GetDevice(REFIID riid, void** ppDevice) {
return m_device->QueryInterface(riid, ppDevice);
}
HRESULT STDMETHODCALLTYPE GetSharedHandle(HANDLE *pSharedHandle) {
Logger::err("DxgiResource::GetSharedHandle: Not implemented");
return DXGI_ERROR_UNSUPPORTED;
}
HRESULT STDMETHODCALLTYPE GetUsage(DXGI_USAGE *pUsage) {
if (pUsage == nullptr)
return DXGI_ERROR_INVALID_CALL;
*pUsage = m_usageFlags;
return S_OK;
}
HRESULT STDMETHODCALLTYPE SetEvictionPriority(UINT EvictionPriority) {
m_evictionPriority = EvictionPriority;
return S_OK;
}
HRESULT STDMETHODCALLTYPE GetEvictionPriority(UINT *pEvictionPriority) {
if (pEvictionPriority == nullptr)
return DXGI_ERROR_INVALID_CALL;
*pEvictionPriority = m_evictionPriority;
return S_OK;
}
private:
Com<IDXGIDevicePrivate> m_device;
UINT m_evictionPriority = DXGI_RESOURCE_PRIORITY_NORMAL;
UINT m_usageFlags = 0;
};
/**
* \brief Image resource
*
* Stores a DXVK image and provides a method to retrieve
* it. D3D textures will be backed by an image resource.
*/
class DxgiImageResource : public DxgiResource<IDXGIImageResourcePrivate> {
using Base = DxgiResource<IDXGIImageResourcePrivate>;
public:
DxgiImageResource(
IDXGIDevicePrivate* pDevice,
const Rc<DxvkImage>& image,
UINT usageFlags);
DxgiImageResource(
IDXGIDevicePrivate* pDevice,
const dxvk::DxvkImageCreateInfo* pCreateInfo,
VkMemoryPropertyFlags memoryFlags,
UINT usageFlags);
~DxgiImageResource();
HRESULT STDMETHODCALLTYPE QueryInterface(
REFIID riid,
void **ppvObject) final;
HRESULT STDMETHODCALLTYPE GetParent(
REFIID riid,
void **ppParent) final;
Rc<DxvkImage> STDMETHODCALLTYPE GetDXVKImage() final;
void STDMETHODCALLTYPE SetResourceLayer(
IUnknown* pLayer) final;
private:
Rc<DxvkImage> m_image;
IUnknown* m_layer = nullptr;
};
}
extern "C" {
DLLEXPORT HRESULT __stdcall DXGICreateImageResourcePrivate(
IDXGIDevicePrivate* pDevice,
const dxvk::DxvkImageCreateInfo* pCreateInfo,
VkMemoryPropertyFlags memoryFlags,
UINT usageFlags,
IDXGIImageResourcePrivate** ppResource);
}

View File

@ -1,5 +1,4 @@
#include "dxgi_factory.h"
#include "dxgi_resource.h"
#include "dxgi_swapchain.h"
namespace dxvk {
@ -99,7 +98,7 @@ namespace dxvk {
return DXGI_ERROR_INVALID_CALL;
}
return m_backBufferIface->QueryInterface(riid, ppSurface);
return m_backBuffer->QueryInterface(riid, ppSurface);
}
@ -327,21 +326,12 @@ namespace dxvk {
VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT;
if (FAILED(GetSampleCount(m_desc.SampleDesc.Count, &sampleCount)))
throw DxvkError("DxgiSwapChain::createBackBuffer: Invalid sample count");
throw DxvkError("DxgiSwapChain: Invalid sample count");
const Rc<DxvkImage> backBuffer = m_presenter->createBackBuffer(
m_desc.BufferDesc.Width, m_desc.BufferDesc.Height,
m_adapter->LookupFormat(m_desc.BufferDesc.Format, DxgiFormatMode::Color).actual,
sampleCount);
if (FAILED(m_presentDevice->CreateSwapChainBackBuffer(&m_desc, &m_backBuffer)))
throw DxvkError("DxgiSwapChain: Failed to create back buffer");
const Com<IDXGIImageResourcePrivate> resource
= new DxgiImageResource(m_device.ptr(), backBuffer,
DXGI_USAGE_BACK_BUFFER | m_desc.BufferUsage);
// Wrap the back buffer image into an interface
// that the device can use to access the image.
if (FAILED(m_presentDevice->WrapSwapChainBackBuffer(resource.ptr(), &m_desc, &m_backBufferIface)))
throw DxvkError("DxgiSwapChain::createBackBuffer: Failed to create back buffer interface");
m_presenter->updateBackBuffer(m_backBuffer->GetDXVKImage());
}

View File

@ -94,7 +94,7 @@ namespace dxvk {
SDL_Window* m_window = nullptr;
Rc<DxgiPresenter> m_presenter;
Com<IUnknown> m_backBufferIface;
Com<IDXGIPresentBackBuffer> m_backBuffer;
void createPresenter();
void createBackBuffer();

View File

@ -6,7 +6,6 @@ dxgi_src = [
'dxgi_main.cpp',
'dxgi_output.cpp',
'dxgi_presenter.cpp',
'dxgi_resource.cpp',
'dxgi_swapchain.cpp',
]

View File

@ -6,9 +6,8 @@
const GUID IDXGIAdapterPrivate::guid = {0x907bf281,0xea3c,0x43b4,{0xa8,0xe4,0x9f,0x23,0x11,0x07,0xb4,0xff}};
const GUID IDXGIDevicePrivate::guid = {0x7a622cf6,0x627a,0x46b2,{0xb5,0x2f,0x36,0x0e,0xf3,0xda,0x83,0x1c}};
const GUID IDXGIPresentBackBuffer::guid = {0x5679becd,0x8547,0x4d93,{0x96,0xa1,0xe6,0x1a,0x1c,0xe7,0xef,0x37}};
const GUID IDXGIPresentDevicePrivate::guid = {0x79352328,0x16f2,0x4f81,{0x97,0x46,0x9c,0x2e,0x2c,0xcd,0x43,0xcf}};
const GUID IDXGIBufferResourcePrivate::guid = {0x5679becd,0x8547,0x4d93,{0x96,0xa1,0xe6,0x1a,0x1c,0xe7,0xef,0x37}};
const GUID IDXGIImageResourcePrivate::guid = {0x1cfe6592,0x7de0,0x4a07,{0x8d,0xcb,0x45,0x43,0xcb,0xbc,0x6a,0x7d}};
std::ostream& operator << (std::ostream& os, REFIID guid) {
os.width(8);