1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-03-14 22:29:15 +01:00

[dxgi] Implemented DxgiSwapChain::GetBuffer and more of Present

This commit is contained in:
Philip Rebohle 2017-11-29 07:55:44 +01:00
parent 0c3a68c519
commit ad9f71fa02
12 changed files with 211 additions and 79 deletions

View File

@ -3,6 +3,7 @@
#include "d3d11_buffer.h" #include "d3d11_buffer.h"
#include "d3d11_context.h" #include "d3d11_context.h"
#include "d3d11_device.h" #include "d3d11_device.h"
#include "d3d11_texture.h"
namespace dxvk { namespace dxvk {
@ -28,6 +29,7 @@ namespace dxvk {
HRESULT D3D11Device::QueryInterface(REFIID riid, void** ppvObject) { HRESULT D3D11Device::QueryInterface(REFIID riid, void** ppvObject) {
COM_QUERY_IFACE(riid, ppvObject, IUnknown); COM_QUERY_IFACE(riid, ppvObject, IUnknown);
COM_QUERY_IFACE(riid, ppvObject, ID3D11Device); COM_QUERY_IFACE(riid, ppvObject, ID3D11Device);
COM_QUERY_IFACE(riid, ppvObject, ID3D11DevicePrivate);
if (riid == __uuidof(IDXGIDevicePrivate) if (riid == __uuidof(IDXGIDevicePrivate)
|| riid == __uuidof(IDXGIDevice)) || riid == __uuidof(IDXGIDevice))
@ -42,20 +44,8 @@ namespace dxvk {
const D3D11_BUFFER_DESC* pDesc, const D3D11_BUFFER_DESC* pDesc,
const D3D11_SUBRESOURCE_DATA* pInitialData, const D3D11_SUBRESOURCE_DATA* pInitialData,
ID3D11Buffer** ppBuffer) { ID3D11Buffer** ppBuffer) {
if (ppBuffer == nullptr) Logger::err("D3D11Device::CreateBuffer: Not implemented");
return S_OK; return E_NOTIMPL;
try {
*ppBuffer = ref(new D3D11Buffer(this, *pDesc));
if (pInitialData != nullptr)
Logger::warn("D3D11Device::CreateBuffer: pInitialData != NULL not supported");
return S_OK;
} catch (const DxvkError& e) {
Logger::err(e.message());
return E_FAIL;
}
} }
@ -384,6 +374,46 @@ namespace dxvk {
} }
HRESULT D3D11Device::WrapSwapChainBackBuffer(
const Rc<DxvkImage>& image,
const DXGI_SWAP_CHAIN_DESC* pSwapChainDesc,
IUnknown** ppInterface) {
UINT bindFlags = 0;
if (pSwapChainDesc->BufferUsage & DXGI_USAGE_RENDER_TARGET_OUTPUT)
bindFlags |= D3D11_BIND_RENDER_TARGET;
if (pSwapChainDesc->BufferUsage & DXGI_USAGE_SHADER_INPUT)
bindFlags |= D3D11_BIND_SHADER_RESOURCE;
D3D11_TEXTURE2D_DESC desc;
desc.Width = pSwapChainDesc->BufferDesc.Width;
desc.Height = pSwapChainDesc->BufferDesc.Height;
desc.MipLevels = 1;
desc.ArraySize = 1;
desc.Format = pSwapChainDesc->BufferDesc.Format;
desc.SampleDesc = pSwapChainDesc->SampleDesc;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.BindFlags = bindFlags;
desc.CPUAccessFlags = 0;
desc.MiscFlags = 0;
*ppInterface = ref(new D3D11Texture2D(this, desc, image));
return S_OK;
}
HRESULT D3D11Device::FlushRenderingCommands() {
m_context->Flush();
return S_OK;
}
Rc<DxvkDevice> D3D11Device::GetDXVKDevice() {
return m_dxvkDevice;
}
bool D3D11Device::CheckFeatureLevelSupport( bool D3D11Device::CheckFeatureLevelSupport(
D3D_FEATURE_LEVEL featureLevel) { D3D_FEATURE_LEVEL featureLevel) {
return featureLevel <= D3D_FEATURE_LEVEL_11_0; return featureLevel <= D3D_FEATURE_LEVEL_11_0;

View File

@ -3,7 +3,7 @@
#include <dxgi_object.h> #include <dxgi_object.h>
#include <dxgi_interfaces.h> #include <dxgi_interfaces.h>
#include "d3d11_include.h" #include "d3d11_interfaces.h"
#include "../util/com/com_private_data.h" #include "../util/com/com_private_data.h"
@ -12,7 +12,7 @@ namespace dxvk {
class DxgiAdapter; class DxgiAdapter;
class D3D11DeviceContext; class D3D11DeviceContext;
class D3D11Device : public ComObject<ID3D11Device> { class D3D11Device : public ComObject<ID3D11DevicePrivate> {
public: public:
@ -215,9 +215,14 @@ namespace dxvk {
UINT GetExceptionMode() final; UINT GetExceptionMode() final;
DxvkDevice* GetDXVKDevice() { HRESULT WrapSwapChainBackBuffer(
return m_dxvkDevice.ptr(); const Rc<DxvkImage>& image,
} const DXGI_SWAP_CHAIN_DESC* pSwapChainDesc,
IUnknown** ppInterface) final;
HRESULT FlushRenderingCommands() final;
Rc<DxvkDevice> GetDXVKDevice() final;
static bool CheckFeatureLevelSupport( static bool CheckFeatureLevelSupport(
D3D_FEATURE_LEVEL featureLevel); D3D_FEATURE_LEVEL featureLevel);

View File

@ -1,4 +1,5 @@
#pragma once #pragma once
#include <dxgi_include.h> #include "../dxgi/dxgi_include.h"
#include <d3d11_1.h> #include <d3d11_1.h>

View File

@ -0,0 +1,50 @@
#pragma once
#include "../dxvk/dxvk_device.h"
#include "d3d11_include.h"
/**
* \brief Private device interface
*
* This interface is used by \ref DxgiSwapChain
* in order to communicate with the device.
*/
MIDL_INTERFACE("ab2a2a58-d2ac-4ca0-9ad9-a260cafa00c8")
ID3D11DevicePrivate : public ID3D11Device {
static const GUID guid;
/**
* \brief Wraps swap chain image into a texture interface
*
* 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 WrapSwapChainBackBuffer(
const dxvk::Rc<dxvk::DxvkImage>& image,
const DXGI_SWAP_CHAIN_DESC* pSwapChainDesc,
IUnknown** ppInterface) = 0;
/**
* \brief Flushes the immediate context
*
* Used by the swap chain's \c Present method to
* ensure that all rendering commands get dispatched
* before presenting the swap chain's back buffer.
* \returns \c S_OK on success
*/
virtual HRESULT FlushRenderingCommands() = 0;
/**
* \brief Underlying DXVK device
* \returns DXVK device handle
*/
virtual dxvk::Rc<dxvk::DxvkDevice> GetDXVKDevice() = 0;
};
DXVK_DEFINE_GUID(ID3D11DevicePrivate);

View File

@ -5,8 +5,11 @@ namespace dxvk {
D3D11Texture2D::D3D11Texture2D( D3D11Texture2D::D3D11Texture2D(
D3D11Device* device, D3D11Device* device,
const D3D11_TEXTURE2D_DESC& desc) const D3D11_TEXTURE2D_DESC& desc,
: m_device(device), m_desc(desc) { const Rc<DxvkImage>& image)
: m_device(device),
m_desc (desc),
m_image (image) {
} }
@ -36,7 +39,7 @@ namespace dxvk {
*pResourceDimension = D3D11_RESOURCE_DIMENSION_TEXTURE2D; *pResourceDimension = D3D11_RESOURCE_DIMENSION_TEXTURE2D;
} }
void D3D11Texture2D::GetDesc(D3D11_TEXTURE2D_DESC *pDesc) { void D3D11Texture2D::GetDesc(D3D11_TEXTURE2D_DESC *pDesc) {
*pDesc = m_desc; *pDesc = m_desc;
} }

View File

@ -14,7 +14,8 @@ namespace dxvk {
D3D11Texture2D( D3D11Texture2D(
D3D11Device* device, D3D11Device* device,
const D3D11_TEXTURE2D_DESC& desc); const D3D11_TEXTURE2D_DESC& desc,
const Rc<DxvkImage>& image);
~D3D11Texture2D(); ~D3D11Texture2D();
HRESULT QueryInterface( HRESULT QueryInterface(

View File

@ -9,7 +9,7 @@ namespace dxvk {
} }
/** /**
* \brief DXVK adapter * \brief Private DXGI adapter interface
* *
* The implementation of \c IDXGIAdapter holds a * The implementation of \c IDXGIAdapter holds a
* \ref DxvkAdapter which can be retrieved using * \ref DxvkAdapter which can be retrieved using
@ -24,7 +24,7 @@ IDXGIAdapterPrivate : public IDXGIAdapter1 {
/** /**
* \brief DXVK device * \brief Private DXGI device interface
* *
* The implementation of \c IDXGIDevice stores a * The implementation of \c IDXGIDevice stores a
* \ref DxvkDevice which can be retrieved using * \ref DxvkDevice which can be retrieved using

View File

@ -12,10 +12,21 @@ namespace dxvk {
// Retrieve a device pointer that allows us to // Retrieve a device pointer that allows us to
// communicate with the underlying D3D device // communicate with the underlying D3D device
if (FAILED(pDevice->QueryInterface(__uuidof(IDXGIDevicePrivate), if (FAILED(pDevice->QueryInterface(__uuidof(ID3D11DevicePrivate),
reinterpret_cast<void**>(&m_device)))) reinterpret_cast<void**>(&m_device))))
throw DxvkError("DxgiSwapChain::DxgiSwapChain: Invalid device"); throw DxvkError("DxgiSwapChain::DxgiSwapChain: Invalid device");
// Retrieve the adapter, which is going
// to be used to enumerate displays.
Com<IDXGIDevice> device;
if (FAILED(pDevice->QueryInterface(__uuidof(IDXGIDevice),
reinterpret_cast<void**>(&device))))
throw DxvkError("DxgiSwapChain::DxgiSwapChain: Invalid device");
if (FAILED(device->GetAdapter(&m_adapter)))
throw DxvkError("DxgiSwapChain::DxgiSwapChain: Failed to retrieve adapter");
// Initialize frame statistics // Initialize frame statistics
m_stats.PresentCount = 0; m_stats.PresentCount = 0;
m_stats.PresentRefreshCount = 0; m_stats.PresentRefreshCount = 0;
@ -39,7 +50,7 @@ namespace dxvk {
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");
// Create swap chain // TODO clean up here
Rc<DxvkDevice> dxvkDevice = m_device->GetDXVKDevice(); Rc<DxvkDevice> dxvkDevice = m_device->GetDXVKDevice();
Rc<DxvkAdapter> dxvkAdapter = dxvkDevice->adapter(); Rc<DxvkAdapter> dxvkAdapter = dxvkDevice->adapter();
@ -65,6 +76,7 @@ namespace dxvk {
m_swapchain = dxvkDevice->createSwapchain( m_swapchain = dxvkDevice->createSwapchain(
m_surface, swapchainProperties); m_surface, swapchainProperties);
this->createBackBuffer();
} }
@ -103,8 +115,7 @@ namespace dxvk {
return DXGI_ERROR_INVALID_CALL; return DXGI_ERROR_INVALID_CALL;
} }
Logger::err("DxgiSwapChain::GetBuffer: Not implemented"); return m_backBufferIface->QueryInterface(riid, ppSurface);
return E_NOTIMPL;
} }
@ -123,12 +134,7 @@ namespace dxvk {
return DXGI_ERROR_DRIVER_INTERNAL_ERROR; return DXGI_ERROR_DRIVER_INTERNAL_ERROR;
} }
Com<IDXGIAdapter> adapter; return m_adapter->EnumOutputs(displayId, ppOutput);
if (FAILED(m_device->GetAdapter(&adapter)))
return DXGI_ERROR_DRIVER_INTERNAL_ERROR;
return adapter->EnumOutputs(displayId, ppOutput);
} }
@ -182,47 +188,56 @@ namespace dxvk {
HRESULT DxgiSwapChain::Present(UINT SyncInterval, UINT Flags) { HRESULT DxgiSwapChain::Present(UINT SyncInterval, UINT Flags) {
std::lock_guard<std::mutex> lock(m_mutex); std::lock_guard<std::mutex> lock(m_mutex);
// TODO implement sync interval try {
// TODO implement flags // Submit pending rendering commands
// before recording the present code.
m_device->FlushRenderingCommands();
auto dxvkDevice = m_device->GetDXVKDevice(); // TODO implement sync interval
// TODO implement flags
auto framebuffer = m_swapchain->getFramebuffer(m_acquireSync);
auto framebufferSize = framebuffer->size(); auto dxvkDevice = m_device->GetDXVKDevice();
m_context->beginRecording(m_commandList); auto framebuffer = m_swapchain->getFramebuffer(m_acquireSync);
m_context->bindFramebuffer(framebuffer); auto framebufferSize = framebuffer->size();
// TODO render back buffer into the swap image, m_context->beginRecording(m_commandList);
// the clear operation is only a placeholder. m_context->bindFramebuffer(framebuffer);
VkClearAttachment clearAttachment;
clearAttachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; // TODO render back buffer into the swap image,
clearAttachment.colorAttachment = 0; // the clear operation is only a placeholder.
clearAttachment.clearValue.color.float32[0] = 1.0f; VkClearAttachment clearAttachment;
clearAttachment.clearValue.color.float32[1] = 1.0f; clearAttachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
clearAttachment.clearValue.color.float32[2] = 1.0f; clearAttachment.colorAttachment = 0;
clearAttachment.clearValue.color.float32[3] = 1.0f; clearAttachment.clearValue.color.float32[0] = 1.0f;
clearAttachment.clearValue.color.float32[1] = 1.0f;
VkClearRect clearArea; clearAttachment.clearValue.color.float32[2] = 1.0f;
clearArea.rect = VkRect2D { { 0, 0 }, framebufferSize.width, framebufferSize.height }; clearAttachment.clearValue.color.float32[3] = 1.0f;
clearArea.baseArrayLayer = 0;
clearArea.layerCount = framebufferSize.layers; VkClearRect clearArea;
clearArea.rect = VkRect2D { { 0, 0 }, framebufferSize.width, framebufferSize.height };
m_context->clearRenderTarget( clearArea.baseArrayLayer = 0;
clearAttachment, clearArea.layerCount = framebufferSize.layers;
clearArea);
m_context->clearRenderTarget(
m_context->endRecording(); clearAttachment,
clearArea);
dxvkDevice->submitCommandList(m_commandList,
m_acquireSync, m_presentSync); m_context->endRecording();
m_swapchain->present( m_presentSync); dxvkDevice->submitCommandList(m_commandList,
m_acquireSync, m_presentSync);
// FIXME Make sure that the semaphores and the command
// list can be safely used without stalling the device. m_swapchain->present(m_presentSync);
dxvkDevice->waitForIdle();
return S_OK; // FIXME Make sure that the semaphores and the command
// list can be safely used without stalling the device.
dxvkDevice->waitForIdle();
return S_OK;
} catch (const DxvkError& err) {
Logger::err(err.message());
return DXGI_ERROR_DRIVER_INTERNAL_ERROR;
}
} }
@ -237,9 +252,11 @@ namespace dxvk {
m_desc.BufferDesc.Width = Width; m_desc.BufferDesc.Width = Width;
m_desc.BufferDesc.Height = Height; m_desc.BufferDesc.Height = Height;
m_desc.BufferDesc.Format = NewFormat; m_desc.BufferDesc.Format = NewFormat;
m_desc.BufferCount = BufferCount;
m_desc.Flags = SwapChainFlags; m_desc.Flags = SwapChainFlags;
if (BufferCount != 0)
m_desc.BufferCount = BufferCount;
try { try {
// TODO implement // TODO implement
return S_OK; return S_OK;
@ -328,4 +345,12 @@ namespace dxvk {
return S_OK; return S_OK;
} }
void DxgiSwapChain::createBackBuffer() {
// TODO create DXVK image and image virw
if (FAILED(m_device->WrapSwapChainBackBuffer(m_backBuffer, &m_desc, &m_backBufferIface)))
throw DxvkError("DxgiSwapChain::createBackBuffer: Failed to create back buffer");
}
} }

View File

@ -9,6 +9,8 @@
#include "dxgi_interfaces.h" #include "dxgi_interfaces.h"
#include "dxgi_object.h" #include "dxgi_object.h"
#include "../d3d11/d3d11_interfaces.h"
namespace dxvk { namespace dxvk {
class DxgiFactory; class DxgiFactory;
@ -78,8 +80,9 @@ namespace dxvk {
std::mutex m_mutex; std::mutex m_mutex;
Com<DxgiFactory> m_factory; Com<DxgiFactory> m_factory;
Com<IDXGIDevicePrivate> m_device; Com<IDXGIAdapter> m_adapter;
Com<ID3D11DevicePrivate> m_device;
DXGI_SWAP_CHAIN_DESC m_desc; DXGI_SWAP_CHAIN_DESC m_desc;
DXGI_FRAME_STATISTICS m_stats; DXGI_FRAME_STATISTICS m_stats;
@ -94,6 +97,12 @@ namespace dxvk {
Rc<DxvkSemaphore> m_acquireSync; Rc<DxvkSemaphore> m_acquireSync;
Rc<DxvkSemaphore> m_presentSync; Rc<DxvkSemaphore> m_presentSync;
Rc<DxvkImage> m_backBuffer;
Rc<DxvkImageView> m_backBufferView;
Com<IUnknown> m_backBufferIface;
void createBackBuffer();
}; };
} }

View File

@ -6,6 +6,7 @@
#include "dxvk_constant_state.h" #include "dxvk_constant_state.h"
#include "dxvk_context.h" #include "dxvk_context.h"
#include "dxvk_framebuffer.h" #include "dxvk_framebuffer.h"
#include "dxvk_image.h"
#include "dxvk_memory.h" #include "dxvk_memory.h"
#include "dxvk_pipemgr.h" #include "dxvk_pipemgr.h"
#include "dxvk_renderpass.h" #include "dxvk_renderpass.h"

View File

@ -1,10 +1,14 @@
#include "com_guid.h" #include "com_guid.h"
#include "../../d3d11/d3d11_interfaces.h"
#include "../../dxgi/dxgi_interfaces.h" #include "../../dxgi/dxgi_interfaces.h"
const GUID IDXGIAdapterPrivate::guid = {0x907bf281,0xea3c,0x43b4,{0xa8,0xe4,0x9f,0x23,0x11,0x07,0xb4,0xff}}; 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 IDXGIDevicePrivate::guid = {0x7a622cf6,0x627a,0x46b2,{0xb5,0x2f,0x36,0x0e,0xf3,0xda,0x83,0x1c}};
const GUID ID3D11DevicePrivate::guid = {0xab2a2a58,0xd2ac,0x4ca0,{0x9a,0xd9,0xa2,0x60,0xca,0xfa,0x00,0xc8}};
std::ostream& operator << (std::ostream& os, REFIID guid) { std::ostream& operator << (std::ostream& os, REFIID guid) {
os.width(8); os.width(8);
os << std::hex << guid.Data1 << '-'; os << std::hex << guid.Data1 << '-';

View File

@ -4,4 +4,7 @@
#include "com_include.h" #include "com_include.h"
#define DXVK_DEFINE_GUID(iface) \
template<> inline GUID const& __mingw_uuidof<iface> () { return iface::guid; }
std::ostream& operator << (std::ostream& os, REFIID guid); std::ostream& operator << (std::ostream& os, REFIID guid);