diff --git a/src/d3d11/d3d11_device.cpp b/src/d3d11/d3d11_device.cpp index c9ef3219..731f0e07 100644 --- a/src/d3d11/d3d11_device.cpp +++ b/src/d3d11/d3d11_device.cpp @@ -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 image; + const Com 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 imageResource; + // Retrieve info about the image + D3D11TextureInfo textureInfo; - if (FAILED(pResource->QueryInterface( - __uuidof(IDXGIImageResourcePrivate), - reinterpret_cast(&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 texture2D; - if (SUCCEEDED(pResource->QueryInterface( - __uuidof(ID3D11Texture2D), - reinterpret_cast(&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 imageResource; + D3D11TextureInfo textureInfo; - if (FAILED(pResource->QueryInterface( - __uuidof(IDXGIImageResourcePrivate), - reinterpret_cast(&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 imageResource; + D3D11TextureInfo textureInfo; - if (FAILED(pResource->QueryInterface( - __uuidof(IDXGIImageResourcePrivate), - reinterpret_cast(&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 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) { diff --git a/src/d3d11/d3d11_device.h b/src/d3d11/d3d11_device.h index 0495d8a7..70cb791b 100644 --- a/src/d3d11/d3d11_device.h +++ b/src/d3d11/d3d11_device.h @@ -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 { @@ -226,6 +228,10 @@ namespace dxvk { VkPipelineStageFlags GetEnabledShaderStages() const; + DxgiFormatPair STDMETHODCALLTYPE LookupFormat( + DXGI_FORMAT format, + DxgiFormatMode mode) const; + static bool CheckFeatureLevelSupport( const Rc& 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; diff --git a/src/d3d11/d3d11_present.cpp b/src/d3d11/d3d11_present.cpp index a090a9cf..236a5f78 100644 --- a/src/d3d11/d3d11_present.cpp +++ b/src/d3d11/d3d11_present.cpp @@ -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 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; + } } diff --git a/src/d3d11/d3d11_present.h b/src/d3d11/d3d11_present.h index 8b3ca333..b7e72d5e 100644 --- a/src/d3d11/d3d11_present.h +++ b/src/d3d11/d3d11_present.h @@ -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 { + + public: + + D3D11PresentBackBuffer(D3D11Texture2D* pTexture) + : m_texture(pTexture) { } + + HRESULT STDMETHODCALLTYPE QueryInterface( + REFIID riid, + void** ppvObject) final; + + Rc GetDXVKImage() final; + + public: + + Com m_texture; + + }; + + class D3D11PresentDevice : public ComObject { 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; diff --git a/src/d3d11/d3d11_texture.cpp b/src/d3d11/d3d11_texture.cpp index d7d594c6..672e4f3a 100644 --- a/src/d3d11/d3d11_texture.cpp +++ b/src/d3d11/d3d11_texture.cpp @@ -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(pResource); + pTextureInfo->formatMode = tex->GetFormatMode(); + pTextureInfo->image = tex->GetDXVKImage(); + } return S_OK; + + default: + return E_INVALIDARG; + } + } + } diff --git a/src/d3d11/d3d11_texture.h b/src/d3d11/d3d11_texture.h index 1e2dddd5..f7b1ffd4 100644 --- a/src/d3d11/d3d11_texture.h +++ b/src/d3d11/d3d11_texture.h @@ -9,16 +9,14 @@ namespace dxvk { class D3D11Device; - class D3D11Texture2D : public D3D11DeviceChild { 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 GetDXVKImage() const { - return m_resource->GetDXVKImage(); + return m_image; } private: Com m_device; - Com m_resource; DxgiFormatMode m_formatMode; D3D11_TEXTURE2D_DESC m_desc; + Rc 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 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); + } diff --git a/src/d3d11/d3d11_util.cpp b/src/d3d11/d3d11_util.cpp index 21dc7380..7fd58872 100644 --- a/src/d3d11/d3d11_util.cpp +++ b/src/d3d11/d3d11_util.cpp @@ -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) { diff --git a/src/d3d11/d3d11_util.h b/src/d3d11/d3d11_util.h index ef22e202..5fc3fd3b 100644 --- a/src/d3d11/d3d11_util.h +++ b/src/d3d11/d3d11_util.h @@ -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); } \ No newline at end of file diff --git a/src/dxgi/dxgi_interfaces.h b/src/dxgi/dxgi_interfaces.h index 5be22fe0..c52ab789 100644 --- a/src/dxgi/dxgi_interfaces.h +++ b/src/dxgi/dxgi_interfaces.h @@ -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 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 STDMETHODCALLTYPE GetDXVKImage() = 0; - - virtual void STDMETHODCALLTYPE SetResourceLayer( - IUnknown* pLayer) = 0; + virtual dxvk::Rc 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); diff --git a/src/dxgi/dxgi_presenter.cpp b/src/dxgi/dxgi_presenter.cpp index 6e2e341f..663c4bd1 100644 --- a/src/dxgi/dxgi_presenter.cpp +++ b/src/dxgi/dxgi_presenter.cpp @@ -207,70 +207,22 @@ namespace dxvk { } - Rc 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& 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; } diff --git a/src/dxgi/dxgi_presenter.h b/src/dxgi/dxgi_presenter.h index acb859ed..4f58ecee 100644 --- a/src/dxgi/dxgi_presenter.h +++ b/src/dxgi/dxgi_presenter.h @@ -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 createBackBuffer( - uint32_t bufferWidth, - uint32_t bufferHeight, - VkFormat bufferFormat, - VkSampleCountFlagBits sampleCount); + void updateBackBuffer( + const Rc& image); /** * \brief Renders image to the screen diff --git a/src/dxgi/dxgi_resource.cpp b/src/dxgi/dxgi_resource.cpp deleted file mode 100644 index f1ba60ce..00000000 --- a/src/dxgi/dxgi_resource.cpp +++ /dev/null @@ -1,81 +0,0 @@ -#include "dxgi_resource.h" - -namespace dxvk { - - DxgiImageResource::DxgiImageResource( - IDXGIDevicePrivate* pDevice, - const Rc& 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 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; - } - } - -} \ No newline at end of file diff --git a/src/dxgi/dxgi_resource.h b/src/dxgi/dxgi_resource.h deleted file mode 100644 index 396ec2e8..00000000 --- a/src/dxgi/dxgi_resource.h +++ /dev/null @@ -1,116 +0,0 @@ -#pragma once - -#include - -#include "dxgi_object.h" -#include "dxgi_interfaces.h" - -namespace dxvk { - - template - class DxgiResource : public DxgiObject { - - 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 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 { - using Base = DxgiResource; - public: - - DxgiImageResource( - IDXGIDevicePrivate* pDevice, - const Rc& 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 STDMETHODCALLTYPE GetDXVKImage() final; - - void STDMETHODCALLTYPE SetResourceLayer( - IUnknown* pLayer) final; - - private: - - Rc m_image; - IUnknown* m_layer = nullptr; - - }; - -} - - -extern "C" { - - DLLEXPORT HRESULT __stdcall DXGICreateImageResourcePrivate( - IDXGIDevicePrivate* pDevice, - const dxvk::DxvkImageCreateInfo* pCreateInfo, - VkMemoryPropertyFlags memoryFlags, - UINT usageFlags, - IDXGIImageResourcePrivate** ppResource); - -} \ No newline at end of file diff --git a/src/dxgi/dxgi_swapchain.cpp b/src/dxgi/dxgi_swapchain.cpp index fae434ea..272f4c3f 100644 --- a/src/dxgi/dxgi_swapchain.cpp +++ b/src/dxgi/dxgi_swapchain.cpp @@ -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 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 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()); } diff --git a/src/dxgi/dxgi_swapchain.h b/src/dxgi/dxgi_swapchain.h index 1dd632d8..d47395b7 100644 --- a/src/dxgi/dxgi_swapchain.h +++ b/src/dxgi/dxgi_swapchain.h @@ -94,7 +94,7 @@ namespace dxvk { SDL_Window* m_window = nullptr; Rc m_presenter; - Com m_backBufferIface; + Com m_backBuffer; void createPresenter(); void createBackBuffer(); diff --git a/src/dxgi/meson.build b/src/dxgi/meson.build index 4d4b4d0f..f58b1323 100644 --- a/src/dxgi/meson.build +++ b/src/dxgi/meson.build @@ -6,7 +6,6 @@ dxgi_src = [ 'dxgi_main.cpp', 'dxgi_output.cpp', 'dxgi_presenter.cpp', - 'dxgi_resource.cpp', 'dxgi_swapchain.cpp', ] diff --git a/src/util/com/com_guid.cpp b/src/util/com/com_guid.cpp index 6db1265f..c01531e4 100644 --- a/src/util/com/com_guid.cpp +++ b/src/util/com/com_guid.cpp @@ -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);