2018-01-31 01:57:43 +01:00
|
|
|
#include <algorithm>
|
2017-10-11 09:51:48 +02:00
|
|
|
#include <cstring>
|
|
|
|
|
2018-12-21 12:23:45 +01:00
|
|
|
#include "../dxgi/dxgi_swapchain.h"
|
|
|
|
|
2018-08-07 14:58:08 +02:00
|
|
|
#include "../dxvk/dxvk_adapter.h"
|
|
|
|
#include "../dxvk/dxvk_instance.h"
|
|
|
|
|
2017-10-15 21:38:09 +02:00
|
|
|
#include "d3d11_buffer.h"
|
2017-12-12 01:07:07 +01:00
|
|
|
#include "d3d11_class_linkage.h"
|
2018-01-23 09:23:31 +01:00
|
|
|
#include "d3d11_context_def.h"
|
2018-01-20 13:22:44 +01:00
|
|
|
#include "d3d11_context_imm.h"
|
2017-10-11 09:51:48 +02:00
|
|
|
#include "d3d11_device.h"
|
2017-12-07 12:45:02 +01:00
|
|
|
#include "d3d11_input_layout.h"
|
2018-04-20 00:19:03 +02:00
|
|
|
#include "d3d11_interop.h"
|
2017-11-29 16:23:33 +01:00
|
|
|
#include "d3d11_present.h"
|
2017-12-29 22:20:31 +01:00
|
|
|
#include "d3d11_query.h"
|
2018-08-05 18:56:42 +02:00
|
|
|
#include "d3d11_resource.h"
|
2017-12-09 20:49:56 +01:00
|
|
|
#include "d3d11_sampler.h"
|
2017-12-06 18:54:01 +01:00
|
|
|
#include "d3d11_shader.h"
|
2017-11-29 07:55:44 +01:00
|
|
|
#include "d3d11_texture.h"
|
2017-10-11 09:51:48 +02:00
|
|
|
|
|
|
|
namespace dxvk {
|
|
|
|
|
2018-12-03 19:26:29 +01:00
|
|
|
constexpr uint32_t D3D11DXGIDevice::DefaultFrameLatency;
|
|
|
|
|
2018-11-29 20:13:36 +01:00
|
|
|
|
2018-03-28 21:24:52 +02:00
|
|
|
|
2017-10-11 09:51:48 +02:00
|
|
|
D3D11Device::D3D11Device(
|
2018-12-03 19:26:29 +01:00
|
|
|
D3D11DXGIDevice* pContainer,
|
2018-03-28 21:24:52 +02:00
|
|
|
D3D_FEATURE_LEVEL FeatureLevel,
|
|
|
|
UINT FeatureFlags)
|
|
|
|
: m_container (pContainer),
|
|
|
|
m_featureLevel (FeatureLevel),
|
|
|
|
m_featureFlags (FeatureFlags),
|
2018-12-03 19:26:29 +01:00
|
|
|
m_dxvkDevice (pContainer->GetDXVKDevice()),
|
2018-01-07 20:05:27 +01:00
|
|
|
m_dxvkAdapter (m_dxvkDevice->adapter()),
|
2018-11-28 18:34:05 +01:00
|
|
|
m_d3d11Formats (m_dxvkAdapter),
|
2018-08-07 14:58:08 +02:00
|
|
|
m_d3d11Options (m_dxvkAdapter->instance()->config()),
|
2018-11-23 16:11:46 +01:00
|
|
|
m_dxbcOptions (m_dxvkDevice, m_d3d11Options) {
|
2018-07-23 15:21:17 +02:00
|
|
|
m_initializer = new D3D11Initializer(m_dxvkDevice);
|
2018-08-11 16:36:54 +02:00
|
|
|
m_context = new D3D11ImmediateContext(this, m_dxvkDevice);
|
|
|
|
m_d3d10Device = new D3D10Device(this, m_context);
|
2018-08-30 15:24:47 +02:00
|
|
|
|
|
|
|
m_uavCounters = CreateUAVCounterBuffer();
|
2018-08-30 15:56:51 +02:00
|
|
|
m_xfbCounters = CreateXFBCounterBuffer();
|
2017-10-11 09:51:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
D3D11Device::~D3D11Device() {
|
2018-08-11 16:36:54 +02:00
|
|
|
delete m_d3d10Device;
|
2017-12-11 17:01:38 +01:00
|
|
|
delete m_context;
|
2018-07-23 15:21:17 +02:00
|
|
|
delete m_initializer;
|
2017-10-11 09:51:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-03-28 21:24:52 +02:00
|
|
|
ULONG STDMETHODCALLTYPE D3D11Device::AddRef() {
|
|
|
|
return m_container->AddRef();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ULONG STDMETHODCALLTYPE D3D11Device::Release() {
|
|
|
|
return m_container->Release();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-12-12 12:50:52 +01:00
|
|
|
HRESULT STDMETHODCALLTYPE D3D11Device::QueryInterface(REFIID riid, void** ppvObject) {
|
2018-03-28 21:24:52 +02:00
|
|
|
return m_container->QueryInterface(riid, ppvObject);
|
2017-10-11 09:51:48 +02:00
|
|
|
}
|
2017-10-11 15:32:24 +02:00
|
|
|
|
2017-10-11 09:51:48 +02:00
|
|
|
|
2017-12-12 12:50:52 +01:00
|
|
|
HRESULT STDMETHODCALLTYPE D3D11Device::CreateBuffer(
|
2017-10-11 09:51:48 +02:00
|
|
|
const D3D11_BUFFER_DESC* pDesc,
|
|
|
|
const D3D11_SUBRESOURCE_DATA* pInitialData,
|
|
|
|
ID3D11Buffer** ppBuffer) {
|
2018-04-02 12:04:20 +02:00
|
|
|
InitReturnPtr(ppBuffer);
|
|
|
|
|
2018-02-27 08:54:24 +01:00
|
|
|
if (ppBuffer == nullptr)
|
|
|
|
return S_FALSE;
|
|
|
|
|
|
|
|
try {
|
2017-12-14 15:59:55 +01:00
|
|
|
const Com<D3D11Buffer> buffer
|
|
|
|
= new D3D11Buffer(this, pDesc);
|
2017-12-07 13:31:32 +01:00
|
|
|
|
2018-07-23 15:21:17 +02:00
|
|
|
m_initializer->InitBuffer(buffer.ptr(), pInitialData);
|
2017-12-14 15:59:55 +01:00
|
|
|
*ppBuffer = buffer.ref();
|
2018-02-27 08:54:24 +01:00
|
|
|
return S_OK;
|
|
|
|
} catch (const DxvkError& e) {
|
|
|
|
Logger::err(e.message());
|
|
|
|
return E_FAIL;
|
2017-12-07 13:17:16 +01:00
|
|
|
}
|
2017-10-11 09:51:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-12-12 12:50:52 +01:00
|
|
|
HRESULT STDMETHODCALLTYPE D3D11Device::CreateTexture1D(
|
2017-10-11 09:51:48 +02:00
|
|
|
const D3D11_TEXTURE1D_DESC* pDesc,
|
|
|
|
const D3D11_SUBRESOURCE_DATA* pInitialData,
|
|
|
|
ID3D11Texture1D** ppTexture1D) {
|
2018-04-02 12:04:20 +02:00
|
|
|
InitReturnPtr(ppTexture1D);
|
|
|
|
|
2018-03-13 23:51:30 +01:00
|
|
|
D3D11_COMMON_TEXTURE_DESC desc;
|
|
|
|
desc.Width = pDesc->Width;
|
|
|
|
desc.Height = 1;
|
|
|
|
desc.Depth = 1;
|
|
|
|
desc.MipLevels = pDesc->MipLevels;
|
|
|
|
desc.ArraySize = pDesc->ArraySize;
|
|
|
|
desc.Format = pDesc->Format;
|
|
|
|
desc.SampleDesc = DXGI_SAMPLE_DESC { 1, 0 };
|
|
|
|
desc.Usage = pDesc->Usage;
|
|
|
|
desc.BindFlags = pDesc->BindFlags;
|
|
|
|
desc.CPUAccessFlags = pDesc->CPUAccessFlags;
|
|
|
|
desc.MiscFlags = pDesc->MiscFlags;
|
|
|
|
|
|
|
|
if (FAILED(D3D11CommonTexture::NormalizeTextureProperties(&desc)))
|
|
|
|
return E_INVALIDARG;
|
|
|
|
|
2018-02-27 08:54:24 +01:00
|
|
|
if (ppTexture1D == nullptr)
|
|
|
|
return S_FALSE;
|
|
|
|
|
|
|
|
try {
|
2018-03-14 00:45:07 +01:00
|
|
|
const Com<D3D11Texture1D> texture = new D3D11Texture1D(this, &desc);
|
2018-07-23 15:21:17 +02:00
|
|
|
m_initializer->InitTexture(texture->GetCommonTexture(), pInitialData);
|
2017-12-23 17:05:07 +01:00
|
|
|
*ppTexture1D = texture.ref();
|
2018-02-27 08:54:24 +01:00
|
|
|
return S_OK;
|
|
|
|
} catch (const DxvkError& e) {
|
|
|
|
Logger::err(e.message());
|
|
|
|
return E_FAIL;
|
2017-12-23 17:05:07 +01:00
|
|
|
}
|
2017-10-11 09:51:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-12-12 12:50:52 +01:00
|
|
|
HRESULT STDMETHODCALLTYPE D3D11Device::CreateTexture2D(
|
2017-10-11 09:51:48 +02:00
|
|
|
const D3D11_TEXTURE2D_DESC* pDesc,
|
|
|
|
const D3D11_SUBRESOURCE_DATA* pInitialData,
|
|
|
|
ID3D11Texture2D** ppTexture2D) {
|
2018-04-02 12:04:20 +02:00
|
|
|
InitReturnPtr(ppTexture2D);
|
|
|
|
|
2018-03-13 23:51:30 +01:00
|
|
|
D3D11_COMMON_TEXTURE_DESC desc;
|
|
|
|
desc.Width = pDesc->Width;
|
|
|
|
desc.Height = pDesc->Height;
|
|
|
|
desc.Depth = 1;
|
|
|
|
desc.MipLevels = pDesc->MipLevels;
|
|
|
|
desc.ArraySize = pDesc->ArraySize;
|
|
|
|
desc.Format = pDesc->Format;
|
|
|
|
desc.SampleDesc = pDesc->SampleDesc;
|
|
|
|
desc.Usage = pDesc->Usage;
|
|
|
|
desc.BindFlags = pDesc->BindFlags;
|
|
|
|
desc.CPUAccessFlags = pDesc->CPUAccessFlags;
|
|
|
|
desc.MiscFlags = pDesc->MiscFlags;
|
|
|
|
|
|
|
|
if (FAILED(D3D11CommonTexture::NormalizeTextureProperties(&desc)))
|
|
|
|
return E_INVALIDARG;
|
|
|
|
|
2018-02-27 08:54:24 +01:00
|
|
|
if (ppTexture2D == nullptr)
|
|
|
|
return S_FALSE;
|
|
|
|
|
|
|
|
try {
|
2018-03-14 00:45:07 +01:00
|
|
|
const Com<D3D11Texture2D> texture = new D3D11Texture2D(this, &desc);
|
2018-07-23 15:21:17 +02:00
|
|
|
m_initializer->InitTexture(texture->GetCommonTexture(), pInitialData);
|
2017-12-19 16:01:50 +01:00
|
|
|
*ppTexture2D = texture.ref();
|
2018-02-27 08:54:24 +01:00
|
|
|
return S_OK;
|
|
|
|
} catch (const DxvkError& e) {
|
|
|
|
Logger::err(e.message());
|
|
|
|
return E_FAIL;
|
2017-12-08 23:13:15 +01:00
|
|
|
}
|
2017-10-11 09:51:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-12-12 12:50:52 +01:00
|
|
|
HRESULT STDMETHODCALLTYPE D3D11Device::CreateTexture3D(
|
2017-10-11 09:51:48 +02:00
|
|
|
const D3D11_TEXTURE3D_DESC* pDesc,
|
|
|
|
const D3D11_SUBRESOURCE_DATA* pInitialData,
|
|
|
|
ID3D11Texture3D** ppTexture3D) {
|
2018-04-02 12:04:20 +02:00
|
|
|
InitReturnPtr(ppTexture3D);
|
|
|
|
|
2018-03-13 23:51:30 +01:00
|
|
|
D3D11_COMMON_TEXTURE_DESC desc;
|
|
|
|
desc.Width = pDesc->Width;
|
|
|
|
desc.Height = pDesc->Height;
|
|
|
|
desc.Depth = pDesc->Depth;
|
|
|
|
desc.MipLevels = pDesc->MipLevels;
|
|
|
|
desc.ArraySize = 1;
|
|
|
|
desc.Format = pDesc->Format;
|
|
|
|
desc.SampleDesc = DXGI_SAMPLE_DESC { 1, 0 };
|
|
|
|
desc.Usage = pDesc->Usage;
|
|
|
|
desc.BindFlags = pDesc->BindFlags;
|
|
|
|
desc.CPUAccessFlags = pDesc->CPUAccessFlags;
|
|
|
|
desc.MiscFlags = pDesc->MiscFlags;
|
|
|
|
|
|
|
|
if (FAILED(D3D11CommonTexture::NormalizeTextureProperties(&desc)))
|
|
|
|
return E_INVALIDARG;
|
|
|
|
|
2018-02-27 08:54:24 +01:00
|
|
|
if (ppTexture3D == nullptr)
|
|
|
|
return S_FALSE;
|
|
|
|
|
|
|
|
try {
|
2018-03-14 00:45:07 +01:00
|
|
|
const Com<D3D11Texture3D> texture = new D3D11Texture3D(this, &desc);
|
2018-07-23 15:21:17 +02:00
|
|
|
m_initializer->InitTexture(texture->GetCommonTexture(), pInitialData);
|
2017-12-23 17:05:07 +01:00
|
|
|
*ppTexture3D = texture.ref();
|
2018-02-27 08:54:24 +01:00
|
|
|
return S_OK;
|
|
|
|
} catch (const DxvkError& e) {
|
|
|
|
Logger::err(e.message());
|
|
|
|
return E_FAIL;
|
2017-12-23 17:05:07 +01:00
|
|
|
}
|
2017-10-11 09:51:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-12-12 12:50:52 +01:00
|
|
|
HRESULT STDMETHODCALLTYPE D3D11Device::CreateShaderResourceView(
|
2017-10-11 09:51:48 +02:00
|
|
|
ID3D11Resource* pResource,
|
|
|
|
const D3D11_SHADER_RESOURCE_VIEW_DESC* pDesc,
|
|
|
|
ID3D11ShaderResourceView** ppSRView) {
|
2018-04-02 12:04:20 +02:00
|
|
|
InitReturnPtr(ppSRView);
|
2018-08-10 02:15:51 +02:00
|
|
|
|
2018-09-19 11:55:11 +02:00
|
|
|
if (pResource == nullptr)
|
|
|
|
return E_INVALIDARG;
|
|
|
|
|
2018-08-10 02:15:51 +02:00
|
|
|
D3D11_COMMON_RESOURCE_DESC resourceDesc;
|
|
|
|
GetCommonResourceDesc(pResource, &resourceDesc);
|
2018-04-02 12:04:20 +02:00
|
|
|
|
2017-12-09 19:36:38 +01:00
|
|
|
// The description is optional. If omitted, we'll create
|
|
|
|
// a view that covers all subresources of the image.
|
2017-12-09 19:06:51 +01:00
|
|
|
D3D11_SHADER_RESOURCE_VIEW_DESC desc;
|
2017-12-09 15:57:05 +01:00
|
|
|
|
2017-12-09 19:06:51 +01:00
|
|
|
if (pDesc == nullptr) {
|
2018-03-17 13:42:37 +01:00
|
|
|
if (FAILED(D3D11ShaderResourceView::GetDescFromResource(pResource, &desc)))
|
2017-12-09 19:06:51 +01:00
|
|
|
return E_INVALIDARG;
|
|
|
|
} else {
|
|
|
|
desc = *pDesc;
|
2018-01-17 15:19:55 +01:00
|
|
|
|
2018-03-17 13:42:37 +01:00
|
|
|
if (FAILED(D3D11ShaderResourceView::NormalizeDesc(pResource, &desc)))
|
2018-01-17 15:19:55 +01:00
|
|
|
return E_INVALIDARG;
|
2017-12-09 19:06:51 +01:00
|
|
|
}
|
|
|
|
|
2018-08-10 02:15:51 +02:00
|
|
|
if (!CheckResourceViewCompatibility(pResource, D3D11_BIND_SHADER_RESOURCE, desc.Format)) {
|
|
|
|
Logger::err(str::format("D3D11: Cannot create shader resource view:",
|
|
|
|
"\n Resource type: ", resourceDesc.Dim,
|
2018-08-10 02:39:14 +02:00
|
|
|
"\n Resource usage: ", resourceDesc.BindFlags,
|
2018-08-10 02:15:51 +02:00
|
|
|
"\n Resource format: ", resourceDesc.Format,
|
|
|
|
"\n View format: ", desc.Format));
|
2018-08-05 18:56:42 +02:00
|
|
|
return E_INVALIDARG;
|
2018-08-10 02:15:51 +02:00
|
|
|
}
|
2018-08-05 18:56:42 +02:00
|
|
|
|
2018-08-05 19:20:12 +02:00
|
|
|
if (ppSRView == nullptr)
|
|
|
|
return S_FALSE;
|
|
|
|
|
|
|
|
try {
|
|
|
|
*ppSRView = ref(new D3D11ShaderResourceView(this, pResource, &desc));
|
|
|
|
return S_OK;
|
|
|
|
} catch (const DxvkError& e) {
|
|
|
|
Logger::err(e.message());
|
|
|
|
return E_FAIL;
|
2017-12-09 19:06:51 +01:00
|
|
|
}
|
2017-10-11 09:51:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-12-12 12:50:52 +01:00
|
|
|
HRESULT STDMETHODCALLTYPE D3D11Device::CreateUnorderedAccessView(
|
2017-10-11 09:51:48 +02:00
|
|
|
ID3D11Resource* pResource,
|
|
|
|
const D3D11_UNORDERED_ACCESS_VIEW_DESC* pDesc,
|
|
|
|
ID3D11UnorderedAccessView** ppUAView) {
|
2018-04-02 12:04:20 +02:00
|
|
|
InitReturnPtr(ppUAView);
|
|
|
|
|
2018-09-19 11:55:11 +02:00
|
|
|
if (pResource == nullptr)
|
|
|
|
return E_INVALIDARG;
|
|
|
|
|
2018-08-10 02:15:51 +02:00
|
|
|
D3D11_COMMON_RESOURCE_DESC resourceDesc;
|
|
|
|
GetCommonResourceDesc(pResource, &resourceDesc);
|
|
|
|
|
2017-12-28 19:05:53 +01:00
|
|
|
// The description is optional. If omitted, we'll create
|
|
|
|
// a view that covers all subresources of the image.
|
|
|
|
D3D11_UNORDERED_ACCESS_VIEW_DESC desc;
|
|
|
|
|
|
|
|
if (pDesc == nullptr) {
|
2018-03-17 13:42:37 +01:00
|
|
|
if (FAILED(D3D11UnorderedAccessView::GetDescFromResource(pResource, &desc)))
|
2017-12-28 19:05:53 +01:00
|
|
|
return E_INVALIDARG;
|
|
|
|
} else {
|
|
|
|
desc = *pDesc;
|
2018-01-28 11:30:15 +01:00
|
|
|
|
2018-03-17 13:42:37 +01:00
|
|
|
if (FAILED(D3D11UnorderedAccessView::NormalizeDesc(pResource, &desc)))
|
2018-01-28 11:30:15 +01:00
|
|
|
return E_INVALIDARG;
|
2017-12-28 19:05:53 +01:00
|
|
|
}
|
|
|
|
|
2018-08-10 02:15:51 +02:00
|
|
|
if (!CheckResourceViewCompatibility(pResource, D3D11_BIND_UNORDERED_ACCESS, desc.Format)) {
|
|
|
|
Logger::err(str::format("D3D11: Cannot create unordered access view:",
|
|
|
|
"\n Resource type: ", resourceDesc.Dim,
|
2018-08-10 02:39:14 +02:00
|
|
|
"\n Resource usage: ", resourceDesc.BindFlags,
|
2018-08-10 02:15:51 +02:00
|
|
|
"\n Resource format: ", resourceDesc.Format,
|
|
|
|
"\n View format: ", desc.Format));
|
2018-08-05 18:56:42 +02:00
|
|
|
return E_INVALIDARG;
|
2018-08-10 02:15:51 +02:00
|
|
|
}
|
2018-08-05 19:28:39 +02:00
|
|
|
|
|
|
|
if (ppUAView == nullptr)
|
|
|
|
return S_FALSE;
|
2018-08-05 18:56:42 +02:00
|
|
|
|
2018-08-05 19:28:39 +02:00
|
|
|
try {
|
|
|
|
*ppUAView = ref(new D3D11UnorderedAccessView(this, pResource, &desc));
|
|
|
|
return S_OK;
|
|
|
|
} catch (const DxvkError& e) {
|
|
|
|
Logger::err(e.message());
|
|
|
|
return E_FAIL;
|
2017-12-28 19:05:53 +01:00
|
|
|
}
|
2017-10-11 09:51:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-12-12 12:50:52 +01:00
|
|
|
HRESULT STDMETHODCALLTYPE D3D11Device::CreateRenderTargetView(
|
2017-10-11 09:51:48 +02:00
|
|
|
ID3D11Resource* pResource,
|
|
|
|
const D3D11_RENDER_TARGET_VIEW_DESC* pDesc,
|
|
|
|
ID3D11RenderTargetView** ppRTView) {
|
2018-04-02 12:04:20 +02:00
|
|
|
InitReturnPtr(ppRTView);
|
2018-09-19 11:55:11 +02:00
|
|
|
|
|
|
|
if (pResource == nullptr)
|
|
|
|
return E_INVALIDARG;
|
2018-04-02 12:04:20 +02:00
|
|
|
|
2018-03-18 21:38:48 +01:00
|
|
|
// DXVK only supports render target views for image resources
|
2018-09-19 11:55:11 +02:00
|
|
|
D3D11_COMMON_RESOURCE_DESC resourceDesc;
|
|
|
|
GetCommonResourceDesc(pResource, &resourceDesc);
|
2017-11-29 15:16:07 +01:00
|
|
|
|
2018-09-19 11:55:11 +02:00
|
|
|
if (resourceDesc.Dim == D3D11_RESOURCE_DIMENSION_BUFFER) {
|
2018-03-31 21:47:54 +02:00
|
|
|
Logger::warn("D3D11: Cannot create render target view for a buffer");
|
|
|
|
return S_OK; // It is required to run Battlefield 3 and Battlefield 4.
|
2018-03-18 21:38:48 +01:00
|
|
|
}
|
|
|
|
|
2017-11-29 20:19:40 +01:00
|
|
|
// The view description is optional. If not defined, it
|
2017-12-08 23:25:38 +01:00
|
|
|
// will use the resource's format and all array layers.
|
2017-11-29 20:19:40 +01:00
|
|
|
D3D11_RENDER_TARGET_VIEW_DESC desc;
|
|
|
|
|
2017-12-09 19:36:38 +01:00
|
|
|
if (pDesc == nullptr) {
|
2018-03-17 13:42:37 +01:00
|
|
|
if (FAILED(D3D11RenderTargetView::GetDescFromResource(pResource, &desc)))
|
2017-12-09 19:36:38 +01:00
|
|
|
return E_INVALIDARG;
|
2017-11-29 20:19:40 +01:00
|
|
|
} else {
|
2017-12-09 19:36:38 +01:00
|
|
|
desc = *pDesc;
|
2018-02-14 01:29:50 +01:00
|
|
|
|
2018-03-17 13:42:37 +01:00
|
|
|
if (FAILED(D3D11RenderTargetView::NormalizeDesc(pResource, &desc)))
|
2018-02-14 01:29:50 +01:00
|
|
|
return E_INVALIDARG;
|
2017-11-29 20:19:40 +01:00
|
|
|
}
|
|
|
|
|
2018-08-10 02:15:51 +02:00
|
|
|
if (!CheckResourceViewCompatibility(pResource, D3D11_BIND_RENDER_TARGET, desc.Format)) {
|
|
|
|
Logger::err(str::format("D3D11: Cannot create render target view:",
|
|
|
|
"\n Resource type: ", resourceDesc.Dim,
|
2018-08-10 02:39:14 +02:00
|
|
|
"\n Resource usage: ", resourceDesc.BindFlags,
|
2018-08-10 02:15:51 +02:00
|
|
|
"\n Resource format: ", resourceDesc.Format,
|
|
|
|
"\n View format: ", desc.Format));
|
2018-02-22 21:38:45 +01:00
|
|
|
return E_INVALIDARG;
|
2018-08-10 02:15:51 +02:00
|
|
|
}
|
2018-08-05 18:56:42 +02:00
|
|
|
|
2017-11-29 20:19:40 +01:00
|
|
|
if (ppRTView == nullptr)
|
2017-12-27 14:32:07 +01:00
|
|
|
return S_FALSE;
|
2017-11-29 15:16:07 +01:00
|
|
|
|
2017-11-29 20:19:40 +01:00
|
|
|
try {
|
2018-08-05 19:07:53 +02:00
|
|
|
*ppRTView = ref(new D3D11RenderTargetView(this, pResource, &desc));
|
2017-11-29 20:19:40 +01:00
|
|
|
return S_OK;
|
|
|
|
} catch (const DxvkError& e) {
|
|
|
|
Logger::err(e.message());
|
2017-12-27 14:32:07 +01:00
|
|
|
return E_FAIL;
|
2017-11-29 20:19:40 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-12-12 12:50:52 +01:00
|
|
|
HRESULT STDMETHODCALLTYPE D3D11Device::CreateDepthStencilView(
|
2017-11-29 20:19:40 +01:00
|
|
|
ID3D11Resource* pResource,
|
|
|
|
const D3D11_DEPTH_STENCIL_VIEW_DESC* pDesc,
|
|
|
|
ID3D11DepthStencilView** ppDepthStencilView) {
|
2018-04-02 12:04:20 +02:00
|
|
|
InitReturnPtr(ppDepthStencilView);
|
|
|
|
|
2018-09-19 11:55:11 +02:00
|
|
|
if (pResource == nullptr)
|
|
|
|
return E_INVALIDARG;
|
|
|
|
|
2018-08-10 02:15:51 +02:00
|
|
|
D3D11_COMMON_RESOURCE_DESC resourceDesc;
|
|
|
|
GetCommonResourceDesc(pResource, &resourceDesc);
|
|
|
|
|
2017-12-08 23:25:38 +01:00
|
|
|
// The view description is optional. If not defined, it
|
|
|
|
// will use the resource's format and all array layers.
|
|
|
|
D3D11_DEPTH_STENCIL_VIEW_DESC desc;
|
|
|
|
|
2017-12-09 19:36:38 +01:00
|
|
|
if (pDesc == nullptr) {
|
2018-03-17 13:42:37 +01:00
|
|
|
if (FAILED(D3D11DepthStencilView::GetDescFromResource(pResource, &desc)))
|
2017-12-09 19:36:38 +01:00
|
|
|
return E_INVALIDARG;
|
2017-12-08 23:25:38 +01:00
|
|
|
} else {
|
2017-12-09 19:36:38 +01:00
|
|
|
desc = *pDesc;
|
2018-02-14 01:29:50 +01:00
|
|
|
|
2018-03-17 13:42:37 +01:00
|
|
|
if (FAILED(D3D11DepthStencilView::NormalizeDesc(pResource, &desc)))
|
2018-02-14 01:29:50 +01:00
|
|
|
return E_INVALIDARG;
|
2017-12-08 23:25:38 +01:00
|
|
|
}
|
|
|
|
|
2018-08-10 02:15:51 +02:00
|
|
|
if (!CheckResourceViewCompatibility(pResource, D3D11_BIND_DEPTH_STENCIL, desc.Format)) {
|
|
|
|
Logger::err(str::format("D3D11: Cannot create depth-stencil view:",
|
|
|
|
"\n Resource type: ", resourceDesc.Dim,
|
2018-08-10 02:39:14 +02:00
|
|
|
"\n Resource usage: ", resourceDesc.BindFlags,
|
2018-08-10 02:15:51 +02:00
|
|
|
"\n Resource format: ", resourceDesc.Format,
|
|
|
|
"\n View format: ", desc.Format));
|
2018-02-22 21:38:45 +01:00
|
|
|
return E_INVALIDARG;
|
2018-08-10 02:15:51 +02:00
|
|
|
}
|
2018-05-05 15:13:35 +02:00
|
|
|
|
2017-12-08 23:25:38 +01:00
|
|
|
if (ppDepthStencilView == nullptr)
|
2017-12-27 14:32:07 +01:00
|
|
|
return S_FALSE;
|
2017-12-08 23:25:38 +01:00
|
|
|
|
|
|
|
try {
|
2018-08-05 19:02:45 +02:00
|
|
|
*ppDepthStencilView = ref(new D3D11DepthStencilView(this, pResource, &desc));
|
2017-12-08 23:25:38 +01:00
|
|
|
return S_OK;
|
|
|
|
} catch (const DxvkError& e) {
|
|
|
|
Logger::err(e.message());
|
2017-12-27 14:32:07 +01:00
|
|
|
return E_FAIL;
|
2017-12-08 23:25:38 +01:00
|
|
|
}
|
2017-10-11 09:51:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-12-12 12:50:52 +01:00
|
|
|
HRESULT STDMETHODCALLTYPE D3D11Device::CreateInputLayout(
|
2017-10-11 09:51:48 +02:00
|
|
|
const D3D11_INPUT_ELEMENT_DESC* pInputElementDescs,
|
|
|
|
UINT NumElements,
|
|
|
|
const void* pShaderBytecodeWithInputSignature,
|
|
|
|
SIZE_T BytecodeLength,
|
|
|
|
ID3D11InputLayout** ppInputLayout) {
|
2018-04-02 12:04:20 +02:00
|
|
|
InitReturnPtr(ppInputLayout);
|
|
|
|
|
2017-12-07 12:45:02 +01:00
|
|
|
try {
|
|
|
|
DxbcReader dxbcReader(reinterpret_cast<const char*>(
|
|
|
|
pShaderBytecodeWithInputSignature), BytecodeLength);
|
|
|
|
DxbcModule dxbcModule(dxbcReader);
|
|
|
|
|
2018-01-08 20:23:21 +01:00
|
|
|
const Rc<DxbcIsgn> inputSignature = dxbcModule.isgn();
|
2018-05-30 13:33:48 +02:00
|
|
|
|
|
|
|
uint32_t attrMask = 0;
|
|
|
|
uint32_t bindMask = 0;
|
2017-12-07 12:45:02 +01:00
|
|
|
|
2018-05-30 13:33:48 +02:00
|
|
|
std::array<DxvkVertexAttribute, D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT> attrList;
|
|
|
|
std::array<DxvkVertexBinding, D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT> bindList;
|
2017-12-07 12:45:02 +01:00
|
|
|
|
|
|
|
for (uint32_t i = 0; i < NumElements; i++) {
|
|
|
|
const DxbcSgnEntry* entry = inputSignature->find(
|
|
|
|
pInputElementDescs[i].SemanticName,
|
2018-06-23 20:13:00 +02:00
|
|
|
pInputElementDescs[i].SemanticIndex, 0);
|
2017-12-07 12:45:02 +01:00
|
|
|
|
|
|
|
if (entry == nullptr) {
|
2018-01-19 01:25:19 +01:00
|
|
|
Logger::debug(str::format(
|
2018-01-02 12:07:30 +01:00
|
|
|
"D3D11Device: No such vertex shader semantic: ",
|
2017-12-07 12:45:02 +01:00
|
|
|
pInputElementDescs[i].SemanticName,
|
|
|
|
pInputElementDescs[i].SemanticIndex));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create vertex input attribute description
|
2017-12-08 00:44:58 +01:00
|
|
|
DxvkVertexAttribute attrib;
|
2018-05-30 13:33:48 +02:00
|
|
|
attrib.location = entry != nullptr ? entry->registerId : 0;
|
2017-12-07 12:45:02 +01:00
|
|
|
attrib.binding = pInputElementDescs[i].InputSlot;
|
2018-11-28 18:34:05 +01:00
|
|
|
attrib.format = LookupFormat(pInputElementDescs[i].Format, DXGI_VK_FORMAT_MODE_COLOR).Format;
|
2017-12-07 12:45:02 +01:00
|
|
|
attrib.offset = pInputElementDescs[i].AlignedByteOffset;
|
|
|
|
|
2017-12-18 23:24:10 +01:00
|
|
|
// The application may choose to let the implementation
|
|
|
|
// generate the exact vertex layout. In that case we'll
|
|
|
|
// pack attributes on the same binding in the order they
|
|
|
|
// are declared, aligning each attribute to four bytes.
|
2017-12-07 12:45:02 +01:00
|
|
|
if (attrib.offset == D3D11_APPEND_ALIGNED_ELEMENT) {
|
2017-12-18 23:24:10 +01:00
|
|
|
attrib.offset = 0;
|
|
|
|
|
|
|
|
for (uint32_t j = 1; j <= i; j++) {
|
2018-05-30 13:33:48 +02:00
|
|
|
const DxvkVertexAttribute& prev = attrList.at(i - j);
|
2017-12-18 23:24:10 +01:00
|
|
|
|
|
|
|
if (prev.binding == attrib.binding) {
|
|
|
|
const DxvkFormatInfo* formatInfo = imageFormatInfo(prev.format);
|
|
|
|
attrib.offset = align(prev.offset + formatInfo->elementSize, 4);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2017-12-07 12:45:02 +01:00
|
|
|
}
|
2018-05-30 13:33:48 +02:00
|
|
|
|
|
|
|
attrList.at(i) = attrib;
|
2017-12-07 12:45:02 +01:00
|
|
|
|
2017-12-07 19:28:54 +01:00
|
|
|
// Create vertex input binding description. The
|
|
|
|
// stride is dynamic state in D3D11 and will be
|
2018-01-08 20:23:21 +01:00
|
|
|
// set by D3D11DeviceContext::IASetVertexBuffers.
|
2017-12-08 00:44:58 +01:00
|
|
|
DxvkVertexBinding binding;
|
2017-12-07 12:45:02 +01:00
|
|
|
binding.binding = pInputElementDescs[i].InputSlot;
|
2018-02-01 20:15:25 +01:00
|
|
|
binding.fetchRate = pInputElementDescs[i].InstanceDataStepRate;
|
|
|
|
binding.inputRate = pInputElementDescs[i].InputSlotClass == D3D11_INPUT_PER_INSTANCE_DATA
|
2018-05-30 13:33:48 +02:00
|
|
|
? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX;
|
2017-12-07 12:45:02 +01:00
|
|
|
|
|
|
|
// Check if the binding was already defined. If so, the
|
|
|
|
// parameters must be identical (namely, the input rate).
|
|
|
|
bool bindingDefined = false;
|
|
|
|
|
2018-05-30 13:33:48 +02:00
|
|
|
for (uint32_t j = 0; j < i; j++) {
|
|
|
|
uint32_t bindingId = attrList.at(j).binding;
|
|
|
|
|
|
|
|
if (binding.binding == bindingId) {
|
2017-12-07 12:45:02 +01:00
|
|
|
bindingDefined = true;
|
|
|
|
|
2018-05-30 13:33:48 +02:00
|
|
|
if (binding.inputRate != bindList.at(bindingId).inputRate) {
|
2017-12-07 12:45:02 +01:00
|
|
|
Logger::err(str::format(
|
2018-01-08 20:23:21 +01:00
|
|
|
"D3D11Device: Conflicting input rate for binding ",
|
2017-12-07 12:45:02 +01:00
|
|
|
binding.binding));
|
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-05-30 13:33:48 +02:00
|
|
|
|
2017-12-07 12:45:02 +01:00
|
|
|
if (!bindingDefined)
|
2018-05-30 13:33:48 +02:00
|
|
|
bindList.at(binding.binding) = binding;
|
|
|
|
|
|
|
|
if (entry != nullptr) {
|
|
|
|
attrMask |= 1u << i;
|
|
|
|
bindMask |= 1u << binding.binding;
|
|
|
|
}
|
2017-12-07 12:45:02 +01:00
|
|
|
}
|
2018-05-30 13:33:48 +02:00
|
|
|
|
|
|
|
// Compact the attribute and binding lists to filter
|
|
|
|
// out attributes and bindings not used by the shader
|
|
|
|
uint32_t attrCount = CompactSparseList(attrList.data(), attrMask);
|
|
|
|
uint32_t bindCount = CompactSparseList(bindList.data(), bindMask);
|
|
|
|
|
2018-01-08 20:23:21 +01:00
|
|
|
// Check if there are any semantics defined in the
|
|
|
|
// shader that are not included in the current input
|
|
|
|
// layout.
|
|
|
|
for (auto i = inputSignature->begin(); i != inputSignature->end(); i++) {
|
|
|
|
bool found = i->systemValue != DxbcSystemValue::None;
|
|
|
|
|
2018-05-30 13:33:48 +02:00
|
|
|
for (uint32_t j = 0; j < attrCount && !found; j++)
|
|
|
|
found = attrList.at(j).location == i->registerId;
|
2018-01-08 20:23:21 +01:00
|
|
|
|
|
|
|
if (!found) {
|
|
|
|
Logger::warn(str::format(
|
|
|
|
"D3D11Device: Vertex input '",
|
|
|
|
i->semanticName, i->semanticIndex,
|
|
|
|
"' not defined by input layout"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-07 12:45:02 +01:00
|
|
|
// Create the actual input layout object
|
|
|
|
// if the application requests it.
|
|
|
|
if (ppInputLayout != nullptr) {
|
|
|
|
*ppInputLayout = ref(
|
|
|
|
new D3D11InputLayout(this,
|
2018-05-30 13:33:48 +02:00
|
|
|
attrCount, attrList.data(),
|
|
|
|
bindCount, bindList.data()));
|
2017-12-07 12:45:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
} catch (const DxvkError& e) {
|
|
|
|
Logger::err(e.message());
|
2017-12-27 14:32:07 +01:00
|
|
|
return E_FAIL;
|
2017-12-07 12:45:02 +01:00
|
|
|
}
|
2017-10-11 09:51:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-12-12 12:50:52 +01:00
|
|
|
HRESULT STDMETHODCALLTYPE D3D11Device::CreateVertexShader(
|
2017-10-11 09:51:48 +02:00
|
|
|
const void* pShaderBytecode,
|
|
|
|
SIZE_T BytecodeLength,
|
|
|
|
ID3D11ClassLinkage* pClassLinkage,
|
|
|
|
ID3D11VertexShader** ppVertexShader) {
|
2018-04-02 12:04:20 +02:00
|
|
|
InitReturnPtr(ppVertexShader);
|
2018-07-30 19:34:48 +02:00
|
|
|
D3D11CommonShader module;
|
2018-06-23 17:14:35 +02:00
|
|
|
|
|
|
|
DxbcModuleInfo moduleInfo;
|
|
|
|
moduleInfo.options = m_dxbcOptions;
|
2018-09-09 23:14:00 +02:00
|
|
|
moduleInfo.tess = nullptr;
|
2018-06-23 20:19:46 +02:00
|
|
|
moduleInfo.xfb = nullptr;
|
2018-10-25 11:28:02 +02:00
|
|
|
|
|
|
|
Sha1Hash hash = Sha1Hash::compute(
|
|
|
|
pShaderBytecode, BytecodeLength);
|
2017-12-06 18:54:01 +01:00
|
|
|
|
|
|
|
if (FAILED(this->CreateShaderModule(&module,
|
2018-10-25 11:28:02 +02:00
|
|
|
DxvkShaderKey(VK_SHADER_STAGE_VERTEX_BIT, hash),
|
2018-04-06 17:54:02 +02:00
|
|
|
pShaderBytecode, BytecodeLength, pClassLinkage,
|
2018-10-25 11:28:02 +02:00
|
|
|
&moduleInfo)))
|
2017-12-06 18:54:01 +01:00
|
|
|
return E_INVALIDARG;
|
|
|
|
|
2018-02-26 17:04:45 +01:00
|
|
|
if (ppVertexShader == nullptr)
|
|
|
|
return S_FALSE;
|
2017-12-06 18:54:01 +01:00
|
|
|
|
2018-06-23 17:14:35 +02:00
|
|
|
*ppVertexShader = ref(new D3D11VertexShader(this, module));
|
2017-12-06 18:54:01 +01:00
|
|
|
return S_OK;
|
2017-10-11 09:51:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-12-12 12:50:52 +01:00
|
|
|
HRESULT STDMETHODCALLTYPE D3D11Device::CreateGeometryShader(
|
2017-10-11 09:51:48 +02:00
|
|
|
const void* pShaderBytecode,
|
|
|
|
SIZE_T BytecodeLength,
|
|
|
|
ID3D11ClassLinkage* pClassLinkage,
|
|
|
|
ID3D11GeometryShader** ppGeometryShader) {
|
2018-04-02 12:04:20 +02:00
|
|
|
InitReturnPtr(ppGeometryShader);
|
2018-07-30 19:34:48 +02:00
|
|
|
D3D11CommonShader module;
|
2017-12-18 12:53:53 +01:00
|
|
|
|
2018-06-23 17:14:35 +02:00
|
|
|
DxbcModuleInfo moduleInfo;
|
|
|
|
moduleInfo.options = m_dxbcOptions;
|
2018-09-09 23:14:00 +02:00
|
|
|
moduleInfo.tess = nullptr;
|
2018-06-23 20:19:46 +02:00
|
|
|
moduleInfo.xfb = nullptr;
|
2018-06-23 17:14:35 +02:00
|
|
|
|
2018-10-25 11:28:02 +02:00
|
|
|
Sha1Hash hash = Sha1Hash::compute(
|
|
|
|
pShaderBytecode, BytecodeLength);
|
|
|
|
|
2017-12-18 12:53:53 +01:00
|
|
|
if (FAILED(this->CreateShaderModule(&module,
|
2018-10-25 11:28:02 +02:00
|
|
|
DxvkShaderKey(VK_SHADER_STAGE_GEOMETRY_BIT, hash),
|
2018-04-06 17:54:02 +02:00
|
|
|
pShaderBytecode, BytecodeLength, pClassLinkage,
|
2018-10-25 11:28:02 +02:00
|
|
|
&moduleInfo)))
|
2017-12-18 12:53:53 +01:00
|
|
|
return E_INVALIDARG;
|
|
|
|
|
2018-02-26 17:04:45 +01:00
|
|
|
if (ppGeometryShader == nullptr)
|
|
|
|
return S_FALSE;
|
2017-12-18 12:53:53 +01:00
|
|
|
|
2018-06-23 17:14:35 +02:00
|
|
|
*ppGeometryShader = ref(new D3D11GeometryShader(this, module));
|
2017-12-18 12:53:53 +01:00
|
|
|
return S_OK;
|
2017-10-11 09:51:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-12-12 12:50:52 +01:00
|
|
|
HRESULT STDMETHODCALLTYPE D3D11Device::CreateGeometryShaderWithStreamOutput(
|
2017-10-11 09:51:48 +02:00
|
|
|
const void* pShaderBytecode,
|
|
|
|
SIZE_T BytecodeLength,
|
|
|
|
const D3D11_SO_DECLARATION_ENTRY* pSODeclaration,
|
|
|
|
UINT NumEntries,
|
|
|
|
const UINT* pBufferStrides,
|
|
|
|
UINT NumStrides,
|
|
|
|
UINT RasterizedStream,
|
|
|
|
ID3D11ClassLinkage* pClassLinkage,
|
|
|
|
ID3D11GeometryShader** ppGeometryShader) {
|
2018-04-02 12:04:20 +02:00
|
|
|
InitReturnPtr(ppGeometryShader);
|
2018-07-24 16:20:38 +02:00
|
|
|
D3D11CommonShader module;
|
|
|
|
|
|
|
|
if (!m_dxvkDevice->features().extTransformFeedback.transformFeedback) {
|
|
|
|
Logger::err(
|
|
|
|
"D3D11: CreateGeometryShaderWithStreamOutput:"
|
|
|
|
"\n Transform feedback not supoorted by device");
|
|
|
|
return m_d3d11Options.fakeStreamOutSupport ? S_OK : E_NOTIMPL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Zero-init some counterss so that we can increment
|
|
|
|
// them while walking over the stream output entries
|
2018-10-25 11:28:02 +02:00
|
|
|
DxbcXfbInfo xfb = { };
|
2018-07-24 16:20:38 +02:00
|
|
|
|
|
|
|
for (uint32_t i = 0; i < NumEntries; i++) {
|
|
|
|
const D3D11_SO_DECLARATION_ENTRY* so = &pSODeclaration[i];
|
|
|
|
|
|
|
|
if (so->OutputSlot >= D3D11_SO_BUFFER_SLOT_COUNT)
|
|
|
|
return E_INVALIDARG;
|
|
|
|
|
|
|
|
if (so->SemanticName != nullptr) {
|
|
|
|
if (so->Stream >= D3D11_SO_BUFFER_SLOT_COUNT
|
|
|
|
|| so->StartComponent >= 4
|
|
|
|
|| so->ComponentCount < 1
|
|
|
|
|| so->ComponentCount > 4)
|
|
|
|
return E_INVALIDARG;
|
|
|
|
|
|
|
|
DxbcXfbEntry* entry = &xfb.entries[xfb.entryCount++];
|
|
|
|
entry->semanticName = so->SemanticName;
|
|
|
|
entry->semanticIndex = so->SemanticIndex;
|
|
|
|
entry->componentIndex = so->StartComponent;
|
|
|
|
entry->componentCount = so->ComponentCount;
|
|
|
|
entry->streamId = so->Stream;
|
|
|
|
entry->bufferId = so->OutputSlot;
|
|
|
|
entry->offset = xfb.strides[so->OutputSlot];
|
|
|
|
}
|
|
|
|
|
|
|
|
xfb.strides[so->OutputSlot] += so->ComponentCount * sizeof(uint32_t);
|
|
|
|
}
|
|
|
|
|
|
|
|
// If necessary, override the buffer strides
|
|
|
|
for (uint32_t i = 0; i < NumStrides; i++)
|
|
|
|
xfb.strides[i] = pBufferStrides[i];
|
|
|
|
|
|
|
|
// Set stream to rasterize, if any
|
|
|
|
xfb.rasterizedStream = -1;
|
2018-05-25 23:53:34 +02:00
|
|
|
|
2018-07-24 16:20:38 +02:00
|
|
|
if (RasterizedStream != D3D11_SO_NO_RASTERIZED_STREAM)
|
|
|
|
Logger::err("D3D11: CreateGeometryShaderWithStreamOutput: Rasterized stream not supported");
|
2018-10-25 11:28:02 +02:00
|
|
|
|
|
|
|
// Compute hash from both the xfb info and the source
|
|
|
|
// code, because both influence the generated code
|
|
|
|
std::array<Sha1Data, 2> chunks = {{
|
|
|
|
{ pShaderBytecode, BytecodeLength },
|
|
|
|
{ &xfb, sizeof(xfb) },
|
|
|
|
}};
|
2018-07-24 16:20:38 +02:00
|
|
|
|
2018-10-25 11:28:02 +02:00
|
|
|
Sha1Hash hash = Sha1Hash::compute(chunks.size(), chunks.data());
|
|
|
|
|
2018-07-24 16:20:38 +02:00
|
|
|
// Create the actual shader module
|
|
|
|
DxbcModuleInfo moduleInfo;
|
|
|
|
moduleInfo.options = m_dxbcOptions;
|
|
|
|
moduleInfo.tess = nullptr;
|
|
|
|
moduleInfo.xfb = &xfb;
|
|
|
|
|
|
|
|
if (FAILED(this->CreateShaderModule(&module,
|
2018-10-25 11:28:02 +02:00
|
|
|
DxvkShaderKey(VK_SHADER_STAGE_GEOMETRY_BIT, hash),
|
2018-07-24 16:20:38 +02:00
|
|
|
pShaderBytecode, BytecodeLength, pClassLinkage,
|
2018-10-25 11:28:02 +02:00
|
|
|
&moduleInfo)))
|
2018-07-24 16:20:38 +02:00
|
|
|
return E_INVALIDARG;
|
|
|
|
|
|
|
|
if (ppGeometryShader == nullptr)
|
|
|
|
return S_FALSE;
|
|
|
|
|
|
|
|
*ppGeometryShader = ref(new D3D11GeometryShader(this, module));
|
|
|
|
return S_OK;
|
2017-10-11 09:51:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-12-12 12:50:52 +01:00
|
|
|
HRESULT STDMETHODCALLTYPE D3D11Device::CreatePixelShader(
|
2017-10-11 09:51:48 +02:00
|
|
|
const void* pShaderBytecode,
|
|
|
|
SIZE_T BytecodeLength,
|
|
|
|
ID3D11ClassLinkage* pClassLinkage,
|
|
|
|
ID3D11PixelShader** ppPixelShader) {
|
2018-04-02 12:04:20 +02:00
|
|
|
InitReturnPtr(ppPixelShader);
|
2018-07-30 19:34:48 +02:00
|
|
|
D3D11CommonShader module;
|
2017-12-06 18:54:01 +01:00
|
|
|
|
2018-06-23 17:14:35 +02:00
|
|
|
DxbcModuleInfo moduleInfo;
|
|
|
|
moduleInfo.options = m_dxbcOptions;
|
2018-09-09 23:14:00 +02:00
|
|
|
moduleInfo.tess = nullptr;
|
2018-06-23 20:19:46 +02:00
|
|
|
moduleInfo.xfb = nullptr;
|
2018-06-23 17:14:35 +02:00
|
|
|
|
2018-10-25 11:28:02 +02:00
|
|
|
Sha1Hash hash = Sha1Hash::compute(
|
|
|
|
pShaderBytecode, BytecodeLength);
|
|
|
|
|
2017-12-06 18:54:01 +01:00
|
|
|
if (FAILED(this->CreateShaderModule(&module,
|
2018-10-25 11:28:02 +02:00
|
|
|
DxvkShaderKey(VK_SHADER_STAGE_FRAGMENT_BIT, hash),
|
2018-04-06 17:54:02 +02:00
|
|
|
pShaderBytecode, BytecodeLength, pClassLinkage,
|
2018-10-25 11:28:02 +02:00
|
|
|
&moduleInfo)))
|
2017-12-06 18:54:01 +01:00
|
|
|
return E_INVALIDARG;
|
|
|
|
|
2018-02-26 17:04:45 +01:00
|
|
|
if (ppPixelShader == nullptr)
|
|
|
|
return S_FALSE;
|
2017-12-06 18:54:01 +01:00
|
|
|
|
2018-06-23 17:14:35 +02:00
|
|
|
*ppPixelShader = ref(new D3D11PixelShader(this, module));
|
2017-12-06 18:54:01 +01:00
|
|
|
return S_OK;
|
2017-10-11 09:51:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-12-12 12:50:52 +01:00
|
|
|
HRESULT STDMETHODCALLTYPE D3D11Device::CreateHullShader(
|
2017-10-11 09:51:48 +02:00
|
|
|
const void* pShaderBytecode,
|
|
|
|
SIZE_T BytecodeLength,
|
|
|
|
ID3D11ClassLinkage* pClassLinkage,
|
|
|
|
ID3D11HullShader** ppHullShader) {
|
2018-04-02 12:04:20 +02:00
|
|
|
InitReturnPtr(ppHullShader);
|
2018-07-30 19:34:48 +02:00
|
|
|
D3D11CommonShader module;
|
2018-01-29 11:53:57 +01:00
|
|
|
|
2018-09-09 23:14:00 +02:00
|
|
|
DxbcTessInfo tessInfo;
|
|
|
|
tessInfo.maxTessFactor = float(m_d3d11Options.maxTessFactor);
|
|
|
|
|
2018-06-23 17:14:35 +02:00
|
|
|
DxbcModuleInfo moduleInfo;
|
|
|
|
moduleInfo.options = m_dxbcOptions;
|
2018-09-09 23:14:00 +02:00
|
|
|
moduleInfo.tess = nullptr;
|
2018-06-23 20:19:46 +02:00
|
|
|
moduleInfo.xfb = nullptr;
|
2018-09-09 23:14:00 +02:00
|
|
|
|
|
|
|
if (tessInfo.maxTessFactor >= 8.0f)
|
|
|
|
moduleInfo.tess = &tessInfo;
|
2018-06-23 17:14:35 +02:00
|
|
|
|
2018-10-25 11:28:02 +02:00
|
|
|
Sha1Hash hash = Sha1Hash::compute(
|
|
|
|
pShaderBytecode, BytecodeLength);
|
|
|
|
|
2018-03-06 17:02:47 +01:00
|
|
|
if (FAILED(this->CreateShaderModule(&module,
|
2018-10-25 11:28:02 +02:00
|
|
|
DxvkShaderKey(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, hash),
|
|
|
|
pShaderBytecode, BytecodeLength, pClassLinkage, &moduleInfo)))
|
2018-03-06 17:02:47 +01:00
|
|
|
return E_INVALIDARG;
|
2018-01-29 11:53:57 +01:00
|
|
|
|
2018-02-26 17:04:45 +01:00
|
|
|
if (ppHullShader == nullptr)
|
|
|
|
return S_FALSE;
|
2018-01-29 11:53:57 +01:00
|
|
|
|
2018-06-23 17:14:35 +02:00
|
|
|
*ppHullShader = ref(new D3D11HullShader(this, module));
|
2018-01-29 11:53:57 +01:00
|
|
|
return S_OK;
|
2017-10-11 09:51:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-12-12 12:50:52 +01:00
|
|
|
HRESULT STDMETHODCALLTYPE D3D11Device::CreateDomainShader(
|
2017-10-11 09:51:48 +02:00
|
|
|
const void* pShaderBytecode,
|
|
|
|
SIZE_T BytecodeLength,
|
|
|
|
ID3D11ClassLinkage* pClassLinkage,
|
|
|
|
ID3D11DomainShader** ppDomainShader) {
|
2018-04-02 12:04:20 +02:00
|
|
|
InitReturnPtr(ppDomainShader);
|
2018-07-30 19:34:48 +02:00
|
|
|
D3D11CommonShader module;
|
2018-02-26 17:04:45 +01:00
|
|
|
|
2018-06-23 17:14:35 +02:00
|
|
|
DxbcModuleInfo moduleInfo;
|
|
|
|
moduleInfo.options = m_dxbcOptions;
|
2018-09-09 23:14:00 +02:00
|
|
|
moduleInfo.tess = nullptr;
|
2018-06-23 20:19:46 +02:00
|
|
|
moduleInfo.xfb = nullptr;
|
2018-06-23 17:14:35 +02:00
|
|
|
|
2018-10-25 11:28:02 +02:00
|
|
|
Sha1Hash hash = Sha1Hash::compute(
|
|
|
|
pShaderBytecode, BytecodeLength);
|
|
|
|
|
2018-03-06 17:02:47 +01:00
|
|
|
if (FAILED(this->CreateShaderModule(&module,
|
2018-10-25 11:28:02 +02:00
|
|
|
DxvkShaderKey(VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, hash),
|
|
|
|
pShaderBytecode, BytecodeLength, pClassLinkage, &moduleInfo)))
|
2018-03-06 17:02:47 +01:00
|
|
|
return E_INVALIDARG;
|
2018-01-29 11:53:57 +01:00
|
|
|
|
2018-02-26 17:04:45 +01:00
|
|
|
if (ppDomainShader == nullptr)
|
|
|
|
return S_FALSE;
|
2018-01-29 11:53:57 +01:00
|
|
|
|
2018-06-23 17:14:35 +02:00
|
|
|
*ppDomainShader = ref(new D3D11DomainShader(this, module));
|
2018-01-29 11:53:57 +01:00
|
|
|
return S_OK;
|
2017-10-11 09:51:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-12-12 12:50:52 +01:00
|
|
|
HRESULT STDMETHODCALLTYPE D3D11Device::CreateComputeShader(
|
2017-10-11 09:51:48 +02:00
|
|
|
const void* pShaderBytecode,
|
|
|
|
SIZE_T BytecodeLength,
|
|
|
|
ID3D11ClassLinkage* pClassLinkage,
|
|
|
|
ID3D11ComputeShader** ppComputeShader) {
|
2018-04-02 12:04:20 +02:00
|
|
|
InitReturnPtr(ppComputeShader);
|
2018-07-30 19:34:48 +02:00
|
|
|
D3D11CommonShader module;
|
2017-12-21 17:27:40 +01:00
|
|
|
|
2018-06-23 17:14:35 +02:00
|
|
|
DxbcModuleInfo moduleInfo;
|
|
|
|
moduleInfo.options = m_dxbcOptions;
|
2018-09-09 23:14:00 +02:00
|
|
|
moduleInfo.tess = nullptr;
|
2018-06-23 20:19:46 +02:00
|
|
|
moduleInfo.xfb = nullptr;
|
2018-06-23 17:14:35 +02:00
|
|
|
|
2018-10-25 11:28:02 +02:00
|
|
|
Sha1Hash hash = Sha1Hash::compute(
|
|
|
|
pShaderBytecode, BytecodeLength);
|
|
|
|
|
2017-12-21 17:27:40 +01:00
|
|
|
if (FAILED(this->CreateShaderModule(&module,
|
2018-10-25 11:28:02 +02:00
|
|
|
DxvkShaderKey(VK_SHADER_STAGE_COMPUTE_BIT, hash),
|
2018-04-06 17:54:02 +02:00
|
|
|
pShaderBytecode, BytecodeLength, pClassLinkage,
|
2018-10-25 11:28:02 +02:00
|
|
|
&moduleInfo)))
|
2017-12-21 17:27:40 +01:00
|
|
|
return E_INVALIDARG;
|
|
|
|
|
2018-02-26 17:04:45 +01:00
|
|
|
if (ppComputeShader == nullptr)
|
|
|
|
return S_FALSE;
|
2017-12-21 17:27:40 +01:00
|
|
|
|
2018-06-23 17:14:35 +02:00
|
|
|
*ppComputeShader = ref(new D3D11ComputeShader(this, module));
|
2017-12-21 17:27:40 +01:00
|
|
|
return S_OK;
|
2017-10-11 09:51:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-12-12 12:50:52 +01:00
|
|
|
HRESULT STDMETHODCALLTYPE D3D11Device::CreateClassLinkage(ID3D11ClassLinkage** ppLinkage) {
|
2017-12-12 01:07:07 +01:00
|
|
|
*ppLinkage = ref(new D3D11ClassLinkage(this));
|
|
|
|
return S_OK;
|
2017-10-11 09:51:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-12-12 12:50:52 +01:00
|
|
|
HRESULT STDMETHODCALLTYPE D3D11Device::CreateBlendState(
|
2017-10-11 09:51:48 +02:00
|
|
|
const D3D11_BLEND_DESC* pBlendStateDesc,
|
|
|
|
ID3D11BlendState** ppBlendState) {
|
2018-04-02 12:04:20 +02:00
|
|
|
InitReturnPtr(ppBlendState);
|
|
|
|
|
2018-03-18 23:27:29 +01:00
|
|
|
D3D11_BLEND_DESC1 desc = pBlendStateDesc != nullptr
|
|
|
|
? D3D11BlendState::PromoteDesc(pBlendStateDesc)
|
|
|
|
: D3D11BlendState::DefaultDesc();
|
2017-12-11 13:03:07 +01:00
|
|
|
|
2018-03-18 23:27:29 +01:00
|
|
|
if (FAILED(D3D11BlendState::NormalizeDesc(&desc)))
|
|
|
|
return E_INVALIDARG;
|
2017-12-11 13:03:07 +01:00
|
|
|
|
2017-12-27 14:32:07 +01:00
|
|
|
if (ppBlendState != nullptr) {
|
2017-12-11 13:03:07 +01:00
|
|
|
*ppBlendState = m_bsStateObjects.Create(this, desc);
|
2017-12-27 14:32:07 +01:00
|
|
|
return S_OK;
|
|
|
|
} return S_FALSE;
|
2017-10-11 09:51:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-03-17 20:11:00 +01:00
|
|
|
HRESULT STDMETHODCALLTYPE D3D11Device::CreateBlendState1(
|
|
|
|
const D3D11_BLEND_DESC1* pBlendStateDesc,
|
|
|
|
ID3D11BlendState1** ppBlendState) {
|
2018-04-02 12:04:20 +02:00
|
|
|
InitReturnPtr(ppBlendState);
|
|
|
|
|
2018-03-18 23:27:29 +01:00
|
|
|
D3D11_BLEND_DESC1 desc = pBlendStateDesc != nullptr
|
|
|
|
? *pBlendStateDesc
|
|
|
|
: D3D11BlendState::DefaultDesc();
|
|
|
|
|
|
|
|
if (FAILED(D3D11BlendState::NormalizeDesc(&desc)))
|
|
|
|
return E_INVALIDARG;
|
|
|
|
|
|
|
|
if (ppBlendState != nullptr) {
|
|
|
|
*ppBlendState = m_bsStateObjects.Create(this, desc);
|
|
|
|
return S_OK;
|
|
|
|
} return S_FALSE;
|
2018-03-17 20:11:00 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-12-12 12:50:52 +01:00
|
|
|
HRESULT STDMETHODCALLTYPE D3D11Device::CreateDepthStencilState(
|
2017-10-11 09:51:48 +02:00
|
|
|
const D3D11_DEPTH_STENCIL_DESC* pDepthStencilDesc,
|
|
|
|
ID3D11DepthStencilState** ppDepthStencilState) {
|
2018-04-02 12:04:20 +02:00
|
|
|
InitReturnPtr(ppDepthStencilState);
|
|
|
|
|
2018-03-18 23:32:01 +01:00
|
|
|
D3D11_DEPTH_STENCIL_DESC desc = pDepthStencilDesc != nullptr
|
|
|
|
? *pDepthStencilDesc
|
|
|
|
: D3D11DepthStencilState::DefaultDesc();
|
2017-12-11 01:43:15 +01:00
|
|
|
|
2018-03-18 23:32:01 +01:00
|
|
|
if (FAILED(D3D11DepthStencilState::NormalizeDesc(&desc)))
|
|
|
|
return E_INVALIDARG;
|
2017-12-11 01:43:15 +01:00
|
|
|
|
2017-12-27 14:32:07 +01:00
|
|
|
if (ppDepthStencilState != nullptr) {
|
2017-12-11 01:43:15 +01:00
|
|
|
*ppDepthStencilState = m_dsStateObjects.Create(this, desc);
|
2017-12-27 14:32:07 +01:00
|
|
|
return S_OK;
|
|
|
|
} return S_FALSE;
|
2017-10-11 09:51:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-12-12 12:50:52 +01:00
|
|
|
HRESULT STDMETHODCALLTYPE D3D11Device::CreateRasterizerState(
|
2017-10-11 09:51:48 +02:00
|
|
|
const D3D11_RASTERIZER_DESC* pRasterizerDesc,
|
|
|
|
ID3D11RasterizerState** ppRasterizerState) {
|
2018-04-02 12:04:20 +02:00
|
|
|
InitReturnPtr(ppRasterizerState);
|
|
|
|
|
2018-03-18 22:53:20 +01:00
|
|
|
D3D11_RASTERIZER_DESC1 desc = pRasterizerDesc != nullptr
|
|
|
|
? D3D11RasterizerState::PromoteDesc(pRasterizerDesc)
|
|
|
|
: D3D11RasterizerState::DefaultDesc();
|
2017-12-06 13:16:54 +01:00
|
|
|
|
2018-03-18 22:53:20 +01:00
|
|
|
if (FAILED(D3D11RasterizerState::NormalizeDesc(&desc)))
|
|
|
|
return E_INVALIDARG;
|
2017-12-06 13:16:54 +01:00
|
|
|
|
2017-12-27 14:32:07 +01:00
|
|
|
if (ppRasterizerState != nullptr) {
|
2017-12-06 13:16:54 +01:00
|
|
|
*ppRasterizerState = m_rsStateObjects.Create(this, desc);
|
2017-12-27 14:32:07 +01:00
|
|
|
return S_OK;
|
|
|
|
} return S_FALSE;
|
2017-10-11 09:51:48 +02:00
|
|
|
}
|
|
|
|
|
2018-03-18 22:53:20 +01:00
|
|
|
|
2018-03-17 20:11:00 +01:00
|
|
|
HRESULT D3D11Device::CreateRasterizerState1(
|
|
|
|
const D3D11_RASTERIZER_DESC1* pRasterizerDesc,
|
|
|
|
ID3D11RasterizerState1** ppRasterizerState) {
|
2018-04-02 12:04:20 +02:00
|
|
|
InitReturnPtr(ppRasterizerState);
|
|
|
|
|
2018-03-18 22:53:20 +01:00
|
|
|
D3D11_RASTERIZER_DESC1 desc = pRasterizerDesc != nullptr
|
|
|
|
? *pRasterizerDesc
|
|
|
|
: D3D11RasterizerState::DefaultDesc();
|
|
|
|
|
|
|
|
if (FAILED(D3D11RasterizerState::NormalizeDesc(&desc)))
|
|
|
|
return E_INVALIDARG;
|
|
|
|
|
|
|
|
if (ppRasterizerState != nullptr) {
|
|
|
|
*ppRasterizerState = m_rsStateObjects.Create(this, desc);
|
|
|
|
return S_OK;
|
|
|
|
} return S_FALSE;
|
2018-03-17 20:11:00 +01:00
|
|
|
}
|
2017-10-11 09:51:48 +02:00
|
|
|
|
2018-03-18 22:53:20 +01:00
|
|
|
|
2017-12-12 12:50:52 +01:00
|
|
|
HRESULT STDMETHODCALLTYPE D3D11Device::CreateSamplerState(
|
2017-10-11 09:51:48 +02:00
|
|
|
const D3D11_SAMPLER_DESC* pSamplerDesc,
|
|
|
|
ID3D11SamplerState** ppSamplerState) {
|
2018-04-02 12:04:20 +02:00
|
|
|
InitReturnPtr(ppSamplerState);
|
2018-03-18 23:35:40 +01:00
|
|
|
D3D11_SAMPLER_DESC desc = *pSamplerDesc;
|
2017-12-09 20:49:56 +01:00
|
|
|
|
2018-03-18 23:35:40 +01:00
|
|
|
if (FAILED(D3D11SamplerState::NormalizeDesc(&desc)))
|
|
|
|
return E_INVALIDARG;
|
2017-12-09 20:49:56 +01:00
|
|
|
|
|
|
|
if (ppSamplerState == nullptr)
|
2017-12-27 14:32:07 +01:00
|
|
|
return S_FALSE;
|
2017-12-09 20:49:56 +01:00
|
|
|
|
|
|
|
try {
|
2018-03-18 23:35:40 +01:00
|
|
|
*ppSamplerState = m_samplerObjects.Create(this, desc);
|
2017-12-09 20:49:56 +01:00
|
|
|
return S_OK;
|
|
|
|
} catch (const DxvkError& e) {
|
|
|
|
Logger::err(e.message());
|
2017-12-27 14:32:07 +01:00
|
|
|
return E_FAIL;
|
2017-12-09 20:49:56 +01:00
|
|
|
}
|
2017-10-11 09:51:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-12-12 12:50:52 +01:00
|
|
|
HRESULT STDMETHODCALLTYPE D3D11Device::CreateQuery(
|
2017-10-11 09:51:48 +02:00
|
|
|
const D3D11_QUERY_DESC* pQueryDesc,
|
|
|
|
ID3D11Query** ppQuery) {
|
2018-04-02 12:04:20 +02:00
|
|
|
InitReturnPtr(ppQuery);
|
|
|
|
|
2017-12-29 22:20:31 +01:00
|
|
|
if (ppQuery == nullptr)
|
|
|
|
return S_FALSE;
|
2018-02-18 22:34:23 +01:00
|
|
|
|
2017-12-29 22:20:31 +01:00
|
|
|
try {
|
2018-01-01 20:59:54 +01:00
|
|
|
*ppQuery = ref(new D3D11Query(this, *pQueryDesc));
|
2017-12-29 22:20:31 +01:00
|
|
|
return S_OK;
|
|
|
|
} catch (const DxvkError& e) {
|
|
|
|
Logger::err(e.message());
|
|
|
|
return E_FAIL;
|
|
|
|
}
|
2017-10-11 09:51:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-12-12 12:50:52 +01:00
|
|
|
HRESULT STDMETHODCALLTYPE D3D11Device::CreatePredicate(
|
2017-10-11 09:51:48 +02:00
|
|
|
const D3D11_QUERY_DESC* pPredicateDesc,
|
|
|
|
ID3D11Predicate** ppPredicate) {
|
2018-04-02 12:04:20 +02:00
|
|
|
InitReturnPtr(ppPredicate);
|
|
|
|
|
2018-02-18 22:34:23 +01:00
|
|
|
if (pPredicateDesc->Query != D3D11_QUERY_OCCLUSION_PREDICATE)
|
|
|
|
return E_INVALIDARG;
|
|
|
|
|
|
|
|
if (ppPredicate == nullptr)
|
|
|
|
return S_FALSE;
|
|
|
|
|
|
|
|
try {
|
|
|
|
*ppPredicate = ref(new D3D11Query(this, *pPredicateDesc));
|
|
|
|
return S_OK;
|
|
|
|
} catch (const DxvkError& e) {
|
|
|
|
Logger::err(e.message());
|
|
|
|
return E_FAIL;
|
|
|
|
}
|
2017-10-11 09:51:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-12-12 12:50:52 +01:00
|
|
|
HRESULT STDMETHODCALLTYPE D3D11Device::CreateCounter(
|
2017-10-11 09:51:48 +02:00
|
|
|
const D3D11_COUNTER_DESC* pCounterDesc,
|
|
|
|
ID3D11Counter** ppCounter) {
|
2018-04-02 12:04:20 +02:00
|
|
|
InitReturnPtr(ppCounter);
|
|
|
|
|
2018-06-11 14:01:45 +02:00
|
|
|
Logger::err(str::format("D3D11: Unsupported counter: ", pCounterDesc->Counter));
|
|
|
|
return E_INVALIDARG;
|
2017-10-11 09:51:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-12-12 12:50:52 +01:00
|
|
|
HRESULT STDMETHODCALLTYPE D3D11Device::CreateDeferredContext(
|
2017-10-11 09:51:48 +02:00
|
|
|
UINT ContextFlags,
|
|
|
|
ID3D11DeviceContext** ppDeferredContext) {
|
2018-01-23 09:23:31 +01:00
|
|
|
*ppDeferredContext = ref(new D3D11DeferredContext(this, m_dxvkDevice, ContextFlags));
|
|
|
|
return S_OK;
|
2017-10-11 09:51:48 +02:00
|
|
|
}
|
|
|
|
|
2018-03-17 20:11:00 +01:00
|
|
|
HRESULT STDMETHODCALLTYPE D3D11Device::CreateDeferredContext1(
|
|
|
|
UINT ContextFlags,
|
|
|
|
ID3D11DeviceContext1** ppDeferredContext) {
|
|
|
|
*ppDeferredContext = ref(new D3D11DeferredContext(this, m_dxvkDevice, ContextFlags));
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE D3D11Device::CreateDeviceContextState(
|
|
|
|
UINT Flags,
|
|
|
|
const D3D_FEATURE_LEVEL* pFeatureLevels,
|
|
|
|
UINT FeatureLevels,
|
|
|
|
UINT SDKVersion,
|
|
|
|
REFIID EmulatedInterface,
|
|
|
|
D3D_FEATURE_LEVEL* pChosenFeatureLevel,
|
|
|
|
ID3DDeviceContextState** ppContextState) {
|
2018-04-02 12:04:20 +02:00
|
|
|
InitReturnPtr(ppContextState);
|
|
|
|
|
2018-03-17 20:11:00 +01:00
|
|
|
Logger::err("D3D11Device::CreateDeviceContextState: Not implemented");
|
|
|
|
return E_NOTIMPL;
|
|
|
|
}
|
2017-10-11 09:51:48 +02:00
|
|
|
|
2017-12-12 12:50:52 +01:00
|
|
|
HRESULT STDMETHODCALLTYPE D3D11Device::OpenSharedResource(
|
2017-10-11 09:51:48 +02:00
|
|
|
HANDLE hResource,
|
|
|
|
REFIID ReturnedInterface,
|
|
|
|
void** ppResource) {
|
2018-04-02 12:04:20 +02:00
|
|
|
InitReturnPtr(ppResource);
|
|
|
|
|
2017-10-11 09:51:48 +02:00
|
|
|
Logger::err("D3D11Device::OpenSharedResource: Not implemented");
|
|
|
|
return E_NOTIMPL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-03-17 20:11:00 +01:00
|
|
|
HRESULT STDMETHODCALLTYPE D3D11Device::OpenSharedResource1(
|
|
|
|
HANDLE hResource,
|
|
|
|
REFIID ReturnedInterface,
|
|
|
|
void** ppResource) {
|
2018-04-02 12:04:20 +02:00
|
|
|
InitReturnPtr(ppResource);
|
|
|
|
|
2018-03-17 20:11:00 +01:00
|
|
|
Logger::err("D3D11Device::OpenSharedResource1: Not implemented");
|
|
|
|
return E_NOTIMPL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE D3D11Device::OpenSharedResourceByName(
|
|
|
|
LPCWSTR lpName,
|
|
|
|
DWORD dwDesiredAccess,
|
|
|
|
REFIID returnedInterface,
|
2018-04-02 12:04:20 +02:00
|
|
|
void** ppResource) {
|
|
|
|
InitReturnPtr(ppResource);
|
|
|
|
|
2018-03-17 20:11:00 +01:00
|
|
|
Logger::err("D3D11Device::OpenSharedResourceByName: Not implemented");
|
|
|
|
return E_NOTIMPL;
|
|
|
|
}
|
|
|
|
|
2017-12-12 12:50:52 +01:00
|
|
|
HRESULT STDMETHODCALLTYPE D3D11Device::CheckFormatSupport(
|
2017-10-11 09:51:48 +02:00
|
|
|
DXGI_FORMAT Format,
|
|
|
|
UINT* pFormatSupport) {
|
2018-03-21 13:31:22 +01:00
|
|
|
return GetFormatSupportFlags(Format, pFormatSupport, nullptr);
|
2017-10-11 09:51:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-12-12 12:50:52 +01:00
|
|
|
HRESULT STDMETHODCALLTYPE D3D11Device::CheckMultisampleQualityLevels(
|
2017-10-11 09:51:48 +02:00
|
|
|
DXGI_FORMAT Format,
|
|
|
|
UINT SampleCount,
|
|
|
|
UINT* pNumQualityLevels) {
|
2017-12-09 19:44:06 +01:00
|
|
|
// There are many error conditions, so we'll just assume
|
|
|
|
// that we will fail and return a non-zero value in case
|
|
|
|
// the device does actually support the format.
|
2019-01-09 00:24:44 +01:00
|
|
|
if (!pNumQualityLevels)
|
|
|
|
return E_INVALIDARG;
|
|
|
|
|
2017-12-09 14:46:23 +01:00
|
|
|
*pNumQualityLevels = 0;
|
|
|
|
|
2019-01-09 00:24:44 +01:00
|
|
|
// For some reason, we can query DXGI_FORMAT_UNKNOWN
|
|
|
|
if (Format == DXGI_FORMAT_UNKNOWN) {
|
|
|
|
*pNumQualityLevels = SampleCount == 1 ? 1 : 0;
|
|
|
|
return SampleCount ? S_OK : E_INVALIDARG;
|
|
|
|
}
|
2017-12-09 14:46:23 +01:00
|
|
|
|
2019-01-09 00:24:44 +01:00
|
|
|
// All other unknown formats should result in an error return.
|
|
|
|
VkFormat format = LookupFormat(Format, DXGI_VK_FORMAT_MODE_ANY).Format;
|
|
|
|
|
|
|
|
if (format == VK_FORMAT_UNDEFINED)
|
2017-12-09 14:46:23 +01:00
|
|
|
return E_INVALIDARG;
|
|
|
|
|
2019-01-09 00:24:44 +01:00
|
|
|
// Non-power of two sample counts are not supported, but querying
|
|
|
|
// support for them is legal, so we return zero quality levels.
|
2017-12-09 14:46:23 +01:00
|
|
|
VkSampleCountFlagBits sampleCountFlag = VK_SAMPLE_COUNT_1_BIT;
|
|
|
|
|
2018-04-13 13:46:45 +02:00
|
|
|
if (FAILED(DecodeSampleCount(SampleCount, &sampleCountFlag)))
|
2019-01-09 00:24:44 +01:00
|
|
|
return SampleCount ? S_OK : E_INVALIDARG;
|
2017-12-09 14:46:23 +01:00
|
|
|
|
2017-12-09 19:44:06 +01:00
|
|
|
// Check if the device supports the given combination of format
|
|
|
|
// and sample count. D3D exposes the opaque concept of quality
|
|
|
|
// levels to the application, we'll just define one such level.
|
2017-12-09 14:46:23 +01:00
|
|
|
VkImageFormatProperties formatProps;
|
|
|
|
|
|
|
|
VkResult status = m_dxvkAdapter->imageFormatProperties(
|
|
|
|
format, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
|
|
|
|
VK_IMAGE_USAGE_SAMPLED_BIT, 0, formatProps);
|
|
|
|
|
|
|
|
if ((status == VK_SUCCESS) && (formatProps.sampleCounts & sampleCountFlag))
|
|
|
|
*pNumQualityLevels = 1;
|
|
|
|
return S_OK;
|
2017-10-11 09:51:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-12-12 12:50:52 +01:00
|
|
|
void STDMETHODCALLTYPE D3D11Device::CheckCounterInfo(D3D11_COUNTER_INFO* pCounterInfo) {
|
2018-06-11 14:01:45 +02:00
|
|
|
// We basically don't support counters
|
|
|
|
pCounterInfo->LastDeviceDependentCounter = D3D11_COUNTER(0);
|
|
|
|
pCounterInfo->NumSimultaneousCounters = 0;
|
|
|
|
pCounterInfo->NumDetectableParallelUnits = 0;
|
2017-10-11 09:51:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-12-12 12:50:52 +01:00
|
|
|
HRESULT STDMETHODCALLTYPE D3D11Device::CheckCounter(
|
2017-10-11 09:51:48 +02:00
|
|
|
const D3D11_COUNTER_DESC* pDesc,
|
|
|
|
D3D11_COUNTER_TYPE* pType,
|
|
|
|
UINT* pActiveCounters,
|
|
|
|
LPSTR szName,
|
|
|
|
UINT* pNameLength,
|
|
|
|
LPSTR szUnits,
|
|
|
|
UINT* pUnitsLength,
|
|
|
|
LPSTR szDescription,
|
|
|
|
UINT* pDescriptionLength) {
|
2018-06-11 14:01:45 +02:00
|
|
|
Logger::err("D3D11: Counters not supported");
|
|
|
|
return E_INVALIDARG;
|
2017-10-11 09:51:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-12-12 12:50:52 +01:00
|
|
|
HRESULT STDMETHODCALLTYPE D3D11Device::CheckFeatureSupport(
|
2017-10-11 09:51:48 +02:00
|
|
|
D3D11_FEATURE Feature,
|
|
|
|
void* pFeatureSupportData,
|
|
|
|
UINT FeatureSupportDataSize) {
|
2017-12-19 11:05:41 +01:00
|
|
|
switch (Feature) {
|
|
|
|
case D3D11_FEATURE_THREADING: {
|
|
|
|
if (FeatureSupportDataSize != sizeof(D3D11_FEATURE_DATA_THREADING))
|
|
|
|
return E_INVALIDARG;
|
|
|
|
|
2018-03-21 04:58:31 +01:00
|
|
|
// We report native support for command lists here so that we do not actually
|
|
|
|
// have to re-implement the UpdateSubresource bug from the D3D11 runtime, see
|
|
|
|
// https://msdn.microsoft.com/en-us/library/windows/desktop/ff476486(v=vs.85).aspx)
|
2017-12-19 11:05:41 +01:00
|
|
|
auto info = static_cast<D3D11_FEATURE_DATA_THREADING*>(pFeatureSupportData);
|
|
|
|
info->DriverConcurrentCreates = TRUE;
|
2018-03-19 17:57:20 +01:00
|
|
|
info->DriverCommandLists = TRUE;
|
2017-12-19 11:05:41 +01:00
|
|
|
} return S_OK;
|
|
|
|
|
|
|
|
case D3D11_FEATURE_DOUBLES: {
|
|
|
|
if (FeatureSupportDataSize != sizeof(D3D11_FEATURE_DATA_DOUBLES))
|
|
|
|
return E_INVALIDARG;
|
|
|
|
|
|
|
|
auto info = static_cast<D3D11_FEATURE_DATA_DOUBLES*>(pFeatureSupportData);
|
2018-07-31 16:58:25 +02:00
|
|
|
info->DoublePrecisionFloatShaderOps = m_dxvkDevice->features().core.features.shaderFloat64
|
|
|
|
&& m_dxvkDevice->features().core.features.shaderInt64;
|
2017-12-19 11:05:41 +01:00
|
|
|
} return S_OK;
|
|
|
|
|
|
|
|
case D3D11_FEATURE_FORMAT_SUPPORT: {
|
|
|
|
if (FeatureSupportDataSize != sizeof(D3D11_FEATURE_DATA_FORMAT_SUPPORT))
|
|
|
|
return E_INVALIDARG;
|
|
|
|
|
|
|
|
auto info = static_cast<D3D11_FEATURE_DATA_FORMAT_SUPPORT*>(pFeatureSupportData);
|
2018-03-21 13:31:22 +01:00
|
|
|
return GetFormatSupportFlags(info->InFormat, &info->OutFormatSupport, nullptr);
|
|
|
|
} return S_OK;
|
|
|
|
|
|
|
|
case D3D11_FEATURE_FORMAT_SUPPORT2: {
|
|
|
|
if (FeatureSupportDataSize != sizeof(D3D11_FEATURE_DATA_FORMAT_SUPPORT2))
|
|
|
|
return E_INVALIDARG;
|
|
|
|
|
|
|
|
auto info = static_cast<D3D11_FEATURE_DATA_FORMAT_SUPPORT2*>(pFeatureSupportData);
|
|
|
|
return GetFormatSupportFlags(info->InFormat, nullptr, &info->OutFormatSupport2);
|
2017-12-19 11:05:41 +01:00
|
|
|
} return S_OK;
|
|
|
|
|
2017-12-29 12:51:54 +01:00
|
|
|
case D3D11_FEATURE_D3D10_X_HARDWARE_OPTIONS: {
|
|
|
|
if (FeatureSupportDataSize != sizeof(D3D11_FEATURE_DATA_D3D10_X_HARDWARE_OPTIONS))
|
|
|
|
return E_INVALIDARG;
|
|
|
|
|
|
|
|
auto info = static_cast<D3D11_FEATURE_DATA_D3D10_X_HARDWARE_OPTIONS*>(pFeatureSupportData);
|
|
|
|
info->ComputeShaders_Plus_RawAndStructuredBuffers_Via_Shader_4_x = TRUE;
|
|
|
|
} return S_OK;
|
|
|
|
|
2018-03-17 20:11:00 +01:00
|
|
|
case D3D11_FEATURE_D3D11_OPTIONS: {
|
|
|
|
if (FeatureSupportDataSize != sizeof(D3D11_FEATURE_DATA_D3D11_OPTIONS))
|
|
|
|
return E_INVALIDARG;
|
2018-03-20 23:25:23 +01:00
|
|
|
|
|
|
|
// https://msdn.microsoft.com/en-us/library/windows/desktop/hh404457(v=vs.85).aspx
|
2018-09-18 13:23:28 +02:00
|
|
|
const auto& features = m_dxvkDevice->features();
|
|
|
|
|
2018-03-17 20:11:00 +01:00
|
|
|
auto info = static_cast<D3D11_FEATURE_DATA_D3D11_OPTIONS*>(pFeatureSupportData);
|
2018-07-31 16:58:25 +02:00
|
|
|
info->OutputMergerLogicOp = features.core.features.logicOp;
|
2018-09-18 13:23:28 +02:00
|
|
|
info->UAVOnlyRenderingForcedSampleCount = features.core.features.variableMultisampleRate;
|
2018-08-03 11:10:40 +02:00
|
|
|
info->DiscardAPIsSeenByDriver = TRUE;
|
2018-08-03 11:22:26 +02:00
|
|
|
info->FlagsForUpdateAndCopySeenByDriver = TRUE;
|
2018-08-15 19:02:14 +02:00
|
|
|
info->ClearView = TRUE;
|
2018-09-18 16:22:47 +02:00
|
|
|
info->CopyWithOverlap = TRUE;
|
2018-03-20 23:25:23 +01:00
|
|
|
info->ConstantBufferPartialUpdate = TRUE;
|
|
|
|
info->ConstantBufferOffsetting = TRUE;
|
|
|
|
info->MapNoOverwriteOnDynamicConstantBuffer = TRUE;
|
|
|
|
info->MapNoOverwriteOnDynamicBufferSRV = TRUE;
|
2018-09-18 13:23:28 +02:00
|
|
|
info->MultisampleRTVWithForcedSampleCountOne = TRUE; /* not really */
|
2018-03-20 23:25:23 +01:00
|
|
|
info->SAD4ShaderInstructions = FALSE;
|
2018-08-15 20:12:41 +02:00
|
|
|
info->ExtendedDoublesShaderInstructions = TRUE;
|
2018-09-18 16:27:40 +02:00
|
|
|
info->ExtendedResourceSharing = TRUE; /* not really */
|
2018-03-17 20:11:00 +01:00
|
|
|
} return S_OK;
|
|
|
|
|
|
|
|
case D3D11_FEATURE_ARCHITECTURE_INFO: {
|
|
|
|
if (FeatureSupportDataSize != sizeof(D3D11_FEATURE_DATA_ARCHITECTURE_INFO))
|
|
|
|
return E_INVALIDARG;
|
|
|
|
|
|
|
|
auto info = static_cast<D3D11_FEATURE_DATA_ARCHITECTURE_INFO*>(pFeatureSupportData);
|
2018-03-21 04:58:31 +01:00
|
|
|
info->TileBasedDeferredRenderer = FALSE;
|
2018-03-17 20:11:00 +01:00
|
|
|
} return S_OK;
|
2018-03-21 04:58:31 +01:00
|
|
|
|
|
|
|
case D3D11_FEATURE_SHADER_MIN_PRECISION_SUPPORT: {
|
|
|
|
if (FeatureSupportDataSize != sizeof(D3D11_FEATURE_DATA_SHADER_MIN_PRECISION_SUPPORT))
|
|
|
|
return E_INVALIDARG;
|
|
|
|
|
|
|
|
// Report that we only support full 32-bit operations
|
|
|
|
auto info = static_cast<D3D11_FEATURE_DATA_SHADER_MIN_PRECISION_SUPPORT*>(pFeatureSupportData);
|
|
|
|
info->PixelShaderMinPrecision = 0;
|
|
|
|
info->AllOtherShaderStagesMinPrecision = 0;
|
|
|
|
} return S_OK;
|
|
|
|
|
|
|
|
case D3D11_FEATURE_D3D9_SHADOW_SUPPORT: {
|
|
|
|
if (FeatureSupportDataSize != sizeof(D3D11_FEATURE_DATA_D3D9_SHADOW_SUPPORT))
|
|
|
|
return E_INVALIDARG;
|
|
|
|
|
|
|
|
auto info = static_cast<D3D11_FEATURE_DATA_D3D9_SHADOW_SUPPORT*>(pFeatureSupportData);
|
|
|
|
info->SupportsDepthAsTextureWithLessEqualComparisonFilter = TRUE;
|
|
|
|
return S_OK;
|
|
|
|
} break;
|
2018-03-17 20:11:00 +01:00
|
|
|
|
2017-12-19 11:05:41 +01:00
|
|
|
default:
|
|
|
|
Logger::err(str::format(
|
2017-12-29 12:51:54 +01:00
|
|
|
"D3D11Device: CheckFeatureSupport: Unknown feature: ",
|
2017-12-19 11:05:41 +01:00
|
|
|
Feature));
|
2018-03-21 15:08:17 +01:00
|
|
|
return E_NOTIMPL;
|
2017-12-19 11:05:41 +01:00
|
|
|
}
|
2017-10-11 09:51:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-12-12 12:50:52 +01:00
|
|
|
HRESULT STDMETHODCALLTYPE D3D11Device::GetPrivateData(
|
2017-10-11 09:51:48 +02:00
|
|
|
REFGUID guid, UINT* pDataSize, void* pData) {
|
2018-03-28 21:24:52 +02:00
|
|
|
return m_container->GetPrivateData(guid, pDataSize, pData);
|
2017-10-11 09:51:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-12-12 12:50:52 +01:00
|
|
|
HRESULT STDMETHODCALLTYPE D3D11Device::SetPrivateData(
|
2017-10-11 09:51:48 +02:00
|
|
|
REFGUID guid, UINT DataSize, const void* pData) {
|
2018-03-28 21:24:52 +02:00
|
|
|
return m_container->SetPrivateData(guid, DataSize, pData);
|
2017-10-11 09:51:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-12-12 12:50:52 +01:00
|
|
|
HRESULT STDMETHODCALLTYPE D3D11Device::SetPrivateDataInterface(
|
2017-10-11 09:51:48 +02:00
|
|
|
REFGUID guid, const IUnknown* pData) {
|
2018-03-28 21:24:52 +02:00
|
|
|
return m_container->SetPrivateDataInterface(guid, pData);
|
2017-10-11 09:51:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-12-12 12:50:52 +01:00
|
|
|
D3D_FEATURE_LEVEL STDMETHODCALLTYPE D3D11Device::GetFeatureLevel() {
|
2017-10-11 09:51:48 +02:00
|
|
|
return m_featureLevel;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-12-12 12:50:52 +01:00
|
|
|
UINT STDMETHODCALLTYPE D3D11Device::GetCreationFlags() {
|
2017-10-11 09:51:48 +02:00
|
|
|
return m_featureFlags;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-12-12 12:50:52 +01:00
|
|
|
HRESULT STDMETHODCALLTYPE D3D11Device::GetDeviceRemovedReason() {
|
2018-01-18 23:59:40 +01:00
|
|
|
static std::atomic<bool> s_errorShown = { false };
|
2018-01-12 11:39:59 +01:00
|
|
|
|
|
|
|
if (!s_errorShown.exchange(true))
|
|
|
|
Logger::warn("D3D11Device::GetDeviceRemovedReason: Stub");
|
|
|
|
|
|
|
|
return S_OK;
|
2017-10-11 09:51:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-12-12 12:50:52 +01:00
|
|
|
void STDMETHODCALLTYPE D3D11Device::GetImmediateContext(ID3D11DeviceContext** ppImmediateContext) {
|
2017-12-11 17:01:38 +01:00
|
|
|
*ppImmediateContext = ref(m_context);
|
2017-10-11 09:51:48 +02:00
|
|
|
}
|
2018-03-17 20:11:00 +01:00
|
|
|
|
|
|
|
|
|
|
|
void STDMETHODCALLTYPE D3D11Device::GetImmediateContext1(ID3D11DeviceContext1 ** ppImmediateContext) {
|
|
|
|
*ppImmediateContext = ref(m_context);
|
|
|
|
}
|
2017-10-11 09:51:48 +02:00
|
|
|
|
|
|
|
|
2017-12-12 12:50:52 +01:00
|
|
|
HRESULT STDMETHODCALLTYPE D3D11Device::SetExceptionMode(UINT RaiseFlags) {
|
2017-10-11 09:51:48 +02:00
|
|
|
Logger::err("D3D11Device::SetExceptionMode: Not implemented");
|
|
|
|
return E_NOTIMPL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-12-12 12:50:52 +01:00
|
|
|
UINT STDMETHODCALLTYPE D3D11Device::GetExceptionMode() {
|
2017-10-11 09:51:48 +02:00
|
|
|
Logger::err("D3D11Device::GetExceptionMode: Not implemented");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-10-11 15:32:24 +02:00
|
|
|
|
2018-05-05 12:57:22 +02:00
|
|
|
DXGI_VK_FORMAT_INFO D3D11Device::LookupFormat(
|
|
|
|
DXGI_FORMAT Format,
|
|
|
|
DXGI_VK_FORMAT_MODE Mode) const {
|
2018-11-28 18:34:05 +01:00
|
|
|
return m_d3d11Formats.GetFormatInfo(Format, Mode);
|
2017-12-19 16:01:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-07-03 12:44:56 +02:00
|
|
|
DXGI_VK_FORMAT_FAMILY D3D11Device::LookupFamily(
|
|
|
|
DXGI_FORMAT Format,
|
|
|
|
DXGI_VK_FORMAT_MODE Mode) const {
|
2018-11-28 18:34:05 +01:00
|
|
|
return m_d3d11Formats.GetFormatFamily(Format, Mode);
|
2018-07-03 12:44:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-01-13 05:00:27 +01:00
|
|
|
void D3D11Device::FlushInitContext() {
|
2018-07-23 15:21:17 +02:00
|
|
|
m_initializer->Flush();
|
2018-01-13 05:00:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-12-14 15:59:55 +01:00
|
|
|
VkPipelineStageFlags D3D11Device::GetEnabledShaderStages() const {
|
|
|
|
VkPipelineStageFlags enabledShaderPipelineStages
|
|
|
|
= VK_PIPELINE_STAGE_VERTEX_SHADER_BIT
|
|
|
|
| VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT
|
|
|
|
| VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
|
|
|
|
|
2018-07-31 16:58:25 +02:00
|
|
|
if (m_dxvkDevice->features().core.features.geometryShader)
|
2017-12-14 15:59:55 +01:00
|
|
|
enabledShaderPipelineStages |= VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT;
|
|
|
|
|
2018-07-31 16:58:25 +02:00
|
|
|
if (m_dxvkDevice->features().core.features.tessellationShader) {
|
2017-12-14 15:59:55 +01:00
|
|
|
enabledShaderPipelineStages |= VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT
|
|
|
|
| VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT;
|
|
|
|
}
|
|
|
|
|
|
|
|
return enabledShaderPipelineStages;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-10-11 15:32:24 +02:00
|
|
|
bool D3D11Device::CheckFeatureLevelSupport(
|
2017-12-02 16:47:06 +01:00
|
|
|
const Rc<DxvkAdapter>& adapter,
|
2017-10-11 15:32:24 +02:00
|
|
|
D3D_FEATURE_LEVEL featureLevel) {
|
2018-08-09 21:08:03 +02:00
|
|
|
if (featureLevel > GetMaxFeatureLevel(adapter))
|
2017-12-02 16:47:06 +01:00
|
|
|
return false;
|
|
|
|
|
|
|
|
// Check whether all features are supported
|
2018-07-31 16:58:25 +02:00
|
|
|
const DxvkDeviceFeatures features
|
2017-12-02 16:47:06 +01:00
|
|
|
= GetDeviceFeatures(adapter, featureLevel);
|
|
|
|
|
|
|
|
if (!adapter->checkFeatureSupport(features))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// TODO also check for required limits
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-07-31 16:58:25 +02:00
|
|
|
DxvkDeviceFeatures D3D11Device::GetDeviceFeatures(
|
2017-12-02 16:47:06 +01:00
|
|
|
const Rc<DxvkAdapter>& adapter,
|
|
|
|
D3D_FEATURE_LEVEL featureLevel) {
|
2018-07-31 16:58:25 +02:00
|
|
|
DxvkDeviceFeatures supported = adapter->features();
|
|
|
|
DxvkDeviceFeatures enabled = {};
|
|
|
|
|
|
|
|
enabled.core.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR;
|
|
|
|
enabled.core.pNext = nullptr;
|
2018-09-10 22:10:16 +02:00
|
|
|
|
2018-09-14 10:42:26 +02:00
|
|
|
enabled.extTransformFeedback.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT;
|
|
|
|
enabled.extTransformFeedback.pNext = nullptr;
|
|
|
|
|
2018-09-10 22:10:16 +02:00
|
|
|
enabled.extVertexAttributeDivisor.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT;
|
|
|
|
enabled.extVertexAttributeDivisor.pNext = nullptr;
|
2017-12-02 16:47:06 +01:00
|
|
|
|
|
|
|
if (featureLevel >= D3D_FEATURE_LEVEL_9_1) {
|
2018-07-31 16:58:25 +02:00
|
|
|
enabled.core.features.depthClamp = VK_TRUE;
|
|
|
|
enabled.core.features.depthBiasClamp = VK_TRUE;
|
|
|
|
enabled.core.features.fillModeNonSolid = VK_TRUE;
|
|
|
|
enabled.core.features.pipelineStatisticsQuery = supported.core.features.pipelineStatisticsQuery;
|
|
|
|
enabled.core.features.sampleRateShading = VK_TRUE;
|
|
|
|
enabled.core.features.samplerAnisotropy = VK_TRUE;
|
|
|
|
enabled.core.features.shaderClipDistance = VK_TRUE;
|
|
|
|
enabled.core.features.shaderCullDistance = VK_TRUE;
|
|
|
|
enabled.core.features.robustBufferAccess = VK_TRUE;
|
2017-12-02 16:47:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (featureLevel >= D3D_FEATURE_LEVEL_9_2) {
|
2018-07-31 16:58:25 +02:00
|
|
|
enabled.core.features.occlusionQueryPrecise = VK_TRUE;
|
2017-12-02 16:47:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (featureLevel >= D3D_FEATURE_LEVEL_9_3) {
|
2018-07-31 16:58:25 +02:00
|
|
|
enabled.core.features.multiViewport = VK_TRUE;
|
|
|
|
enabled.core.features.independentBlend = VK_TRUE;
|
2017-12-02 16:47:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (featureLevel >= D3D_FEATURE_LEVEL_10_0) {
|
2018-07-31 16:58:25 +02:00
|
|
|
enabled.core.features.fullDrawIndexUint32 = VK_TRUE;
|
|
|
|
enabled.core.features.fragmentStoresAndAtomics = VK_TRUE;
|
|
|
|
enabled.core.features.geometryShader = VK_TRUE;
|
|
|
|
enabled.core.features.logicOp = supported.core.features.logicOp;
|
|
|
|
enabled.core.features.shaderImageGatherExtended = VK_TRUE;
|
|
|
|
enabled.core.features.textureCompressionBC = VK_TRUE;
|
2018-09-18 13:23:28 +02:00
|
|
|
enabled.core.features.variableMultisampleRate = supported.core.features.variableMultisampleRate;
|
2018-09-14 10:42:26 +02:00
|
|
|
enabled.extTransformFeedback.transformFeedback = supported.extTransformFeedback.transformFeedback;
|
|
|
|
enabled.extTransformFeedback.geometryStreams = supported.extTransformFeedback.geometryStreams;
|
2017-12-02 16:47:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (featureLevel >= D3D_FEATURE_LEVEL_10_1) {
|
2018-07-31 16:58:25 +02:00
|
|
|
enabled.core.features.dualSrcBlend = VK_TRUE;
|
|
|
|
enabled.core.features.imageCubeArray = VK_TRUE;
|
2017-12-02 16:47:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (featureLevel >= D3D_FEATURE_LEVEL_11_0) {
|
2018-08-10 04:34:54 +02:00
|
|
|
enabled.core.features.drawIndirectFirstInstance = VK_TRUE;
|
2018-07-31 16:58:25 +02:00
|
|
|
enabled.core.features.shaderFloat64 = supported.core.features.shaderFloat64;
|
|
|
|
enabled.core.features.shaderInt64 = supported.core.features.shaderInt64;
|
|
|
|
enabled.core.features.tessellationShader = VK_TRUE;
|
2018-05-26 20:34:40 +02:00
|
|
|
// TODO enable unconditionally once RADV gains support
|
2018-07-31 16:58:25 +02:00
|
|
|
enabled.core.features.shaderStorageImageMultisample = supported.core.features.shaderStorageImageMultisample;
|
|
|
|
enabled.core.features.shaderStorageImageWriteWithoutFormat = VK_TRUE;
|
2017-12-02 16:47:06 +01:00
|
|
|
}
|
|
|
|
|
2018-03-18 23:39:40 +01:00
|
|
|
if (featureLevel >= D3D_FEATURE_LEVEL_11_1) {
|
2018-07-31 16:58:25 +02:00
|
|
|
enabled.core.features.logicOp = VK_TRUE;
|
2018-09-18 13:23:28 +02:00
|
|
|
enabled.core.features.variableMultisampleRate = VK_TRUE;
|
2018-07-31 16:58:25 +02:00
|
|
|
enabled.core.features.vertexPipelineStoresAndAtomics = VK_TRUE;
|
2018-03-18 23:39:40 +01:00
|
|
|
}
|
|
|
|
|
2018-09-10 22:10:16 +02:00
|
|
|
if (supported.extVertexAttributeDivisor.vertexAttributeInstanceRateDivisor
|
|
|
|
&& supported.extVertexAttributeDivisor.vertexAttributeInstanceRateZeroDivisor) {
|
|
|
|
enabled.extVertexAttributeDivisor.vertexAttributeInstanceRateDivisor = VK_TRUE;
|
|
|
|
enabled.extVertexAttributeDivisor.vertexAttributeInstanceRateZeroDivisor = VK_TRUE;
|
|
|
|
}
|
|
|
|
|
2017-12-02 16:47:06 +01:00
|
|
|
return enabled;
|
2017-10-11 15:32:24 +02:00
|
|
|
}
|
|
|
|
|
2017-12-06 18:54:01 +01:00
|
|
|
|
2018-08-30 15:24:47 +02:00
|
|
|
Rc<D3D11CounterBuffer> D3D11Device::CreateUAVCounterBuffer() {
|
|
|
|
// UAV counters are going to be used as raw storage buffers, so
|
|
|
|
// we need to align them to the minimum SSBO offset alignment
|
|
|
|
const auto& devInfo = m_dxvkAdapter->deviceProperties();
|
|
|
|
|
|
|
|
VkDeviceSize uavCounterSliceLength = align<VkDeviceSize>(
|
2018-09-27 16:50:34 +02:00
|
|
|
sizeof(uint32_t), devInfo.limits.minStorageBufferOffsetAlignment);
|
2018-08-30 15:24:47 +02:00
|
|
|
|
|
|
|
DxvkBufferCreateInfo uavCounterInfo;
|
|
|
|
uavCounterInfo.size = 4096 * uavCounterSliceLength;
|
|
|
|
uavCounterInfo.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT
|
|
|
|
| VK_BUFFER_USAGE_TRANSFER_SRC_BIT
|
|
|
|
| VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
|
|
|
|
uavCounterInfo.stages = VK_PIPELINE_STAGE_TRANSFER_BIT
|
|
|
|
| GetEnabledShaderStages();
|
|
|
|
uavCounterInfo.access = VK_ACCESS_TRANSFER_READ_BIT
|
|
|
|
| VK_ACCESS_TRANSFER_WRITE_BIT
|
|
|
|
| VK_ACCESS_SHADER_READ_BIT
|
|
|
|
| VK_ACCESS_SHADER_WRITE_BIT;
|
|
|
|
|
|
|
|
return new D3D11CounterBuffer(m_dxvkDevice,
|
|
|
|
uavCounterInfo, uavCounterSliceLength);
|
|
|
|
}
|
2018-08-30 15:56:51 +02:00
|
|
|
|
|
|
|
|
|
|
|
Rc<D3D11CounterBuffer> D3D11Device::CreateXFBCounterBuffer() {
|
|
|
|
DxvkBufferCreateInfo xfbCounterInfo;
|
|
|
|
xfbCounterInfo.size = 4096 * sizeof(D3D11SOCounter);
|
|
|
|
xfbCounterInfo.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT
|
|
|
|
| VK_BUFFER_USAGE_TRANSFER_SRC_BIT
|
|
|
|
| VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT
|
|
|
|
| VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT;
|
|
|
|
xfbCounterInfo.stages = VK_PIPELINE_STAGE_TRANSFER_BIT
|
|
|
|
| VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT
|
|
|
|
| VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT;
|
|
|
|
xfbCounterInfo.access = VK_ACCESS_TRANSFER_READ_BIT
|
|
|
|
| VK_ACCESS_TRANSFER_WRITE_BIT
|
|
|
|
| VK_ACCESS_INDIRECT_COMMAND_READ_BIT
|
|
|
|
| VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT
|
|
|
|
| VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT;
|
|
|
|
|
|
|
|
return new D3D11CounterBuffer(m_dxvkDevice,
|
|
|
|
xfbCounterInfo, sizeof(D3D11SOCounter));
|
|
|
|
}
|
2018-08-30 15:24:47 +02:00
|
|
|
|
|
|
|
|
2017-12-06 18:54:01 +01:00
|
|
|
HRESULT D3D11Device::CreateShaderModule(
|
2018-07-30 19:34:48 +02:00
|
|
|
D3D11CommonShader* pShaderModule,
|
2018-10-25 11:28:02 +02:00
|
|
|
DxvkShaderKey ShaderKey,
|
2017-12-06 18:54:01 +01:00
|
|
|
const void* pShaderBytecode,
|
|
|
|
size_t BytecodeLength,
|
2018-04-06 17:54:02 +02:00
|
|
|
ID3D11ClassLinkage* pClassLinkage,
|
2018-10-25 11:28:02 +02:00
|
|
|
const DxbcModuleInfo* pModuleInfo) {
|
2017-12-12 01:07:07 +01:00
|
|
|
if (pClassLinkage != nullptr)
|
|
|
|
Logger::warn("D3D11Device::CreateShaderModule: Class linkage not supported");
|
2017-12-06 18:54:01 +01:00
|
|
|
|
|
|
|
try {
|
2018-07-30 20:15:19 +02:00
|
|
|
*pShaderModule = m_shaderModules.GetShaderModule(this,
|
2018-10-25 11:28:02 +02:00
|
|
|
&ShaderKey, pModuleInfo, pShaderBytecode, BytecodeLength);
|
2017-12-06 18:54:01 +01:00
|
|
|
return S_OK;
|
|
|
|
} catch (const DxvkError& e) {
|
|
|
|
Logger::err(e.message());
|
2017-12-27 14:32:07 +01:00
|
|
|
return E_FAIL;
|
2017-12-06 18:54:01 +01:00
|
|
|
}
|
|
|
|
}
|
2018-08-30 15:24:47 +02:00
|
|
|
|
|
|
|
|
2018-03-21 13:31:22 +01:00
|
|
|
HRESULT D3D11Device::GetFormatSupportFlags(DXGI_FORMAT Format, UINT* pFlags1, UINT* pFlags2) const {
|
2018-04-14 16:07:01 +02:00
|
|
|
// Query some general information from DXGI, DXVK and Vulkan about the format
|
2018-11-28 18:34:05 +01:00
|
|
|
const DXGI_VK_FORMAT_INFO fmtMapping = LookupFormat(Format, DXGI_VK_FORMAT_MODE_ANY);
|
2018-04-14 16:07:01 +02:00
|
|
|
const VkFormatProperties fmtSupport = m_dxvkAdapter->formatProperties(fmtMapping.Format);
|
|
|
|
const DxvkFormatInfo* fmtProperties = imageFormatInfo(fmtMapping.Format);
|
|
|
|
|
|
|
|
// Reset output flags preemptively
|
|
|
|
if (pFlags1 != nullptr) *pFlags1 = 0;
|
|
|
|
if (pFlags2 != nullptr) *pFlags2 = 0;
|
|
|
|
|
|
|
|
// Unsupported or invalid format
|
|
|
|
if (fmtMapping.Format == VK_FORMAT_UNDEFINED)
|
|
|
|
return E_INVALIDARG;
|
2017-12-19 11:05:41 +01:00
|
|
|
|
2018-03-21 13:31:22 +01:00
|
|
|
UINT flags1 = 0;
|
|
|
|
UINT flags2 = 0;
|
2017-12-19 11:05:41 +01:00
|
|
|
|
2018-04-14 16:07:01 +02:00
|
|
|
// Format can be used for shader resource views with buffers
|
|
|
|
if (fmtSupport.bufferFeatures & VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT)
|
2018-03-21 13:31:22 +01:00
|
|
|
flags1 |= D3D11_FORMAT_SUPPORT_BUFFER;
|
2017-12-19 11:05:41 +01:00
|
|
|
|
2018-04-14 16:07:01 +02:00
|
|
|
// Format can be used for vertex data
|
|
|
|
if (fmtSupport.bufferFeatures & VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)
|
2018-03-21 13:31:22 +01:00
|
|
|
flags1 |= D3D11_FORMAT_SUPPORT_IA_VERTEX_BUFFER;
|
2017-12-19 11:05:41 +01:00
|
|
|
|
2018-04-14 16:07:01 +02:00
|
|
|
// Format can be used for index data. Only
|
|
|
|
// these two formats are supported by D3D11.
|
|
|
|
if (Format == DXGI_FORMAT_R16_UINT
|
|
|
|
|| Format == DXGI_FORMAT_R32_UINT)
|
2018-03-21 13:31:22 +01:00
|
|
|
flags1 |= D3D11_FORMAT_SUPPORT_IA_INDEX_BUFFER;
|
2017-12-19 11:05:41 +01:00
|
|
|
|
2018-07-25 11:42:05 +02:00
|
|
|
// These formats are technically irrelevant since
|
|
|
|
// SO buffers are passed in as raw buffers and not
|
|
|
|
// as views, but the feature flag exists regardless
|
|
|
|
if (Format == DXGI_FORMAT_R32_FLOAT
|
|
|
|
|| Format == DXGI_FORMAT_R32_UINT
|
|
|
|
|| Format == DXGI_FORMAT_R32_SINT
|
|
|
|
|| Format == DXGI_FORMAT_R32G32_FLOAT
|
|
|
|
|| Format == DXGI_FORMAT_R32G32_UINT
|
|
|
|
|| Format == DXGI_FORMAT_R32G32_SINT
|
|
|
|
|| Format == DXGI_FORMAT_R32G32B32_FLOAT
|
|
|
|
|| Format == DXGI_FORMAT_R32G32B32_UINT
|
|
|
|
|| Format == DXGI_FORMAT_R32G32B32_SINT
|
|
|
|
|| Format == DXGI_FORMAT_R32G32B32A32_FLOAT
|
|
|
|
|| Format == DXGI_FORMAT_R32G32B32A32_UINT
|
|
|
|
|| Format == DXGI_FORMAT_R32G32B32A32_SINT)
|
|
|
|
flags1 |= D3D11_FORMAT_SUPPORT_SO_BUFFER;
|
2017-12-19 11:05:41 +01:00
|
|
|
|
2018-04-14 16:07:01 +02:00
|
|
|
if (fmtSupport.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT
|
|
|
|
|| fmtSupport.optimalTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT) {
|
2018-11-28 18:34:05 +01:00
|
|
|
const VkFormat depthFormat = LookupFormat(Format, DXGI_VK_FORMAT_MODE_DEPTH).Format;
|
2018-04-14 16:07:01 +02:00
|
|
|
|
|
|
|
if (GetImageTypeSupport(fmtMapping.Format, VK_IMAGE_TYPE_1D)) flags1 |= D3D11_FORMAT_SUPPORT_TEXTURE1D;
|
|
|
|
if (GetImageTypeSupport(fmtMapping.Format, VK_IMAGE_TYPE_2D)) flags1 |= D3D11_FORMAT_SUPPORT_TEXTURE2D;
|
|
|
|
if (GetImageTypeSupport(fmtMapping.Format, VK_IMAGE_TYPE_3D)) flags1 |= D3D11_FORMAT_SUPPORT_TEXTURE3D;
|
|
|
|
|
|
|
|
flags1 |= D3D11_FORMAT_SUPPORT_MIP
|
|
|
|
| D3D11_FORMAT_SUPPORT_CPU_LOCKABLE
|
2018-03-21 13:31:22 +01:00
|
|
|
| D3D11_FORMAT_SUPPORT_CAST_WITHIN_BIT_LAYOUT;
|
2017-12-19 11:05:41 +01:00
|
|
|
|
2018-04-14 16:07:01 +02:00
|
|
|
// Format can be read
|
|
|
|
if (fmtSupport.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) {
|
|
|
|
flags1 |= D3D11_FORMAT_SUPPORT_TEXTURECUBE
|
|
|
|
| D3D11_FORMAT_SUPPORT_SHADER_LOAD
|
|
|
|
| D3D11_FORMAT_SUPPORT_SHADER_GATHER
|
|
|
|
| D3D11_FORMAT_SUPPORT_SHADER_SAMPLE;
|
|
|
|
|
|
|
|
if (depthFormat != VK_FORMAT_UNDEFINED) {
|
|
|
|
flags1 |= D3D11_FORMAT_SUPPORT_SHADER_GATHER_COMPARISON
|
|
|
|
| D3D11_FORMAT_SUPPORT_SHADER_SAMPLE_COMPARISON;
|
|
|
|
}
|
|
|
|
}
|
2018-03-21 13:31:22 +01:00
|
|
|
|
2018-04-14 16:07:01 +02:00
|
|
|
// Format is a color format that can be used for rendering
|
|
|
|
if (fmtSupport.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) {
|
|
|
|
flags1 |= D3D11_FORMAT_SUPPORT_RENDER_TARGET
|
|
|
|
| D3D11_FORMAT_SUPPORT_MIP_AUTOGEN;
|
|
|
|
|
2018-07-31 16:58:25 +02:00
|
|
|
if (m_dxvkDevice->features().core.features.logicOp)
|
2018-04-14 16:07:01 +02:00
|
|
|
flags2 |= D3D11_FORMAT_SUPPORT2_OUTPUT_MERGER_LOGIC_OP;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Format supports blending when used for rendering
|
|
|
|
if (fmtSupport.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT)
|
|
|
|
flags1 |= D3D11_FORMAT_SUPPORT_BLENDABLE;
|
|
|
|
|
|
|
|
// Format is a depth-stencil format that can be used for rendering
|
|
|
|
if (fmtSupport.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)
|
|
|
|
flags1 |= D3D11_FORMAT_SUPPORT_DEPTH_STENCIL;
|
|
|
|
|
|
|
|
// FIXME implement properly. This would require a VkSurface.
|
|
|
|
if (Format == DXGI_FORMAT_R8G8B8A8_UNORM
|
|
|
|
|| Format == DXGI_FORMAT_R8G8B8A8_UNORM_SRGB
|
|
|
|
|| Format == DXGI_FORMAT_B8G8R8A8_UNORM
|
|
|
|
|| Format == DXGI_FORMAT_B8G8R8A8_UNORM_SRGB
|
|
|
|
|| Format == DXGI_FORMAT_R16G16B16A16_FLOAT
|
|
|
|
|| Format == DXGI_FORMAT_R10G10B10A2_UNORM
|
|
|
|
|| Format == DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM)
|
|
|
|
flags1 |= D3D11_FORMAT_SUPPORT_DISPLAY;
|
|
|
|
|
|
|
|
// Query multisample support for this format
|
|
|
|
VkImageFormatProperties imgFmtProperties;
|
|
|
|
|
|
|
|
VkResult status = m_dxvkAdapter->imageFormatProperties(fmtMapping.Format,
|
|
|
|
VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
|
|
|
|
(fmtProperties->aspectMask & VK_IMAGE_ASPECT_COLOR_BIT)
|
|
|
|
? VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT
|
|
|
|
: VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
|
|
|
|
0, imgFmtProperties);
|
|
|
|
|
|
|
|
if (status == VK_SUCCESS && imgFmtProperties.sampleCounts > VK_SAMPLE_COUNT_1_BIT) {
|
|
|
|
flags1 |= D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET
|
|
|
|
| D3D11_FORMAT_SUPPORT_MULTISAMPLE_RESOLVE
|
|
|
|
| D3D11_FORMAT_SUPPORT_MULTISAMPLE_LOAD;
|
|
|
|
}
|
2018-03-21 13:31:22 +01:00
|
|
|
}
|
2017-12-19 11:05:41 +01:00
|
|
|
|
2018-04-14 16:07:01 +02:00
|
|
|
// Format can be used for storage images or storage texel buffers
|
|
|
|
if ((fmtSupport.bufferFeatures & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT)
|
2018-04-14 23:20:35 +02:00
|
|
|
&& (fmtSupport.optimalTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT)) {
|
2018-03-21 13:31:22 +01:00
|
|
|
flags1 |= D3D11_FORMAT_SUPPORT_TYPED_UNORDERED_ACCESS_VIEW;
|
|
|
|
flags2 |= D3D11_FORMAT_SUPPORT2_UAV_TYPED_STORE;
|
|
|
|
|
2018-07-31 16:58:25 +02:00
|
|
|
if (m_dxvkDevice->features().core.features.shaderStorageImageReadWithoutFormat
|
2018-03-21 13:31:22 +01:00
|
|
|
|| Format == DXGI_FORMAT_R32_UINT
|
|
|
|
|| Format == DXGI_FORMAT_R32_SINT
|
|
|
|
|| Format == DXGI_FORMAT_R32_FLOAT)
|
|
|
|
flags2 |= D3D11_FORMAT_SUPPORT2_UAV_TYPED_LOAD;
|
2018-04-14 16:07:01 +02:00
|
|
|
|
|
|
|
if (Format == DXGI_FORMAT_R32_UINT
|
|
|
|
|| Format == DXGI_FORMAT_R32_SINT) {
|
|
|
|
flags2 |= D3D11_FORMAT_SUPPORT2_UAV_ATOMIC_ADD
|
|
|
|
| D3D11_FORMAT_SUPPORT2_UAV_ATOMIC_BITWISE_OPS
|
|
|
|
| D3D11_FORMAT_SUPPORT2_UAV_ATOMIC_COMPARE_STORE_OR_COMPARE_EXCHANGE
|
|
|
|
| D3D11_FORMAT_SUPPORT2_UAV_ATOMIC_EXCHANGE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Format == DXGI_FORMAT_R32_SINT)
|
|
|
|
flags2 |= D3D11_FORMAT_SUPPORT2_UAV_ATOMIC_SIGNED_MIN_OR_MAX;
|
|
|
|
|
|
|
|
if (Format == DXGI_FORMAT_R32_UINT)
|
|
|
|
flags2 |= D3D11_FORMAT_SUPPORT2_UAV_ATOMIC_UNSIGNED_MIN_OR_MAX;
|
2018-03-21 13:31:22 +01:00
|
|
|
}
|
2017-12-19 11:05:41 +01:00
|
|
|
|
2018-04-14 16:07:01 +02:00
|
|
|
// Write back format support flags
|
2018-03-21 13:31:22 +01:00
|
|
|
if (pFlags1 != nullptr) *pFlags1 = flags1;
|
|
|
|
if (pFlags2 != nullptr) *pFlags2 = flags2;
|
2017-12-19 11:05:41 +01:00
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
2018-01-11 12:23:55 +01:00
|
|
|
|
2018-04-14 16:07:01 +02:00
|
|
|
BOOL D3D11Device::GetImageTypeSupport(VkFormat Format, VkImageType Type) const {
|
|
|
|
VkImageFormatProperties props;
|
|
|
|
|
|
|
|
VkResult status = m_dxvkAdapter->imageFormatProperties(
|
|
|
|
Format, Type, VK_IMAGE_TILING_OPTIMAL,
|
|
|
|
VK_IMAGE_USAGE_SAMPLED_BIT, 0, props);
|
|
|
|
|
|
|
|
return status == VK_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-08-09 21:08:03 +02:00
|
|
|
D3D_FEATURE_LEVEL D3D11Device::GetMaxFeatureLevel(const Rc<DxvkAdapter>& Adapter) {
|
2018-03-18 23:39:40 +01:00
|
|
|
static const std::array<std::pair<std::string, D3D_FEATURE_LEVEL>, 7> s_featureLevels = {{
|
|
|
|
{ "11_1", D3D_FEATURE_LEVEL_11_1 },
|
2018-01-30 12:19:53 +01:00
|
|
|
{ "11_0", D3D_FEATURE_LEVEL_11_0 },
|
|
|
|
{ "10_1", D3D_FEATURE_LEVEL_10_1 },
|
|
|
|
{ "10_0", D3D_FEATURE_LEVEL_10_0 },
|
|
|
|
{ "9_3", D3D_FEATURE_LEVEL_9_3 },
|
|
|
|
{ "9_2", D3D_FEATURE_LEVEL_9_2 },
|
|
|
|
{ "9_1", D3D_FEATURE_LEVEL_9_1 },
|
|
|
|
}};
|
|
|
|
|
2018-08-09 21:08:03 +02:00
|
|
|
const std::string maxLevel = Adapter->instance()->config()
|
|
|
|
.getOption<std::string>("d3d11.maxFeatureLevel");
|
2018-01-30 12:19:53 +01:00
|
|
|
|
|
|
|
auto entry = std::find_if(s_featureLevels.begin(), s_featureLevels.end(),
|
|
|
|
[&] (const std::pair<std::string, D3D_FEATURE_LEVEL>& pair) {
|
|
|
|
return pair.first == maxLevel;
|
|
|
|
});
|
|
|
|
|
|
|
|
return entry != s_featureLevels.end()
|
|
|
|
? entry->second
|
2018-09-18 16:27:40 +02:00
|
|
|
: D3D_FEATURE_LEVEL_11_1;
|
2018-01-30 12:19:53 +01:00
|
|
|
}
|
|
|
|
|
2018-12-03 19:26:29 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
2018-12-21 15:53:29 +01:00
|
|
|
WineDXGISwapChainFactory::WineDXGISwapChainFactory(
|
|
|
|
IDXGIVkPresentDevice* pDevice)
|
|
|
|
: m_device(pDevice) {
|
2018-12-21 12:23:45 +01:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ULONG STDMETHODCALLTYPE WineDXGISwapChainFactory::AddRef() {
|
2018-12-21 15:53:29 +01:00
|
|
|
return m_device->AddRef();
|
2018-12-21 12:23:45 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ULONG STDMETHODCALLTYPE WineDXGISwapChainFactory::Release() {
|
2018-12-21 15:53:29 +01:00
|
|
|
return m_device->Release();
|
2018-12-21 12:23:45 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE WineDXGISwapChainFactory::QueryInterface(
|
|
|
|
REFIID riid,
|
|
|
|
void** ppvObject) {
|
2018-12-21 15:53:29 +01:00
|
|
|
return m_device->QueryInterface(riid, ppvObject);
|
2018-12-21 12:23:45 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE WineDXGISwapChainFactory::CreateSwapChainForHwnd(
|
|
|
|
IDXGIFactory* pFactory,
|
|
|
|
HWND hWnd,
|
|
|
|
const DXGI_SWAP_CHAIN_DESC1* pDesc,
|
|
|
|
const DXGI_SWAP_CHAIN_FULLSCREEN_DESC* pFullscreenDesc,
|
|
|
|
IDXGIOutput* pRestrictToOutput,
|
|
|
|
IDXGISwapChain1** ppSwapChain) {
|
|
|
|
InitReturnPtr(ppSwapChain);
|
|
|
|
|
2018-12-21 15:53:29 +01:00
|
|
|
if (!ppSwapChain || !pDesc || !hWnd)
|
2018-12-21 12:23:45 +01:00
|
|
|
return DXGI_ERROR_INVALID_CALL;
|
2018-12-21 15:53:29 +01:00
|
|
|
|
|
|
|
return CreateDxvkSwapChainForHwnd(
|
|
|
|
pFactory, m_device, hWnd, pDesc,
|
|
|
|
pFullscreenDesc, pRestrictToOutput,
|
|
|
|
ppSwapChain);
|
2018-12-21 12:23:45 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2018-12-03 19:26:29 +01:00
|
|
|
D3D11DXGIDevice::D3D11DXGIDevice(
|
|
|
|
IDXGIAdapter* pAdapter,
|
|
|
|
DxvkAdapter* pDxvkAdapter,
|
|
|
|
D3D_FEATURE_LEVEL FeatureLevel,
|
|
|
|
UINT FeatureFlags)
|
|
|
|
: m_dxgiAdapter (pAdapter),
|
|
|
|
m_dxvkAdapter (pDxvkAdapter),
|
|
|
|
m_dxvkDevice (CreateDevice(FeatureLevel)),
|
|
|
|
m_d3d11Device (this, FeatureLevel, FeatureFlags),
|
|
|
|
m_d3d11Presenter(this, &m_d3d11Device),
|
2018-12-21 12:23:45 +01:00
|
|
|
m_d3d11Interop (this, &m_d3d11Device),
|
2018-12-21 15:53:29 +01:00
|
|
|
m_wineFactory (&m_d3d11Presenter) {
|
2018-12-03 19:26:29 +01:00
|
|
|
for (uint32_t i = 0; i < m_frameEvents.size(); i++)
|
|
|
|
m_frameEvents[i] = new DxvkEvent();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
D3D11DXGIDevice::~D3D11DXGIDevice() {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE D3D11DXGIDevice::QueryInterface(REFIID riid, void** ppvObject) {
|
|
|
|
*ppvObject = nullptr;
|
|
|
|
|
|
|
|
if (riid == __uuidof(IUnknown)
|
|
|
|
|| riid == __uuidof(IDXGIObject)
|
|
|
|
|| riid == __uuidof(IDXGIDevice)
|
|
|
|
|| riid == __uuidof(IDXGIDevice1)
|
|
|
|
|| riid == __uuidof(IDXGIDevice2)
|
|
|
|
|| riid == __uuidof(IDXGIDevice3)) {
|
|
|
|
*ppvObject = ref(this);
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (riid == __uuidof(IDXGIVkInteropDevice)) {
|
|
|
|
*ppvObject = ref(&m_d3d11Interop);
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (riid == __uuidof(ID3D10Device)
|
|
|
|
|| riid == __uuidof(ID3D10Device1)) {
|
|
|
|
*ppvObject = ref(m_d3d11Device.GetD3D10Interface());
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (riid == __uuidof(ID3D11Device)
|
|
|
|
|| riid == __uuidof(ID3D11Device1)) {
|
|
|
|
*ppvObject = ref(&m_d3d11Device);
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (riid == __uuidof(IDXGIVkPresentDevice)) {
|
|
|
|
*ppvObject = ref(&m_d3d11Presenter);
|
|
|
|
return S_OK;
|
|
|
|
}
|
2018-12-21 12:23:45 +01:00
|
|
|
|
|
|
|
if (riid == __uuidof(IWineDXGISwapChainFactory)) {
|
|
|
|
*ppvObject = ref(&m_wineFactory);
|
|
|
|
return S_OK;
|
|
|
|
}
|
2018-12-03 19:26:29 +01:00
|
|
|
|
|
|
|
if (riid == __uuidof(ID3D10Multithread)) {
|
2018-12-30 20:38:35 +01:00
|
|
|
Com<ID3D11DeviceContext> context;
|
|
|
|
m_d3d11Device.GetImmediateContext(&context);
|
|
|
|
return context->QueryInterface(riid, ppvObject);
|
2018-12-03 19:26:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (riid == __uuidof(ID3D11Debug))
|
|
|
|
return E_NOINTERFACE;
|
|
|
|
|
|
|
|
// Undocumented interfaces that are queried by some games
|
|
|
|
if (riid == GUID{0xd56e2a4c,0x5127,0x8437,{0x65,0x8a,0x98,0xc5,0xbb,0x78,0x94,0x98}})
|
|
|
|
return E_NOINTERFACE;
|
|
|
|
|
|
|
|
Logger::warn("D3D11DXGIDevice::QueryInterface: Unknown interface query");
|
|
|
|
Logger::warn(str::format(riid));
|
|
|
|
return E_NOINTERFACE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE D3D11DXGIDevice::GetParent(
|
|
|
|
REFIID riid,
|
|
|
|
void** ppParent) {
|
|
|
|
return m_dxgiAdapter->QueryInterface(riid, ppParent);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE D3D11DXGIDevice::CreateSurface(
|
|
|
|
const DXGI_SURFACE_DESC* pDesc,
|
|
|
|
UINT NumSurfaces,
|
|
|
|
DXGI_USAGE Usage,
|
|
|
|
const DXGI_SHARED_RESOURCE* pSharedResource,
|
|
|
|
IDXGISurface** ppSurface) {
|
|
|
|
InitReturnPtr(ppSurface);
|
|
|
|
|
|
|
|
Logger::err("D3D11DXGIDevice::CreateSurface: Not implemented");
|
|
|
|
return E_NOTIMPL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE D3D11DXGIDevice::GetAdapter(
|
|
|
|
IDXGIAdapter** pAdapter) {
|
|
|
|
if (pAdapter == nullptr)
|
|
|
|
return DXGI_ERROR_INVALID_CALL;
|
|
|
|
|
|
|
|
*pAdapter = m_dxgiAdapter.ref();
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE D3D11DXGIDevice::GetGPUThreadPriority(
|
|
|
|
INT* pPriority) {
|
|
|
|
*pPriority = 0;
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE D3D11DXGIDevice::QueryResourceResidency(
|
|
|
|
IUnknown* const* ppResources,
|
|
|
|
DXGI_RESIDENCY* pResidencyStatus,
|
|
|
|
UINT NumResources) {
|
|
|
|
static bool s_errorShown = false;
|
|
|
|
|
|
|
|
if (!std::exchange(s_errorShown, true))
|
|
|
|
Logger::err("D3D11DXGIDevice::QueryResourceResidency: Stub");
|
|
|
|
|
|
|
|
if (!ppResources || !pResidencyStatus)
|
|
|
|
return E_INVALIDARG;
|
|
|
|
|
|
|
|
for (uint32_t i = 0; i < NumResources; i++)
|
|
|
|
pResidencyStatus[i] = DXGI_RESIDENCY_FULLY_RESIDENT;
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE D3D11DXGIDevice::SetGPUThreadPriority(
|
|
|
|
INT Priority) {
|
|
|
|
if (Priority < -7 || Priority > 7)
|
|
|
|
return E_INVALIDARG;
|
|
|
|
|
|
|
|
Logger::err("DXGI: SetGPUThreadPriority: Ignoring");
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE D3D11DXGIDevice::GetMaximumFrameLatency(
|
|
|
|
UINT* pMaxLatency) {
|
|
|
|
*pMaxLatency = m_frameLatency;
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE D3D11DXGIDevice::SetMaximumFrameLatency(
|
|
|
|
UINT MaxLatency) {
|
|
|
|
if (MaxLatency == 0)
|
|
|
|
MaxLatency = DefaultFrameLatency;
|
|
|
|
|
|
|
|
if (MaxLatency > m_frameEvents.size())
|
|
|
|
MaxLatency = m_frameEvents.size();
|
|
|
|
|
|
|
|
m_frameLatency = MaxLatency;
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE D3D11DXGIDevice::OfferResources(
|
|
|
|
UINT NumResources,
|
|
|
|
IDXGIResource* const* ppResources,
|
|
|
|
DXGI_OFFER_RESOURCE_PRIORITY Priority) {
|
|
|
|
|
|
|
|
Logger::err("D3D11DXGIDevice::OfferResources: Not implemented");
|
|
|
|
return DXGI_ERROR_UNSUPPORTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE D3D11DXGIDevice::ReclaimResources(
|
|
|
|
UINT NumResources,
|
|
|
|
IDXGIResource* const* ppResources,
|
|
|
|
BOOL* pDiscarded) {
|
|
|
|
Logger::err("D3D11DXGIDevice::ReclaimResources: Not implemented");
|
|
|
|
return DXGI_ERROR_UNSUPPORTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE D3D11DXGIDevice::EnqueueSetEvent(HANDLE hEvent) {
|
|
|
|
Logger::err("D3D11DXGIDevice::EnqueueSetEvent: Not implemented");
|
|
|
|
return DXGI_ERROR_UNSUPPORTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void STDMETHODCALLTYPE D3D11DXGIDevice::Trim() {
|
|
|
|
static bool s_errorShown = false;
|
|
|
|
|
|
|
|
if (!std::exchange(s_errorShown, true))
|
|
|
|
Logger::warn("D3D11DXGIDevice::Trim: Stub");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Rc<DxvkEvent> STDMETHODCALLTYPE D3D11DXGIDevice::GetFrameSyncEvent() {
|
|
|
|
uint32_t frameLatency = m_frameLatency;
|
|
|
|
|
|
|
|
if (m_frameLatencyCap != 0
|
|
|
|
&& m_frameLatencyCap <= frameLatency)
|
|
|
|
frameLatency = m_frameLatencyCap;
|
|
|
|
|
|
|
|
uint32_t frameId = m_frameId++ % frameLatency;
|
|
|
|
return m_frameEvents[frameId];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Rc<DxvkDevice> STDMETHODCALLTYPE D3D11DXGIDevice::GetDXVKDevice() {
|
|
|
|
return m_dxvkDevice;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Rc<DxvkDevice> D3D11DXGIDevice::CreateDevice(D3D_FEATURE_LEVEL FeatureLevel) {
|
|
|
|
DxvkDeviceFeatures deviceFeatures = D3D11Device::GetDeviceFeatures(m_dxvkAdapter, FeatureLevel);
|
|
|
|
return m_dxvkAdapter->createDevice(deviceFeatures);
|
|
|
|
}
|
|
|
|
|
2017-10-11 09:51:48 +02:00
|
|
|
}
|